KVM: SVM: Don't reinject event that caused a task switch
authorGleb Natapov <gleb@redhat.com>
Thu, 23 Apr 2009 14:03:48 +0000 (17:03 +0300)
committerAvi Kivity <avi@redhat.com>
Wed, 10 Jun 2009 08:48:51 +0000 (11:48 +0300)
If a task switch caused by an event remove it from the event queue.
VMX already does that.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/x86/kvm/svm.c

index e3ea982..f994c6d 100644 (file)
@@ -1811,6 +1811,10 @@ static int task_switch_interception(struct vcpu_svm *svm,
        int int_type = svm->vmcb->control.exit_int_info &
                SVM_EXITINTINFO_TYPE_MASK;
        int int_vec = svm->vmcb->control.exit_int_info & SVM_EVTINJ_VEC_MASK;
+       uint32_t type =
+               svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
+       uint32_t idt_v =
+               svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID;
 
        tss_selector = (u16)svm->vmcb->control.exit_info_1;
 
@@ -1820,11 +1824,26 @@ static int task_switch_interception(struct vcpu_svm *svm,
        else if (svm->vmcb->control.exit_info_2 &
                 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
                reason = TASK_SWITCH_JMP;
-       else if (svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID)
+       else if (idt_v)
                reason = TASK_SWITCH_GATE;
        else
                reason = TASK_SWITCH_CALL;
 
+       if (reason == TASK_SWITCH_GATE) {
+               switch (type) {
+               case SVM_EXITINTINFO_TYPE_NMI:
+                       svm->vcpu.arch.nmi_injected = false;
+                       break;
+               case SVM_EXITINTINFO_TYPE_EXEPT:
+                       kvm_clear_exception_queue(&svm->vcpu);
+                       break;
+               case SVM_EXITINTINFO_TYPE_INTR:
+                       kvm_clear_interrupt_queue(&svm->vcpu);
+                       break;
+               default:
+                       break;
+               }
+       }
 
        if (reason != TASK_SWITCH_GATE ||
            int_type == SVM_EXITINTINFO_TYPE_SOFT ||
@@ -2203,7 +2222,7 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
            exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
-           exit_code != SVM_EXIT_NPF)
+           exit_code != SVM_EXIT_NPF && exit_code != SVM_EXIT_TASK_SWITCH)
                printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
                       "exit_code 0x%x\n",
                       __func__, svm->vmcb->control.exit_int_info,