diff options
| author | Brijesh Singh <brijesh.singh@amd.com> | 2022-03-07 15:33:51 -0600 |
|---|---|---|
| committer | Borislav Petkov <bp@suse.de> | 2022-04-07 16:47:12 +0200 |
| commit | d5af44dde5461d125d1602ac913ab5c6bdf09b8b (patch) | |
| tree | 37b7a764183747cb3a64700efe4b9ea5eac913e6 /arch/x86/kernel/sev.c | |
| parent | ba37a1438aeb540cc48722d629f4b2e7e4398466 (diff) | |
| download | linux-d5af44dde5461d125d1602ac913ab5c6bdf09b8b.tar.gz linux-d5af44dde5461d125d1602ac913ab5c6bdf09b8b.tar.bz2 linux-d5af44dde5461d125d1602ac913ab5c6bdf09b8b.zip | |
x86/sev: Provide support for SNP guest request NAEs
Version 2 of GHCB specification provides SNP_GUEST_REQUEST and
SNP_EXT_GUEST_REQUEST NAE that can be used by the SNP guest to
communicate with the PSP.
While at it, add a snp_issue_guest_request() helper that will be used by
driver or other subsystem to issue the request to PSP.
See SEV-SNP firmware and GHCB spec for more details.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-42-brijesh.singh@amd.com
Diffstat (limited to 'arch/x86/kernel/sev.c')
| -rw-r--r-- | arch/x86/kernel/sev.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index 70ecc6e2f251..7237b4178935 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2106,3 +2106,60 @@ static int __init init_sev_config(char *str) return 1; } __setup("sev=", init_sev_config); + +int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err) +{ + struct ghcb_state state; + struct es_em_ctxt ctxt; + unsigned long flags; + struct ghcb *ghcb; + int ret; + + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) + return -ENODEV; + + if (!fw_err) + return -EINVAL; + + /* + * __sev_get_ghcb() needs to run with IRQs disabled because it is using + * a per-CPU GHCB. + */ + local_irq_save(flags); + + ghcb = __sev_get_ghcb(&state); + if (!ghcb) { + ret = -EIO; + goto e_restore_irq; + } + + vc_ghcb_invalidate(ghcb); + + if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { + ghcb_set_rax(ghcb, input->data_gpa); + ghcb_set_rbx(ghcb, input->data_npages); + } + + ret = sev_es_ghcb_hv_call(ghcb, true, &ctxt, exit_code, input->req_gpa, input->resp_gpa); + if (ret) + goto e_put; + + if (ghcb->save.sw_exit_info_2) { + /* Number of expected pages are returned in RBX */ + if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && + ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) + input->data_npages = ghcb_get_rbx(ghcb); + + *fw_err = ghcb->save.sw_exit_info_2; + + ret = -EIO; + } + +e_put: + __sev_put_ghcb(&state); +e_restore_irq: + local_irq_restore(flags); + + return ret; +} +EXPORT_SYMBOL_GPL(snp_issue_guest_request); |
