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>
Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Subject: [PATCH v8 12/30] KVM: selftests: TDX: Add basic TDX CPUID test
Date: Thu, 7 Aug 2025 13:16:08 -0700 [thread overview]
Message-ID: <20250807201628.1185915-13-sagis@google.com> (raw)
In-Reply-To: <20250807201628.1185915-1-sagis@google.com>
The test reads CPUID values from inside a TD VM and compare them
to expected values.
The test targets CPUID values which are virtualized as "As Configured",
"As Configured (if Native)", "Calculated", "Fixed" and "Native"
according to the TDX spec.
Co-developed-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Sagi Shahar <sagis@google.com>
---
.../selftests/kvm/include/x86/tdx/test_util.h | 15 +++
.../selftests/kvm/lib/x86/tdx/test_util.c | 20 ++++
tools/testing/selftests/kvm/x86/tdx_vm_test.c | 98 ++++++++++++++++++-
3 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h
index cf11955d56d6..2af6e810ef78 100644
--- a/tools/testing/selftests/kvm/include/x86/tdx/test_util.h
+++ b/tools/testing/selftests/kvm/include/x86/tdx/test_util.h
@@ -9,6 +9,9 @@
#define TDX_TEST_SUCCESS_PORT 0x30
#define TDX_TEST_SUCCESS_SIZE 4
+#define TDX_TEST_REPORT_PORT 0x31
+#define TDX_TEST_REPORT_SIZE 4
+
/* Port I/O direction */
#define PORT_READ 0
#define PORT_WRITE 1
@@ -77,4 +80,16 @@ void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa);
*/
void tdx_assert_error(uint64_t error);
+/*
+ * Report a 32 bit value from the guest to user space using TDG.VP.VMCALL
+ * <Instruction.IO> call. Data is reported on port TDX_TEST_REPORT_PORT.
+ */
+uint64_t tdx_test_report_to_user_space(uint32_t data);
+
+/*
+ * Read a 32 bit value from the guest in user space, sent using
+ * tdx_test_report_to_user_space().
+ */
+uint32_t tdx_test_read_report_from_guest(struct kvm_vcpu *vcpu);
+
#endif // SELFTEST_TDX_TEST_UTIL_H
diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c
index 4ccc5298ba25..f9bde114a8bc 100644
--- a/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c
+++ b/tools/testing/selftests/kvm/lib/x86/tdx/test_util.c
@@ -104,3 +104,23 @@ void tdx_assert_error(uint64_t error)
if (error)
tdx_test_fatal(error);
}
+
+uint64_t tdx_test_report_to_user_space(uint32_t data)
+{
+ /* Upcast data to match tdg_vp_vmcall_instruction_io() signature */
+ uint64_t data_64 = data;
+
+ return tdg_vp_vmcall_instruction_io(TDX_TEST_REPORT_PORT,
+ TDX_TEST_REPORT_SIZE, PORT_WRITE,
+ &data_64);
+}
+
+uint32_t tdx_test_read_report_from_guest(struct kvm_vcpu *vcpu)
+{
+ uint32_t res;
+
+ tdx_test_assert_io(vcpu, TDX_TEST_REPORT_PORT, 4, PORT_WRITE);
+ res = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset);
+
+ return res;
+}
diff --git a/tools/testing/selftests/kvm/x86/tdx_vm_test.c b/tools/testing/selftests/kvm/x86/tdx_vm_test.c
index 97330e28f236..bbdcca358d71 100644
--- a/tools/testing/selftests/kvm/x86/tdx_vm_test.c
+++ b/tools/testing/selftests/kvm/x86/tdx_vm_test.c
@@ -3,6 +3,7 @@
#include <signal.h>
#include "kvm_util.h"
+#include "processor.h"
#include "tdx/tdcall.h"
#include "tdx/tdx.h"
#include "tdx/tdx_util.h"
@@ -146,6 +147,99 @@ void verify_td_ioexit(void)
printf("\t ... PASSED\n");
}
+/*
+ * Verifies CPUID functionality by reading CPUID values in guest. The guest
+ * will then send the values to userspace using an IO write to be checked
+ * against the expected values.
+ */
+void guest_code_cpuid(void)
+{
+ uint32_t ebx, ecx;
+ uint64_t err;
+
+ /* Read CPUID leaf 0x1 */
+ asm volatile ("cpuid"
+ : "=b" (ebx), "=c" (ecx)
+ : "a" (0x1)
+ : "edx");
+
+ err = tdx_test_report_to_user_space(ebx);
+ tdx_assert_error(err);
+
+ err = tdx_test_report_to_user_space(ecx);
+ tdx_assert_error(err);
+
+ tdx_test_success();
+}
+
+void verify_td_cpuid(void)
+{
+ uint32_t guest_max_addressable_ids, host_max_addressable_ids;
+ const struct kvm_cpuid_entry2 *cpuid_entry;
+ uint32_t guest_clflush_line_size;
+ uint32_t guest_initial_apic_id;
+ uint32_t guest_sse3_enabled;
+ uint32_t guest_fma_enabled;
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ uint32_t ebx, ecx;
+
+ vm = td_create();
+ td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0);
+ vcpu = td_vcpu_add(vm, 0, guest_code_cpuid);
+ td_finalize(vm);
+
+ printf("Verifying TD CPUID:\n");
+
+ /* Wait for guest to report ebx value */
+ tdx_run(vcpu);
+ ebx = tdx_test_read_report_from_guest(vcpu);
+
+ /* Wait for guest to report either ecx value or error */
+ tdx_run(vcpu);
+ ecx = tdx_test_read_report_from_guest(vcpu);
+
+ /* Wait for guest to complete execution */
+ tdx_run(vcpu);
+ tdx_test_assert_success(vcpu);
+
+ /* Verify the CPUID values received from the guest. */
+ printf("\t ... Verifying CPUID values from guest\n");
+
+ /* Get KVM CPUIDs for reference */
+ cpuid_entry = vcpu_get_cpuid_entry(vcpu, 1);
+ TEST_ASSERT(cpuid_entry, "CPUID entry missing\n");
+
+ host_max_addressable_ids = (cpuid_entry->ebx >> 16) & 0xFF;
+
+ guest_sse3_enabled = ecx & 0x1; // Native
+ guest_clflush_line_size = (ebx >> 8) & 0xFF; // Fixed
+ guest_max_addressable_ids = (ebx >> 16) & 0xFF; // As Configured
+ guest_fma_enabled = (ecx >> 12) & 0x1; // As Configured (if Native)
+ guest_initial_apic_id = (ebx >> 24) & 0xFF; // Calculated
+
+ TEST_ASSERT_EQ(guest_sse3_enabled, 1);
+ TEST_ASSERT_EQ(guest_clflush_line_size, 8);
+ TEST_ASSERT_EQ(guest_max_addressable_ids, host_max_addressable_ids);
+
+ /* TODO: This only tests the native value. To properly test
+ * "As Configured (if Native)" this value needs override in the
+ * TD params.
+ */
+ TEST_ASSERT_EQ(guest_fma_enabled, (cpuid_entry->ecx >> 12) & 0x1);
+
+ /* TODO: guest_initial_apic_id is calculated based on the number of
+ * vCPUs in the TD. From the spec: "Virtual CPU index, starting from 0
+ * and allocated sequentially on each successful TDH.VP.INIT"
+ * To test non-trivial values either use a TD with multiple vCPUs
+ * or pick a different calculated value.
+ */
+ TEST_ASSERT_EQ(guest_initial_apic_id, 0);
+
+ kvm_vm_free(vm);
+ printf("\t ... PASSED\n");
+}
+
int main(int argc, char **argv)
{
ksft_print_header();
@@ -153,13 +247,15 @@ int main(int argc, char **argv)
if (!is_tdx_enabled())
ksft_exit_skip("TDX is not supported by the KVM. Exiting.\n");
- ksft_set_plan(3);
+ ksft_set_plan(4);
ksft_test_result(!run_in_new_process(&verify_td_lifecycle),
"verify_td_lifecycle\n");
ksft_test_result(!run_in_new_process(&verify_report_fatal_error),
"verify_report_fatal_error\n");
ksft_test_result(!run_in_new_process(&verify_td_ioexit),
"verify_td_ioexit\n");
+ ksft_test_result(!run_in_new_process(&verify_td_cpuid),
+ "verify_td_cpuid\n");
ksft_finished();
return 0;
--
2.51.0.rc0.155.g4a0f42376b-goog
next prev parent reply other threads:[~2025-08-07 20:16 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-07 20:15 [PATCH v8 00/30] TDX KVM selftests Sagi Shahar
2025-08-07 20:15 ` [PATCH v8 01/30] KVM: selftests: Add function to allow one-to-one GVA to GPA mappings Sagi Shahar
2025-08-11 17:49 ` Sean Christopherson
2025-08-15 4:16 ` Sagi Shahar
2025-08-07 20:15 ` [PATCH v8 02/30] KVM: selftests: Expose function that sets up sregs based on VM's mode Sagi Shahar
2025-08-11 18:11 ` Sean Christopherson
2025-08-15 4:24 ` Sagi Shahar
2025-08-07 20:15 ` [PATCH v8 03/30] KVM: selftests: Store initial stack address in struct kvm_vcpu Sagi Shahar
2025-08-11 18:12 ` Sean Christopherson
2025-08-07 20:16 ` [PATCH v8 04/30] KVM: selftests: Add vCPU descriptor table initialization utility Sagi Shahar
2025-08-11 18:25 ` Sean Christopherson
2025-08-15 4:29 ` Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 05/30] KVM: selftests: Update kvm_init_vm_address_properties() for TDX Sagi Shahar
2025-08-11 18:34 ` Sean Christopherson
2025-08-15 4:31 ` Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 06/30] KVM: selftests: Add helper functions to create TDX VMs Sagi Shahar
2025-08-11 20:13 ` Sean Christopherson
2025-08-12 21:05 ` Ira Weiny
2025-08-13 4:22 ` Binbin Wu
2025-08-15 5:20 ` Sagi Shahar
2025-08-16 0:22 ` Sean Christopherson
2025-08-16 0:32 ` Reinette Chatre
2025-08-16 0:28 ` Reinette Chatre
2025-08-13 7:41 ` Binbin Wu
2025-08-15 2:20 ` Chao Gao
2025-08-21 4:08 ` Sagi Shahar
2025-08-14 0:48 ` Edgecombe, Rick P
2025-08-21 4:15 ` Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 07/30] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration Sagi Shahar
2025-08-13 13:34 ` Chenyi Qiang
2025-08-20 21:18 ` Sagi Shahar
2025-08-20 21:49 ` Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 08/30] KVM: selftests: TDX: Update load_td_memory_region() for VM memory backed by guest memfd Sagi Shahar
2025-08-11 14:19 ` Ira Weiny
2025-08-11 20:31 ` Sean Christopherson
2025-08-13 9:23 ` Binbin Wu
2025-08-13 14:42 ` Reinette Chatre
2025-08-14 2:49 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 09/30] KVM: selftests: TDX: Add TDX lifecycle test Sagi Shahar
2025-08-13 10:36 ` Binbin Wu
2025-08-21 4:19 ` Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 10/30] KVM: selftests: TDX: Add report_fatal_error test Sagi Shahar
2025-08-13 10:58 ` Binbin Wu
2025-08-14 7:05 ` Binbin Wu
2025-08-25 21:49 ` Sagi Shahar
2025-08-25 21:28 ` Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 11/30] KVM: selftests: TDX: Adding test case for TDX port IO Sagi Shahar
2025-08-14 3:24 ` Binbin Wu
2025-08-07 20:16 ` Sagi Shahar [this message]
2025-08-14 3:20 ` [PATCH v8 12/30] KVM: selftests: TDX: Add basic TDX CPUID test Chenyi Qiang
2025-08-14 6:11 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 13/30] KVM: selftests: TDX: Add basic TDG.VP.VMCALL<GetTdVmCallInfo> test Sagi Shahar
2025-08-14 6:34 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 14/30] KVM: selftests: TDX: Add TDX IO writes test Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 15/30] KVM: selftests: TDX: Add TDX IO reads test Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 16/30] KVM: selftests: TDX: Add TDX MSR read/write tests Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 17/30] KVM: selftests: TDX: Add TDX HLT exit test Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 18/30] KVM: selftests: TDX: Add TDX MMIO reads test Sagi Shahar
2025-08-14 9:58 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 19/30] KVM: selftests: TDX: Add TDX MMIO writes test Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 20/30] KVM: selftests: TDX: Add TDX CPUID TDVMCALL test Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 21/30] KVM: selftests: TDX: Verify the behavior when host consumes a TD private memory Sagi Shahar
2025-08-11 20:35 ` Sean Christopherson
2025-08-14 11:17 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 22/30] KVM: selftests: TDX: Add TDG.VP.INFO test Sagi Shahar
2025-08-14 9:04 ` Chenyi Qiang
2025-08-14 11:48 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 23/30] KVM: selftests: Add functions to allow mapping as shared Sagi Shahar
2025-08-11 18:49 ` Ira Weiny
2025-08-15 2:37 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 24/30] KVM: selftests: TDX: Add shared memory test Sagi Shahar
2025-08-11 21:06 ` Sean Christopherson
2025-08-07 20:16 ` [PATCH v8 25/30] KVM: selftests: KVM: selftests: Expose new vm_vaddr_alloc_private() Sagi Shahar
2025-08-11 21:07 ` Sean Christopherson
2025-08-15 3:15 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 26/30] KVM: selftests: TDX: Add support for TDG.MEM.PAGE.ACCEPT Sagi Shahar
2025-08-15 5:38 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 27/30] KVM: selftests: TDX: Add support for TDG.VP.VEINFO.GET Sagi Shahar
2025-08-07 20:16 ` [PATCH v8 28/30] KVM: selftests: TDX: Add TDX UPM selftest Sagi Shahar
2025-08-13 16:05 ` Ira Weiny
2025-08-13 17:30 ` Reinette Chatre
2025-08-15 7:03 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 29/30] KVM: selftests: TDX: Add TDX UPM selftests for implicit conversion Sagi Shahar
2025-08-15 7:18 ` Binbin Wu
2025-08-07 20:16 ` [PATCH v8 30/30] KVM: selftests: TDX: Test LOG_DIRTY_PAGES flag to a non-GUEST_MEMFD memslot Sagi Shahar
2025-08-13 16:10 ` Ira Weiny
2025-08-11 17:38 ` [PATCH v8 00/30] TDX KVM selftests Sean Christopherson
2025-08-11 18:11 ` Edgecombe, Rick P
2025-08-11 20:00 ` Sagi Shahar
2025-08-11 20:53 ` Sean Christopherson
2025-08-15 4:14 ` Sagi Shahar
2025-08-15 22:52 ` Sean Christopherson
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=20250807201628.1185915-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=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;
as well as URLs for NNTP newsgroup(s).