If the hypervisor has the interrupt acknowledgement bit set, vector information is already present in intr_info during a vmexit. The hypervisor then uses it to call the appropriate handler. Signed-off-by: Bandan Das <bsd@xxxxxxxxxx> --- lib/x86/isr.c | 32 ++++++++++++++++++++++++++++++++ lib/x86/isr.h | 2 +- x86/vmx_tests.c | 26 +++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/lib/x86/isr.c b/lib/x86/isr.c index 7dcd38a..b0c6f53 100644 --- a/lib/x86/isr.c +++ b/lib/x86/isr.c @@ -90,3 +90,35 @@ void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)) *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4); #endif } + +void handle_external_interrupt(int vector) +{ +#ifdef __x86_64__ + unsigned long tmp; +#endif + idt_entry_t *idt = &boot_idt[vector]; + unsigned long entry = + idt->offset0 | ((unsigned long)idt->offset1 << 16) | + ((unsigned long)idt->offset2 << 32); + + asm volatile( +#ifdef __x86_64__ + "mov %%rsp, %[sp]\n\t" + "and $0xfffffffffffffff0, %%rsp\n\t" + "push $%c[ss]\n\t" + "push %[sp]\n\t" +#endif + "pushf\n\t" + "orl $0x200, (%%rsp)\n\t" + "push $%c[cs]\n\t" + "call *%[entry]\n\t" + : +#ifdef __x86_64__ + [sp]"=&r"(tmp) +#endif + : + [entry]"r"(entry), + [ss]"i"(KERNEL_DS), + [cs]"i"(KERNEL_CS) + ); +} diff --git a/lib/x86/isr.h b/lib/x86/isr.h index b07a32a..a509291 100644 --- a/lib/x86/isr.h +++ b/lib/x86/isr.h @@ -10,5 +10,5 @@ typedef struct { } isr_regs_t; void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)); - +void handle_external_interrupt(int vector); #endif diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 324f074..a40cb18 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1290,6 +1290,16 @@ static void interrupt_main(void) report("intercepted interrupt + activity state hlt", rdtsc() - start > 10000 && timer_fired); + + apic_write(APIC_TMICT, 0); + irq_disable(); + set_stage(7); + vmcall(); + timer_fired = false; + apic_write(APIC_TMICT, 1); + for (loops = 0; loops < 10000000 && !timer_fired; loops++) + asm volatile ("nop"); + report("running a guest with interrupt acknowledgement set", timer_fired); } static int interrupt_exit_handler(void) @@ -1307,6 +1317,11 @@ static int interrupt_exit_handler(void) vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) | PIN_EXTINT); break; + case 7: + vmcs_write(EXI_CONTROLS, vmcs_read(EXI_CONTROLS) | EXI_INTA); + vmcs_write(PIN_CONTROLS, + vmcs_read(PIN_CONTROLS) | PIN_EXTINT); + break; case 1: case 3: vmcs_write(PIN_CONTROLS, @@ -1321,9 +1336,14 @@ static int interrupt_exit_handler(void) vmcs_write(GUEST_RIP, guest_rip + insn_len); return VMX_TEST_RESUME; case VMX_EXTINT: - irq_enable(); - asm volatile ("nop"); - irq_disable(); + if (vmcs_read(EXI_CONTROLS) & EXI_INTA) { + int vector = vmcs_read(EXI_INTR_INFO) & 0xff; + handle_external_interrupt(vector); + } else { + irq_enable(); + asm volatile ("nop"); + irq_disable(); + } if (get_stage() >= 2) { vmcs_write(GUEST_ACTV_STATE, ACTV_ACTIVE); vmcs_write(GUEST_RIP, guest_rip + insn_len); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html