[x86][hypervisor] Use appropriate vector constants
Throw an error when we attempt to inject an invalid vector.
TEST=hypervisor_unittests
Change-Id: I27e980230196fbd795997ffabcc83ad6ea35a413
diff --git a/kernel/arch/x86/hypervisor/vcpu.cpp b/kernel/arch/x86/hypervisor/vcpu.cpp
index e997846..f5f2d2a 100644
--- a/kernel/arch/x86/hypervisor/vcpu.cpp
+++ b/kernel/arch/x86/hypervisor/vcpu.cpp
@@ -148,8 +148,8 @@
interrupt_info |= kInterruptTypeSoftwareException;
} else if (vector == X86_INT_NMI) {
interrupt_info |= kInterruptTypeNmi;
- } else if (vector < X86_INT_PLATFORM_BASE) {
- // From Volume 3, Section 6.15. Vectors from 0 to 32 (X86_INT_PLATFORM_BASE) are exceptions.
+ } else if (vector <= X86_INT_VIRT) {
+ // From Volume 3, Section 6.15. All other vectors from 0 to X86_INT_VIRT are exceptions.
interrupt_info |= kInterruptTypeHardwareException;
}
if (has_error_code(vector)) {
@@ -707,24 +707,27 @@
// Since hardware generated exceptions are delivered to the guest directly, the only exceptions
// we see here are those we generate in the VMM, e.g. GP faults in vmexit handlers. Therefore
// we simplify interrupt priority to 1) NMIs, 2) interrupts, and 3) generated exceptions. See
- // Intel Volume 3, Section 6.9, Table 6-2.
+ // Volume 3, Section 6.9, Table 6-2.
uint32_t vector;
hypervisor::InterruptType type = local_apic_state->interrupt_tracker.TryPop(X86_INT_NMI);
if (type != hypervisor::InterruptType::INACTIVE) {
vector = X86_INT_NMI;
} else {
// Pop scans vectors from highest to lowest, which will correctly pop interrupts before
- // exceptions. All vectors < X86_INT_PLATFORM_BASE except the NMI vector are exceptions.
+ // exceptions. All vectors <= X86_INT_VIRT except the NMI vector are exceptions.
type = local_apic_state->interrupt_tracker.Pop(&vector);
if (type == hypervisor::InterruptType::INACTIVE) {
return ZX_OK;
}
}
- // Intel Volume 3, Section 6.8.1: The IF flag does not affect non-maskable interrupts (NMIs),
- // [...] nor does it affect processor generated exceptions.
- if (vector >= X86_INT_PLATFORM_BASE &&
+ if (vector > X86_INT_VIRT && vector < X86_INT_PLATFORM_BASE) {
+ dprintf(INFO, "Invalid interrupt vector: %u\n", vector);
+ return ZX_ERR_NOT_SUPPORTED;
+ } else if (vector >= X86_INT_PLATFORM_BASE &&
!(vmcs->Read(VmcsFieldXX::GUEST_RFLAGS) & X86_FLAGS_IF)) {
+ // Volume 3, Section 6.8.1: The IF flag does not affect non-maskable interrupts (NMIs),
+ // [...] nor does it affect processor generated exceptions.
local_apic_state->interrupt_tracker.Track(vector, type);
// If interrupts are disabled, we set VM exit on interrupt enable.
vmcs->InterruptWindowExiting(true);
@@ -734,12 +737,12 @@
// If the vector is non-maskable or interrupts are enabled, we inject an interrupt.
vmcs->IssueInterrupt(vector);
- // Intel Volume 3, Section 6.9: Lower priority exceptions are discarded; lower priority
- // interrupts are held pending. Discarded exceptions are re-generated when the interrupt handler
- // returns execution to the point in the program or task where the exceptions and/or interrupts
+ // Volume 3, Section 6.9: Lower priority exceptions are discarded; lower priority interrupts are
+ // held pending. Discarded exceptions are re-generated when the interrupt handler returns
+ // execution to the point in the program or task where the exceptions and/or interrupts
// occurred.
local_apic_state->interrupt_tracker.Clear(0, X86_INT_NMI);
- local_apic_state->interrupt_tracker.Clear(X86_INT_NMI + 1, X86_INT_PLATFORM_BASE);
+ local_apic_state->interrupt_tracker.Clear(X86_INT_NMI + 1, X86_INT_VIRT + 1);
return ZX_OK;
}