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 + * 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 */ -- 2.25.1