From: Sagi Shahar <sagis@google.com>
To: linux-kselftest@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Isaku Yamahata <isaku.yamahata@intel.com>,
Sagi Shahar <sagis@google.com>,
Erdem Aktas <erdemaktas@google.com>,
Ryan Afranji <afranji@google.com>,
Roger Wang <runanwang@google.com>, Shuah Khan <shuah@kernel.org>,
Andrew Jones <drjones@redhat.com>, Marc Zyngier <maz@kernel.org>,
Ben Gardon <bgardon@google.com>,
Jim Mattson <jmattson@google.com>,
David Matlack <dmatlack@google.com>, Peter Xu <peterx@redhat.com>,
Oliver Upton <oupton@google.com>,
Ricardo Koller <ricarkol@google.com>,
Yang Zhong <yang.zhong@intel.com>,
Wei Wang <wei.w.wang@intel.com>,
Xiaoyao Li <xiaoyao.li@intel.com>,
Peter Gonda <pgonda@google.com>, Marc Orr <marcorr@google.com>,
Emanuele Giuseppe Esposito <eesposit@redhat.com>,
Christian Borntraeger <borntraeger@de.ibm.com>,
Eric Auger <eric.auger@redhat.com>,
Yanan Wang <wangyanan55@huawei.com>,
Aaron Lewis <aaronlewis@google.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>,
Peter Shier <pshier@google.com>,
Axel Rasmussen <axelrasmussen@google.com>,
Zhenzhong Duan <zhenzhong.duan@intel.com>,
"Maciej S . Szmigiero" <maciej.szmigiero@oracle.com>,
Like Xu <like.xu@linux.intel.com>,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Subject: [RFC PATCH v2 16/17] KVM: selftest: TDX: Add TDG.VP.INFO test
Date: Tue, 30 Aug 2022 22:19:59 +0000 [thread overview]
Message-ID: <20220830222000.709028-17-sagis@google.com> (raw)
In-Reply-To: <20220830222000.709028-1-sagis@google.com>
From: Roger Wang <runanwang@google.com>
Adds a test for TDG.VP.INFO
Signed-off-by: Roger Wang <runanwang@google.com>
Signed-off-by: Sagi Shahar <sagis@google.com>
---
tools/testing/selftests/kvm/lib/x86_64/tdx.h | 103 ++++++++----
.../selftests/kvm/lib/x86_64/tdx_lib.c | 18 ++-
.../selftests/kvm/x86_64/tdx_vm_tests.c | 150 ++++++++++++++++++
3 files changed, 235 insertions(+), 36 deletions(-)
diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx.h b/tools/testing/selftests/kvm/lib/x86_64/tdx.h
index 3729543a05a3..7af2d189043f 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx.h
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx.h
@@ -10,6 +10,11 @@
*/
#define TDX_GUEST_MAX_NR_PAGES 10000
+/*
+ * Max number of vCPUs for the guest VM
+ */
+ #define TDX_GUEST_MAX_NUM_VCPUS 3
+
/*
* Page Table Address used when paging is enabled.
*/
@@ -71,6 +76,11 @@
#define TDX_MMIO_READ 0
#define TDX_MMIO_WRITE 1
+#define TDX_TDCALL_INFO 1
+
+#define TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT (1UL << 28)
+#define TDX_TDPARAM_ATTR_PKS_BIT (1UL << 30)
+
#define GDT_ENTRY(flags, base, limit) \
((((base) & 0xff000000ULL) << (56-24)) | \
(((flags) & 0x0000f0ffULL) << 40) | \
@@ -98,6 +108,7 @@ 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 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);
void prepare_source_image(struct kvm_vm *vm, void *guest_code,
size_t guest_code_size,
@@ -116,40 +127,41 @@ void prepare_source_image(struct kvm_vm *vm, void *guest_code,
static inline void tdcall(struct kvm_regs *regs)
{
asm volatile (
- "mov %13, %%rax;\n\t"
- "mov %14, %%rbx;\n\t"
- "mov %15, %%rcx;\n\t"
- "mov %16, %%rdx;\n\t"
- "mov %17, %%r8;\n\t"
- "mov %18, %%r9;\n\t"
- "mov %19, %%r10;\n\t"
- "mov %20, %%r11;\n\t"
- "mov %21, %%r12;\n\t"
- "mov %22, %%r13;\n\t"
- "mov %23, %%r14;\n\t"
- "mov %24, %%r15;\n\t"
- "mov %25, %%rbp;\n\t"
- "mov %26, %%rsi;\n\t"
- "mov %27, %%rdi;\n\t"
+ "mov %14, %%rax;\n\t"
+ "mov %15, %%rbx;\n\t"
+ "mov %16, %%rcx;\n\t"
+ "mov %17, %%rdx;\n\t"
+ "mov %18, %%r8;\n\t"
+ "mov %19, %%r9;\n\t"
+ "mov %20, %%r10;\n\t"
+ "mov %21, %%r11;\n\t"
+ "mov %22, %%r12;\n\t"
+ "mov %23, %%r13;\n\t"
+ "mov %24, %%r14;\n\t"
+ "mov %25, %%r15;\n\t"
+ "mov %26, %%rbp;\n\t"
+ "mov %27, %%rsi;\n\t"
+ "mov %28, %%rdi;\n\t"
".byte 0x66, 0x0F, 0x01, 0xCC;\n\t"
"mov %%rax, %0;\n\t"
"mov %%rbx, %1;\n\t"
- "mov %%rdx, %2;\n\t"
- "mov %%r8, %3;\n\t"
- "mov %%r9, %4;\n\t"
- "mov %%r10, %5;\n\t"
- "mov %%r11, %6;\n\t"
- "mov %%r12, %7;\n\t"
- "mov %%r13, %8;\n\t"
- "mov %%r14, %9;\n\t"
- "mov %%r15, %10;\n\t"
- "mov %%rsi, %11;\n\t"
- "mov %%rdi, %12;\n\t"
- : "=m" (regs->rax), "=m" (regs->rbx), "=m" (regs->rdx),
- "=m" (regs->r8), "=m" (regs->r9), "=m" (regs->r10),
- "=m" (regs->r11), "=m" (regs->r12), "=m" (regs->r13),
- "=m" (regs->r14), "=m" (regs->r15), "=m" (regs->rsi),
- "=m" (regs->rdi)
+ "mov %%rcx, %2;\n\t"
+ "mov %%rdx, %3;\n\t"
+ "mov %%r8, %4;\n\t"
+ "mov %%r9, %5;\n\t"
+ "mov %%r10, %6;\n\t"
+ "mov %%r11, %7;\n\t"
+ "mov %%r12, %8;\n\t"
+ "mov %%r13, %9;\n\t"
+ "mov %%r14, %10;\n\t"
+ "mov %%r15, %11;\n\t"
+ "mov %%rsi, %12;\n\t"
+ "mov %%rdi, %13;\n\t"
+ : "=m" (regs->rax), "=m" (regs->rbx), "=m" (regs->rcx),
+ "=m" (regs->rdx), "=m" (regs->r8), "=m" (regs->r9),
+ "=m" (regs->r10), "=m" (regs->r11), "=m" (regs->r12),
+ "=m" (regs->r13), "=m" (regs->r14), "=m" (regs->r15),
+ "=m" (regs->rsi), "=m" (regs->rdi)
: "m" (regs->rax), "m" (regs->rbx), "m" (regs->rcx),
"m" (regs->rdx), "m" (regs->r8), "m" (regs->r9),
"m" (regs->r10), "m" (regs->r11), "m" (regs->r12),
@@ -370,6 +382,35 @@ static inline uint64_t tdvmcall_cpuid(uint32_t eax, uint32_t ecx,
return regs.r10;
}
+/*
+ * Execute TDG.VP.INFO instruction.
+ */
+static inline uint64_t tdcall_vp_info(uint64_t *rcx, uint64_t *rdx,
+ uint64_t *r8, uint64_t *r9,
+ uint64_t *r10, uint64_t *r11)
+{
+ struct kvm_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+ regs.rax = TDX_TDCALL_INFO;
+ tdcall(®s);
+
+ if (rcx)
+ *rcx = regs.rcx;
+ if (rdx)
+ *rdx = regs.rdx;
+ if (r8)
+ *r8 = regs.r8;
+ if (r9)
+ *r9 = regs.r9;
+ if (r10)
+ *r10 = regs.r10;
+ if (r11)
+ *r11 = regs.r11;
+
+ return regs.rax;
+}
+
/*
* Reports a 32 bit value from the guest to user space using a TDVM IO call.
* Data is reported on port TDX_DATA_REPORT_PORT.
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 72bf2ff24a29..dc9a44ae4064 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx_lib.c
@@ -78,10 +78,10 @@ static struct tdx_cpuid_data get_tdx_cpuid_data(struct kvm_vm *vm)
}
/*
- * Initialize a VM as a TD.
+ * Initialize a VM as a TD with attributes.
*
*/
-void initialize_td(struct kvm_vm *vm)
+void initialize_td_with_attributes(struct kvm_vm *vm, uint64_t attributes)
{
struct tdx_cpuid_data cpuid_data;
int rc;
@@ -99,7 +99,7 @@ void initialize_td(struct kvm_vm *vm)
KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK);
vm_enable_cap(vm, KVM_CAP_SPLIT_IRQCHIP, 24);
- /* Allocate and setup memoryfor the td guest. */
+ /* Allocate and setup memory for the td guest. */
vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
TDX_GUEST_PT_FIXED_ADDR,
0, TDX_GUEST_MAX_NR_PAGES, 0);
@@ -108,12 +108,20 @@ void initialize_td(struct kvm_vm *vm)
cpuid_data = get_tdx_cpuid_data(vm);
- init_vm.max_vcpus = 1;
- init_vm.attributes = 0;
+ init_vm.max_vcpus = TDX_GUEST_MAX_NUM_VCPUS;
+ init_vm.attributes = attributes;
memcpy(&init_vm.cpuid, &cpuid_data, sizeof(cpuid_data));
tdx_ioctl(vm->fd, KVM_TDX_INIT_VM, 0, &init_vm);
}
+/*
+ * Initialize a VM as a TD with no attributes.
+ *
+ */
+void initialize_td(struct kvm_vm *vm)
+{
+ initialize_td_with_attributes(vm, 0);
+}
void initialize_td_vcpu(struct kvm_vcpu *vcpu)
{
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 1776b39b7d9e..8d49099e1ed8 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 "asm/kvm.h"
#include "linux/kernel.h"
+#include <assert.h>
#include <bits/stdint-uintn.h>
#include <fcntl.h>
#include <limits.h>
@@ -1366,6 +1367,154 @@ void verify_host_reading_private_mem(void)
printf("\t ... PASSED\n");
}
+/*
+ * Do a TDG.VP.INFO call from the guest
+ */
+TDX_GUEST_FUNCTION(guest_tdcall_vp_info)
+{
+ uint64_t err;
+ uint64_t rcx, rdx, r8, r9, r10, r11;
+
+ err = tdcall_vp_info(&rcx, &rdx, &r8, &r9, &r10, &r11);
+ if (err)
+ tdvmcall_fatal(err);
+
+ /* return values to user space host */
+ err = tdvm_report_64bit_to_user_space(rcx);
+ if (err)
+ tdvmcall_fatal(err);
+
+ err = tdvm_report_64bit_to_user_space(rdx);
+ if (err)
+ tdvmcall_fatal(err);
+
+ err = tdvm_report_64bit_to_user_space(r8);
+ if (err)
+ tdvmcall_fatal(err);
+
+ err = tdvm_report_64bit_to_user_space(r9);
+ if (err)
+ tdvmcall_fatal(err);
+
+ err = tdvm_report_64bit_to_user_space(r10);
+ if (err)
+ tdvmcall_fatal(err);
+
+ err = tdvm_report_64bit_to_user_space(r11);
+ if (err)
+ tdvmcall_fatal(err);
+
+ tdvmcall_success();
+}
+
+/*
+ * TDG.VP.INFO call from the guest. Verify the right values are returned
+ */
+void verify_tdcall_vp_info(void)
+{
+ const int num_vcpus = 2;
+ struct kvm_vcpu *vcpus[num_vcpus];
+ struct kvm_vm *vm;
+ uint64_t rcx, rdx, r8, r9, r10, r11;
+ uint32_t ret_num_vcpus, ret_max_vcpus;
+ uint64_t attributes;
+ uint32_t i;
+ struct kvm_cpuid_entry2 *cpuid_entry;
+ struct tdx_cpuid_data cpuid_data;
+ int max_pa = -1;
+ int ret;
+
+ printf("Verifying TDG.VP.INFO call:\n");
+ /* Create a TD VM with no memory.*/
+ vm = vm_create_tdx();
+
+ /* Setting attributes parameter used by TDH.MNG.INIT to 0x50000000 */
+ attributes = TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT |
+ TDX_TDPARAM_ATTR_PKS_BIT;
+
+ /* Allocate TD guest memory and initialize the TD.*/
+ initialize_td_with_attributes(vm, attributes);
+
+ /* Create vCPUs*/
+ for (i = 0; i < num_vcpus; i++)
+ vcpus[i] = vm_vcpu_add_tdx(vm, i);
+
+ /* Setup and initialize VM memory */
+ prepare_source_image(vm, guest_tdcall_vp_info,
+ TDX_FUNCTION_SIZE(guest_tdcall_vp_info), 0);
+ finalize_td_memory(vm);
+
+ /* Get KVM CPUIDs for reference */
+ memset(&cpuid_data, 0, sizeof(cpuid_data));
+ cpuid_data.cpuid.nent = KVM_MAX_CPUID_ENTRIES;
+ ret = ioctl(vm->kvm_fd, KVM_GET_SUPPORTED_CPUID, &cpuid_data);
+ TEST_ASSERT(!ret, "KVM_GET_SUPPORTED_CPUID failed\n");
+ cpuid_entry = find_cpuid_entry(cpuid_data, 0x80000008, 0);
+ TEST_ASSERT(cpuid_entry, "CPUID entry missing\n");
+ max_pa = cpuid_entry->eax & 0xff;
+
+ for (i = 0; i < num_vcpus; i++) {
+ struct kvm_vcpu *vcpu = vcpus[i];
+
+ /* Wait for guest to report rcx value */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ rcx = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+
+ /* Wait for guest to report rdx value */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ rdx = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+
+ /* Wait for guest to report r8 value */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ r8 = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+
+ /* Wait for guest to report r9 value */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ r9 = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+
+ /* Wait for guest to report r10 value */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ r10 = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+
+ /* Wait for guest to report r11 value */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ r11 = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+
+ ret_num_vcpus = r8 & 0xFFFFFFFF;
+ ret_max_vcpus = (r8 >> 32) & 0xFFFFFFFF;
+
+ /* first bits 5:0 of rcx represent the GPAW */
+ ASSERT_EQ(rcx & 0x3F, max_pa);
+ /* next 63:6 bits of rcx is reserved and must be 0 */
+ ASSERT_EQ(rcx >> 6, 0);
+ ASSERT_EQ(rdx, attributes);
+ ASSERT_EQ(ret_num_vcpus, num_vcpus);
+ ASSERT_EQ(ret_max_vcpus, TDX_GUEST_MAX_NUM_VCPUS);
+ /* VCPU_INDEX = i */
+ ASSERT_EQ(r9, i);
+ /* verify reserved registers are 0 */
+ ASSERT_EQ(r10, 0);
+ ASSERT_EQ(r11, 0);
+
+ /* Wait for guest to complete execution */
+ vcpu_run(vcpu);
+
+ CHECK_GUEST_FAILURE(vcpu);
+ CHECK_GUEST_COMPLETION(vcpu);
+
+ printf("\t ... Guest completed run on VCPU=%u\n", i);
+ }
+
+ kvm_vm_free(vm);
+ printf("\t ... PASSED\n");
+}
+
int main(int argc, char **argv)
{
if (!is_tdx_enabled()) {
@@ -1387,6 +1536,7 @@ int main(int argc, char **argv)
run_in_new_process(&verify_mmio_reads);
run_in_new_process(&verify_mmio_writes);
run_in_new_process(&verify_host_reading_private_mem);
+ run_in_new_process(&verify_tdcall_vp_info);
return 0;
}
--
2.37.2.789.g6183377224-goog
next prev parent reply other threads:[~2022-08-30 22:22 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-30 22:19 [RFC PATCH v2 00/17] TDX KVM selftests Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 01/17] KVM: selftests: Add support for creating non-default type VMs Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 02/17] KVM: selftest: Add helper functions to create TDX VMs Sagi Shahar
2022-09-01 1:20 ` Isaku Yamahata
2022-09-01 1:22 ` Isaku Yamahata
2022-08-30 22:19 ` [RFC PATCH v2 03/17] KVM: selftest: Adding TDX life cycle test Sagi Shahar
2022-09-01 0:46 ` Isaku Yamahata
2022-09-01 14:37 ` Sean Christopherson
2022-08-30 22:19 ` [RFC PATCH v2 04/17] KVM: selftest: TDX: Add report_fatal_error test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 05/17] KVM: selftest: Adding test case for TDX port IO Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 06/17] KVM: selftest: TDX: Add basic TDX CPUID test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 07/17] KVM: selftest: TDX: Add basic get_td_vmcall_info test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 08/17] KVM: selftest: TDX: Add TDX IO writes test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 09/17] KVM: selftest: TDX: Add TDX IO reads test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 10/17] KVM: selftest: TDX: Add TDX MSR read/write tests Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 11/17] KVM: selftest: TDX: Add TDX HLT exit test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 12/17] KVM: selftest: TDX: Add TDX MMIO reads test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 13/17] KVM: selftest: TDX: Add TDX MMIO writes test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 14/17] KVM: selftest: TDX: Add TDX CPUID TDVMCALL test Sagi Shahar
2022-08-30 22:19 ` [RFC PATCH v2 15/17] KVM: selftest: TDX: Verify the behavior when host consumes a TD private memory Sagi Shahar
2022-08-30 22:19 ` Sagi Shahar [this message]
2022-08-30 22:20 ` [RFC PATCH v2 17/17] KVM: selftest: TDX: Add shared memory test Sagi Shahar
2022-09-01 1:28 ` [RFC PATCH v2 00/17] TDX KVM selftests Isaku Yamahata
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=20220830222000.709028-17-sagis@google.com \
--to=sagis@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=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.