diff options
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r-- | arch/x86/kvm/svm.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 63fec1531e89..6bb15d583e47 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -135,6 +135,8 @@ struct vcpu_svm { | |||
135 | 135 | ||
136 | u32 *msrpm; | 136 | u32 *msrpm; |
137 | 137 | ||
138 | ulong nmi_iret_rip; | ||
139 | |||
138 | struct nested_state nested; | 140 | struct nested_state nested; |
139 | 141 | ||
140 | bool nmi_singlestep; | 142 | bool nmi_singlestep; |
@@ -1153,8 +1155,10 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu) | |||
1153 | wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); | 1155 | wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); |
1154 | load_gs_index(svm->host.gs); | 1156 | load_gs_index(svm->host.gs); |
1155 | #else | 1157 | #else |
1158 | #ifdef CONFIG_X86_32_LAZY_GS | ||
1156 | loadsegment(gs, svm->host.gs); | 1159 | loadsegment(gs, svm->host.gs); |
1157 | #endif | 1160 | #endif |
1161 | #endif | ||
1158 | for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++) | 1162 | for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++) |
1159 | wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]); | 1163 | wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]); |
1160 | } | 1164 | } |
@@ -2653,6 +2657,7 @@ static int iret_interception(struct vcpu_svm *svm) | |||
2653 | ++svm->vcpu.stat.nmi_window_exits; | 2657 | ++svm->vcpu.stat.nmi_window_exits; |
2654 | clr_intercept(svm, INTERCEPT_IRET); | 2658 | clr_intercept(svm, INTERCEPT_IRET); |
2655 | svm->vcpu.arch.hflags |= HF_IRET_MASK; | 2659 | svm->vcpu.arch.hflags |= HF_IRET_MASK; |
2660 | svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu); | ||
2656 | return 1; | 2661 | return 1; |
2657 | } | 2662 | } |
2658 | 2663 | ||
@@ -3474,7 +3479,12 @@ static void svm_complete_interrupts(struct vcpu_svm *svm) | |||
3474 | 3479 | ||
3475 | svm->int3_injected = 0; | 3480 | svm->int3_injected = 0; |
3476 | 3481 | ||
3477 | if (svm->vcpu.arch.hflags & HF_IRET_MASK) { | 3482 | /* |
3483 | * If we've made progress since setting HF_IRET_MASK, we've | ||
3484 | * executed an IRET and can allow NMI injection. | ||
3485 | */ | ||
3486 | if ((svm->vcpu.arch.hflags & HF_IRET_MASK) | ||
3487 | && kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip) { | ||
3478 | svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK); | 3488 | svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK); |
3479 | kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); | 3489 | kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); |
3480 | } | 3490 | } |
@@ -3641,19 +3651,30 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) | |||
3641 | wrmsrl(MSR_GS_BASE, svm->host.gs_base); | 3651 | wrmsrl(MSR_GS_BASE, svm->host.gs_base); |
3642 | #else | 3652 | #else |
3643 | loadsegment(fs, svm->host.fs); | 3653 | loadsegment(fs, svm->host.fs); |
3654 | #ifndef CONFIG_X86_32_LAZY_GS | ||
3655 | loadsegment(gs, svm->host.gs); | ||
3656 | #endif | ||
3644 | #endif | 3657 | #endif |
3645 | 3658 | ||
3646 | reload_tss(vcpu); | 3659 | reload_tss(vcpu); |
3647 | 3660 | ||
3648 | local_irq_disable(); | 3661 | local_irq_disable(); |
3649 | 3662 | ||
3650 | stgi(); | ||
3651 | |||
3652 | vcpu->arch.cr2 = svm->vmcb->save.cr2; | 3663 | vcpu->arch.cr2 = svm->vmcb->save.cr2; |
3653 | vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax; | 3664 | vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax; |
3654 | vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; | 3665 | vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; |
3655 | vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; | 3666 | vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; |
3656 | 3667 | ||
3668 | if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI)) | ||
3669 | kvm_before_handle_nmi(&svm->vcpu); | ||
3670 | |||
3671 | stgi(); | ||
3672 | |||
3673 | /* Any pending NMI will happen here */ | ||
3674 | |||
3675 | if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI)) | ||
3676 | kvm_after_handle_nmi(&svm->vcpu); | ||
3677 | |||
3657 | sync_cr8_to_lapic(vcpu); | 3678 | sync_cr8_to_lapic(vcpu); |
3658 | 3679 | ||
3659 | svm->next_rip = 0; | 3680 | svm->next_rip = 0; |