From ff2095935f6b5deae4cceb278dc2c3b124ea3045 Mon Sep 17 00:00:00 2001 From: Dionna Glaze Date: Tue, 11 Oct 2022 19:57:11 +0000 Subject: [PATCH 1/2] virt/coco/sev-guest: Initialize err in handle_guest_request The err variable may not be set in the call to snp_issue_guest_request, yet it is unconditionally written back to fw_err if fw_err is non-null. This is undefined behavior, and currently returns uninitialized kernel stack memory to user space. Cc: Tom Lendacky Cc: Paolo Bonzini Cc: Joerg Roedel Cc: Peter Gonda Cc: Thomas Gleixner Cc: Dave Hansen Signed-off-by: Dionna Glaze --- drivers/virt/coco/sevguest/sevguest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/virt/coco/sevguest/sevguest.c b/drivers/virt/coco/sevguest/sevguest.c index 112c0458cbda8c..7a62bfc063fc22 100644 --- a/drivers/virt/coco/sevguest/sevguest.c +++ b/drivers/virt/coco/sevguest/sevguest.c @@ -307,7 +307,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in u8 type, void *req_buf, size_t req_sz, void *resp_buf, u32 resp_sz, __u64 *fw_err) { - unsigned long err; + unsigned long err = 0; u64 seqno; int rc; From 73d8c9111d0f0253a02199e18b045ec1076eae78 Mon Sep 17 00:00:00 2001 From: Dionna Glaze Date: Tue, 11 Oct 2022 21:13:29 +0000 Subject: [PATCH 2/2] x86/sev: Interpret vmm result as throttling The GHCB specification recommends the host kernel implement a throttling mechanism for guest requests. The VMGEXIT that initiates the request can then fail for throttling reasons. Add a new return code and interpret it as -EAGAIN in snp_issue_guest_request Cc: Tom Lendacky Cc: Paolo Bonzini Cc: Joerg Roedel Cc: Thomas Gleixner Cc: Michael Roth Cc: Dave Hansen Signed-off-by: Dionna Glaze --- arch/x86/include/asm/sev-common.h | 6 ++++++ arch/x86/kernel/sev-shared.c | 4 +++- arch/x86/kernel/sev.c | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h index b8357d6ecd47ef..c250b453288c35 100644 --- a/arch/x86/include/asm/sev-common.h +++ b/arch/x86/include/asm/sev-common.h @@ -149,6 +149,12 @@ struct snp_psc_desc { #define GHCB_SEV_ES_PROT_UNSUPPORTED 1 #define GHCB_SNP_UNSUPPORTED 2 +/* Error codes from hypervisor in EXITINFO[31:0] after VMGEXIT */ +#define VMGEXIT_RESULT_OK 0 +#define VMGEXIT_RESULT_EXCEPTION 1 +#define VMGEXIT_RESULT_BAD_INPUT 2 +#define VMGEXIT_RESULT_THROTTLED 3 + /* Linux-specific reason codes (used with reason set 1) */ #define SEV_TERM_SET_LINUX 1 #define GHCB_TERM_REGISTER 0 /* GHCB GPA registration failure */ diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c index 2b4270d5559e54..b8effcb594929a 100644 --- a/arch/x86/kernel/sev-shared.c +++ b/arch/x86/kernel/sev-shared.c @@ -199,7 +199,7 @@ static enum es_result verify_exception_info(struct ghcb *ghcb, struct es_em_ctxt if (!ret) return ES_OK; - if (ret == 1) { + if (ret == VMGEXIT_RESULT_EXCEPTION) { u64 info = ghcb->save.sw_exit_info_2; unsigned long v; @@ -217,6 +217,8 @@ static enum es_result verify_exception_info(struct ghcb *ghcb, struct es_em_ctxt return ES_EXCEPTION; } + } else if (ret == VMGEXIT_RESULT_THROTTLED) { + return ES_RETRY; } return ES_VMM_ERROR; diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index 5f48263bff8a71..d3b72142068e63 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2161,8 +2161,12 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned } ret = sev_es_ghcb_hv_call(ghcb, true, &ctxt, exit_code, input->req_gpa, input->resp_gpa); - if (ret) + /* ret is an es_result at this point */ + if (ret) { + if (ret == ES_RETRY) + ret = -EAGAIN; goto e_put; + } if (ghcb->save.sw_exit_info_2) { /* Number of expected pages are returned in RBX */