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
next prev 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 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.