mbox series

[RFC,v2,00/17] TDX KVM selftests

Message ID 20220830222000.709028-1-sagis@google.com (mailing list archive)
Headers show
Series TDX KVM selftests | expand

Message

Sagi Shahar Aug. 30, 2022, 10:19 p.m. UTC
Hello,

This is v2 of the patch series for TDX selftests.

It is based on v5.19-rc8 and Intel's V8 of the TDX host patches which
was proposed in https://lkml.org/lkml/2022/8/8/877

The tree can be found at
https://github.com/googleprodkernel/linux-cc/tree/selftests

Major changes vrom v1:
- rebased to v5.19
- added helpers for success and failure reporting
- added additional test cases

---
TDX stands for Trust Domain Extensions which isolates VMs from the
virtual-machine manager (VMM)/hypervisor and any other software on the
platform.

Intel has recently submitted a set of RFC patches for KVM support for
TDX and more information can be found on the latest TDX Support
Patches: https://lkml.org/lkml/2022/8/8/877

Due to the nature of the confidential computing environment that TDX
provides, it is very difficult to verify/test the KVM support. TDX
requires UEFI and the guest kernel to be enlightened which are all under
development.

We are working on a set of selftests to close this gap and be able to
verify the KVM functionality to support TDX lifecycle and GHCI [1]
interface.

We are looking for any feedback on:
- Patch series itself
- Any suggestion on how we should approach testing TDX functionality.
Does selftests seems reasonable or should we switch to using KVM
unit tests. I would be happy to get some perspective on how KVM unit
tests can help us more.
- Any test case or scenario that we should add.
- Anything else I have not thought of yet.

Current patch series provide the following capabilities:

- Provide helper functions to create a TD (Trusted Domain) using the KVM
  ioctls
- Provide helper functions to create a guest image that can include any
  testing code
- Provide helper functions and wrapper functions to write testing code
  using GHCI interface
- Add a test case that verifies TDX life cycle
- Add a test case that verifies TDX GHCI port IO

TODOs:
- Use existing function to create page tables dynamically
  (ie __virt_pg_map())
- Remove arbitrary defined magic numbers for data structure offsets
- Add TDVMCALL for error reporting
- Add additional test cases as some listed below
- Add #VE handlers to help testing more complicated test cases

---
Erdem Aktas (4):
  KVM: selftests: Add support for creating non-default type VMs
  KVM: selftest: Add helper functions to create TDX VMs
  KVM: selftest: Adding TDX life cycle test.
  KVM: selftest: Adding test case for TDX port IO

Roger Wang (1):
  KVM: selftest: TDX: Add TDG.VP.INFO test

Ryan Afranji (2):
  KVM: selftest: TDX: Verify the behavior when host consumes a TD
    private memory
  KVM: selftest: TDX: Add shared memory test

Sagi Shahar (10):
  KVM: selftest: TDX: Add report_fatal_error test
  KVM: selftest: TDX: Add basic TDX CPUID test
  KVM: selftest: TDX: Add basic get_td_vmcall_info test
  KVM: selftest: TDX: Add TDX IO writes test
  KVM: selftest: TDX: Add TDX IO reads test
  KVM: selftest: TDX: Add TDX MSR read/write tests
  KVM: selftest: TDX: Add TDX HLT exit test
  KVM: selftest: TDX: Add TDX MMIO reads test
  KVM: selftest: TDX: Add TDX MMIO writes test
  KVM: selftest: TDX: Add TDX CPUID TDVMCALL test

 tools/testing/selftests/kvm/Makefile          |    2 +
 .../selftests/kvm/include/kvm_util_base.h     |   12 +-
 .../selftests/kvm/include/x86_64/processor.h  |    1 +
 tools/testing/selftests/kvm/lib/kvm_util.c    |    6 +-
 .../selftests/kvm/lib/x86_64/processor.c      |   27 +
 tools/testing/selftests/kvm/lib/x86_64/tdx.h  |  495 +++++
 .../selftests/kvm/lib/x86_64/tdx_lib.c        |  373 ++++
 .../selftests/kvm/x86_64/tdx_vm_tests.c       | 1666 +++++++++++++++++
 8 files changed, 2577 insertions(+), 5 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx.h
 create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c
 create mode 100644 tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c

Comments

Isaku Yamahata Sept. 1, 2022, 1:28 a.m. UTC | #1
Here is one more test to exercise KVM_TDX_CAPABILITIES on top of this patch
series.

From f9c4c9013040ce7dee84e1d3370875e5158900bf Mon Sep 17 00:00:00 2001
Message-Id: <f9c4c9013040ce7dee84e1d3370875e5158900bf.1661995648.git.isaku.yamahata@intel.com>
In-Reply-To: <6ce32225079b83991b9f170730a8810005a079b0.1661995647.git.isaku.yamahata@intel.com>
References: <6ce32225079b83991b9f170730a8810005a079b0.1661995647.git.isaku.yamahata@intel.com>
From: Isaku Yamahata <isaku.yamahata@intel.com>
Date: Wed, 16 Mar 2022 09:15:40 -0700
Subject: [PATCH] KVM: selftest: tdx: call KVM_TDX_CAPABILITIES for
 test

Add exercise of KVM_TDX_CAPABILITIES.  The result isn't used.

Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
---
 tools/testing/selftests/kvm/lib/x86_64/tdx.h  |  1 +
 .../selftests/kvm/lib/x86_64/tdx_lib.c        | 52 +++++++++++++++++--
 .../selftests/kvm/x86_64/tdx_vm_tests.c       |  3 ++
 3 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx.h b/tools/testing/selftests/kvm/lib/x86_64/tdx.h
index be8564f4672d..bfa3709a76e5 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx.h
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx.h
@@ -119,6 +119,7 @@ struct page_table {
 void add_td_memory(struct kvm_vm *vm, void *source_page,
 		   uint64_t gpa, int size);
 void finalize_td_memory(struct kvm_vm *vm);
+void get_tdx_capabilities(struct kvm_vm *vm);
 void initialize_td(struct kvm_vm *vm);
 void initialize_td_with_attributes(struct kvm_vm *vm, uint64_t attributes);
 void initialize_td_vcpu(struct kvm_vcpu *vcpu);
diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c b/tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c
index 23893949c3a1..b07af314737a 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c
@@ -27,10 +27,9 @@ char *tdx_cmd_str[] = {
 #define XFEATURE_MASK_XTILE	(XFEATURE_MASK_XTILECFG | XFEATURE_MASK_XTILEDATA)
 
 
-static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data)
+static int __tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data)
 {
 	struct kvm_tdx_cmd tdx_cmd;
-	int r;
 
 	TEST_ASSERT(ioctl_no < TDX_MAX_CMD_STR, "Unknown TDX CMD : %d\n",
 		    ioctl_no);
@@ -39,7 +38,15 @@ static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data)
 	tdx_cmd.id = ioctl_no;
 	tdx_cmd.flags = flags;
 	tdx_cmd.data = (uint64_t)data;
-	r = ioctl(fd, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd);
+	return ioctl(fd, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd);
+}
+
+
+static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data)
+{
+	int r;
+
+	r = __tdx_ioctl(fd, ioctl_no, flags, data);
 	TEST_ASSERT(r == 0, "%s failed: %d  %d", tdx_cmd_str[ioctl_no], r,
 		    errno);
 }
@@ -77,6 +84,45 @@ static struct tdx_cpuid_data get_tdx_cpuid_data(struct kvm_vm *vm)
 	return cpuid_data;
 }
 
+/* Call KVM_TDX_CAPABILITIES for API test. The result isn't used. */
+void get_tdx_capabilities(struct kvm_vm *vm)
+{
+	int i;
+	int rc;
+	int nr_cpuid_configs = 8;
+	struct kvm_tdx_capabilities *tdx_cap = NULL;
+
+	while (true) {
+		tdx_cap = realloc(
+			tdx_cap, sizeof(*tdx_cap) +
+			nr_cpuid_configs * sizeof(*tdx_cap->cpuid_configs));
+		tdx_cap->nr_cpuid_configs = nr_cpuid_configs;
+		TEST_ASSERT(tdx_cap != NULL,
+			"Could not allocate memory for tdx capability "
+			"nr_cpuid_configs %d\n", nr_cpuid_configs);
+		rc = __tdx_ioctl(vm->fd, KVM_TDX_CAPABILITIES, 0, tdx_cap);
+		if (rc < 0 && errno == E2BIG) {
+			nr_cpuid_configs *= 2;
+			continue;
+		}
+		TEST_ASSERT(rc == 0, "%s failed: %d %d",
+			tdx_cmd_str[KVM_TDX_CAPABILITIES], rc, errno);
+		break;
+	}
+	pr_debug("tdx_cap: attrs: fixed0 0x%016llx fixed1 0x%016llx\n"
+		"tdx_cap: xfam fixed0 0x%016llx fixed1 0x%016llx\n",
+		tdx_cap->attrs_fixed0, tdx_cap->attrs_fixed1,
+		tdx_cap->xfam_fixed0, tdx_cap->xfam_fixed1);
+	for (i = 0; i < tdx_cap->nr_cpuid_configs; i++) {
+		const struct kvm_tdx_cpuid_config *config =
+			&tdx_cap->cpuid_configs[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->leaf, config->sub_leaf,
+			config->eax, config->ebx, config->ecx, config->edx);
+	}
+}
+
 /*
  * Initialize a VM as a TD with attributes.
  *
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 a96abada54b6..b3f9e3fa41f4 100644
--- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
+++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
@@ -197,6 +197,9 @@ void verify_td_lifecycle(void)
 	/* Create a TD VM with no memory.*/
 	vm = vm_create_tdx();
 
+	/* Get TDX capabilities */
+	get_tdx_capabilities(vm);
+
 	/* Allocate TD guest memory and initialize the TD.*/
 	initialize_td(vm);