KVM: SVM: Skip instruction on a task switch only when appropriate
authorGleb Natapov <gleb@redhat.com>
Sun, 12 Apr 2009 10:37:02 +0000 (13:37 +0300)
committerAvi Kivity <avi@redhat.com>
Wed, 10 Jun 2009 08:48:42 +0000 (11:48 +0300)
If a task switch was initiated because off a task gate in IDT and IDT
was accessed because of an external even the instruction should not
be skipped.

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

index bba67b70c4b01212513a85640865f8035a03b047..8fc6eea148e7fde208d763c1ffdbebc1c23e76e6 100644 (file)
@@ -1828,6 +1828,7 @@ static int task_switch_interception(struct vcpu_svm *svm,
        int reason;
        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;
 
        tss_selector = (u16)svm->vmcb->control.exit_info_1;
 
@@ -1843,8 +1844,14 @@ static int task_switch_interception(struct vcpu_svm *svm,
                reason = TASK_SWITCH_CALL;
 
 
-       if (reason != TASK_SWITCH_GATE || int_type == SVM_EXITINTINFO_TYPE_SOFT)
-               skip_emulated_instruction(&svm->vcpu);
+       if (reason != TASK_SWITCH_GATE ||
+           int_type == SVM_EXITINTINFO_TYPE_SOFT ||
+           (int_type == SVM_EXITINTINFO_TYPE_EXEPT &&
+            (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) {
+               if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0,
+                                       EMULTYPE_SKIP) != EMULATE_DONE)
+                       return 0;
+       }
 
        return kvm_task_switch(&svm->vcpu, tss_selector, reason);
 }