Commit 35920a35 authored by Avi Kivity's avatar Avi Kivity

KVM: VMX: Fix pending exception processing

The vmx code assumes that IDT-Vectoring can only be set when an exception
is injected due to the exception in question.  That's not true, however:
if the exception is injected correctly, and later another exception occurs
but its delivery is blocked due to a fault, then we will incorrectly assume
the first exception was not delivered.

Fix by unconditionally dequeuing the pending exception, and requeuing it
(or the second exception) if we see it in the IDT-Vectoring field.
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 26eef70c
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include "kvm_cache_regs.h" #include "kvm_cache_regs.h"
#include "x86.h"
#include <asm/io.h> #include <asm/io.h>
#include <asm/desc.h> #include <asm/desc.h>
...@@ -744,9 +745,7 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, ...@@ -744,9 +745,7 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
static bool vmx_exception_injected(struct kvm_vcpu *vcpu) static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); return false;
return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
} }
/* /*
...@@ -2824,6 +2823,7 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) ...@@ -2824,6 +2823,7 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
u8 vector; u8 vector;
int type; int type;
bool idtv_info_valid; bool idtv_info_valid;
u32 error;
exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO); exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
if (cpu_has_virtual_nmis()) { if (cpu_has_virtual_nmis()) {
...@@ -2855,6 +2855,15 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) ...@@ -2855,6 +2855,15 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
else else
vmx->vcpu.arch.nmi_injected = false; vmx->vcpu.arch.nmi_injected = false;
} }
kvm_clear_exception_queue(&vmx->vcpu);
if (idtv_info_valid && type == INTR_TYPE_EXCEPTION) {
if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
error = vmcs_read32(IDT_VECTORING_ERROR_CODE);
kvm_queue_exception_e(&vmx->vcpu, vector, error);
} else
kvm_queue_exception(&vmx->vcpu, vector);
vmx->idt_vectoring_info = 0;
}
} }
static void vmx_intr_assist(struct kvm_vcpu *vcpu) static void vmx_intr_assist(struct kvm_vcpu *vcpu)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment