On 12/18/2023 3:22 PM, Qian Wen wrote:
From: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>
Detect TDX during at start of efi setup. And define a dummy is_tdx_guest()
if CONFIG_EFI is undefined as this function will be used globally in the
future.
In addition, it is fine to use the print function even before the #VE
handler of the unit test has complete configuration.
TDVF provides the default #VE exception handler, which will convert some
of the forbidden instructions to TDCALL [TDG.VP.VMCALL] <INSTRUCTION>,
e.g., IO => TDCALL [TDG.VP.VMCALL] <Instruction.IO> (see “10 Exception
Handling” in TDVF spec [1]).
[1] TDVF spec: https://cdrdv2.intel.com/v1/dl/getContent/733585
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>
Reviewed-by: Yu Zhang <yu.c.zhang@xxxxxxxxx>
Link: https://lore.kernel.org/r/20220303071907.650203-2-zhenzhong.duan@xxxxxxxxx
Co-developed-by: Qian Wen <qian.wen@xxxxxxxxx>
Signed-off-by: Qian Wen <qian.wen@xxxxxxxxx>
---
lib/x86/asm/setup.h | 1 +
lib/x86/setup.c | 6 ++++++
lib/x86/tdx.c | 39 +++++++++++++++++++++++++++++++++++++++
lib/x86/tdx.h | 9 +++++++++
4 files changed, 55 insertions(+)
diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h
index 458eac85..1deed1cd 100644
--- a/lib/x86/asm/setup.h
+++ b/lib/x86/asm/setup.h
@@ -15,6 +15,7 @@ unsigned long setup_tss(u8 *stacktop);
efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
void setup_5level_page_table(void);
#endif /* CONFIG_EFI */
+#include "x86/tdx.h"
void save_id(void);
void bsp_rest_init(void);
diff --git a/lib/x86/setup.c b/lib/x86/setup.c
index d509a248..97d9e896 100644
--- a/lib/x86/setup.c
+++ b/lib/x86/setup.c
@@ -308,6 +308,12 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
efi_status_t status;
const char *phase;
+ status = setup_tdx();
+ if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
+ printf("INTEL TDX setup failed, error = 0x%lx\n", status);
+ return status;
+ }
+
status = setup_memory_allocator(efi_bootinfo);
if (status != EFI_SUCCESS) {
printf("Failed to set up memory allocator: ");
diff --git a/lib/x86/tdx.c b/lib/x86/tdx.c
index 1f1abeff..a01bfcbb 100644
--- a/lib/x86/tdx.c
+++ b/lib/x86/tdx.c
@@ -276,3 +276,42 @@ static int handle_io(struct ex_regs *regs, struct ve_info *ve)
return ve_instr_len(ve);
}
+
+bool is_tdx_guest(void)
+{
+ static int tdx_guest = -1;
+ struct cpuid c;
+ u32 sig[3];
+
+ if (tdx_guest >= 0)
+ goto done;
+
+ if (cpuid(0).a < TDX_CPUID_LEAF_ID) {
+ tdx_guest = 0;
+ goto done;
+ }
+
+ c = cpuid(TDX_CPUID_LEAF_ID);
+ sig[0] = c.b;
+ sig[1] = c.d;
+ sig[2] = c.c;
+
+ tdx_guest = !memcmp(TDX_IDENT, sig, sizeof(sig));
+
+done:
+ return !!tdx_guest;
+}
+
+efi_status_t setup_tdx(void)
+{
+ if (!is_tdx_guest())
+ return EFI_UNSUPPORTED;
+
+ /* The printf can work here. Since TDVF default exception handler
Comments need start at another new line with leading asterisk.
+ * can handle the #VE caused by IO read/write during printf() before
+ * finalizing configuration of the unit test's #VE handler.
+ */
+ printf("Initialized TDX.\n");
+
+ return EFI_SUCCESS;
+}
diff --git a/lib/x86/tdx.h b/lib/x86/tdx.h
index cf0fc917..45350b70 100644
--- a/lib/x86/tdx.h
+++ b/lib/x86/tdx.h
@@ -21,6 +21,9 @@
#define TDX_HYPERCALL_STANDARD 0
+#define TDX_CPUID_LEAF_ID 0x21
+#define TDX_IDENT "IntelTDX "
+
/* TDX module Call Leaf IDs */
#define TDG_VP_VMCALL 0
@@ -136,6 +139,12 @@ struct ve_info {
u32 instr_info;
};
+bool is_tdx_guest(void);
+efi_status_t setup_tdx(void);
+
+#else
+inline bool is_tdx_guest(void) { return false; }
+
#endif /* CONFIG_EFI */
#endif /* _ASM_X86_TDX_H */