[PATCH v12 06/22] x86/virt/tdx: Handle SEAMCALL running out of entropy error

From: Kai Huang
Date: Mon Jun 26 2023 - 10:15:12 EST


Some SEAMCALLs use the RDRAND hardware and can fail for the same reasons
as RDRAND. Use the kernel RDRAND retry logic for them.

Signed-off-by: Kai Huang <kai.huang@xxxxxxxxx>
Reviewed-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
Reviewed-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>
Reviewed-by: David Hildenbrand <david@xxxxxxxxxx>
---

v11 -> v12:
- Added tags from Dave/Kirill/David.
- Improved changelog (Dave).
- Slight code improvement (David)
- Initialize retry directly when declaring it.
- Simplify comment around mimic rdrand_long().

v10 -> v11:
- New patch

---
arch/x86/virt/vmx/tdx/tdx.c | 16 ++++++++++++++--
arch/x86/virt/vmx/tdx/tdx.h | 17 +++++++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index f8233cba5931..141d12376c4d 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -15,6 +15,7 @@
#include <linux/smp.h>
#include <asm/msr-index.h>
#include <asm/msr.h>
+#include <asm/archrandom.h>
#include <asm/tdx.h>
#include "tdx.h"

@@ -32,12 +33,23 @@ static int __always_unused seamcall(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
u64 *seamcall_ret,
struct tdx_module_output *out)
{
+ int cpu, retry = RDRAND_RETRY_LOOPS;
u64 sret;
- int cpu;

/* Need a stable CPU id for printing error message */
cpu = get_cpu();
- sret = __seamcall(fn, rcx, rdx, r8, r9, out);
+
+ /*
+ * Certain SEAMCALL leaf functions may return error due to
+ * running out of entropy, in which case the SEAMCALL should
+ * be retried. Handle this in SEAMCALL common function.
+ *
+ * Mimic rdrand_long() retry behavior.
+ */
+ do {
+ sret = __seamcall(fn, rcx, rdx, r8, r9, out);
+ } while (sret == TDX_RND_NO_ENTROPY && --retry);
+
put_cpu();

/* Save SEAMCALL return code if the caller wants it */
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index 48ad1a1ba737..55dbb1b8c971 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -4,6 +4,23 @@

#include <linux/types.h>

+/*
+ * This file contains both macros and data structures defined by the TDX
+ * architecture and Linux defined software data structures and functions.
+ * The two should not be mixed together for better readability. The
+ * architectural definitions come first.
+ */
+
+/*
+ * TDX SEAMCALL error codes
+ */
+#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL
+
+/*
+ * Do not put any hardware-defined TDX structure representations below
+ * this comment!
+ */
+
struct tdx_module_output;
u64 __seamcall(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
struct tdx_module_output *out);
--
2.40.1