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 16/31] KVM: selftests: TDX: Add TDX MSR read/write tests
Date: Sat, 21 Jan 2023 00:15:27 +0000	[thread overview]
Message-ID: <20230121001542.2472357-17-ackerleytng@google.com> (raw)
In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com>

From: Sagi Shahar <sagis@google.com>

The test verifies reads and writes for MSR registers with different access
level.

Signed-off-by: Sagi Shahar <sagis@google.com>
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
Changes RFCv2 -> RFCv3
+ Fixed typo in MTTR->MTRR
---
 .../selftests/kvm/include/x86_64/tdx/tdx.h    |   4 +
 .../selftests/kvm/lib/x86_64/tdx/tdx.c        |  27 +++
 .../selftests/kvm/x86_64/tdx_vm_tests.c       | 217 ++++++++++++++++++
 3 files changed, 248 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
index 37ad16943e299..fbac1951cfe35 100644
--- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
+++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
@@ -8,11 +8,15 @@
 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003

 #define TDG_VP_VMCALL_INSTRUCTION_IO 30
+#define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31
+#define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32

 uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size,
 				      uint64_t write, uint64_t *data);
 void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_gpa);
 uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12,
 					uint64_t *r13, uint64_t *r14);
+uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_value);
+uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value);

 #endif // SELFTEST_TDX_TDX_H
diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
index 7254d61515db2..43088d6f40b50 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
@@ -66,3 +66,30 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12,

 	return ret;
 }
+
+uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_value)
+{
+	uint64_t ret;
+	struct tdx_hypercall_args args = {
+		.r11 = TDG_VP_VMCALL_INSTRUCTION_RDMSR,
+		.r12 = index,
+	};
+
+	ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT);
+
+	if (ret_value)
+		*ret_value = args.r11;
+
+	return ret;
+}
+
+uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value)
+{
+	struct tdx_hypercall_args args = {
+		.r11 = TDG_VP_VMCALL_INSTRUCTION_WRMSR,
+		.r12 = index,
+		.r13 = value,
+	};
+
+	return __tdx_hypercall(&args, 0);
+}
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 71aa4e5907a05..65ca1ec2a6e82 100644
--- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
+++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
@@ -514,6 +514,221 @@ void verify_guest_reads(void)
 	printf("\t ... PASSED\n");
 }

+/*
+ * 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 tdx_msr_test_allow_bits = 0xFFFFFFFFFFFFFFFF;
+#define MTTR_BASE_0 (0x200)
+#define MTTR_BASE_1 (0x202)
+#define MTTR_BASE_2 (0x204)
+struct kvm_msr_filter tdx_msr_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 *)&tdx_msr_test_allow_bits,
+		}, {
+			.flags = KVM_MSR_FILTER_READ,
+			.nmsrs = 1,
+			.base = MTTR_BASE_1,
+			.bitmap = (uint8_t *)&tdx_msr_test_allow_bits,
+		}, {
+			.flags = KVM_MSR_FILTER_WRITE,
+			.nmsrs = 1,
+			.base = MTTR_BASE_2,
+			.bitmap = (uint8_t *)&tdx_msr_test_allow_bits,
+		},
+	},
+};
+
+/*
+ * Verifies MSR read functionality.
+ */
+void guest_msr_read(void)
+{
+	uint64_t data;
+	uint64_t ret;
+
+	ret = tdg_vp_vmcall_instruction_rdmsr(MTTR_BASE_0, &data);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	ret = tdx_test_report_64bit_to_user_space(data);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	ret = tdg_vp_vmcall_instruction_rdmsr(MTTR_BASE_1, &data);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	ret = tdx_test_report_64bit_to_user_space(data);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	/* We expect this call to fail since MTTR_BASE_2 is write only */
+	ret = tdg_vp_vmcall_instruction_rdmsr(MTTR_BASE_2, &data);
+	if (ret) {
+		ret = tdx_test_report_64bit_to_user_space(ret);
+		if (ret)
+			tdx_test_fatal(ret);
+	} else {
+		tdx_test_fatal(-99);
+	}
+
+	tdx_test_success();
+}
+
+void verify_guest_msr_reads(void)
+{
+	struct kvm_vm *vm;
+	struct kvm_vcpu *vcpu;
+
+	uint64_t data;
+	int ret;
+
+	vm = td_create();
+	td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0);
+
+	/*
+	 * 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, &tdx_msr_test_filter);
+	TEST_ASSERT(ret == 0,
+		    "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)",
+		    ret, errno, strerror(errno));
+
+	vcpu = td_vcpu_add(vm, 0, guest_msr_read);
+	td_finalize(vm);
+
+	printf("Verifying guest msr reads:\n");
+
+	printf("\t ... Setting test MTTR values\n");
+	/* valid values for mtrr 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);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	data = tdx_test_read_64bit_report_from_guest(vcpu);
+	ASSERT_EQ(data, 4);
+
+	vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	data = tdx_test_read_64bit_report_from_guest(vcpu);
+	ASSERT_EQ(data, 5);
+
+	vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	data = tdx_test_read_64bit_report_from_guest(vcpu);
+	ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND);
+
+	vcpu_run(vcpu);
+	TDX_TEST_ASSERT_SUCCESS(vcpu);
+
+	kvm_vm_free(vm);
+	printf("\t ... PASSED\n");
+}
+
+/*
+ * Verifies MSR write functionality.
+ */
+void guest_msr_write(void)
+{
+	uint64_t ret;
+
+	ret = tdg_vp_vmcall_instruction_wrmsr(MTTR_BASE_0, 4);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	/* We expect this call to fail since MTTR_BASE_1 is read only */
+	ret = tdg_vp_vmcall_instruction_wrmsr(MTTR_BASE_1, 5);
+	if (ret) {
+		ret = tdx_test_report_64bit_to_user_space(ret);
+		if (ret)
+			tdx_test_fatal(ret);
+	} else {
+		tdx_test_fatal(-99);
+	}
+
+
+	ret = tdg_vp_vmcall_instruction_wrmsr(MTTR_BASE_2, 6);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	tdx_test_success();
+}
+
+void verify_guest_msr_writes(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+
+	uint64_t data;
+	int ret;
+
+	vm = td_create();
+	td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0);
+
+	/*
+	 * 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, &tdx_msr_test_filter);
+	TEST_ASSERT(ret == 0,
+		    "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)",
+		    ret, errno, strerror(errno));
+
+	vcpu = td_vcpu_add(vm, 0, guest_msr_write);
+	td_finalize(vm);
+
+	printf("Verifying guest msr writes:\n");
+
+	printf("\t ... Running guest\n");
+	/* Only the write to MTTR_BASE_1 should trigger an exit */
+	vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	data = tdx_test_read_64bit_report_from_guest(vcpu);
+	ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND);
+
+	vcpu_run(vcpu);
+	TDX_TEST_ASSERT_SUCCESS(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)
 {
 	setbuf(stdout, NULL);
@@ -530,6 +745,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_writes);
+	run_in_new_process(&verify_guest_msr_reads);

 	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 ` [RFC PATCH v3 12/31] KVM: selftests: TDX: Add basic TDX CPUID test Ackerley Tng
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 ` Ackerley Tng [this message]
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-17-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.