All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bandan Das <bsd@redhat.com>
To: kvm@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>
Subject: [kvm-unit-tests PATCH v2] vmx_tests: Add vmfunc tests
Date: Fri, 28 Jul 2017 15:59:12 -0400	[thread overview]
Message-ID: <jpg8tj82uzz.fsf@linux.bootlegged.copy> (raw)
In-Reply-To: <jpgr2xtkvjr.fsf@linux.bootlegged.copy> (Bandan Das's message of "Thu, 06 Jul 2017 19:14:16 -0400")


Besides for the obvious vmfunc call in L2 for eptp switching,
other tests are to check for valid error paths when L2 calls
vmfunc when L1 hasn't enabled it in the secondary controls,
L2 calls vmfunc with an invalid function number or calls it
with an invalid field from the eptp list

Signed-off-by: Bandan Das <bsd@redhat.com>
---
v2:
 Use eptp instead of pml4 in the eptp_list buffer because
 That would have the necessary bits set for eptp validity
 
 lib/x86/msr.h   |   1 +
 x86/vmx.h       |   8 +++-
 x86/vmx_tests.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+), 1 deletion(-)

diff --git a/lib/x86/msr.h b/lib/x86/msr.h
index 2c0598c..41f75d9 100644
--- a/lib/x86/msr.h
+++ b/lib/x86/msr.h
@@ -400,6 +400,7 @@
 #define MSR_IA32_VMX_TRUE_PROC		0x0000048e
 #define MSR_IA32_VMX_TRUE_EXIT		0x0000048f
 #define MSR_IA32_VMX_TRUE_ENTRY		0x00000490
+#define MSR_IA32_VMX_VMFUNC             0x00000491
 
 #define MSR_IA32_TSCDEADLINE		0x000006e0
 
diff --git a/x86/vmx.h b/x86/vmx.h
index d12b9de..b424674 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -138,11 +138,14 @@ enum Encoding {
 	TSC_OFFSET_HI		= 0x2011ul,
 	APIC_VIRT_ADDR		= 0x2012ul,
 	APIC_ACCS_ADDR		= 0x2014ul,
+	VMFUNC_CTRL             = 0x2018ul,
+	VMFUNC_CTRL_HI          = 0x2019ul,
 	EPTP			= 0x201aul,
 	EPTP_HI			= 0x201bul,
 	PMLADDR                 = 0x200eul,
 	PMLADDR_HI              = 0x200ful,
-
+	EPTP_LIST_ADDR          = 0x2024ul,
+	EPTP_LIST_ADDR_HI       = 0x2025ul,
 
 	/* 64-Bit Readonly Data Field */
 	INFO_PHYS_ADDR		= 0x2400ul,
@@ -394,6 +397,7 @@ enum Ctrl1 {
 	CPU_URG			= 1ul << 7,
 	CPU_WBINVD		= 1ul << 6,
 	CPU_RDRAND		= 1ul << 11,
+	CPU_VMFUNC              = 1ul << 13,
 	CPU_PML                 = 1ul << 17,
 };
 
@@ -405,6 +409,8 @@ enum Intr_type {
 	VMX_INTR_TYPE_SOFT_EXCEPTION = 6,
 };
 
+#define EPTP_SWITCHING 0x1
+
 /*
  * Interruption-information format
  */
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 2522d3a..c97aad4 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -29,6 +29,9 @@ void *data_page1, *data_page2;
 void *pml_log;
 #define PML_INDEX 512
 
+void *vpage, *hpage1, *hpage2;
+void *eptp_list;
+
 static inline unsigned ffs(unsigned x)
 {
 	int pos = -1;
@@ -1332,6 +1335,148 @@ static int eptad_init()
 	return r;
 }
 
+static int vmfunc_init()
+{
+	eptp_list = alloc_page();
+	u64 *buf = eptp_list;
+
+	vpage = alloc_page();
+	hpage1 = alloc_page();
+	hpage2 = alloc_page();
+
+	*((u32 *)vpage) = 0x1;
+	*((u32 *)hpage1) = 0x2;
+	*((u32 *)hpage2) = 0x3;
+
+	ept_init_common(false);
+	buf[0] = eptp;
+	install_ept(pml4, (unsigned long)hpage1, (unsigned long)vpage,
+		    EPT_RA | EPT_WA | EPT_EA);
+
+	ept_init_common(false);
+	buf[1] = eptp;
+	install_ept(pml4, (unsigned long)hpage2, (unsigned long)vpage,
+		    EPT_RA | EPT_WA | EPT_EA);
+
+	if (!(ctrl_cpu_rev[1].clr & CPU_VMFUNC)) {
+		printf("\tVMFUNC is not supported");
+		return VMX_TEST_EXIT;
+	}
+
+	return VMX_TEST_START;
+}
+
+static void vmfunc_ud_handler(struct ex_regs *regs)
+{
+	switch(vmx_get_test_stage()) {
+	case 0:
+	case 3:
+		regs->rip += 3;
+		vmx_inc_test_stage();
+		vmx_inc_test_stage();
+		break;
+	default:
+		printf("Unexpected #UD hit!\n");
+		print_vmexit_info();
+		exit(0);
+	}
+}
+
+static void vmfunc_main()
+{
+	int nr = 0, ept = 0;
+
+	handle_exception(UD_VECTOR, vmfunc_ud_handler);
+	vmx_set_test_stage(0);
+
+	/* Call vmfunc when L1 hasn't enabled it' */
+	asm volatile("vmfunc"
+		     :
+		     : "a"(nr), "c"(ept)
+		     : "memory");
+
+	report("VMFUNC - Disabled VMFUNC in sec controls causes #UD",
+	       vmx_get_test_stage() == 2);
+
+	vmcall();
+	/* function > 64 causes #UD */
+	nr = 64;
+	asm volatile("vmfunc"
+		     :
+		     : "a"(nr), "c"(ept)
+		     : "memory");
+	report("VMFUNC - guest call with EAX > 63 causes #UD",
+	       vmx_get_test_stage() == 5);
+
+	/* invalid vm function causes vmexit */
+	nr = 1;
+	asm volatile("vmfunc"
+		     :
+		     : "a"(nr), "c"(ept)
+		     : "memory");
+	report("VMFUNC - guest call with non-existant function",
+	       vmx_get_test_stage() == 6);
+
+	/* invalid entry from the eptp list causes vmexit */
+	nr = 0;
+	ept = 512;
+	asm volatile("vmfunc"
+		     :
+		     : "a"(nr), "c"(ept)
+		     : "memory");
+	report("VMFUNC - guest call with invalid entry in eptp list",
+	       vmx_get_test_stage() == 7);
+
+	/*
+	 * vpage points to hpage2 with value 0x3
+	 * vmfunc with ecx = 0 should make vpage
+	 * point to 0x2
+	 */
+	if (*((u32 *)vpage) != 0x3) {
+		printf("Guest address points to unexpected page\n");
+		exit(0);
+	}
+	ept = 0;
+	asm volatile("vmfunc"
+		     :
+		     : "a"(nr), "c"(ept)
+		     : "memory");
+	report("VMFUNC - call to switch ept pointer without an exit",
+	       (vmx_get_test_stage() == 7) && (*((u32 *)vpage) == 0x2));
+}
+
+static int vmfunc_exit_handler(void)
+{
+	ulong reason = vmcs_read(EXI_REASON) & 0xff;
+	u64 guest_rip = vmcs_read(GUEST_RIP);
+	u32 insn_len = vmcs_read(EXI_INST_LEN);
+	u32 ctrl_cpu;
+	u64 controls;
+
+	switch (reason) {
+	case VMX_VMCALL:
+		ctrl_cpu = vmcs_read(CPU_EXEC_CTRL1) | CPU_VMFUNC;
+		vmcs_write(CPU_EXEC_CTRL1, ctrl_cpu);
+
+		controls = rdmsr(MSR_IA32_VMX_VMFUNC) & 1;
+		if (!(controls & EPTP_SWITCHING)) {
+			printf("\tEPTP switching is not supported");
+			return VMX_TEST_EXIT;
+		}
+
+		vmcs_write(EPTP_LIST_ADDR, (u64)eptp_list);
+		vmcs_write(VMFUNC_CTRL, controls);
+	case VMX_VMFUNC:
+		vmx_inc_test_stage();
+		vmcs_write(GUEST_RIP, guest_rip + insn_len);
+		return VMX_TEST_RESUME;
+	default:
+		report("Unknown exit reason, %ld", false, reason);
+		print_vmexit_info();
+	}
+	return VMX_TEST_VMEXIT;
+}
+
 static int pml_init()
 {
 	u32 ctrl_cpu;
@@ -3173,6 +3318,7 @@ struct vmx_test vmx_tests[] = {
 		disable_rdtscp_exit_handler, NULL, {0} },
 	{ "int3", int3_init, int3_guest_main, int3_exit_handler, NULL, {0} },
 	{ "into", into_init, into_guest_main, into_exit_handler, NULL, {0} },
+	{ "vmfunc", vmfunc_init, vmfunc_main, vmfunc_exit_handler, NULL, {0} },
 	{ "exit_monitor_from_l2_test", NULL, exit_monitor_from_l2_main,
 		exit_monitor_from_l2_handler, NULL, {0} },
 	/* Basic V2 tests. */
-- 
2.9.4

      parent reply	other threads:[~2017-07-28 19:59 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-06 23:14 [kvm-unit-tests PATCH] vmx_tests: Add vmfunc tests Bandan Das
2017-07-07  8:46 ` Paolo Bonzini
2017-07-28 19:59 ` Bandan Das [this message]

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=jpg8tj82uzz.fsf@linux.bootlegged.copy \
    --to=bsd@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.