From: Binbin Wu <binbin.wu@linux.intel.com>
To: Lisa Wang <wyihan@google.com>
Cc: Andrew Jones <ajones@ventanamicro.com>,
Ackerley Tng <ackerleytng@google.com>,
Chao Gao <chao.gao@intel.com>,
Chenyi Qiang <chenyi.qiang@intel.com>,
Dave Hansen <dave.hansen@linux.intel.com>,
Erdem Aktas <erdemaktas@google.com>,
Ira Weiny <iweiny@kernel.org>,
Isaku Yamahata <isaku.yamahata@intel.com>,
Kiryl Shutsemau <kas@kernel.org>,
linux-kselftest@vger.kernel.org,
Paolo Bonzini <pbonzini@redhat.com>,
"Pratik R. Sampat" <pratikrajesh.sampat@amd.com>,
Reinette Chatre <reinette.chatre@intel.com>,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
Roger Wang <runanwang@google.com>,
Ryan Afranji <afranji@google.com>, Sagi Shahar <sagis@google.com>,
Sean Christopherson <seanjc@google.com>,
Shuah Khan <shuah@kernel.org>, Xiaoyao Li <xiaoyao.li@intel.com>,
Oliver Upton <oupton@kernel.org>,
Jeremiah McReynolds <jmcrey@google.com>,
kvm@vger.kernel.org, linux-coco@lists.linux.dev,
linux-kernel@vger.kernel.org, x86@kernel.org
Subject: Re: [PATCH v15 03/23] KVM: selftests: Initialize the TDX VM
Date: Sat, 10 Oct 2026 10:05:02 +0800 [thread overview]
Message-ID: <dc3ff4f6-0017-45ce-96c4-1e40d91cbfc4@linux.intel.com> (raw)
In-Reply-To: <20261001-tdx-selftests-v15-3-7c62a5d8a992@google.com>
On 10/2/2026 3:37 AM, Lisa Wang wrote:
> From: Sagi Shahar <sagis@google.com>
>
> Add tdx_init_vm() to handle the mandatory VM-level initialization
> sequence required for Intel TDX.
>
> For TDX, the VM's CPUID configuration must be "sealed" during
> KVM_TDX_INIT_VM before any vCPUs are created. This is necessary because
> the TDX module does not allow the host to create and initialize any
> vCPUs before the VM's CPUID configuration is accepted and sealed into
> the TDCS.
>
> Additionally, to satisfy the strict requirements of the TDH.MNG.INIT
> SEAMCALL, the helper masks the host-supported CPUID
^
KVM-supported is more accurate
> (kvm_get_supported_cpuid()) against the "directly configurable"bits
> reported by KVM_TDX_CAPABILITIES.
>
> 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>
> Signed-off-by: Lisa Wang <wyihan@google.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> ---
> tools/testing/selftests/kvm/Makefile.kvm | 1 +
> .../testing/selftests/kvm/include/x86/processor.h | 2 +
> .../selftests/kvm/include/x86/tdx/tdx_util.h | 37 +++++++
> tools/testing/selftests/kvm/lib/x86/processor.c | 21 +++-
> tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c | 121 +++++++++++++++++++++
> 5 files changed, 178 insertions(+), 4 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
> index 239bc61ea384..8f514008daa2 100644
> --- a/tools/testing/selftests/kvm/Makefile.kvm
> +++ b/tools/testing/selftests/kvm/Makefile.kvm
> @@ -28,6 +28,7 @@ LIBKVM_x86 += lib/x86/pmu.c
> LIBKVM_x86 += lib/x86/processor.c
> LIBKVM_x86 += lib/x86/sev.c
> LIBKVM_x86 += lib/x86/svm.c
> +LIBKVM_x86 += lib/x86/tdx/tdx_util.c
> LIBKVM_x86 += lib/x86/ucall.c
> LIBKVM_x86 += lib/x86/vmx.c
>
> diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/testing/selftests/kvm/include/x86/processor.h
> index ed50007e3504..08b7b194f213 100644
> --- a/tools/testing/selftests/kvm/include/x86/processor.h
> +++ b/tools/testing/selftests/kvm/include/x86/processor.h
> @@ -1024,6 +1024,8 @@ static inline void vcpu_xcrs_set(struct kvm_vcpu *vcpu, struct kvm_xcrs *xcrs)
> vcpu_ioctl(vcpu, KVM_SET_XCRS, xcrs);
> }
>
> +const struct kvm_cpuid_entry2 *__get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
> + u32 function, u32 index);
> const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
> u32 function, u32 index);
> const struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
> 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 f647e6ca6b34..571f7ce4b8fe 100644
> --- a/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h
> +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx_util.h
> @@ -11,4 +11,41 @@ static inline bool is_tdx_vm(struct kvm_vm *vm)
> return vm->type == KVM_X86_TDX_VM;
> }
>
> +/*
> + * TDX ioctls
> + * Use underscores to avoid collisions with struct member names.
> + */
> +#define __tdx_vm_ioctl(vm, cmd, _flags, arg, hw_err) \
> +({ \
> + u64 *__hw_err = (hw_err); \
> + int r; \
> + \
> + union { \
> + struct kvm_tdx_cmd c; \
> + unsigned long raw; \
> + } tdx_cmd = { .c = { \
> + .id = (cmd), \
> + .flags = (u32)(_flags), \
> + .data = (u64)(arg), \
> + } }; \
> + \
> + r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd.raw); \
> + if (__hw_err) \
> + *__hw_err = tdx_cmd.c.hw_error; \
> + r; \
> +})
> +
> +#define tdx_vm_ioctl(vm, cmd, flags, arg) \
> +({ \
> + u64 hw_error; \
> + int ret = __tdx_vm_ioctl(vm, cmd, flags, arg, &hw_error); \
> + \
> + TEST_ASSERT(!ret, \
> + "%s failed, rc: %d errno: %i (%s) hw_error: 0x%llx",\
> + #cmd, ret, errno, strerror(errno), \
> + (unsigned long long)hw_error); \
hw_error is already u64, why cast it to unsigned long long?
TDX cases can only be done in x86-64, just use 0x%lx for u64?
> +})
> +
> +void tdx_init_vm(struct kvm_vm *vm);
> +
> #endif /* SELFTESTS_TDX_TDX_UTIL_H */
> diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/selftests/kvm/lib/x86/processor.c
> index 24395a8e654a..b87ba7d8538b 100644
> --- a/tools/testing/selftests/kvm/lib/x86/processor.c
> +++ b/tools/testing/selftests/kvm/lib/x86/processor.c
> @@ -829,6 +829,9 @@ void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus)
> vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
> }
>
> + if (is_tdx_vm(vm))
> + tdx_init_vm(vm);
> +
> r = __vm_ioctl(vm, KVM_GET_TSC_KHZ, NULL);
> TEST_ASSERT(r > 0, "KVM_GET_TSC_KHZ did not provide a valid TSC frequency.");
> guest_tsc_khz = r;
> @@ -1347,8 +1350,8 @@ void kvm_init_vm_address_properties(struct kvm_vm *vm)
> }
> }
>
> -const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
> - u32 function, u32 index)
> +const struct kvm_cpuid_entry2 *__get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
> + u32 function, u32 index)
> {
> int i;
>
> @@ -1358,11 +1361,21 @@ const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
> return &cpuid->entries[i];
> }
>
> - TEST_FAIL("CPUID function 0x%x index 0x%x not found ", function, index);
> -
> return NULL;
> }
>
> +const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
> + u32 function, u32 index)
> +{
> + const struct kvm_cpuid_entry2 *entry;
> +
> + entry = __get_cpuid_entry(cpuid, function, index);
> + if (!entry)
> + TEST_FAIL("CPUID function 0x%x index 0x%x not found ", function, index);
> +
> + return entry;
> +}
> +
> #define X86_HYPERCALL(inputs...) \
> ({ \
> u64 r; \
> diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
> new file mode 100644
> index 000000000000..3a8900ff2540
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx_util.c
> @@ -0,0 +1,121 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include "processor.h"
> +#include "tdx/tdx_util.h"
> +
> +static const struct kvm_tdx_capabilities *tdx_read_capabilities(struct kvm_vm *vm)
> +{
> + static struct kvm_tdx_capabilities *tdx_cap;
> + int nr_cpuid_configs = 4;
> + int rc = -1;
> + int i;
> +
> + if (tdx_cap)
> + return tdx_cap;
> +
> + do {
> + nr_cpuid_configs *= 2;
> +
> + tdx_cap = realloc(tdx_cap, sizeof(*tdx_cap) +
> + (sizeof(struct kvm_cpuid_entry2) * nr_cpuid_configs));
> + TEST_ASSERT(tdx_cap,
> + "Could not allocate memory for tdx capability nr_cpuid_configs %d\n",
Nit: Trailing newline in the message could be dropped.
> + nr_cpuid_configs);
> +
> + tdx_cap->cpuid.nent = nr_cpuid_configs;
> + rc = __tdx_vm_ioctl(vm, KVM_TDX_CAPABILITIES, 0, tdx_cap, NULL);
> + } 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;
> +}
> +
> +/*
> + * Filter CPUID based on TDX supported capabilities
> + *
> + * Input Args:
> + * vm - Virtual Machine
> + * cpuid_data - CPUID fields to filter
> + *
> + * Output Args: None
cpuid_data should be Input/Output Arg?
I am not sure Input Args / Output Args / Return needed though.
It seems the selftests code in kvm/x86 doesn't use this format.
> + *
> + * Return: None
> + *
> + * For each CPUID leaf, filter out unsupported bits based on the capabilities
> + * reported by the TDX module
KVM filters directly configurable features that it doesn't support.
The capabilities reported are not the original version reported by the TDX module.
the TDX module -> KVM ?
> + */
> +static void tdx_filter_cpuid(struct kvm_vm *vm,
> + struct kvm_cpuid2 *cpuid_data)
> +{
> + const struct kvm_tdx_capabilities *tdx_cap;
> + const 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 = __get_cpuid_entry(&tdx_cap->cpuid, 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++;
> + }
> +}
> +
> +void tdx_init_vm(struct kvm_vm *vm)
> +{
> + 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(tmp->nent);
> + memcpy(cpuid, tmp, kvm_cpuid2_size(tmp->nent));
> + 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 = 0;
> + init_vm->xfam = 0;
May be some comments for setting attributes and xfam to 0.
Especially why the test doesn't need SEPT_VE_DISABLE?
> +
> + tdx_vm_ioctl(vm, KVM_TDX_INIT_VM, 0, init_vm);
> +
> + free(init_vm);
> +}
>
next prev parent reply other threads:[~2026-10-10 2:05 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 19:37 [PATCH v15 00/23] TDX KVM selftests Lisa Wang
2026-10-01 19:37 ` [PATCH v15 01/23] KVM: selftests: Add macros to simplify creating VM shapes for non-default types Lisa Wang
2026-10-01 19:37 ` [PATCH v15 02/23] KVM: selftests: Update kvm_init_vm_address_properties() for TDX Lisa Wang
2026-10-01 19:37 ` [PATCH v15 03/23] KVM: selftests: Initialize the TDX VM Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-05 21:26 ` Lisa Wang
2026-10-09 6:00 ` Xiaoyao Li
2026-10-10 2:05 ` Binbin Wu [this message]
2026-10-01 19:37 ` [PATCH v15 04/23] KVM: selftests: Expose segment definitions to assembly files Lisa Wang
2026-10-01 19:37 ` [PATCH v15 05/23] tools: include: Add kbuild.h for assembly structure offsets Lisa Wang
2026-10-09 6:10 ` Xiaoyao Li
2026-10-01 19:37 ` [PATCH v15 06/23] KVM: selftests: Introduce structures for TDX guest boot parameters Lisa Wang
2026-10-09 6:13 ` Xiaoyao Li
2026-10-01 19:37 ` [PATCH v15 07/23] KVM: selftests: Add TDX boot code Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-05 22:31 ` Lisa Wang
2026-10-01 19:37 ` [PATCH v15 08/23] KVM: selftests: Expose functions to get default sregs values Lisa Wang
2026-10-01 19:37 ` [PATCH v15 09/23] KVM: selftests: Set up TDX boot code region Lisa Wang
2026-10-01 19:37 ` [PATCH v15 10/23] KVM: selftests: Set up TDX boot parameters region Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-05 22:33 ` Lisa Wang
2026-10-09 7:22 ` Xiaoyao Li
2026-10-10 2:46 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 11/23] KVM: selftests: Set shared attributes for ucall guest_memfd pages Lisa Wang
2026-10-09 15:44 ` Xiaoyao Li
2026-10-01 19:37 ` [PATCH v15 12/23] KVM: selftests: Require guest_memfd for TDX VMs Lisa Wang
2026-10-09 7:38 ` Xiaoyao Li
2026-10-01 19:37 ` [PATCH v15 13/23] KVM: selftests: Support guest_memfd in-place conversion Lisa Wang
2026-10-10 3:32 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 14/23] KVM: selftests: Expose function to allocate vCPU stack Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-09 7:56 ` Xiaoyao Li
2026-10-10 3:54 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 15/23] KVM: selftests: Call KVM_TDX_INIT_VCPU when creating a new TDX vcpu Lisa Wang
2026-10-09 8:02 ` Xiaoyao Li
2026-10-10 4:31 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 16/23] KVM: selftests: Load per-vCPU guest stack in TDX boot parameters Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-07 19:07 ` Lisa Wang
2026-10-01 19:37 ` [PATCH v15 17/23] KVM: selftests: Set entry point for TDX guest code Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-01 19:37 ` [PATCH v15 18/23] KVM: selftests: Add helpers to init TDX memory and finalize VM Lisa Wang
2026-10-01 19:37 ` [PATCH v15 19/23] KVM: selftests: Finalize TDX VM in kvm_arch_vm_finalize_vcpus() Lisa Wang
2026-10-09 8:12 ` Xiaoyao Li
2026-10-10 5:57 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 20/23] KVM: selftests: Add a helper to issue TDVMCALLs from the TDX vm Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-09 8:20 ` Xiaoyao Li
2026-10-09 8:23 ` Xiaoyao Li
2026-10-10 6:34 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 21/23] KVM: selftests: Add support for per-VM ucall ops on x86 Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-10 6:52 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 22/23] KVM: selftests: Add support for TDX ucalls, via TDVMCALL_REPORT_FATAL_ERROR Lisa Wang
2026-10-02 9:13 ` sashiko-bot
2026-10-10 7:30 ` Binbin Wu
2026-10-10 7:20 ` Binbin Wu
2026-10-01 19:37 ` [PATCH v15 23/23] KVM: selftests: Add TDX lifecycle test Lisa Wang
2026-10-10 7:40 ` Binbin Wu
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=dc3ff4f6-0017-45ce-96c4-1e40d91cbfc4@linux.intel.com \
--to=binbin.wu@linux.intel.com \
--cc=ackerleytng@google.com \
--cc=afranji@google.com \
--cc=ajones@ventanamicro.com \
--cc=chao.gao@intel.com \
--cc=chenyi.qiang@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=erdemaktas@google.com \
--cc=isaku.yamahata@intel.com \
--cc=iweiny@kernel.org \
--cc=jmcrey@google.com \
--cc=kas@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=oupton@kernel.org \
--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=sagis@google.com \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
--cc=wyihan@google.com \
--cc=x86@kernel.org \
--cc=xiaoyao.li@intel.com \
/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.