aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/svm.h1
-rw-r--r--arch/x86/kvm/svm.c25
-rw-r--r--arch/x86/kvm/vmx.c38
-rw-r--r--arch/x86/kvm/x86.c5
4 files changed, 51 insertions, 18 deletions
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 82ada75f3ebf..85574b7c1bc1 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -225,6 +225,7 @@ struct __attribute__ ((__packed__)) vmcb {
225#define SVM_EVTINJ_VALID_ERR (1 << 11) 225#define SVM_EVTINJ_VALID_ERR (1 << 11)
226 226
227#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK 227#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
228#define SVM_EXITINTINFO_TYPE_MASK SVM_EVTINJ_TYPE_MASK
228 229
229#define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR 230#define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
230#define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI 231#define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index de741043c5b1..bba67b70c4b0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1825,17 +1825,28 @@ static int task_switch_interception(struct vcpu_svm *svm,
1825 struct kvm_run *kvm_run) 1825 struct kvm_run *kvm_run)
1826{ 1826{
1827 u16 tss_selector; 1827 u16 tss_selector;
1828 int reason;
1829 int int_type = svm->vmcb->control.exit_int_info &
1830 SVM_EXITINTINFO_TYPE_MASK;
1828 1831
1829 tss_selector = (u16)svm->vmcb->control.exit_info_1; 1832 tss_selector = (u16)svm->vmcb->control.exit_info_1;
1833
1830 if (svm->vmcb->control.exit_info_2 & 1834 if (svm->vmcb->control.exit_info_2 &
1831 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET)) 1835 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
1832 return kvm_task_switch(&svm->vcpu, tss_selector, 1836 reason = TASK_SWITCH_IRET;
1833 TASK_SWITCH_IRET); 1837 else if (svm->vmcb->control.exit_info_2 &
1834 if (svm->vmcb->control.exit_info_2 & 1838 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
1835 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP)) 1839 reason = TASK_SWITCH_JMP;
1836 return kvm_task_switch(&svm->vcpu, tss_selector, 1840 else if (svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID)
1837 TASK_SWITCH_JMP); 1841 reason = TASK_SWITCH_GATE;
1838 return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL); 1842 else
1843 reason = TASK_SWITCH_CALL;
1844
1845
1846 if (reason != TASK_SWITCH_GATE || int_type == SVM_EXITINTINFO_TYPE_SOFT)
1847 skip_emulated_instruction(&svm->vcpu);
1848
1849 return kvm_task_switch(&svm->vcpu, tss_selector, reason);
1839} 1850}
1840 1851
1841static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) 1852static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index e4ad9d3c0636..c6997c0e8ca6 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3038,22 +3038,40 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3038 struct vcpu_vmx *vmx = to_vmx(vcpu); 3038 struct vcpu_vmx *vmx = to_vmx(vcpu);
3039 unsigned long exit_qualification; 3039 unsigned long exit_qualification;
3040 u16 tss_selector; 3040 u16 tss_selector;
3041 int reason; 3041 int reason, type, idt_v;
3042
3043 idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
3044 type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
3042 3045
3043 exit_qualification = vmcs_readl(EXIT_QUALIFICATION); 3046 exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
3044 3047
3045 reason = (u32)exit_qualification >> 30; 3048 reason = (u32)exit_qualification >> 30;
3046 if (reason == TASK_SWITCH_GATE && vmx->vcpu.arch.nmi_injected && 3049 if (reason == TASK_SWITCH_GATE && idt_v) {
3047 (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) && 3050 switch (type) {
3048 (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK) 3051 case INTR_TYPE_NMI_INTR:
3049 == INTR_TYPE_NMI_INTR) { 3052 vcpu->arch.nmi_injected = false;
3050 vcpu->arch.nmi_injected = false; 3053 if (cpu_has_virtual_nmis())
3051 if (cpu_has_virtual_nmis()) 3054 vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
3052 vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, 3055 GUEST_INTR_STATE_NMI);
3053 GUEST_INTR_STATE_NMI); 3056 break;
3057 case INTR_TYPE_EXT_INTR:
3058 kvm_clear_interrupt_queue(vcpu);
3059 break;
3060 case INTR_TYPE_HARD_EXCEPTION:
3061 case INTR_TYPE_SOFT_EXCEPTION:
3062 kvm_clear_exception_queue(vcpu);
3063 break;
3064 default:
3065 break;
3066 }
3054 } 3067 }
3055 tss_selector = exit_qualification; 3068 tss_selector = exit_qualification;
3056 3069
3070 if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
3071 type != INTR_TYPE_EXT_INTR &&
3072 type != INTR_TYPE_NMI_INTR))
3073 skip_emulated_instruction(vcpu);
3074
3057 if (!kvm_task_switch(vcpu, tss_selector, reason)) 3075 if (!kvm_task_switch(vcpu, tss_selector, reason))
3058 return 0; 3076 return 0;
3059 3077
@@ -3306,7 +3324,7 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
3306 vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK; 3324 vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
3307 type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK; 3325 type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
3308 3326
3309 switch(type) { 3327 switch (type) {
3310 case INTR_TYPE_NMI_INTR: 3328 case INTR_TYPE_NMI_INTR:
3311 vmx->vcpu.arch.nmi_injected = true; 3329 vmx->vcpu.arch.nmi_injected = true;
3312 /* 3330 /*
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index adcf73871a9d..bb04f11bf70f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3935,7 +3935,10 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
3935 kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT); 3935 kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT);
3936 } 3936 }
3937 3937
3938 kvm_x86_ops->skip_emulated_instruction(vcpu); 3938 /* set back link to prev task only if NT bit is set in eflags
3939 note that old_tss_sel is not used afetr this point */
3940 if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
3941 old_tss_sel = 0xffff;
3939 3942
3940 /* set back link to prev task only if NT bit is set in eflags 3943 /* set back link to prev task only if NT bit is set in eflags
3941 note that old_tss_sel is not used afetr this point */ 3944 note that old_tss_sel is not used afetr this point */