All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ackerley Tng <ackerleytng@google.com>
To: linux-kselftest@vger.kernel.org
Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com,
	sagis@google.com, erdemaktas@google.com, afranji@google.com,
	runanwang@google.com, shuah@kernel.org, drjones@redhat.com,
	maz@kernel.org, bgardon@google.com, jmattson@google.com,
	dmatlack@google.com, peterx@redhat.com, oupton@google.com,
	ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com,
	xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com,
	eesposit@redhat.com, borntraeger@de.ibm.com,
	eric.auger@redhat.com, wangyanan55@huawei.com,
	aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com,
	axelrasmussen@google.com, zhenzhong.duan@intel.com,
	maciej.szmigiero@oracle.com, like.xu@linux.intel.com,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
	Ackerley Tng <ackerleytng@google.com>
Subject: [RFC PATCH v3 12/31] KVM: selftests: TDX: Add basic TDX CPUID test
Date: Sat, 21 Jan 2023 00:15:23 +0000	[thread overview]
Message-ID: <20230121001542.2472357-13-ackerleytng@google.com> (raw)
In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com>

From: Sagi Shahar <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.

Signed-off-by: Sagi Shahar <sagis@google.com>
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
Changes RFCv2 -> RFCv3
+ Manually inlined cpuid function in cpuid test. This highlights the
  purpose of this test - to test the result of the cpuid instruction.
+ Replace find_cpuid_entry with kvm_get_supported_cpuid_entry from
  tools/testing/selftests/kvm/lib/x86_64/processor.c
---
 .../kvm/include/x86_64/tdx/test_util.h        |   9 ++
 .../selftests/kvm/lib/x86_64/tdx/test_util.c  |  11 ++
 .../selftests/kvm/x86_64/tdx_vm_tests.c       | 106 ++++++++++++++++++
 3 files changed, 126 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h
index 95a5d5be7f0bf..af0ddbfe8d71b 100644
--- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h
+++ b/tools/testing/selftests/kvm/include/x86_64/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
+
 /**
  * Assert that some IO operation involving tdg_vp_vmcall_instruction_io() was
  * called in the guest.
@@ -102,4 +105,10 @@ void tdx_test_fatal(uint64_t error_code);
  */
 void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa);

+/**
+ * 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);
+
 #endif // SELFTEST_TDX_TEST_UTIL_H
diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c
index 7f3cd8089cea3..55c5a1e634df7 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c
@@ -42,3 +42,14 @@ void tdx_test_fatal(uint64_t error_code)
 {
 	tdx_test_fatal_with_data(error_code, 0);
 }
+
+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,
+					TDG_VP_VMCALL_INSTRUCTION_IO_WRITE,
+					&data_64);
+}
diff --git a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
index 885c2b6bb1b96..b6072769967fa 100644
--- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
+++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
@@ -2,6 +2,7 @@

 #include <signal.h>
 #include "kvm_util_base.h"
+#include "processor.h"
 #include "tdx/tdcall.h"
 #include "tdx/tdx.h"
 #include "tdx/tdx_util.h"
@@ -154,6 +155,110 @@ 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)
+{
+	uint64_t err;
+	uint32_t ebx, ecx;
+
+	/* Read CPUID leaf 0x1 */
+	asm volatile (
+		"cpuid"
+		: "=b" (ebx), "=c" (ecx)
+		: "a" (0x1)
+		: "edx");
+
+	err = tdx_test_report_to_user_space(ebx);
+	if (err)
+		tdx_test_fatal(err);
+
+	err = tdx_test_report_to_user_space(ecx);
+	if (err)
+		tdx_test_fatal(err);
+
+	tdx_test_success();
+}
+
+void verify_td_cpuid(void)
+{
+	struct kvm_vm *vm;
+	struct kvm_vcpu *vcpu;
+
+	uint32_t ebx, ecx;
+	const struct kvm_cpuid_entry2 *cpuid_entry;
+	uint32_t guest_clflush_line_size;
+	uint32_t guest_max_addressable_ids, host_max_addressable_ids;
+	uint32_t guest_sse3_enabled;
+	uint32_t guest_fma_enabled;
+	uint32_t guest_initial_apic_id;
+
+	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 */
+	vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4,
+			TDG_VP_VMCALL_INSTRUCTION_IO_WRITE);
+	ebx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset);
+
+	/* Wait for guest to report either ecx value or error */
+	vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4,
+			TDG_VP_VMCALL_INSTRUCTION_IO_WRITE);
+	ecx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset);
+
+	/* Wait for guest to complete execution */
+	vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	TDX_TEST_ASSERT_SUCCESS(vcpu);
+
+	/* Verify the CPUID values we got from the guest. */
+	printf("\t ... Verifying CPUID values from guest\n");
+
+	/* Get KVM CPUIDs for reference */
+	cpuid_entry = kvm_get_supported_cpuid_entry(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
+
+	ASSERT_EQ(guest_sse3_enabled, 1);
+	ASSERT_EQ(guest_clflush_line_size, 8);
+	ASSERT_EQ(guest_max_addressable_ids, host_max_addressable_ids);
+
+	/* TODO: This only tests the native value. To properly test
+	 * "As Configured (if Native)" we need to override this value
+	 * in the TD params
+	 */
+	ASSERT_EQ(guest_fma_enabled, 1);
+
+	/* 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 we either need a TD with multiple VCPUs
+	 * or to pick a different calculated value.
+	 */
+	ASSERT_EQ(guest_initial_apic_id, 0);
+
+	kvm_vm_free(vm);
+	printf("\t ... PASSED\n");
+}
+
 int main(int argc, char **argv)
 {
 	setbuf(stdout, NULL);
@@ -166,6 +271,7 @@ int main(int argc, char **argv)
 	run_in_new_process(&verify_td_lifecycle);
 	run_in_new_process(&verify_report_fatal_error);
 	run_in_new_process(&verify_td_ioexit);
+	run_in_new_process(&verify_td_cpuid);

 	return 0;
 }
--
2.39.0.246.g2a6d74b583-goog

  parent reply	other threads:[~2023-01-21  0:18 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-21  0:15 [RFC PATCH v3 00/31] TDX KVM selftests Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 01/31] KVM: selftests: Add function to allow one-to-one GVA to GPA mappings Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 02/31] KVM: selftests: Add support for creating non-default type VMs Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 03/31] KVM: selftests: Expose function that sets up sregs based on VM's mode Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 04/31] KVM: selftests: Store initial stack address in struct kvm_vcpu Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 05/31] KVM: selftests: Refactor steps in vCPU descriptor table initialization Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 06/31] KVM: selftests: Add helper functions to create TDX VMs Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 07/31] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 08/31] KVM: selftests: Require GCC to realign stacks on function entry Ackerley Tng
2023-01-21  0:27   ` Sean Christopherson
2023-01-23 18:30     ` Erdem Aktas
2023-01-23 18:50       ` Maciej S. Szmigiero
2023-01-23 18:53         ` Sean Christopherson
2023-01-24  0:04           ` Erdem Aktas
2023-01-24  1:21             ` Sean Christopherson
2023-02-15  0:50               ` Ackerley Tng
2023-02-15 18:44                 ` Maciej S. Szmigiero
2023-02-15 22:19                   ` Sean Christopherson
2023-02-15 22:24                 ` Sean Christopherson
2023-02-17 18:57                   ` Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 09/31] KVM: selftests: TDX: Add TDX lifecycle test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 10/31] KVM: selftests: TDX: Add report_fatal_error test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 11/31] KVM: selftests: TDX: Adding test case for TDX port IO Ackerley Tng
2023-01-21  0:15 ` Ackerley Tng [this message]
2023-01-21  0:15 ` [RFC PATCH v3 13/31] KVM: selftests: TDX: Add basic get_td_vmcall_info test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 14/31] KVM: selftests: TDX: Add TDX IO writes test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 15/31] KVM: selftests: TDX: Add TDX IO reads test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 16/31] KVM: selftests: TDX: Add TDX MSR read/write tests Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 17/31] KVM: selftests: TDX: Add TDX HLT exit test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 18/31] KVM: selftests: TDX: Add TDX MMIO reads test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 19/31] KVM: selftests: TDX: Add TDX MMIO writes test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 20/31] KVM: selftests: TDX: Add TDX CPUID TDVMCALL test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 21/31] KVM: selftests: TDX: Verify the behavior when host consumes a TD private memory Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 22/31] KVM: selftests: TDX: Add TDG.VP.INFO test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 23/31] KVM: selftests: Add functions to allow mapping as shared Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 24/31] KVM: selftests: TDX: Add shared memory test Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 25/31] KVM: selftests: Add support for restricted memory Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 26/31] KVM: selftests: TDX: Update load_td_memory_region for VM memory backed by restricted memfd Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 27/31] KVM: selftests: Expose _vm_vaddr_alloc Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 28/31] KVM: selftests: TDX: Add support for TDG.MEM.PAGE.ACCEPT Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 29/31] KVM: selftests: TDX: Add support for TDG.VP.VEINFO.GET Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 30/31] KVM: selftests: TDX: Add TDX UPM selftest Ackerley Tng
2023-01-21  0:15 ` [RFC PATCH v3 31/31] KVM: selftests: TDX: Add TDX UPM selftests for implicit conversion Ackerley Tng

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=20230121001542.2472357-13-ackerleytng@google.com \
    --to=ackerleytng@google.com \
    --cc=aaronlewis@google.com \
    --cc=afranji@google.com \
    --cc=axelrasmussen@google.com \
    --cc=bgardon@google.com \
    --cc=borntraeger@de.ibm.com \
    --cc=dmatlack@google.com \
    --cc=drjones@redhat.com \
    --cc=eesposit@redhat.com \
    --cc=erdemaktas@google.com \
    --cc=eric.auger@redhat.com \
    --cc=isaku.yamahata@intel.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=like.xu@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=maciej.szmigiero@oracle.com \
    --cc=marcorr@google.com \
    --cc=maz@kernel.org \
    --cc=oupton@google.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=pgonda@google.com \
    --cc=pshier@google.com \
    --cc=ricarkol@google.com \
    --cc=runanwang@google.com \
    --cc=sagis@google.com \
    --cc=seanjc@google.com \
    --cc=shuah@kernel.org \
    --cc=vkuznets@redhat.com \
    --cc=wangyanan55@huawei.com \
    --cc=wei.w.wang@intel.com \
    --cc=xiaoyao.li@intel.com \
    --cc=yang.zhong@intel.com \
    --cc=zhenzhong.duan@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.