P-SEAMLDR is another component alongside the TDX module within the
protected SEAM range. P-SEAMLDR can update the TDX module at runtime.
Software can talk with P-SEAMLDR via SEAMCALLs with the bit 63 of RAX
(leaf number) set to 1 (a.k.a P-SEAMLDR SEAMCALLs).
P-SEAMLDR SEAMCALLs differ from SEAMCALLs of the TDX module in terms of
error codes and the handling of the current VMCS.
In preparation for adding support for P-SEAMLDR SEAMCALLs, do the two
following changes to SEAMCALL low-level helpers:
1) Tweak sc_retry() to retry on "lack of entropy" errors reported by
P-SEAMLDR because it uses a different error code.
2) Add seamldr_err() to log error messages on P-SEAMLDR SEAMCALL failures.
Signed-off-by: Chao Gao <chao.gao@intel.com>
Tested-by: Farrah Chen <farrah.chen@intel.com>
---
Add seamldr_prerr() as a macro to be consistent with existing code. If
maintainers would like to switch these to static inline functions then I
would be happy to add a new patch to convert existing macros to static
inline functions and build on that.
v2:
- use a macro rather than an inline function for seamldr_err() for
consistency.
---
arch/x86/include/asm/tdx.h | 5 +++++
arch/x86/virt/vmx/tdx/seamcall.h | 29 ++++++++++++++++++++++++++++-
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index e872a411a359..7ad026618a23 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -32,6 +32,11 @@
#define TDX_SUCCESS 0ULL
#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL
+/* P-SEAMLDR SEAMCALL leaf function error codes */
+#define SEAMLDR_RND_NO_ENTROPY 0x8000000000030001ULL
+
+#define SEAMLDR_SEAMCALL_MASK _BITUL(63)
+
#ifndef __ASSEMBLER__
#include <uapi/asm/mce.h>
diff --git a/arch/x86/virt/vmx/tdx/seamcall.h b/arch/x86/virt/vmx/tdx/seamcall.h
index 71b6ffddfa40..3f462e58d68e 100644
--- a/arch/x86/virt/vmx/tdx/seamcall.h
+++ b/arch/x86/virt/vmx/tdx/seamcall.h
@@ -14,6 +14,19 @@ u64 __seamcall_saved_ret(u64 fn, struct tdx_module_args *args);
typedef u64 (*sc_func_t)(u64 fn, struct tdx_module_args *args);
+static inline bool is_seamldr_call(u64 fn)
+{
+ return fn & SEAMLDR_SEAMCALL_MASK;
+}
+
+static inline bool sc_need_retry(u64 fn, u64 error_code)
+{
+ if (is_seamldr_call(fn))
+ return error_code == SEAMLDR_RND_NO_ENTROPY;
+ else
+ return error_code == TDX_RND_NO_ENTROPY;
+}
+
static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
struct tdx_module_args *args)
{
@@ -22,7 +35,7 @@ static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
do {
ret = func(fn, args);
- } while (ret == TDX_RND_NO_ENTROPY && --retry);
+ } while (sc_need_retry(fn, ret) && --retry);
return ret;
}
@@ -48,6 +61,17 @@ static inline void seamcall_err_ret(u64 fn, u64 err,
args->r9, args->r10, args->r11);
}
+static inline void seamldr_err(u64 fn, u64 err, struct tdx_module_args *args)
+{
+ /*
+ * Get the actual leaf number. No need to print the bit used to
+ * differentiate between P-SEAMLDR and TDX module as the "P-SEAMLDR"
+ * string in the error message already provides that information.
+ */
+ fn &= ~SEAMLDR_SEAMCALL_MASK;
+ pr_err("P-SEAMLDR (%lld) failed: 0x%016llx\n", fn, err);
+}
+
static __always_inline int sc_retry_prerr(sc_func_t func,
sc_err_func_t err_func,
u64 fn, struct tdx_module_args *args)
@@ -76,4 +100,7 @@ static __always_inline int sc_retry_prerr(sc_func_t func,
#define seamcall_prerr_ret(__fn, __args) \
sc_retry_prerr(__seamcall_ret, seamcall_err_ret, (__fn), (__args))
+#define seamldr_prerr(__fn, __args) \
+ sc_retry_prerr(__seamcall, seamldr_err, (__fn), (__args))
+
#endif
--
2.47.3