x86-mm-fix-use-of-uninitialized-buffer-in-sme_enable.patch
x86-resctrl-clear-staged_config-before-and-after-it-is-used.patch
powerpc-pass-correct-cpu-reference-to-assembler.patch
+virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch
+virt-coco-sev-guest-simplify-extended-guest-request-handling.patch
+virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch
+virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch
+virt-coco-sev-guest-do-some-code-style-cleanups.patch
+virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch
+virt-coco-sev-guest-add-throttling-awareness.patch
--- /dev/null
+From 72f7754dcf31c87c92c0c353dcf747814cc5ce10 Mon Sep 17 00:00:00 2001
+From: Dionna Glaze <dionnaglaze@google.com>
+Date: Thu, 16 Feb 2023 11:08:02 +0100
+Subject: virt/coco/sev-guest: Add throttling awareness
+
+From: Dionna Glaze <dionnaglaze@google.com>
+
+commit 72f7754dcf31c87c92c0c353dcf747814cc5ce10 upstream.
+
+A potentially malicious SEV guest can constantly hammer the hypervisor
+using this driver to send down requests and thus prevent or at least
+considerably hinder other guests from issuing requests to the secure
+processor which is a shared platform resource.
+
+Therefore, the host is permitted and encouraged to throttle such guest
+requests.
+
+Add the capability to handle the case when the hypervisor throttles
+excessive numbers of requests issued by the guest. Otherwise, the VM
+platform communication key will be disabled, preventing the guest from
+attesting itself.
+
+Realistically speaking, a well-behaved guest should not even care about
+throttling. During its lifetime, it would end up issuing a handful of
+requests which the hardware can easily handle.
+
+This is more to address the case of a malicious guest. Such guest should
+get throttled and if its VMPCK gets disabled, then that's its own
+wrongdoing and perhaps that guest even deserves it.
+
+To the implementation: the hypervisor signals with SNP_GUEST_REQ_ERR_BUSY
+that the guest requests should be throttled. That error code is returned
+in the upper 32-bit half of exitinfo2 and this is part of the GHCB spec
+v2.
+
+So the guest is given a throttling period of 1 minute in which it
+retries the request every 2 seconds. This is a good default but if it
+turns out to not pan out in practice, it can be tweaked later.
+
+For safety, since the encryption algorithm in GHCBv2 is AES_GCM, control
+must remain in the kernel to complete the request with the current
+sequence number. Returning without finishing the request allows the
+guest to make another request but with different message contents. This
+is IV reuse, and breaks cryptographic protections.
+
+ [ bp:
+ - Rewrite commit message and do a simplified version.
+ - The stable tags are supposed to denote that a cleanup should go
+ upfront before backporting this so that any future fixes to this
+ can preserve the sanity of the backporter(s). ]
+
+Fixes: d5af44dde546 ("x86/sev: Provide support for SNP guest request NAEs")
+Signed-off-by: Dionna Glaze <dionnaglaze@google.com>
+Co-developed-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: <stable@kernel.org> # d6fd48eff750 ("virt/coco/sev-guest: Check SEV_SNP attribute at probe time")
+Cc: <stable@kernel.org> # 970ab823743f (" virt/coco/sev-guest: Simplify extended guest request handling")
+Cc: <stable@kernel.org> # c5a338274bdb ("virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request()")
+Cc: <stable@kernel.org> # 0fdb6cc7c89c ("virt/coco/sev-guest: Carve out the request issuing logic into a helper")
+Cc: <stable@kernel.org> # d25bae7dc7b0 ("virt/coco/sev-guest: Do some code style cleanups")
+Cc: <stable@kernel.org> # fa4ae42cc60a ("virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case")
+Link: https://lore.kernel.org/r/20230214164638.1189804-2-dionnaglaze@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/sev-common.h | 3 ++-
+ arch/x86/kernel/sev.c | 4 ++++
+ drivers/virt/coco/sev-guest/sev-guest.c | 19 ++++++++++++++++++-
+ 3 files changed, 24 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/include/asm/sev-common.h
++++ b/arch/x86/include/asm/sev-common.h
+@@ -128,8 +128,9 @@ struct snp_psc_desc {
+ struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY];
+ } __packed;
+
+-/* Guest message request error code */
++/* Guest message request error codes */
+ #define SNP_GUEST_REQ_INVALID_LEN BIT_ULL(32)
++#define SNP_GUEST_REQ_ERR_BUSY BIT_ULL(33)
+
+ #define GHCB_MSR_TERM_REQ 0x100
+ #define GHCB_MSR_TERM_REASON_SET_POS 12
+--- a/arch/x86/kernel/sev.c
++++ b/arch/x86/kernel/sev.c
+@@ -2214,6 +2214,10 @@ int snp_issue_guest_request(u64 exit_cod
+ case 0:
+ break;
+
++ case SNP_GUEST_REQ_ERR_BUSY:
++ ret = -EAGAIN;
++ break;
++
+ case SNP_GUEST_REQ_INVALID_LEN:
+ /* Number of expected pages are returned in RBX */
+ if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -31,6 +31,9 @@
+ #define AAD_LEN 48
+ #define MSG_HDR_VER 1
+
++#define SNP_REQ_MAX_RETRY_DURATION (60*HZ)
++#define SNP_REQ_RETRY_DELAY (2*HZ)
++
+ struct snp_guest_crypto {
+ struct crypto_aead *tfm;
+ u8 *iv, *authtag;
+@@ -322,7 +325,8 @@ static int enc_payload(struct snp_guest_
+
+ static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err)
+ {
+- unsigned long err, override_err = 0;
++ unsigned long err = 0xff, override_err = 0;
++ unsigned long req_start = jiffies;
+ unsigned int override_npages = 0;
+ int rc;
+
+@@ -362,6 +366,19 @@ retry_request:
+ * user as an ioctl() return code.
+ */
+ goto retry_request;
++
++ /*
++ * The host may return SNP_GUEST_REQ_ERR_EBUSY if the request has been
++ * throttled. Retry in the driver to avoid returning and reusing the
++ * message sequence number on a different message.
++ */
++ case -EAGAIN:
++ if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) {
++ rc = -ETIMEDOUT;
++ break;
++ }
++ schedule_timeout_killable(SNP_REQ_RETRY_DELAY);
++ goto retry_request;
+ }
+
+ /*
--- /dev/null
+From 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Tue, 7 Mar 2023 09:19:19 -0600
+Subject: virt/coco/sev-guest: Carve out the request issuing logic into a helper
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 upstream.
+
+This makes the code flow a lot easier to follow.
+
+No functional changes.
+
+ [ Tom: touchups. ]
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230307192449.24732-6-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/virt/coco/sev-guest/sev-guest.c | 44 +++++++++++++++++++-------------
+ 1 file changed, 27 insertions(+), 17 deletions(-)
+
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -320,27 +320,12 @@ static int enc_payload(struct snp_guest_
+ return __enc_payload(snp_dev, req, payload, sz);
+ }
+
+-static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver,
+- u8 type, void *req_buf, size_t req_sz, void *resp_buf,
+- u32 resp_sz, __u64 *fw_err)
++static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err)
+ {
+ unsigned long err, override_err = 0;
+ unsigned int override_npages = 0;
+- u64 seqno;
+ int rc;
+
+- /* Get message sequence and verify that its a non-zero */
+- seqno = snp_get_msg_seqno(snp_dev);
+- if (!seqno)
+- return -EIO;
+-
+- memset(snp_dev->response, 0, sizeof(struct snp_guest_msg));
+-
+- /* Encrypt the userspace provided payload */
+- rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz);
+- if (rc)
+- return rc;
+-
+ retry_request:
+ /*
+ * Call firmware to process the request. In this function the encrypted
+@@ -349,7 +334,6 @@ retry_request:
+ * prevent reuse of the IV.
+ */
+ rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+-
+ switch (rc) {
+ case -ENOSPC:
+ /*
+@@ -403,7 +387,33 @@ retry_request:
+ if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN)
+ return -EIO;
+
++ return rc;
++}
++
++static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver,
++ u8 type, void *req_buf, size_t req_sz, void *resp_buf,
++ u32 resp_sz, __u64 *fw_err)
++{
++ u64 seqno;
++ int rc;
++
++ /* Get message sequence and verify that its a non-zero */
++ seqno = snp_get_msg_seqno(snp_dev);
++ if (!seqno)
++ return -EIO;
++
++ memset(snp_dev->response, 0, sizeof(struct snp_guest_msg));
++
++ /* Encrypt the userspace provided payload */
++ rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz);
++ if (rc)
++ return rc;
++
++ rc = __handle_guest_request(snp_dev, exit_code, fw_err);
+ if (rc) {
++ if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN)
++ return rc;
++
+ dev_alert(snp_dev->dev,
+ "Detected error from ASP request. rc: %d, fw_err: %llu\n",
+ rc, *fw_err);
--- /dev/null
+From d6fd48eff7506bb866a54e40369df8899f2078a9 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Feb 2023 11:01:42 +0100
+Subject: virt/coco/sev-guest: Check SEV_SNP attribute at probe time
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit d6fd48eff7506bb866a54e40369df8899f2078a9 upstream.
+
+No need to check it on every ioctl. And yes, this is a common SEV driver
+but it does only SNP-specific operations currently. This can be
+revisited later, when more use cases appear.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-3-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/sev.c | 3 ---
+ drivers/virt/coco/sev-guest/sev-guest.c | 3 +++
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kernel/sev.c
++++ b/arch/x86/kernel/sev.c
+@@ -2183,9 +2183,6 @@ int snp_issue_guest_request(u64 exit_cod
+ struct ghcb *ghcb;
+ int ret;
+
+- if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+- return -ENODEV;
+-
+ if (!fw_err)
+ return -EINVAL;
+
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -705,6 +705,9 @@ static int __init sev_guest_probe(struct
+ void __iomem *mapping;
+ int ret;
+
++ if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
++ return -ENODEV;
++
+ if (!dev->platform_data)
+ return -ENODEV;
+
--- /dev/null
+From fa4ae42cc60a7dea30e8f2db444b808d80862345 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Thu, 16 Feb 2023 10:50:11 +0100
+Subject: virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit fa4ae42cc60a7dea30e8f2db444b808d80862345 upstream.
+
+snp_issue_guest_request() checks the value returned by the hypervisor in
+sw_exit_info_2 and returns a different error depending on it.
+
+Convert those checks into a switch-case to make it more readable when
+more error values are going to be checked in the future.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-8-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/sev.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/kernel/sev.c
++++ b/arch/x86/kernel/sev.c
+@@ -2210,15 +2210,21 @@ int snp_issue_guest_request(u64 exit_cod
+ goto e_put;
+
+ *fw_err = ghcb->save.sw_exit_info_2;
+- if (ghcb->save.sw_exit_info_2) {
++ switch (*fw_err) {
++ case 0:
++ break;
++
++ case SNP_GUEST_REQ_INVALID_LEN:
+ /* 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) {
++ if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
+ input->data_npages = ghcb_get_rbx(ghcb);
+ ret = -ENOSPC;
+- } else {
+- ret = -EIO;
++ break;
+ }
++ fallthrough;
++ default:
++ ret = -EIO;
++ break;
+ }
+
+ e_put:
--- /dev/null
+From d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Feb 2023 11:54:59 +0100
+Subject: virt/coco/sev-guest: Do some code style cleanups
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 upstream.
+
+Remove unnecessary linebreaks, make the code more compact.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-7-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/virt/coco/sev-guest/sev-guest.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -414,18 +414,14 @@ static int handle_guest_request(struct s
+ if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN)
+ return rc;
+
+- dev_alert(snp_dev->dev,
+- "Detected error from ASP request. rc: %d, fw_err: %llu\n",
+- rc, *fw_err);
++ dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err);
+ snp_disable_vmpck(snp_dev);
+ return rc;
+ }
+
+ rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz);
+ if (rc) {
+- dev_alert(snp_dev->dev,
+- "Detected unexpected decode failure from ASP. rc: %d\n",
+- rc);
++ dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc);
+ snp_disable_vmpck(snp_dev);
+ return rc;
+ }
--- /dev/null
+From c5a338274bdb894f088767bea856be344d0ccaef Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Feb 2023 11:43:43 +0100
+Subject: virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request()
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit c5a338274bdb894f088767bea856be344d0ccaef upstream.
+
+Call the function directly instead.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-5-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/virt/coco/sev-guest/sev-guest.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -407,7 +407,8 @@ retry_request:
+ dev_alert(snp_dev->dev,
+ "Detected error from ASP request. rc: %d, fw_err: %llu\n",
+ rc, *fw_err);
+- goto disable_vmpck;
++ snp_disable_vmpck(snp_dev);
++ return rc;
+ }
+
+ rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz);
+@@ -415,14 +416,11 @@ retry_request:
+ dev_alert(snp_dev->dev,
+ "Detected unexpected decode failure from ASP. rc: %d\n",
+ rc);
+- goto disable_vmpck;
++ snp_disable_vmpck(snp_dev);
++ return rc;
+ }
+
+ return 0;
+-
+-disable_vmpck:
+- snp_disable_vmpck(snp_dev);
+- return rc;
+ }
+
+ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
--- /dev/null
+From 970ab823743fb54b42002ec76c51481f67436444 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Feb 2023 11:39:41 +0100
+Subject: virt/coco/sev-guest: Simplify extended guest request handling
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit 970ab823743fb54b42002ec76c51481f67436444 upstream.
+
+Return a specific error code - -ENOSPC - to signal the too small cert
+data buffer instead of checking exit code and exitinfo2.
+
+While at it, hoist the *fw_err assignment in snp_issue_guest_request()
+so that a proper error value is returned to the callers.
+
+ [ Tom: check override_err instead of err. ]
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230307192449.24732-4-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/sev.c | 11 ++++---
+ drivers/virt/coco/sev-guest/sev-guest.c | 48 +++++++++++++++++---------------
+ 2 files changed, 32 insertions(+), 27 deletions(-)
+
+--- a/arch/x86/kernel/sev.c
++++ b/arch/x86/kernel/sev.c
+@@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_cod
+ if (ret)
+ goto e_put;
+
++ *fw_err = ghcb->save.sw_exit_info_2;
+ 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)
++ 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;
++ ret = -ENOSPC;
++ } else {
++ ret = -EIO;
++ }
+ }
+
+ e_put:
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -324,7 +324,8 @@ static int handle_guest_request(struct s
+ u8 type, void *req_buf, size_t req_sz, void *resp_buf,
+ u32 resp_sz, __u64 *fw_err)
+ {
+- unsigned long err;
++ unsigned long err, override_err = 0;
++ unsigned int override_npages = 0;
+ u64 seqno;
+ int rc;
+
+@@ -340,6 +341,7 @@ static int handle_guest_request(struct s
+ if (rc)
+ return rc;
+
++retry_request:
+ /*
+ * Call firmware to process the request. In this function the encrypted
+ * message enters shared memory with the host. So after this call the
+@@ -348,17 +350,24 @@ static int handle_guest_request(struct s
+ */
+ rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+
+- /*
+- * If the extended guest request fails due to having too small of a
+- * certificate data buffer, retry the same guest request without the
+- * extended data request in order to increment the sequence number
+- * and thus avoid IV reuse.
+- */
+- if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
+- err == SNP_GUEST_REQ_INVALID_LEN) {
+- const unsigned int certs_npages = snp_dev->input.data_npages;
++ switch (rc) {
++ case -ENOSPC:
++ /*
++ * If the extended guest request fails due to having too
++ * small of a certificate data buffer, retry the same
++ * guest request without the extended data request in
++ * order to increment the sequence number and thus avoid
++ * IV reuse.
++ */
++ override_npages = snp_dev->input.data_npages;
++ exit_code = SVM_VMGEXIT_GUEST_REQUEST;
+
+- exit_code = SVM_VMGEXIT_GUEST_REQUEST;
++ /*
++ * Override the error to inform callers the given extended
++ * request buffer size was too small and give the caller the
++ * required buffer size.
++ */
++ override_err = SNP_GUEST_REQ_INVALID_LEN;
+
+ /*
+ * If this call to the firmware succeeds, the sequence number can
+@@ -368,15 +377,7 @@ static int handle_guest_request(struct s
+ * of the VMPCK and the error code being propagated back to the
+ * user as an ioctl() return code.
+ */
+- rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+-
+- /*
+- * Override the error to inform callers the given extended
+- * request buffer size was too small and give the caller the
+- * required buffer size.
+- */
+- err = SNP_GUEST_REQ_INVALID_LEN;
+- snp_dev->input.data_npages = certs_npages;
++ goto retry_request;
+ }
+
+ /*
+@@ -388,7 +389,10 @@ static int handle_guest_request(struct s
+ snp_inc_msg_seqno(snp_dev);
+
+ if (fw_err)
+- *fw_err = err;
++ *fw_err = override_err ?: err;
++
++ if (override_npages)
++ snp_dev->input.data_npages = override_npages;
+
+ /*
+ * If an extended guest request was issued and the supplied certificate
+@@ -396,7 +400,7 @@ static int handle_guest_request(struct s
+ * prevent IV reuse. If the standard request was successful, return -EIO
+ * back to the caller as would have originally been returned.
+ */
+- if (!rc && err == SNP_GUEST_REQ_INVALID_LEN)
++ if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN)
+ return -EIO;
+
+ if (rc) {