All of lore.kernel.org
 help / color / mirror / Atom feed
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 v12 12/23] KVM: selftests: Add helper to initialize TDX VM
Date: Tue, 28 Oct 2025 21:20:38 +0000	[thread overview]
Message-ID: <20251028212052.200523-13-sagis@google.com> (raw)
In-Reply-To: <20251028212052.200523-1-sagis@google.com>

KVM_TDX_INIT_VM needs to be called after KVM_CREATE_VM and before
creating any VCPUs, thus before KVM_SET_CPUID2. KVM_TDX_INIT_VM accepts
the CPUID values directly.

Since KVM_GET_CPUID2 can't be used at this point, calculate the CPUID
values manually by using kvm_get_supported_cpuid() and filter the
returned CPUIDs against the supported CPUID values read from the TDX
module.

Co-developed-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Co-developed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Sagi Shahar <sagis@google.com>
---
 .../selftests/kvm/include/x86/tdx/tdx_util.h  |  54 +++++++
 .../selftests/kvm/lib/x86/tdx/tdx_util.c      | 132 ++++++++++++++++++
 2 files changed, 186 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h
index dafdc7e46abe..a2509959c7ce 100644
--- a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h
+++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h
@@ -11,6 +11,60 @@ static inline bool is_tdx_vm(struct kvm_vm *vm)
 	return vm->type == KVM_X86_TDX_VM;
 }
 
+/*
+ * TDX ioctls
+ */
+
+#define __vm_tdx_vm_ioctl(vm, cmd, metadata, arg)			\
+({									\
+	int r;								\
+									\
+	union {								\
+		struct kvm_tdx_cmd c;					\
+		unsigned long raw;					\
+	} tdx_cmd = { .c = {						\
+		.id = (cmd),						\
+		.flags = (uint32_t)(metadata),				\
+		.data = (uint64_t)(arg),				\
+	} };								\
+									\
+	r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd.raw);	\
+	r ?: tdx_cmd.c.hw_error;					\
+})
+
+#define vm_tdx_vm_ioctl(vm, cmd, flags, arg)				\
+({									\
+	int ret = __vm_tdx_vm_ioctl(vm, cmd, flags, arg);		\
+									\
+	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd,	ret, vm);		\
+})
+
+#define __vm_tdx_vcpu_ioctl(vcpu, cmd, metadata, arg)			\
+({									\
+	int r;								\
+									\
+	union {								\
+		struct kvm_tdx_cmd c;					\
+		unsigned long raw;					\
+	} tdx_cmd = { .c = {						\
+		.id = (cmd),						\
+		.flags = (uint32_t)(metadata),				\
+		.data = (uint64_t)(arg),				\
+	} };								\
+									\
+	r = __vcpu_ioctl(vcpu, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd.raw);	\
+	r ?: tdx_cmd.c.hw_error;					\
+})
+
+#define vm_tdx_vcpu_ioctl(vcpu, cmd, flags, arg)			\
+({									\
+	int ret = __vm_tdx_vcpu_ioctl(vcpu, cmd, flags, arg);		\
+									\
+	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, (vcpu)->vm);	\
+})
+
+void vm_tdx_init_vm(struct kvm_vm *vm, uint64_t attributes);
+
 void vm_tdx_setup_boot_code_region(struct kvm_vm *vm);
 void vm_tdx_setup_boot_parameters_region(struct kvm_vm *vm, uint32_t nr_runnable_vcpus);
 void vm_tdx_load_common_boot_parameters(struct kvm_vm *vm);
diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
index f3b69923e928..7a622b4810b1 100644
--- a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
+++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
@@ -124,3 +124,135 @@ void vm_tdx_set_vcpu_entry_point(struct kvm_vcpu *vcpu, void *guest_code)
 
 	vcpu_params->guest_code = (uint64_t)guest_code;
 }
+
+static struct kvm_tdx_capabilities *tdx_read_capabilities(struct kvm_vm *vm)
+{
+	struct kvm_tdx_capabilities *tdx_cap = NULL;
+	int nr_cpuid_configs = 4;
+	int rc = -1;
+	int i;
+
+	do {
+		nr_cpuid_configs *= 2;
+
+		tdx_cap = realloc(tdx_cap, sizeof(*tdx_cap) +
+					   sizeof(tdx_cap->cpuid) +
+					   (sizeof(struct kvm_cpuid_entry2) * nr_cpuid_configs));
+		TEST_ASSERT(tdx_cap,
+			    "Could not allocate memory for tdx capability nr_cpuid_configs %d\n",
+			    nr_cpuid_configs);
+
+		tdx_cap->cpuid.nent = nr_cpuid_configs;
+		rc = __vm_tdx_vm_ioctl(vm, KVM_TDX_CAPABILITIES, 0, tdx_cap);
+	} while (rc < 0 && errno == E2BIG);
+
+	TEST_ASSERT(rc == 0, "KVM_TDX_CAPABILITIES failed: %d %d",
+		    rc, errno);
+
+	pr_debug("tdx_cap: supported_attrs: 0x%016llx\n"
+		 "tdx_cap: supported_xfam 0x%016llx\n",
+		 tdx_cap->supported_attrs, tdx_cap->supported_xfam);
+
+	for (i = 0; i < tdx_cap->cpuid.nent; i++) {
+		const struct kvm_cpuid_entry2 *config = &tdx_cap->cpuid.entries[i];
+
+		pr_debug("cpuid config[%d]: leaf 0x%x sub_leaf 0x%x eax 0x%08x ebx 0x%08x ecx 0x%08x edx 0x%08x\n",
+			 i, config->function, config->index,
+			 config->eax, config->ebx, config->ecx, config->edx);
+	}
+
+	return tdx_cap;
+}
+
+static struct kvm_cpuid_entry2 *tdx_find_cpuid_config(struct kvm_tdx_capabilities *cap,
+						      uint32_t leaf, uint32_t sub_leaf)
+{
+	struct kvm_cpuid_entry2 *config;
+	uint32_t i;
+
+	for (i = 0; i < cap->cpuid.nent; i++) {
+		config = &cap->cpuid.entries[i];
+
+		if (config->function == leaf && config->index == sub_leaf)
+			return config;
+	}
+
+	return NULL;
+}
+
+/*
+ * Filter CPUID based on TDX supported capabilities
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   cpuid_data - CPUID fileds to filter
+ *
+ * Output Args: None
+ *
+ * Return: None
+ *
+ * For each CPUID leaf, filter out non-supported bits based on the capabilities reported
+ * by the TDX module
+ */
+static void vm_tdx_filter_cpuid(struct kvm_vm *vm,
+				struct kvm_cpuid2 *cpuid_data)
+{
+	struct kvm_tdx_capabilities *tdx_cap;
+	struct kvm_cpuid_entry2 *config;
+	struct kvm_cpuid_entry2 *e;
+	int i;
+
+	tdx_cap = tdx_read_capabilities(vm);
+
+	i = 0;
+	while (i < cpuid_data->nent) {
+		e = cpuid_data->entries + i;
+		config = tdx_find_cpuid_config(tdx_cap, e->function, e->index);
+
+		if (!config) {
+			int left = cpuid_data->nent - i - 1;
+
+			if (left > 0)
+				memmove(cpuid_data->entries + i,
+					cpuid_data->entries + i + 1,
+					sizeof(*cpuid_data->entries) * left);
+			cpuid_data->nent--;
+			continue;
+		}
+
+		e->eax &= config->eax;
+		e->ebx &= config->ebx;
+		e->ecx &= config->ecx;
+		e->edx &= config->edx;
+
+		i++;
+	}
+
+	free(tdx_cap);
+}
+
+void vm_tdx_init_vm(struct kvm_vm *vm, uint64_t attributes)
+{
+	struct kvm_tdx_init_vm *init_vm;
+	const struct kvm_cpuid2 *tmp;
+	struct kvm_cpuid2 *cpuid;
+
+	tmp = kvm_get_supported_cpuid();
+
+	cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
+	memcpy(cpuid, tmp, kvm_cpuid2_size(tmp->nent));
+	vm_tdx_filter_cpuid(vm, cpuid);
+
+	init_vm = calloc(1, sizeof(*init_vm) +
+			 sizeof(init_vm->cpuid.entries[0]) * cpuid->nent);
+	TEST_ASSERT(init_vm, "init_vm allocation failed");
+
+	memcpy(&init_vm->cpuid, cpuid, kvm_cpuid2_size(cpuid->nent));
+	free(cpuid);
+
+	init_vm->attributes = attributes;
+
+	vm_tdx_vm_ioctl(vm, KVM_TDX_INIT_VM, 0, init_vm);
+
+	free(init_vm);
+}
-- 
2.51.1.851.g4ebd6896fd-goog


  parent reply	other threads:[~2025-10-28 21:21 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-28 21:20 [PATCH v12 00/23] TDX KVM selftests Sagi Shahar
2025-10-28 21:20 ` [PATCH v12 01/23] KVM: selftests: Add macros so simplify creating VM shapes for non-default types Sagi Shahar
2025-10-29  1:13   ` Ira Weiny
2025-10-29  6:57   ` Binbin Wu
2025-10-31  3:42   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 02/23] KVM: selftests: Allocate pgd in virt_map() as necessary Sagi Shahar
2025-10-31  3:51   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 03/23] KVM: selftests: Expose functions to get default sregs values Sagi Shahar
2025-10-29  1:40   ` Ira Weiny
2025-10-31  3:43   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 04/23] KVM: selftests: Expose function to allocate guest vCPU stack Sagi Shahar
2025-10-29 13:24   ` Ira Weiny
2025-10-31  3:52   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 05/23] KVM: selftests: Update kvm_init_vm_address_properties() for TDX Sagi Shahar
2025-10-29 15:22   ` Ira Weiny
2025-10-31  3:53   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 06/23] KVM: selftests: Expose segment definitons to assembly files Sagi Shahar
2025-10-31  3:54   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 07/23] KVM: selftests: Add kbuild definitons Sagi Shahar
2025-10-29  7:43   ` Binbin Wu
2025-10-29 15:46     ` Ira Weiny
2025-10-29 15:55   ` Ira Weiny
2025-10-31  3:56   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 08/23] KVM: selftests: Define structs to pass parameters to TDX boot code Sagi Shahar
2025-10-29 16:37   ` Reinette Chatre
2025-10-30 14:20     ` Sean Christopherson
2025-10-31  4:01   ` Reinette Chatre
2025-11-26 22:32   ` Ira Weiny
2025-12-01 20:28     ` Ira Weiny
2025-10-28 21:20 ` [PATCH v12 09/23] KVM: selftests: Add " Sagi Shahar
2025-10-28 21:20 ` [PATCH v12 10/23] KVM: selftests: Set up TDX boot code region Sagi Shahar
2025-10-28 21:20 ` [PATCH v12 11/23] KVM: selftests: Set up TDX boot parameters region Sagi Shahar
2025-10-29  8:52   ` Binbin Wu
2025-10-29 21:01   ` Reinette Chatre
2025-10-28 21:20 ` Sagi Shahar [this message]
2025-10-29 21:16   ` [PATCH v12 12/23] KVM: selftests: Add helper to initialize TDX VM Ira Weiny
2025-10-29 23:01     ` Reinette Chatre
2025-10-30  1:25   ` Binbin Wu
2025-10-31  4:06   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 13/23] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration Sagi Shahar
2025-10-29 21:19   ` Ira Weiny
2025-10-30  1:35   ` Binbin Wu
2025-10-28 21:20 ` [PATCH v12 14/23] KVM: selftests: Add helpers to init TDX memory and finalize VM Sagi Shahar
2025-10-29 21:27   ` Ira Weiny
2025-10-30  2:32   ` Binbin Wu
2025-10-31 15:58   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 15/23] KVM: selftests: Call TDX init when creating a new TDX vm Sagi Shahar
2025-10-30 22:20   ` Ira Weiny
2025-10-31 16:03   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 16/23] KVM: selftests: Setup memory regions for TDX on vm creation Sagi Shahar
2025-10-29 13:18   ` Ira Weiny
2025-10-30  6:01     ` Binbin Wu
2025-10-28 21:20 ` [PATCH v12 17/23] KVM: selftests: Call KVM_TDX_INIT_VCPU when creating a new TDX vcpu Sagi Shahar
2025-10-30  6:15   ` Binbin Wu
2025-10-28 21:20 ` [PATCH v12 18/23] KVM: selftests: Set entry point for TDX guest code Sagi Shahar
2025-10-31 16:03   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 19/23] KVM: selftests: Finalize TD memory as part of kvm_arch_vm_finalize_vcpus Sagi Shahar
2025-10-31 13:10   ` Ira Weiny
2025-10-31 16:05   ` Reinette Chatre
2025-10-28 21:20 ` [PATCH v12 20/23] KVM: selftests: Add support for TDX TDCALL from guest Sagi Shahar
2025-10-31 14:11   ` Ira Weiny
2025-10-31 15:15     ` Sean Christopherson
2025-10-31 15:58       ` Sagi Shahar
2025-10-31 16:12         ` Sean Christopherson
2025-10-31 16:01       ` Sean Christopherson
2025-10-28 21:20 ` [PATCH v12 21/23] KVM: selftests: Add wrapper for TDX MMIO " Sagi Shahar
2025-10-31 14:21   ` Ira Weiny
2025-10-28 21:20 ` [PATCH v12 22/23] KVM: selftests: Add ucall support for TDX Sagi Shahar
2025-10-31 14:38   ` Ira Weiny
2025-10-31 15:55   ` Sean Christopherson
2025-10-28 21:20 ` [PATCH v12 23/23] KVM: selftests: Add TDX lifecycle test Sagi Shahar

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=20251028212052.200523-13-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.