public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Maxim Levitsky <mlevitsk@redhat.com>
To: kvm@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Maxim Levitsky <mlevitsk@redhat.com>
Subject: [kvm-unit-tests PATCH 5/5] nVMX: add a test for canonical checks of various host state vmcs12 fields.
Date: Fri,  6 Sep 2024 20:54:40 -0400	[thread overview]
Message-ID: <20240907005440.500075-6-mlevitsk@redhat.com> (raw)
In-Reply-To: <20240907005440.500075-1-mlevitsk@redhat.com>

This test tests canonical VM entry checks of various host state fields
(mostly segment bases) in vmcs12.

Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 x86/vmx_tests.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 183 insertions(+)

diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index ffe7064c9..b6f3d634d 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -10732,6 +10732,7 @@ static void handle_exception_in_l1(u32 vector)
 	vmcs_write(EXC_BITMAP, old_eb);
 }
 
+
 static void vmx_exception_test(void)
 {
 	struct vmx_exception_test *t;
@@ -10754,6 +10755,187 @@ static void vmx_exception_test(void)
 	test_set_guest_finished();
 }
 
+
+#define TEST_VALUE1  0xff45454545000000
+#define TEST_VALUE2  0xff55555555000000
+
+static void vmx_canonical_test_guest(void)
+{
+	while (true)
+		vmcall();
+}
+
+static int get_host_value(u64 vmcs_field, u64 *value)
+{
+	struct descriptor_table_ptr dt_ptr;
+
+	switch (vmcs_field) {
+	case HOST_SYSENTER_ESP:
+		*value = rdmsr(MSR_IA32_SYSENTER_ESP);
+		break;
+	case HOST_SYSENTER_EIP:
+		*value =  rdmsr(MSR_IA32_SYSENTER_EIP);
+		break;
+	case HOST_BASE_FS:
+		*value =  rdmsr(MSR_FS_BASE);
+		break;
+	case HOST_BASE_GS:
+		*value =  rdmsr(MSR_GS_BASE);
+		break;
+	case HOST_BASE_GDTR:
+		sgdt(&dt_ptr);
+		*value =  dt_ptr.base;
+		break;
+	case HOST_BASE_IDTR:
+		sidt(&dt_ptr);
+		*value =  dt_ptr.base;
+		break;
+	case HOST_BASE_TR:
+		*value = get_gdt_entry_base(get_tss_descr());
+		/* value might not reflect the actual base if changed by VMX */
+		return 1;
+	default:
+		assert(0);
+	}
+	return 0;
+}
+
+static int set_host_value(u64 vmcs_field, u64 value)
+{
+	struct descriptor_table_ptr dt_ptr;
+
+	switch (vmcs_field) {
+	case HOST_SYSENTER_ESP:
+		return wrmsr_safe(MSR_IA32_SYSENTER_ESP, value);
+	case HOST_SYSENTER_EIP:
+		return wrmsr_safe(MSR_IA32_SYSENTER_EIP, value);
+	case HOST_BASE_FS:
+		return wrmsr_safe(MSR_FS_BASE, value);
+	case HOST_BASE_GS:
+		/* TODO: _safe variants assume per-cpu gs base*/
+		wrmsr(MSR_GS_BASE, value);
+		return 0;
+	case HOST_BASE_GDTR:
+		sgdt(&dt_ptr);
+		dt_ptr.base = value;
+		lgdt(&dt_ptr);
+		return lgdt_fep_safe(&dt_ptr);
+	case HOST_BASE_IDTR:
+		sidt(&dt_ptr);
+		dt_ptr.base = value;
+		return lidt_fep_safe(&dt_ptr);
+	case HOST_BASE_TR:
+		/* Set the base and clear the busy bit */
+		set_gdt_entry(FIRST_SPARE_SEL, value, 0x200, 0x89, 0);
+		return ltr_safe(FIRST_SPARE_SEL);
+	default:
+		assert(0);
+	}
+}
+
+static void test_host_value_natively(const char *field_name, u64 vmcs_field, u64 value)
+{
+	int vector;
+	u64 actual_value;
+
+	/*
+	 * Set the register via host native interface (e.g lgdt) and check
+	 * that we got no exception
+	 */
+	vector = set_host_value(vmcs_field, value);
+	if (vector) {
+		report(false,
+		       "Exception %d when setting %s to 0x%lx via host",
+		       vector, field_name, value);
+		return;
+	}
+
+	/*
+	 * Now check that the host value matches what we expect for fields
+	 * that can be read back (these that we can't we assume that are correct)
+	 */
+
+	if (get_host_value(vmcs_field, &actual_value))
+		actual_value = value;
+
+	report(actual_value == value,
+	       "%s: HOST value is set to test value 0x%lx directly",
+	       field_name, value);
+}
+
+static void test_host_value_via_guest(const char *field_name, u64 vmcs_field, u64 value)
+{
+	u64 actual_value;
+
+	/* Set host state field in the vmcs and do the VM entry
+	 * Success of VM entry already shows that L0 accepted the value
+	 */
+	vmcs_write(vmcs_field, TEST_VALUE2);
+	enter_guest();
+	skip_exit_vmcall();
+
+	/*
+	 * Now check that the host value matches what we expect for fields
+	 * that can be read back (these that we can't we assume that are correct)
+	 */
+
+	if (get_host_value(vmcs_field, &actual_value))
+		actual_value = value;
+
+	/* Check that now the msr value is the same as the field value */
+	report(actual_value == TEST_VALUE2,
+	       "%s: HOST value is set to test value 0x%lx via VMLAUNCH/VMRESUME",
+	       field_name, value);
+}
+
+static void do_vmx_canonical_test_one_field(const char *field_name, u64 field)
+{
+	u64 host_org_value, field_org_value;
+
+	/* Backup the current host value and vmcs field value values */
+	get_host_value(field, &host_org_value);
+	field_org_value = vmcs_read(field);
+
+	/*
+	 * Write TEST_VALUE1 57-canonical value on the host
+	 * and check that it was written correctly
+	 */
+	test_host_value_natively(field_name, field, TEST_VALUE1);
+
+	/*
+	 * Write TEST_VALUE2 57-canonical value on the host
+	 * via VM entry/exit and check that it was written correctly
+	 */
+	test_host_value_via_guest(field_name, field, TEST_VALUE2);
+
+	/* Restore original values */
+	vmcs_write(field, field_org_value);
+	set_host_value(field, host_org_value);
+}
+
+#define vmx_canonical_test_one_field(field) \
+	do_vmx_canonical_test_one_field(#field, field)
+
+static void vmx_canonical_test(void)
+{
+	report(!(read_cr4() & X86_CR4_LA57), "4 level paging");
+
+	if (!this_cpu_has(X86_FEATURE_LA57))
+		test_skip("5 level paging not supported");
+
+	test_set_guest(vmx_canonical_test_guest);
+
+	vmx_canonical_test_one_field(HOST_SYSENTER_ESP);
+	vmx_canonical_test_one_field(HOST_SYSENTER_EIP);
+	vmx_canonical_test_one_field(HOST_BASE_FS);
+	vmx_canonical_test_one_field(HOST_BASE_GS);
+	vmx_canonical_test_one_field(HOST_BASE_GDTR);
+	vmx_canonical_test_one_field(HOST_BASE_IDTR);
+	vmx_canonical_test_one_field(HOST_BASE_TR);
+
+	test_set_guest_finished();
+}
+
 enum Vid_op {
 	VID_OP_SET_ISR,
 	VID_OP_NOP,
@@ -11262,5 +11444,6 @@ struct vmx_test vmx_tests[] = {
 	TEST(vmx_pf_invvpid_test),
 	TEST(vmx_pf_vpid_test),
 	TEST(vmx_exception_test),
+	TEST(vmx_canonical_test),
 	{ NULL, NULL, NULL, NULL, NULL, {0} },
 };
-- 
2.26.3


  parent reply	other threads:[~2024-09-07  0:54 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-07  0:54 [kvm-unit-tests PATCH 0/5] Collection of tests for canonical checks on LA57 enabled CPUs Maxim Levitsky
2024-09-07  0:54 ` [kvm-unit-tests PATCH 1/5] x86: add _safe and _fep_safe variants to segment base load instructions Maxim Levitsky
2024-09-07  0:54 ` [kvm-unit-tests PATCH 2/5] x86: add a few functions for gdt manipulation Maxim Levitsky
2024-09-07  0:54 ` [kvm-unit-tests PATCH 3/5] x86: move struct invpcid_desc descriptor to processor.h Maxim Levitsky
2024-09-07  0:54 ` [kvm-unit-tests PATCH 4/5] Add a test for writing canonical values to various msrs and fields Maxim Levitsky
2025-02-14 22:00   ` Sean Christopherson
2024-09-07  0:54 ` Maxim Levitsky [this message]
2025-02-14 22:08   ` [kvm-unit-tests PATCH 5/5] nVMX: add a test for canonical checks of various host state vmcs12 fields Sean Christopherson
2024-11-03 21:08 ` [kvm-unit-tests PATCH 0/5] Collection of tests for canonical checks on LA57 enabled CPUs Maxim Levitsky
2024-11-22  1:31   ` Maxim Levitsky
2024-12-14  0:19     ` Maxim Levitsky
2025-02-14 21:25 ` Sean Christopherson
2025-02-24 17:23 ` Sean Christopherson

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=20240907005440.500075-6-mlevitsk@redhat.com \
    --to=mlevitsk@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox