Skip to content

Commit 74458e4

Browse files
mdrothbonzini
authored andcommitted
KVM: SEV: Provide support for SNP_EXTENDED_GUEST_REQUEST NAE event
Version 2 of GHCB specification added support for the SNP Extended Guest Request Message NAE event. This event serves a nearly identical purpose to the previously-added SNP_GUEST_REQUEST event, but for certain message types it allows the guest to supply a buffer to be used for additional information in some cases. Currently the GHCB spec only defines extended handling of this sort in the case of attestation requests, where the additional buffer is used to supply a table of certificate data corresponding to the attestion report's signing key. Support for this extended handling will require additional KVM APIs to handle coordinating with userspace. Whether or not the hypervisor opts to provide this certificate data is optional. However, support for processing SNP_EXTENDED_GUEST_REQUEST GHCB requests is required by the GHCB 2.0 specification for SNP guests, so for now implement a stub implementation that provides an empty certificate table to the guest if it supplies an additional buffer, but otherwise behaves identically to SNP_GUEST_REQUEST. Reviewed-by: Carlos Bilbao <[email protected]> Reviewed-by: Tom Lendacky <[email protected]> Reviewed-by: Liam Merwick <[email protected]> Signed-off-by: Michael Roth <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent f55f3c3 commit 74458e4

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

arch/x86/kvm/svm/sev.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3379,6 +3379,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
33793379
goto vmgexit_err;
33803380
break;
33813381
case SVM_VMGEXIT_GUEST_REQUEST:
3382+
case SVM_VMGEXIT_EXT_GUEST_REQUEST:
33823383
if (!sev_snp_guest(vcpu->kvm) ||
33833384
!PAGE_ALIGNED(control->exit_info_1) ||
33843385
!PAGE_ALIGNED(control->exit_info_2) ||
@@ -4048,6 +4049,58 @@ static int snp_handle_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t resp_
40484049
return ret;
40494050
}
40504051

4052+
static int snp_handle_ext_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t resp_gpa)
4053+
{
4054+
struct kvm *kvm = svm->vcpu.kvm;
4055+
u8 msg_type;
4056+
4057+
if (!sev_snp_guest(kvm))
4058+
return -EINVAL;
4059+
4060+
if (kvm_read_guest(kvm, req_gpa + offsetof(struct snp_guest_msg_hdr, msg_type),
4061+
&msg_type, 1))
4062+
return -EIO;
4063+
4064+
/*
4065+
* As per GHCB spec, requests of type MSG_REPORT_REQ also allow for
4066+
* additional certificate data to be provided alongside the attestation
4067+
* report via the guest-provided data pages indicated by RAX/RBX. The
4068+
* certificate data is optional and requires additional KVM enablement
4069+
* to provide an interface for userspace to provide it, but KVM still
4070+
* needs to be able to handle extended guest requests either way. So
4071+
* provide a stub implementation that will always return an empty
4072+
* certificate table in the guest-provided data pages.
4073+
*/
4074+
if (msg_type == SNP_MSG_REPORT_REQ) {
4075+
struct kvm_vcpu *vcpu = &svm->vcpu;
4076+
u64 data_npages;
4077+
gpa_t data_gpa;
4078+
4079+
if (!kvm_ghcb_rax_is_valid(svm) || !kvm_ghcb_rbx_is_valid(svm))
4080+
goto request_invalid;
4081+
4082+
data_gpa = vcpu->arch.regs[VCPU_REGS_RAX];
4083+
data_npages = vcpu->arch.regs[VCPU_REGS_RBX];
4084+
4085+
if (!PAGE_ALIGNED(data_gpa))
4086+
goto request_invalid;
4087+
4088+
/*
4089+
* As per GHCB spec (see "SNP Extended Guest Request"), the
4090+
* certificate table is terminated by 24-bytes of zeroes.
4091+
*/
4092+
if (data_npages && kvm_clear_guest(kvm, data_gpa, 24))
4093+
return -EIO;
4094+
}
4095+
4096+
return snp_handle_guest_req(svm, req_gpa, resp_gpa);
4097+
4098+
request_invalid:
4099+
ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
4100+
ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
4101+
return 1; /* resume guest */
4102+
}
4103+
40514104
static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
40524105
{
40534106
struct vmcb_control_area *control = &svm->vmcb->control;
@@ -4325,6 +4378,9 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
43254378
case SVM_VMGEXIT_GUEST_REQUEST:
43264379
ret = snp_handle_guest_req(svm, control->exit_info_1, control->exit_info_2);
43274380
break;
4381+
case SVM_VMGEXIT_EXT_GUEST_REQUEST:
4382+
ret = snp_handle_ext_guest_req(svm, control->exit_info_1, control->exit_info_2);
4383+
break;
43284384
case SVM_VMGEXIT_UNSUPPORTED_EVENT:
43294385
vcpu_unimpl(vcpu,
43304386
"vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n",

0 commit comments

Comments
 (0)