hv: virq: update apicv irr/rvi before handle vmcs event injection

From SDM Vol3 26.3.2.5:
Once the virtual interrupt is recognized, it will be delivered in VMX
non-root operation immediately after VM entry(including any specified
event injection) completes.

So the hardware can handle vmcs event injection and evaluation/delivery
of apicv virtual interrupts in one time vm-entry.

This patch move the apicv irr/rvi sync before handle vmcs events
injection. The old code cause the apicv virtual interrupt evaluation and
delivery be handled until next vm-exit if met pending exceptions.

Tracked-On: #1443
Signed-off-by: Yu Wang <yu1.wang@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yu Wang 2018-10-10 05:49:31 +00:00 committed by wenlingz
parent 90eca21d16
commit 7f2b9a1c7d

View File

@ -430,6 +430,25 @@ int acrn_handle_pending_request(struct vcpu *vcpu)
goto INTR_WIN;
}
/*
* From SDM Vol3 26.3.2.5:
* Once the virtual interrupt is recognized, it will be delivered
* in VMX non-root operation immediately after VM entry(including
* any specified event injection) completes.
*
* So the hardware can handle vmcs event injection and
* evaluation/delivery of apicv virtual interrupts in one time
* vm-entry.
*
* Here to sync the pending interrupts to irr and update rvi if
* needed. And then try to handle vmcs event injection.
*/
if (is_apicv_intr_delivery_supported() &&
bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT,
pending_req_bits)) {
vlapic_apicv_inject_pir(vlapic);
}
/* SDM Vol 3 - table 6-2, inject high priority exception before
* maskable hardware interrupt */
if (vcpu_inject_hi_exception(vcpu) != 0) {
@ -458,19 +477,6 @@ int acrn_handle_pending_request(struct vcpu *vcpu)
goto INTR_WIN;
}
/*
* If the "virtual-interrupt delivery" is enabled,
* sync the pending interrupts to irr and update rvi if needed.
* Then CPU will start evaluate the pending virtual interrupts
* in the later vm-entry.
*
*/
if (is_apicv_intr_delivery_supported() &&
bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT,
pending_req_bits)) {
vlapic_apicv_inject_pir(vlapic);
}
/* Guest interruptable or not */
if (is_guest_irq_enabled(vcpu)) {
/* Inject external interrupt first */