[RFC PATCH v2 11/69] KVM: TDX: Introduce pr_seamcall_ex_ret_info() to print more info when SEAMCALL fails

From: isaku . yamahata
Date: Fri Jul 02 2021 - 18:08:10 EST


From: Xiaoyao Li <xiaoyao.li@xxxxxxxxx>

Various SEAMCALLs may have additional info in RCX, RDX, R8, R9, R10
when it completes. Introduce pr_seamcall_ex_ret_info() to parse those
additional info based on returned SEAMCALL status code.

It only processes some cases for reference. More processes for other
SEAMCALL status code can be added in the future on demand.

Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx>
Co-developed-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>
Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>
---
arch/x86/kvm/boot/seam/tdx_common.c | 54 +++++++++++++++++++++++++++++
arch/x86/kvm/vmx/seamcall.h | 6 ++--
2 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/boot/seam/tdx_common.c b/arch/x86/kvm/boot/seam/tdx_common.c
index 4fe352fb8586..a81a4672bf58 100644
--- a/arch/x86/kvm/boot/seam/tdx_common.c
+++ b/arch/x86/kvm/boot/seam/tdx_common.c
@@ -186,3 +186,57 @@ const char *tdx_seamcall_error_name(u64 error_code)
return "Unknown SEAMCALL status code";
}
EXPORT_SYMBOL_GPL(tdx_seamcall_error_name);
+
+static const char * const TDX_SEPT_ENTRY_STATES[] = {
+ "SEPT_FREE",
+ "SEPT_BLOCKED",
+ "SEPT_PENDING",
+ "SEPT_PENDING_BLOCKED",
+ "SEPT_PRESENT"
+};
+
+void pr_seamcall_ex_ret_info(u64 op, u64 error_code, struct tdx_ex_ret *ex_ret)
+{
+ if (!ex_ret)
+ return;
+
+ switch (error_code & TDX_SEAMCALL_STATUS_MASK) {
+ case TDX_INCORRECT_CPUID_VALUE:
+ pr_err("Expected CPUID [leaf 0x%x subleaf 0x%x]: "
+ "eax 0x%x check_mask 0x%x, ebx 0x%x check_mask 0x%x, "
+ "ecx 0x%x check_mask 0x%x, edx 0x%x check_mask 0x%x\n",
+ ex_ret->leaf, ex_ret->subleaf,
+ ex_ret->eax_val, ex_ret->eax_mask,
+ ex_ret->ebx_val, ex_ret->ebx_mask,
+ ex_ret->ecx_val, ex_ret->ecx_mask,
+ ex_ret->edx_val, ex_ret->edx_mask);
+ break;
+ case TDX_INCONSISTENT_CPUID_FIELD:
+ pr_err("Inconsistent CPUID [leaf 0x%x subleaf 0x%x]: "
+ "eax_mask 0x%x, ebx_mask 0x%x, ecx_mask %x, edx_mask 0x%x\n",
+ ex_ret->leaf, ex_ret->subleaf,
+ ex_ret->eax_mask, ex_ret->ebx_mask,
+ ex_ret->ecx_mask, ex_ret->edx_mask);
+ break;
+ case TDX_EPT_WALK_FAILED: {
+ const char *state;
+
+ if (ex_ret->state >= ARRAY_SIZE(TDX_SEPT_ENTRY_STATES))
+ state = "Invalid";
+ else
+ state = TDX_SEPT_ENTRY_STATES[ex_ret->state];
+
+ pr_err("Secure EPT walk error: SEPTE 0x%llx, level %d, %s\n",
+ ex_ret->septe, ex_ret->level, state);
+ break;
+ }
+ default:
+ /* TODO: print only meaningful registers depending on op */
+ pr_err("RCX 0x%llx, RDX 0x%llx, R8 0x%llx, R9 0x%llx, "
+ "R10 0x%llx, R11 0x%llx\n",
+ ex_ret->rcx, ex_ret->rdx, ex_ret->r8, ex_ret->r9,
+ ex_ret->r10, ex_ret->r11);
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(pr_seamcall_ex_ret_info);
diff --git a/arch/x86/kvm/vmx/seamcall.h b/arch/x86/kvm/vmx/seamcall.h
index fbb18aea1720..85eeedc06a4f 100644
--- a/arch/x86/kvm/vmx/seamcall.h
+++ b/arch/x86/kvm/vmx/seamcall.h
@@ -38,6 +38,7 @@ static inline u64 _seamcall(u64 op, u64 rcx, u64 rdx, u64 r8, u64 r9, u64 r10,
#endif

const char *tdx_seamcall_error_name(u64 error_code);
+void pr_seamcall_ex_ret_info(u64 op, u64 error_code, struct tdx_ex_ret *ex_ret);

static inline void __pr_seamcall_error(u64 op, const char *op_str,
u64 err, struct tdx_ex_ret *ex)
@@ -46,10 +47,7 @@ static inline void __pr_seamcall_error(u64 op, const char *op_str,
op_str, smp_processor_id(),
tdx_seamcall_error_name(err), err);
if (ex)
- pr_err_ratelimited(
- "RCX 0x%llx, RDX 0x%llx, R8 0x%llx, R9 0x%llx, R10 0x%llx, R11 0x%llx\n",
- (ex)->rcx, (ex)->rdx, (ex)->r8, (ex)->r9, (ex)->r10,
- (ex)->r11);
+ pr_seamcall_ex_ret_info(op, err, ex);
}

#define pr_seamcall_error(op, err, ex) \
--
2.25.1