linuxx86virtual-machinevirtualizationapic

"Acknowledge interrupt on exit" control in VT-x causes CPU lockup


I am working on supporting posted interrupts in a VMM that I'm writing that uses Intel VT-x virtualization. One of the VM entry requirements specified in the documentation for enabling posted interrupts is that the "Acknowledge interrupt on exit" VM-exit control must be set to 1.

When I set this control to 1, my guest OS runs for a short while before it stops responding. Then, the host OS stops responding as well, and a message is printed to the host kernel log that says that the CPU core that the guest OS was running on has experienced a hard lockup (NMI watchdog: Watchdog detected hard LOCKUP on cpu 10).

I'm reading the Intel documentation and trying to think through this, but was wondering if anyone else knew what's going on. My general thoughts right now are that the host OS must be sending an interrupt to the core that the guest OS is running on at the moment (i.e. my guest OS is not involved in sending the interrupt), which causes a VM exit. Since I set the "Acknowledge interrupt on exit" control to 1, the processor acknowledges to the interrupt controller that the interrupt was received, and puts the vector in the VM-exit interruption-information field. Furthermore, since I don't do anything with the interruption-information field in my VMM at the moment, the interrupt then doesn't get handled by the host OS, which causes the problem. Am I heading in the right direction?


Solution

  • Yes, not allowing the host OS to handle device interrupts would be a problem. Instead of setting the "acknowledge interrupt on exit" control to one you should probably set it to 0. Then when you get a VM exit due to a hardware interrupt you should set the processor interrupt enable flag to allow the interrupt to be acknowledged and serviced normally in the host.

    From the Intel 64 and IA-32 Architectures Software Developer’s Manual:

    33.2 INTERRUPT HANDLING IN VMX OPERATION

    • Acknowledge interrupt on exit. The “acknowledge interrupt on exit” VM-exit control in the controlling VMCS controls processor behavior for external interrupt acknowledgement. If the control is 1, the processor acknowledges the interrupt controller to acquire the interrupt vector upon VM exit, and stores the vector in the VM-exit interruption-information field. If the control is 0, the external interrupt is not acknowledged during VM exit. Since RFLAGS.IF is automatically cleared on VM exits due to external interrupts, VMM re-enabling of interrupts (setting RFLAGS.IF = 1) initiates the external interrupt acknowledgement and vectoring of the external interrupt through the monitor/host IDT

    Alternatively, if you have a good reason to set this this bit, say if you need to route certain hardware interrupts to the guest, then you'll need to invoke the host OS's interrupt handler as if it had been invoked by the CPU.