mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
VMX: fix interaction of APIC-V and Viridian emulation
Viridian using a synthetic MSR for issuing EOI notifications bypasses the normal in-processor handling, which would clear GUEST_INTR_STATUS.SVI. Hence we need to do this in software in order for future interrupts to get delivered. Based on analysis by Yang Z Zhang <yang.z.zhang@intel.com>. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Yang Zhang <yang.z.zhang@intel.com>
This commit is contained in:
1 parent
85047d9e4f
commit
303066fdb1
3 files changed
+18
-1
No files matched your search
@@ -386,6 +386,9 @@ void vlapic_EOI_set(struct vlapic *vlapic)
|
||||
|
||||
vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]);
|
||||
|
||||
if ( hvm_funcs.handle_eoi )
|
||||
hvm_funcs.handle_eoi(vector);
|
||||
|
||||
if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) )
|
||||
vioapic_update_EOI(vlapic_domain(vlapic), vector);
|
||||
|
||||
|
||||
@@ -1505,6 +1505,15 @@ static void vmx_sync_pir_to_irr(struct vcpu *v)
|
||||
vlapic_set_vector(i, &vlapic->regs->data[APIC_IRR]);
|
||||
}
|
||||
|
||||
static void vmx_handle_eoi(u8 vector)
|
||||
{
|
||||
unsigned long status = __vmread(GUEST_INTR_STATUS);
|
||||
|
||||
/* We need to clear the SVI field. */
|
||||
status &= VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK;
|
||||
__vmwrite(GUEST_INTR_STATUS, status);
|
||||
}
|
||||
|
||||
static struct hvm_function_table __initdata vmx_function_table = {
|
||||
.name = "VMX",
|
||||
.cpu_up_prepare = vmx_cpu_up_prepare,
|
||||
@@ -1557,6 +1566,7 @@ static struct hvm_function_table __initdata vmx_function_table = {
|
||||
.process_isr = vmx_process_isr,
|
||||
.deliver_posted_intr = vmx_deliver_posted_intr,
|
||||
.sync_pir_to_irr = vmx_sync_pir_to_irr,
|
||||
.handle_eoi = vmx_handle_eoi,
|
||||
.nhvm_hap_walk_L1_p2m = nvmx_hap_walk_L1_p2m,
|
||||
};
|
||||
|
||||
@@ -1583,7 +1593,10 @@ const struct hvm_function_table * __init start_vmx(void)
|
||||
|
||||
setup_ept_dump();
|
||||
}
|
||||
|
||||
|
||||
if ( !cpu_has_vmx_virtual_intr_delivery )
|
||||
vmx_function_table.handle_eoi = NULL;
|
||||
|
||||
if ( cpu_has_vmx_posted_intr_processing )
|
||||
alloc_direct_apic_vector(&posted_intr_vector, event_check_interrupt);
|
||||
else
|
||||
|
||||
@@ -186,6 +186,7 @@ struct hvm_function_table {
|
||||
void (*process_isr)(int isr, struct vcpu *v);
|
||||
void (*deliver_posted_intr)(struct vcpu *v, u8 vector);
|
||||
void (*sync_pir_to_irr)(struct vcpu *v);
|
||||
void (*handle_eoi)(u8 vector);
|
||||
|
||||
/*Walk nested p2m */
|
||||
int (*nhvm_hap_walk_L1_p2m)(struct vcpu *v, paddr_t L2_gpa,
|
||||
|
||||