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 10/17] KVM: selftest: TDX: Add TDX MSR read/write tests
Date: Tue, 30 Aug 2022 22:19:53 +0000 [thread overview]
Message-ID: <20220830222000.709028-11-sagis@google.com> (raw)
In-Reply-To: <20220830222000.709028-1-sagis@google.com>
The test verifies reads and writes for MSR registers with different access
level.
Signed-off-by: Sagi Shahar <sagis@google.com>
---
tools/testing/selftests/kvm/lib/x86_64/tdx.h | 34 +++
.../selftests/kvm/x86_64/tdx_vm_tests.c | 229 ++++++++++++++++++
2 files changed, 263 insertions(+)
diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx.h b/tools/testing/selftests/kvm/lib/x86_64/tdx.h
index f1f44c2ad40e..263834979727 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx.h
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx.h
@@ -57,6 +57,8 @@
#define TDX_GET_TD_VM_CALL_INFO 0x10000
#define TDX_REPORT_FATAL_ERROR 0x10003
#define TDX_INSTRUCTION_IO 30
+#define TDX_INSTRUCTION_RDMSR 31
+#define TDX_INSTRUCTION_WRMSR 32
#define TDX_SUCCESS_PORT 0x30
#define TDX_TEST_PORT 0x31
@@ -258,6 +260,38 @@ static inline uint64_t tdvmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12,
return regs.r10;
}
+/*
+ * Read MSR register.
+ */
+static inline uint64_t tdvmcall_rdmsr(uint64_t index, uint64_t *ret_value)
+{
+ struct kvm_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+ regs.r11 = TDX_INSTRUCTION_RDMSR;
+ regs.r12 = index;
+ regs.rcx = 0x1C00;
+ tdcall(®s);
+ *ret_value = regs.r11;
+ return regs.r10;
+}
+
+/*
+ * Write MSR register.
+ */
+static inline uint64_t tdvmcall_wrmsr(uint64_t index, uint64_t value)
+{
+ struct kvm_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+ regs.r11 = TDX_INSTRUCTION_WRMSR;
+ regs.r12 = index;
+ regs.r13 = value;
+ regs.rcx = 0x3C00;
+ tdcall(®s);
+ return regs.r10;
+}
+
/*
* 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/x86_64/tdx_vm_tests.c b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
index 85b5ab99424e..fb3b8de7e5cd 100644
--- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
+++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
@@ -55,6 +55,40 @@
(VCPU)->run->system_event.data[1]); \
} while (0)
+
+/*
+ * Define a filter which denies all MSR access except the following:
+ * MTTR_BASE_0: Allow read/write access
+ * MTTR_BASE_1: Allow read access
+ * MTTR_BASE_2: Allow write access
+ */
+static u64 allow_bits = 0xFFFFFFFFFFFFFFFF;
+#define MTTR_BASE_0 (0x200)
+#define MTTR_BASE_1 (0x202)
+#define MTTR_BASE_2 (0x204)
+struct kvm_msr_filter test_filter = {
+ .flags = KVM_MSR_FILTER_DEFAULT_DENY,
+ .ranges = {
+ {
+ .flags = KVM_MSR_FILTER_READ |
+ KVM_MSR_FILTER_WRITE,
+ .nmsrs = 1,
+ .base = MTTR_BASE_0,
+ .bitmap = (uint8_t *)&allow_bits,
+ }, {
+ .flags = KVM_MSR_FILTER_READ,
+ .nmsrs = 1,
+ .base = MTTR_BASE_1,
+ .bitmap = (uint8_t *)&allow_bits,
+ }, {
+ .flags = KVM_MSR_FILTER_WRITE,
+ .nmsrs = 1,
+ .base = MTTR_BASE_2,
+ .bitmap = (uint8_t *)&allow_bits,
+ },
+ },
+};
+
static uint64_t read_64bit_from_guest(struct kvm_vcpu *vcpu, uint64_t port)
{
uint32_t lo, hi;
@@ -656,6 +690,199 @@ void verify_guest_reads(void)
printf("\t ... PASSED\n");
}
+/*
+ * Verifies MSR read functionality.
+ */
+TDX_GUEST_FUNCTION(guest_msr_read)
+{
+ uint64_t data;
+ uint64_t ret;
+
+ ret = tdvmcall_rdmsr(MTTR_BASE_0, &data);
+ if (ret)
+ tdvmcall_fatal(ret);
+
+ ret = tdvm_report_64bit_to_user_space(data);
+ if (ret)
+ tdvmcall_fatal(ret);
+
+ ret = tdvmcall_rdmsr(MTTR_BASE_1, &data);
+ if (ret)
+ tdvmcall_fatal(ret);
+
+ ret = tdvm_report_64bit_to_user_space(data);
+ if (ret)
+ tdvmcall_fatal(ret);
+
+ /* We expect this call to fail since MTTR_BASE_2 is write only */
+ ret = tdvmcall_rdmsr(MTTR_BASE_2, &data);
+ if (ret) {
+ ret = tdvm_report_64bit_to_user_space(ret);
+ if (ret)
+ tdvmcall_fatal(ret);
+ } else {
+ tdvmcall_fatal(-99);
+ }
+
+ tdvmcall_success();
+}
+
+void verify_guest_msr_reads(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ uint64_t data;
+ int ret;
+
+ printf("Verifying guest msr reads:\n");
+
+ /* Create a TD VM with no memory.*/
+ vm = vm_create_tdx();
+
+ /* Set explicit MSR filter map to control access to the MSR registers
+ * used in the test.
+ */
+ printf("\t ... Setting test MSR filter\n");
+ ret = kvm_check_cap(KVM_CAP_X86_USER_SPACE_MSR);
+ TEST_ASSERT(ret, "KVM_CAP_X86_USER_SPACE_MSR is unavailable");
+ vm_enable_cap(vm, KVM_CAP_X86_USER_SPACE_MSR, KVM_MSR_EXIT_REASON_FILTER);
+
+ ret = kvm_check_cap(KVM_CAP_X86_MSR_FILTER);
+ TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable");
+
+ ret = ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &test_filter);
+ TEST_ASSERT(ret == 0,
+ "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)",
+ ret, errno, strerror(errno));
+
+ /* Allocate TD guest memory and initialize the TD.*/
+ initialize_td(vm);
+
+ /* Initialize the TD vcpu and copy the test code to the guest memory.*/
+ vcpu = vm_vcpu_add_tdx(vm, 0);
+
+ /* Setup and initialize VM memory */
+ prepare_source_image(vm, guest_msr_read,
+ TDX_FUNCTION_SIZE(guest_msr_read), 0);
+ finalize_td_memory(vm);
+
+ printf("\t ... Setting test MTTR values\n");
+ /* valid values for mttr type are 0, 1, 4, 5, 6 */
+ vcpu_set_msr(vcpu, MTTR_BASE_0, 4);
+ vcpu_set_msr(vcpu, MTTR_BASE_1, 5);
+ vcpu_set_msr(vcpu, MTTR_BASE_2, 6);
+
+ printf("\t ... Running guest\n");
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ data = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+ ASSERT_EQ(data, 4);
+
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ data = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+ ASSERT_EQ(data, 5);
+
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ data = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+ ASSERT_EQ(data, TDX_VMCALL_INVALID_OPERAND);
+
+ vcpu_run(vcpu);
+ CHECK_GUEST_COMPLETION(vcpu);
+
+ kvm_vm_free(vm);
+ printf("\t ... PASSED\n");
+}
+
+/*
+ * Verifies MSR write functionality.
+ */
+TDX_GUEST_FUNCTION(guest_msr_write)
+{
+ uint64_t ret;
+
+ ret = tdvmcall_wrmsr(MTTR_BASE_0, 4);
+ if (ret)
+ tdvmcall_fatal(ret);
+
+ /* We expect this call to fail since MTTR_BASE_1 is read only */
+ ret = tdvmcall_wrmsr(MTTR_BASE_1, 5);
+ if (ret) {
+ ret = tdvm_report_64bit_to_user_space(ret);
+ if (ret)
+ tdvmcall_fatal(ret);
+ } else {
+ tdvmcall_fatal(-99);
+ }
+
+
+ ret = tdvmcall_wrmsr(MTTR_BASE_2, 6);
+ if (ret)
+ tdvmcall_fatal(ret);
+
+ tdvmcall_success();
+}
+
+void verify_guest_msr_writes(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ uint64_t data;
+ int ret;
+
+ printf("Verifying guest msr writes:\n");
+
+ /* Create a TD VM with no memory.*/
+ vm = vm_create_tdx();
+
+ /* Set explicit MSR filter map to control access to the MSR registers
+ * used in the test.
+ */
+ printf("\t ... Setting test MSR filter\n");
+ ret = kvm_check_cap(KVM_CAP_X86_USER_SPACE_MSR);
+ TEST_ASSERT(ret, "KVM_CAP_X86_USER_SPACE_MSR is unavailable");
+ vm_enable_cap(vm, KVM_CAP_X86_USER_SPACE_MSR, KVM_MSR_EXIT_REASON_FILTER);
+
+ ret = kvm_check_cap(KVM_CAP_X86_MSR_FILTER);
+ TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable");
+
+ ret = ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &test_filter);
+ TEST_ASSERT(ret == 0,
+ "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)",
+ ret, errno, strerror(errno));
+
+ /* Allocate TD guest memory and initialize the TD.*/
+ initialize_td(vm);
+
+ /* Initialize the TD vcpu and copy the test code to the guest memory.*/
+ vcpu = vm_vcpu_add_tdx(vm, 0);
+
+ /* Setup and initialize VM memory */
+ prepare_source_image(vm, guest_msr_write,
+ TDX_FUNCTION_SIZE(guest_msr_write), 0);
+ finalize_td_memory(vm);
+
+ printf("\t ... Running guest\n");
+ /* Only the write to MTTR_BASE_1 should trigger an exit */
+ vcpu_run(vcpu);
+ CHECK_GUEST_FAILURE(vcpu);
+ data = read_64bit_from_guest(vcpu, TDX_DATA_REPORT_PORT);
+ ASSERT_EQ(data, TDX_VMCALL_INVALID_OPERAND);
+
+ vcpu_run(vcpu);
+ CHECK_GUEST_COMPLETION(vcpu);
+
+ printf("\t ... Verifying MTTR values writen by guest\n");
+
+ ASSERT_EQ(vcpu_get_msr(vcpu, MTTR_BASE_0), 4);
+ ASSERT_EQ(vcpu_get_msr(vcpu, MTTR_BASE_1), 0);
+ ASSERT_EQ(vcpu_get_msr(vcpu, MTTR_BASE_2), 6);
+
+ kvm_vm_free(vm);
+ printf("\t ... PASSED\n");
+}
+
int main(int argc, char **argv)
{
if (!is_tdx_enabled()) {
@@ -670,6 +897,8 @@ int main(int argc, char **argv)
run_in_new_process(&verify_get_td_vmcall_info);
run_in_new_process(&verify_guest_writes);
run_in_new_process(&verify_guest_reads);
+ run_in_new_process(&verify_guest_msr_reads);
+ run_in_new_process(&verify_guest_msr_writes);
return 0;
}
--
2.37.2.789.g6183377224-goog
next prev parent reply other threads:[~2022-08-30 22:21 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 ` Sagi Shahar [this message]
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 ` [RFC PATCH v2 16/17] KVM: selftest: TDX: Add TDG.VP.INFO test Sagi Shahar
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-11-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.