#define SVM_EVTINJ_VALID_ERR (1 << 11)
 
 #define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
+#define SVM_EXITINTINFO_TYPE_MASK SVM_EVTINJ_TYPE_MASK
 
 #define        SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
 #define        SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
 
                                    struct kvm_run *kvm_run)
 {
        u16 tss_selector;
+       int reason;
+       int int_type = svm->vmcb->control.exit_int_info &
+               SVM_EXITINTINFO_TYPE_MASK;
 
        tss_selector = (u16)svm->vmcb->control.exit_info_1;
+
        if (svm->vmcb->control.exit_info_2 &
            (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
-               return kvm_task_switch(&svm->vcpu, tss_selector,
-                                      TASK_SWITCH_IRET);
-       if (svm->vmcb->control.exit_info_2 &
-           (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
-               return kvm_task_switch(&svm->vcpu, tss_selector,
-                                      TASK_SWITCH_JMP);
-       return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL);
+               reason = TASK_SWITCH_IRET;
+       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)
+               reason = TASK_SWITCH_GATE;
+       else
+               reason = TASK_SWITCH_CALL;
+
+
+       if (reason != TASK_SWITCH_GATE || int_type == SVM_EXITINTINFO_TYPE_SOFT)
+               skip_emulated_instruction(&svm->vcpu);
+
+       return kvm_task_switch(&svm->vcpu, tss_selector, reason);
 }
 
 static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long exit_qualification;
        u16 tss_selector;
-       int reason;
+       int reason, type, idt_v;
+
+       idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
        reason = (u32)exit_qualification >> 30;
-       if (reason == TASK_SWITCH_GATE && vmx->vcpu.arch.nmi_injected &&
-           (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
-           (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK)
-           == INTR_TYPE_NMI_INTR) {
-               vcpu->arch.nmi_injected = false;
-               if (cpu_has_virtual_nmis())
-                       vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
-                                     GUEST_INTR_STATE_NMI);
+       if (reason == TASK_SWITCH_GATE && idt_v) {
+               switch (type) {
+               case INTR_TYPE_NMI_INTR:
+                       vcpu->arch.nmi_injected = false;
+                       if (cpu_has_virtual_nmis())
+                               vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+                                             GUEST_INTR_STATE_NMI);
+                       break;
+               case INTR_TYPE_EXT_INTR:
+                       kvm_clear_interrupt_queue(vcpu);
+                       break;
+               case INTR_TYPE_HARD_EXCEPTION:
+               case INTR_TYPE_SOFT_EXCEPTION:
+                       kvm_clear_exception_queue(vcpu);
+                       break;
+               default:
+                       break;
+               }
        }
        tss_selector = exit_qualification;
 
+       if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
+                      type != INTR_TYPE_EXT_INTR &&
+                      type != INTR_TYPE_NMI_INTR))
+               skip_emulated_instruction(vcpu);
+
        if (!kvm_task_switch(vcpu, tss_selector, reason))
                return 0;
 
        vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
        type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
 
-       switch(type) {
+       switch (type) {
        case INTR_TYPE_NMI_INTR:
                vmx->vcpu.arch.nmi_injected = true;
                /*
 
                kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT);
        }
 
-       kvm_x86_ops->skip_emulated_instruction(vcpu);
+       /* set back link to prev task only if NT bit is set in eflags
+          note that old_tss_sel is not used afetr this point */
+       if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
+               old_tss_sel = 0xffff;
 
        /* set back link to prev task only if NT bit is set in eflags
           note that old_tss_sel is not used afetr this point */