arm: remote IPI call support for VIRQS

Added support for injecting remote IPI calls towards given VCPU's
on SMP configured systems. This introudcing a new type of
IpiRemoteCall and handlers for updating the vgic state on
incoming/outgoing IPI's.

Co-authored-by: Yanyan Shen <yanyan.shen@data61.csiro.au>
This commit is contained in:
Anna Lyons 2020-01-28 17:54:30 +11:00 committed by Kent McLeod
parent bddd405417
commit c4fe536984
5 changed files with 35 additions and 0 deletions

View file

@ -116,6 +116,9 @@ exception_t decodeARMVCPUInvocation(
void vcpu_restore(vcpu_t *cpu);
void vcpu_switch(vcpu_t *cpu);
#ifdef ENABLE_SMP_SUPPORT
void handleVCPUInjectInterruptIPI(vcpu_t *vcpu, unsigned long index, virq_t virq);
#endif /* ENABLE_SMP_SUPPORT */
exception_t decodeVCPUWriteReg(cap_t cap, unsigned int length, word_t *buffer);
exception_t decodeVCPUReadReg(cap_t cap, unsigned int length, bool_t call, word_t *buffer);

View file

@ -23,6 +23,9 @@ typedef enum {
IpiRemoteCall_InvalidateTranslationAll,
IpiRemoteCall_switchFpuOwner,
IpiRemoteCall_MaskPrivateInterrupt,
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
IpiRemoteCall_VCPUInjectInterrupt,
#endif
/* Add relevant calls here upon required */
IpiNumArchRemoteCall
} IpiRemoteCall_t;

View file

@ -150,6 +150,11 @@ static void inline doRemoteOp2Arg(IpiRemoteCall_t func, word_t data1, word_t dat
doRemoteOp(func, data1, data2, 0, cpu);
}
static void inline doRemoteOp3Arg(IpiRemoteCall_t func, word_t data1, word_t data2, word_t data3, word_t cpu)
{
doRemoteOp(func, data1, data2, data3, cpu);
}
/* This is asynchronous call and could be called outside the lock.
* Returns immediately.
*

View file

@ -369,6 +369,10 @@ exception_t invokeVCPUInjectIRQ(vcpu_t *vcpu, unsigned long index, virq_t virq)
{
if (likely(ARCH_NODE_STATE(armHSCurVCPU) == vcpu)) {
set_gic_vcpu_ctrl_lr(index, virq);
#ifdef ENABLE_SMP_SUPPORT
} else if (vcpu->vcpuTCB->tcbAffinity != getCurrentCPUIndex()) {
doRemoteOp3Arg(IpiRemoteCall_VCPUInjectInterrupt, (word_t)vcpu, index, virq.words[0], vcpu->vcpuTCB->tcbAffinity);
#endif /* CONFIG_ENABLE_SMP */
} else {
vcpu->vgic.lr[index] = virq;
}
@ -564,4 +568,15 @@ void handleVCPUFault(word_t hsr)
activateThread();
}
#ifdef ENABLE_SMP_SUPPORT
void handleVCPUInjectInterruptIPI(vcpu_t *vcpu, unsigned long index, virq_t virq)
{
if (likely(ARCH_NODE_STATE(armHSCurVCPU) == vcpu)) {
set_gic_vcpu_ctrl_lr(index, virq);
} else {
vcpu->vgic.lr[index] = virq;
}
}
#endif /* ENABLE_SMP_SUPPORT */
#endif

View file

@ -65,6 +65,15 @@ static void handleRemoteCall(IpiModeRemoteCall_t call, word_t arg0,
maskInterrupt(arg0, IDX_TO_IRQT(arg1));
break;
#if defined CONFIG_ARM_HYPERVISOR_SUPPORT && defined ENABLE_SMP_SUPPORT
case IpiRemoteCall_VCPUInjectInterrupt: {
virq_t virq;
virq.words[0] = arg2;
handleVCPUInjectInterruptIPI((vcpu_t *) arg0, arg1, virq);
break;
}
#endif
default:
fail("Invalid remote call");
break;