From: Sagi Shahar <sagis@google.com>
To: linux-kselftest@vger.kernel.org,
Paolo Bonzini <pbonzini@redhat.com>,
Shuah Khan <shuah@kernel.org>,
Sean Christopherson <seanjc@google.com>,
Ackerley Tng <ackerleytng@google.com>,
Ryan Afranji <afranji@google.com>,
Andrew Jones <ajones@ventanamicro.com>,
Isaku Yamahata <isaku.yamahata@intel.com>,
Erdem Aktas <erdemaktas@google.com>,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
Sagi Shahar <sagis@google.com>,
Roger Wang <runanwang@google.com>,
Binbin Wu <binbin.wu@linux.intel.com>,
Oliver Upton <oliver.upton@linux.dev>,
"Pratik R. Sampat" <pratikrajesh.sampat@amd.com>,
Reinette Chatre <reinette.chatre@intel.com>,
Ira Weiny <ira.weiny@intel.com>, Chao Gao <chao.gao@intel.com>,
Chenyi Qiang <chenyi.qiang@intel.com>
Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Subject: [PATCH v11 07/21] KVM: selftests: Define structs to pass parameters to TDX boot code
Date: Thu, 25 Sep 2025 10:28:35 -0700 [thread overview]
Message-ID: <20250925172851.606193-8-sagis@google.com> (raw)
In-Reply-To: <20250925172851.606193-1-sagis@google.com>
TDX registers are inaccessible to KVM. Therefore we need a different
mechanism to load boot parameters for TDX code. TDX boot code will read
the registers values from memory and set the registers manually.
This patch defines the data structures used to communicate between c
code and the TDX assembly boot code which will be added in a later
patch.
Use kbuild.h to expose the offsets into the structs from c code to
assembly code.
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Co-developed-by: Ackerley Tng <ackerleytng@google.com>
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
Signed-off-by: Sagi Shahar <sagis@google.com>
---
tools/testing/selftests/kvm/Makefile.kvm | 18 +++++
.../selftests/kvm/include/x86/tdx/td_boot.h | 69 +++++++++++++++++++
.../kvm/lib/x86/tdx/td_boot_offsets.c | 21 ++++++
3 files changed, 108 insertions(+)
create mode 100644 tools/testing/selftests/kvm/include/x86/tdx/td_boot.h
create mode 100644 tools/testing/selftests/kvm/lib/x86/tdx/td_boot_offsets.c
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 41b40c676d7f..3f93c093b046 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -19,6 +19,8 @@ LIBKVM += lib/userfaultfd_util.c
LIBKVM_STRING += lib/string_override.c
+LIBKVM_ASM_DEFS += lib/x86/tdx/td_boot_offsets.c
+
LIBKVM_x86 += lib/x86/apic.c
LIBKVM_x86 += lib/x86/handlers.S
LIBKVM_x86 += lib/x86/hyperv.c
@@ -230,6 +232,10 @@ OVERRIDE_TARGETS = 1
include ../lib.mk
include ../cgroup/lib/libcgroup.mk
+# Enable Kbuild tools.
+include $(top_srcdir)/scripts/Kbuild.include
+include $(top_srcdir)/scripts/Makefile.lib
+
INSTALL_HDR_PATH = $(top_srcdir)/usr
LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
@@ -282,6 +288,7 @@ LIBKVM_S := $(filter %.S,$(LIBKVM))
LIBKVM_C_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_C))
LIBKVM_S_OBJ := $(patsubst %.S, $(OUTPUT)/%.o, $(LIBKVM_S))
LIBKVM_STRING_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_STRING))
+LIBKVM_ASM_DEFS_OBJ += $(patsubst %.c, $(OUTPUT)/%.s, $(LIBKVM_ASM_DEFS))
LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ) $(LIBKVM_STRING_OBJ) $(LIBCGROUP_O)
SPLIT_TEST_GEN_PROGS := $(patsubst %, $(OUTPUT)/%, $(SPLIT_TESTS))
SPLIT_TEST_GEN_OBJ := $(patsubst %, $(OUTPUT)/$(ARCH)/%.o, $(SPLIT_TESTS))
@@ -308,6 +315,7 @@ $(SPLIT_TEST_GEN_OBJ): $(OUTPUT)/$(ARCH)/%.o: $(ARCH)/%.c
EXTRA_CLEAN += $(GEN_HDRS) \
$(LIBKVM_OBJS) \
+ $(LIBKVM_ASM_DEFS_OBJ) \
$(SPLIT_TEST_GEN_OBJ) \
$(TEST_DEP_FILES) \
$(TEST_GEN_OBJ) \
@@ -319,18 +327,28 @@ $(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c $(GEN_HDRS)
$(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S $(GEN_HDRS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
+$(LIBKVM_ASM_DEFS_OBJ): $(OUTPUT)/%.s: %.c FORCE
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@
+
# Compile the string overrides as freestanding to prevent the compiler from
# generating self-referential code, e.g. without "freestanding" the compiler may
# "optimize" memcmp() by invoking memcmp(), thus causing infinite recursion.
$(LIBKVM_STRING_OBJ): $(OUTPUT)/%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -ffreestanding $< -o $@
+$(OUTPUT)/include/x86/tdx/td_boot_offsets.h: $(OUTPUT)/lib/x86/tdx/td_boot_offsets.s FORCE
+ $(call filechk,offsets,__TDX_BOOT_OFFSETS_H__)
+
+EXTRA_CLEAN += $(OUTPUT)/include/x86/tdx/td_boot_offsets.h
+
$(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
$(SPLIT_TEST_GEN_OBJ): $(GEN_HDRS)
$(TEST_GEN_PROGS): $(LIBKVM_OBJS)
$(TEST_GEN_PROGS_EXTENDED): $(LIBKVM_OBJS)
$(TEST_GEN_OBJ): $(GEN_HDRS)
+FORCE:
+
cscope: include_paths = $(LINUX_TOOL_INCLUDE) $(LINUX_HDR_PATH) include lib ..
cscope:
$(RM) cscope.*
diff --git a/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h b/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h
new file mode 100644
index 000000000000..32631645fe13
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/x86/tdx/td_boot.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef SELFTEST_TDX_TD_BOOT_H
+#define SELFTEST_TDX_TD_BOOT_H
+
+#include <stdint.h>
+
+#include <linux/compiler.h>
+#include <linux/sizes.h>
+
+/*
+ * Layout for boot section (not to scale)
+ *
+ * GPA
+ * _________________________________ 0x1_0000_0000 (4GB)
+ * | Boot code trampoline |
+ * |___________________________|____ 0x0_ffff_fff0: Reset vector (16B below 4GB)
+ * | Boot code |
+ * |___________________________|____ td_boot will be copied here, so that the
+ * | | jmp to td_boot is exactly at the reset vector
+ * | Empty space |
+ * | |
+ * |───────────────────────────|
+ * | |
+ * | |
+ * | Boot parameters |
+ * | |
+ * | |
+ * |___________________________|____ 0x0_ffff_0000: TD_BOOT_PARAMETERS_GPA
+ */
+#define FOUR_GIGABYTES_GPA (SZ_4G)
+
+/*
+ * The exact memory layout for LGDT or LIDT instructions.
+ */
+struct __packed td_boot_parameters_dtr {
+ uint16_t limit;
+ uint32_t base;
+};
+
+/*
+ * Allows each vCPU to be initialized with different rip and esp.
+ */
+struct td_per_vcpu_parameters {
+ uint32_t esp_gva;
+ uint64_t guest_code;
+};
+
+/*
+ * Boot parameters for the TD.
+ *
+ * Unlike a regular VM, KVM cannot set registers such as esp, eip, etc
+ * before boot, so to run selftests, these registers' values have to be
+ * initialized by the TD.
+ *
+ * This struct is loaded in TD private memory at TD_BOOT_PARAMETERS_GPA.
+ *
+ * The TD boot code will read off parameters from this struct and set up the
+ * vCPU for executing selftests.
+ */
+struct td_boot_parameters {
+ uint32_t cr0;
+ uint32_t cr3;
+ uint32_t cr4;
+ struct td_boot_parameters_dtr gdtr;
+ struct td_boot_parameters_dtr idtr;
+ struct td_per_vcpu_parameters per_vcpu[];
+};
+
+#endif /* SELFTEST_TDX_TD_BOOT_H */
diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/td_boot_offsets.c b/tools/testing/selftests/kvm/lib/x86/tdx/td_boot_offsets.c
new file mode 100644
index 000000000000..7f76a3585b99
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/x86/tdx/td_boot_offsets.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+#define COMPILE_OFFSETS
+
+#include <linux/kbuild.h>
+
+#include "tdx/td_boot.h"
+
+static void __attribute__((used)) common(void)
+{
+ OFFSET(TD_BOOT_PARAMETERS_CR0, td_boot_parameters, cr0);
+ OFFSET(TD_BOOT_PARAMETERS_CR3, td_boot_parameters, cr3);
+ OFFSET(TD_BOOT_PARAMETERS_CR4, td_boot_parameters, cr4);
+ OFFSET(TD_BOOT_PARAMETERS_GDT, td_boot_parameters, gdtr);
+ OFFSET(TD_BOOT_PARAMETERS_IDT, td_boot_parameters, idtr);
+ OFFSET(TD_BOOT_PARAMETERS_PER_VCPU, td_boot_parameters, per_vcpu);
+ OFFSET(TD_PER_VCPU_PARAMETERS_ESP_GVA, td_per_vcpu_parameters, esp_gva);
+ OFFSET(TD_PER_VCPU_PARAMETERS_GUEST_CODE, td_per_vcpu_parameters,
+ guest_code);
+ DEFINE(SIZEOF_TD_PER_VCPU_PARAMETERS,
+ sizeof(struct td_per_vcpu_parameters));
+}
--
2.51.0.536.g15c5d4f767-goog
next prev parent reply other threads:[~2025-09-25 17:29 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-25 17:28 [PATCH v11 00/21] TDX KVM selftests Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 01/21] KVM: selftests: Allocate pgd in virt_map() as necessary Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 02/21] KVM: selftests: Expose functions to get default sregs values Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 03/21] KVM: selftests: Expose function to allocate guest vCPU stack Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 04/21] KVM: selftests: Update kvm_init_vm_address_properties() for TDX Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 05/21] KVM: selftests: Expose segment definitons to assembly files Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 06/21] KVM: selftests: Add kbuild definitons Sagi Shahar
2025-09-25 17:28 ` Sagi Shahar [this message]
2025-09-25 17:28 ` [PATCH v11 08/21] KVM: selftests: Add TDX boot code Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 09/21] KVM: selftests: Set up TDX boot code region Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 10/21] KVM: selftests: Set up TDX boot parameters region Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 11/21] KVM: selftests: Add helper to initialize TDX VM Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 12/21] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 13/21] KVM: selftests: Add helpers to init TDX memory and finalize VM Sagi Shahar
2025-10-15 16:27 ` Ira Weiny
2025-10-23 23:59 ` Sagi Shahar
2025-10-24 16:01 ` Sean Christopherson
2025-10-24 16:45 ` Sagi Shahar
2025-10-24 17:24 ` Sean Christopherson
2025-09-25 17:28 ` [PATCH v11 14/21] KVM: selftests: Call TDX init when creating a new TDX vm Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 15/21] KVM: selftests: Setup memory regions for TDX on vm creation Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 16/21] KVM: selftests: Call KVM_TDX_INIT_VCPU when creating a new TDX vcpu Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 17/21] KVM: selftests: Set entry point for TDX guest code Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 18/21] KVM: selftests: Add support for TDX TDCALL from guest Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 19/21] KVM: selftests: Add wrapper for TDX MMIO " Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 20/21] KVM: selftests: Add ucall support for TDX Sagi Shahar
2025-09-25 17:28 ` [PATCH v11 21/21] KVM: selftests: Add TDX lifecycle test Sagi Shahar
2025-10-24 16:18 ` Sean Christopherson
2025-10-27 22:58 ` Ira Weiny
2025-10-27 23:42 ` Sean Christopherson
2025-10-28 0:53 ` Sagi Shahar
2025-10-28 17:12 ` Ira Weiny
2025-10-28 14:56 ` Ira Weiny
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250925172851.606193-8-sagis@google.com \
--to=sagis@google.com \
--cc=ackerleytng@google.com \
--cc=afranji@google.com \
--cc=ajones@ventanamicro.com \
--cc=binbin.wu@linux.intel.com \
--cc=chao.gao@intel.com \
--cc=chenyi.qiang@intel.com \
--cc=erdemaktas@google.com \
--cc=ira.weiny@intel.com \
--cc=isaku.yamahata@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=oliver.upton@linux.dev \
--cc=pbonzini@redhat.com \
--cc=pratikrajesh.sampat@amd.com \
--cc=reinette.chatre@intel.com \
--cc=rick.p.edgecombe@intel.com \
--cc=runanwang@google.com \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox