All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ryan Afranji <afranji@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, 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, ackerleytng@google.com
Subject: [PATCH v4 15/28] KVM: selftests: TDX: Add TDX MSR read/write tests
Date: Tue, 25 Jul 2023 22:01:08 +0000	[thread overview]
Message-ID: <20230725220132.2310657-16-afranji@google.com> (raw)
In-Reply-To: <20230725220132.2310657-1-afranji@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>
Change-Id: Idb98e4e9ae64f31ab99b80d2e0e01252316d256a
Signed-off-by: Ryan Afranji <afranji@google.com>
---
 .../selftests/kvm/include/x86_64/tdx/tdx.h    |   5 +
 .../selftests/kvm/lib/x86_64/tdx/tdx.c        |  27 +++
 .../selftests/kvm/x86_64/tdx_vm_tests.c       | 209 ++++++++++++++++++
 3 files changed, 241 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 63788012bf94..85ba6aab79a7 100644
--- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
+++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
@@ -9,11 +9,16 @@
 #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
+
 void handle_userspace_tdg_vp_vmcall_exit(struct kvm_vcpu *vcpu);
 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 e5a9e13c62e2..88ea6f2a6469 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
@@ -87,3 +87,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 9ac0b793f8c5..41dad6cf249b 100644
--- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
+++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
@@ -515,6 +515,213 @@ void verify_guest_reads(void)
 	printf("\t ... PASSED\n");
 }
 
+/*
+ * Define a filter which denies all MSR access except the following:
+ * MSR_X2APIC_APIC_ICR: Allow read/write access (allowed by default)
+ * MSR_IA32_MISC_ENABLE: Allow read access
+ * MSR_IA32_POWER_CTL: Allow write access
+ */
+#define MSR_X2APIC_APIC_ICR 0x830
+static u64 tdx_msr_test_allow_bits = 0xFFFFFFFFFFFFFFFF;
+struct kvm_msr_filter tdx_msr_test_filter = {
+	.flags = KVM_MSR_FILTER_DEFAULT_DENY,
+	.ranges = {
+		{
+			.flags = KVM_MSR_FILTER_READ,
+			.nmsrs = 1,
+			.base = MSR_IA32_MISC_ENABLE,
+			.bitmap = (uint8_t *)&tdx_msr_test_allow_bits,
+		}, {
+			.flags = KVM_MSR_FILTER_WRITE,
+			.nmsrs = 1,
+			.base = MSR_IA32_POWER_CTL,
+			.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(MSR_X2APIC_APIC_ICR, &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(MSR_IA32_MISC_ENABLE, &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 MSR_IA32_POWER_CTL is write only */
+	ret = tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_POWER_CTL, &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 MSR values\n");
+	/* Write arbitrary to the MSRs. */
+	vcpu_set_msr(vcpu, MSR_X2APIC_APIC_ICR, 4);
+	vcpu_set_msr(vcpu, MSR_IA32_MISC_ENABLE, 5);
+	vcpu_set_msr(vcpu, MSR_IA32_POWER_CTL, 6);
+
+	printf("\t ... Running guest\n");
+	td_vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	data = tdx_test_read_64bit_report_from_guest(vcpu);
+	ASSERT_EQ(data, 4);
+
+	td_vcpu_run(vcpu);
+	TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
+	data = tdx_test_read_64bit_report_from_guest(vcpu);
+	ASSERT_EQ(data, 5);
+
+	td_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);
+
+	td_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(MSR_X2APIC_APIC_ICR, 4);
+	if (ret)
+		tdx_test_fatal(ret);
+
+	/* We expect this call to fail since MSR_IA32_MISC_ENABLE is read only */
+	ret = tdg_vp_vmcall_instruction_wrmsr(MSR_IA32_MISC_ENABLE, 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(MSR_IA32_POWER_CTL, 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 MSR_IA32_MISC_ENABLE should trigger an exit */
+	td_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);
+
+	td_vcpu_run(vcpu);
+	TDX_TEST_ASSERT_SUCCESS(vcpu);
+
+	printf("\t ... Verifying MSR values writen by guest\n");
+
+	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_X2APIC_APIC_ICR), 4);
+	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_MISC_ENABLE), 0x1800);
+	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_POWER_CTL), 6);
+
+	kvm_vm_free(vm);
+	printf("\t ... PASSED\n");
+}
+
+
 int main(int argc, char **argv)
 {
 	setbuf(stdout, NULL);
@@ -531,6 +738,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.41.0.487.g6d72f3e995-goog


  parent reply	other threads:[~2023-07-25 22:04 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-25 22:00 [PATCH v4 00/28] TDX KVM selftests Ryan Afranji
2023-07-25 22:00 ` [PATCH v4 01/28] KVM: selftests: Add function to allow one-to-one GVA to GPA mappings Ryan Afranji
2023-07-25 22:00 ` [PATCH v4 02/28] KVM: selftests: Expose function that sets up sregs based on VM's mode Ryan Afranji
2023-07-25 22:00 ` [PATCH v4 03/28] KVM: selftests: Store initial stack address in struct kvm_vcpu Ryan Afranji
2023-07-25 22:00 ` [PATCH v4 04/28] KVM: selftests: Refactor steps in vCPU descriptor table initialization Ryan Afranji
2023-07-25 22:00 ` [PATCH v4 05/28] KVM: selftests: Add helper functions to create TDX VMs Ryan Afranji
2023-07-25 22:00 ` [PATCH v4 06/28] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 07/28] KVM: selftests: TDX: Update load_td_memory_region for VM memory backed by guest memfd Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 08/28] KVM: selftests: TDX: Add TDX lifecycle test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 09/28] KVM: selftests: TDX: Add report_fatal_error test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 10/28] KVM: selftests: TDX: Adding test case for TDX port IO Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 11/28] KVM: selftests: TDX: Add basic TDX CPUID test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 12/28] KVM: selftests: TDX: Add basic get_td_vmcall_info test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 13/28] KVM: selftests: TDX: Add TDX IO writes test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 14/28] KVM: selftests: TDX: Add TDX IO reads test Ryan Afranji
2023-07-25 22:01 ` Ryan Afranji [this message]
2023-07-25 22:01 ` [PATCH v4 16/28] KVM: selftests: TDX: Add TDX HLT exit test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 17/28] KVM: selftests: TDX: Add TDX MMIO reads test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 18/28] KVM: selftests: TDX: Add TDX MMIO writes test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 19/28] KVM: selftests: TDX: Add TDX CPUID TDVMCALL test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 20/28] KVM: selftests: TDX: Verify the behavior when host consumes a TD private memory Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 21/28] KVM: selftests: TDX: Add TDG.VP.INFO test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 22/28] KVM: selftests: Add functions to allow mapping as shared Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 23/28] KVM: selftests: TDX: Add shared memory test Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 24/28] KVM: selftests: Expose _vm_vaddr_alloc Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 25/28] KVM: selftests: TDX: Add support for TDG.MEM.PAGE.ACCEPT Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 26/28] KVM: selftests: TDX: Add support for TDG.VP.VEINFO.GET Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 27/28] KVM: selftests: TDX: Add TDX UPM selftest Ryan Afranji
2023-07-25 22:01 ` [PATCH v4 28/28] KVM: selftests: TDX: Add TDX UPM selftests for implicit conversion Ryan Afranji
2023-07-26 18:55 ` [PATCH v4 00/28] 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=20230725220132.2310657-16-afranji@google.com \
    --to=afranji@google.com \
    --cc=aaronlewis@google.com \
    --cc=ackerleytng@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=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.