diff mbox series

[2/3,v2] nSVM: Test MBZ bits in nested CR3 (nCR3)

Message ID 20211209235334.85166-3-krish.sadhukhan@oracle.com (mailing list archive)
State New, archived
Headers show
Series KVM: nSVM: Test MBZ bits in nested CR3 (nCR3) | expand

Commit Message

Krish Sadhukhan Dec. 9, 2021, 11:53 p.m. UTC
According to section "Nested Paging and VMRUN/#VMEXIT" in APM vol 2, the
following guest state is illegal:

            "Any MBZ bit of nCR3 is set"

According to section "System-Control Registers" in APM vol 2,

    "All CR3 bits are writable, except for unimplemented physical
    address bits, which must be cleared to 0."

Therefore, test that any bit in nCR3 that is set beyond VCPU's implemented
physical bit width, results in VMEXIT_ERR.

Signed-off-by: Krish Sadhukhan <krish.sadhkhan@oracle.com>
---
 x86/svm_tests.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 8ad6122..4897a21 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -2183,7 +2183,10 @@  static void basic_guest_main(struct svm_test *test)
 			vmcb->save.cr0 = tmp;				\
 			break;						\
 		case 3:							\
-			vmcb->save.cr3 = tmp;				\
+			if (strcmp(test_name, "nested ") == 0)		\
+				vmcb->control.nested_cr3 = tmp;		\
+			else						\
+				vmcb->save.cr3 = tmp;			\
 			break;						\
 		case 4:							\
 			vmcb->save.cr4 = tmp;				\
@@ -2547,6 +2550,42 @@  static void guest_rflags_test_db_handler(struct ex_regs *r)
 	r->rflags &= ~X86_EFLAGS_TF;
 }
 
+static void test_ncr3(void)
+{
+	u64 ncr3_saved = vmcb->control.nested_cr3;
+	u64 nested_ctl_saved = vmcb->control.nested_ctl;
+	u64 ncr3_mbz_mask = GENMASK_ULL(63, cpuid_maxphyaddr());
+	u32 ret;
+
+	if (!npt_supported()) {
+		report_skip("NPT not supported");
+		return;
+	}
+
+	vmcb->control.nested_ctl = 0;
+	SVM_TEST_CR_RESERVED_BITS(0, 63, 1, 3, ncr3_saved, ncr3_mbz_mask,
+	    SVM_EXIT_VMMCALL, "nested ");
+
+	vmcb->control.nested_cr3 = ncr3_saved & ~ncr3_mbz_mask;
+	ret = svm_vmrun();
+	report (ret == SVM_EXIT_VMMCALL, "Test CR3 nested 63:0: %lx, wanted "
+	    "exit 0x%x, got 0x%x", ncr3_saved & ~ncr3_mbz_mask,
+	    SVM_EXIT_VMMCALL, ret);
+
+	vmcb->control.nested_ctl = 1;
+	SVM_TEST_CR_RESERVED_BITS(0, 63, 1, 3, ncr3_saved, ncr3_mbz_mask,
+	    SVM_EXIT_ERR, "nested ");
+
+	vmcb->control.nested_cr3 = ncr3_saved & ~ncr3_mbz_mask;
+	ret = svm_vmrun();
+	report (ret == SVM_EXIT_VMMCALL, "Test CR3 nested 63:0: %lx, wanted "
+	    "exit 0x%x, got 0x%x", ncr3_saved & ~ncr3_mbz_mask,
+	    SVM_EXIT_VMMCALL, ret);
+
+	vmcb->control.nested_cr3 = ncr3_saved;
+	vmcb->control.nested_ctl = nested_ctl_saved;
+}
+
 static void svm_guest_state_test(void)
 {
 	test_set_guest(basic_guest_main);
@@ -2557,6 +2596,7 @@  static void svm_guest_state_test(void)
 	test_dr();
 	test_msrpm_iopm_bitmap_addrs();
 	test_canonicalization();
+	test_ncr3();
 }
 
 extern void guest_rflags_test_guest(struct svm_test *test);