[kvm-unit-tests RFC v2 02/18] x86 TDX: Add support functions for TDX framework

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux