Skip to content

Commit 4444dfe

Browse files
tlendackybonzini
authored andcommitted
KVM: SVM: Add NMI support for an SEV-ES guest
The GHCB specification defines how NMIs are to be handled for an SEV-ES guest. To detect the completion of an NMI the hypervisor must not intercept the IRET instruction (because a #VC while running the NMI will issue an IRET) and, instead, must receive an NMI Complete exit event from the guest. Update the KVM support for detecting the completion of NMIs in the guest to follow the GHCB specification. When an SEV-ES guest is active, the IRET instruction will no longer be intercepted. Now, when the NMI Complete exit event is received, the iret_interception() function will be called to simulate the completion of the NMI. Signed-off-by: Tom Lendacky <[email protected]> Message-Id: <5ea3dd69b8d4396cefdc9048ebc1ab7caa70a847.1607620209.git.thomas.lendacky@amd.com> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent ed02b21 commit 4444dfe

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

arch/x86/kvm/svm/sev.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
14491449
if (!ghcb_sw_scratch_is_valid(ghcb))
14501450
goto vmgexit_err;
14511451
break;
1452+
case SVM_VMGEXIT_NMI_COMPLETE:
14521453
case SVM_VMGEXIT_UNSUPPORTED_EVENT:
14531454
break;
14541455
default:
@@ -1770,6 +1771,9 @@ int sev_handle_vmgexit(struct vcpu_svm *svm)
17701771
control->exit_info_2,
17711772
svm->ghcb_sa);
17721773
break;
1774+
case SVM_VMGEXIT_NMI_COMPLETE:
1775+
ret = svm_invoke_exit_handler(svm, SVM_EXIT_IRET);
1776+
break;
17731777
case SVM_VMGEXIT_UNSUPPORTED_EVENT:
17741778
vcpu_unimpl(&svm->vcpu,
17751779
"vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n",

arch/x86/kvm/svm/svm.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,9 +2319,11 @@ static int cpuid_interception(struct vcpu_svm *svm)
23192319
static int iret_interception(struct vcpu_svm *svm)
23202320
{
23212321
++svm->vcpu.stat.nmi_window_exits;
2322-
svm_clr_intercept(svm, INTERCEPT_IRET);
23232322
svm->vcpu.arch.hflags |= HF_IRET_MASK;
2324-
svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
2323+
if (!sev_es_guest(svm->vcpu.kvm)) {
2324+
svm_clr_intercept(svm, INTERCEPT_IRET);
2325+
svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
2326+
}
23252327
kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
23262328
return 1;
23272329
}
@@ -3302,7 +3304,8 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu)
33023304

33033305
svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
33043306
vcpu->arch.hflags |= HF_NMI_MASK;
3305-
svm_set_intercept(svm, INTERCEPT_IRET);
3307+
if (!sev_es_guest(svm->vcpu.kvm))
3308+
svm_set_intercept(svm, INTERCEPT_IRET);
33063309
++vcpu->stat.nmi_injections;
33073310
}
33083311

@@ -3386,10 +3389,12 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
33863389

33873390
if (masked) {
33883391
svm->vcpu.arch.hflags |= HF_NMI_MASK;
3389-
svm_set_intercept(svm, INTERCEPT_IRET);
3392+
if (!sev_es_guest(svm->vcpu.kvm))
3393+
svm_set_intercept(svm, INTERCEPT_IRET);
33903394
} else {
33913395
svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
3392-
svm_clr_intercept(svm, INTERCEPT_IRET);
3396+
if (!sev_es_guest(svm->vcpu.kvm))
3397+
svm_clr_intercept(svm, INTERCEPT_IRET);
33933398
}
33943399
}
33953400

@@ -3567,8 +3572,9 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
35673572
* If we've made progress since setting HF_IRET_MASK, we've
35683573
* executed an IRET and can allow NMI injection.
35693574
*/
3570-
if ((svm->vcpu.arch.hflags & HF_IRET_MASK)
3571-
&& kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip) {
3575+
if ((svm->vcpu.arch.hflags & HF_IRET_MASK) &&
3576+
(sev_es_guest(svm->vcpu.kvm) ||
3577+
kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip)) {
35723578
svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
35733579
kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
35743580
}

0 commit comments

Comments
 (0)