Revert "hv: Offload syncing PIR to vIRR to processor hardware"

This reverts commit bf1ff8c98f.

Tracked-On: #4937
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
This commit is contained in:
Shuo A Liu 2020-06-11 09:52:50 +08:00 committed by wenlingz
parent 6b93675225
commit e66de66697

View File

@ -2229,21 +2229,75 @@ static void apicv_basic_inject_intr(struct acrn_vlapic *vlapic,
}
/*
* @brief Send a Posted Interrupt to itself.
*
* Interrupts are disabled on pCPU at this point of time.
* Upon the next VMEnter the self-IPI is serviced by the logical processor.
* Since the IPI vector is Posted Interrupt vector, logical processor syncs
* PIR to vIRR and updates RVI.
*
* @pre get_pi_desc(vlapic->vcpu) != NULL
* Transfer the pending interrupts in the PIR descriptor to the IRR
* in the virtual APIC page.
* @pre get_pi_desc(vlapic2vcpu(vlapic)) != NULL
*/
static void vlapic_apicv_inject_pir(struct acrn_vlapic *vlapic)
{
struct pi_desc *pid;
struct lapic_regs *lapic;
uint64_t val, pirval;
uint16_t rvi, pirbase = 0U, i;
uint16_t intr_status_old, intr_status_new;
struct lapic_reg *irr = NULL;
pid = get_pi_desc(vlapic2vcpu(vlapic));
if (bitmap_test_and_clear_lock(POSTED_INTR_ON, &pid->control.value)) {
pirval = 0UL;
lapic = &(vlapic->apic_page);
irr = &lapic->irr[0];
for (i = 0U; i < 4U; i++) {
val = atomic_readandclear64(&pid->pir[i]);
if (val != 0UL) {
irr[i * 2U].v |= (uint32_t)val;
irr[(i * 2U) + 1U].v |= (uint32_t)(val >> 32U);
pirbase = 64U * i;
pirval = val;
}
}
/*
* Update RVI so the processor can evaluate pending virtual
* interrupts on VM-entry.
*
* It is possible for pirval to be 0 here, even though the
* pending bit has been set. The scenario is:
* CPU-Y is sending a posted interrupt to CPU-X, which
* is running a guest and processing posted interrupts in h/w.
* CPU-X will eventually exit and the state seen in s/w is
* the pending bit set, but no PIR bits set.
*
* CPU-X CPU-Y
* (vm running) (host running)
* rx posted interrupt
* CLEAR pending bit
* SET PIR bit
* READ/CLEAR PIR bits
* SET pending bit
* (vm exit)
* pending bit set, PIR 0
*/
if (pirval != 0UL) {
rvi = pirbase + fls64(pirval);
intr_status_old = 0xFFFFU &
exec_vmread16(VMX_GUEST_INTR_STATUS);
intr_status_new = (intr_status_old & 0xFF00U) | rvi;
if (intr_status_new > intr_status_old) {
exec_vmwrite16(VMX_GUEST_INTR_STATUS,
intr_status_new);
}
}
}
}
static void apicv_advanced_inject_intr(struct acrn_vlapic *vlapic,
__unused bool guest_irq_enabled, __unused bool injected)
{
struct acrn_vcpu *vcpu = vlapic2vcpu(vlapic);
struct pi_desc *pid = get_pi_desc(vcpu);
/*
* From SDM Vol3 26.3.2.5:
* Once the virtual interrupt is recognized, it will be delivered
@ -2254,12 +2308,10 @@ static void apicv_advanced_inject_intr(struct acrn_vlapic *vlapic,
* evaluation/delivery of apicv virtual interrupts in one time
* vm-entry.
*
* Here to sync the pending interrupts to irr and update rvi
* self-IPI with Posted Interrupt Notification Vector is sent.
* Here to sync the pending interrupts to irr and update rvi if
* needed. And then try to handle vmcs event injection.
*/
if (bitmap_test(POSTED_INTR_ON, &(pid->control.value))) {
apicv_trigger_pi_anv(pcpuid_from_vcpu(vcpu), (uint32_t)(vcpu->arch.pid.control.bits.nv));
}
vlapic_apicv_inject_pir(vlapic);
}
void vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected)