diff mbox series

[3/3,v3] nVMX: Test vmentry of unrestricted (unpaged protected) nested guest

Message ID 20200921081027.23047-4-krish.sadhukhan@oracle.com (mailing list archive)
State New, archived
Headers show
Series kvm-unit-test: nVMX: Test Selector and Base Address fields of Guest Segment registers | expand

Commit Message

Krish Sadhukhan Sept. 21, 2020, 8:10 a.m. UTC
According to section "UNRESTRICTED GUESTS" in SDM vol 3c, if the
"unrestricted guest" secondary VM-execution control is set, guests can run
in unpaged protected mode or in real mode. This patch tests vmetnry of an
unrestricted guest in unpaged protected mode.

Signed-off-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
---
 x86/vmx.c       |  2 +-
 x86/vmx.h       |  1 +
 x86/vmx_tests.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 1 deletion(-)

Comments

Sean Christopherson Sept. 29, 2020, 3:21 a.m. UTC | #1
On Mon, Sep 21, 2020 at 08:10:27AM +0000, Krish Sadhukhan wrote:
> According to section "UNRESTRICTED GUESTS" in SDM vol 3c, if the
> "unrestricted guest" secondary VM-execution control is set, guests can run
> in unpaged protected mode or in real mode. This patch tests vmetnry of an
> unrestricted guest in unpaged protected mode.
> 
> Signed-off-by: Jim Mattson <jmattson@google.com>
> Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>

SOB chain is wrong.  Missing a Co-developed-by?  Or is Jim supposed to be
the author?

> ---
>  x86/vmx.c       |  2 +-
>  x86/vmx.h       |  1 +
>  x86/vmx_tests.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/x86/vmx.c b/x86/vmx.c
> index 07415b4..1a84a74 100644
> --- a/x86/vmx.c
> +++ b/x86/vmx.c
> @@ -1699,7 +1699,7 @@ static void test_vmx_caps(void)
>  }
>  
>  /* This function can only be called in guest */
> -static void __attribute__((__used__)) hypercall(u32 hypercall_no)
> +void __attribute__((__used__)) hypercall(u32 hypercall_no)
>  {
>  	u64 val = 0;
>  	val = (hypercall_no & HYPERCALL_MASK) | HYPERCALL_BIT;
> diff --git a/x86/vmx.h b/x86/vmx.h
> index d1c2436..e29301e 100644
> --- a/x86/vmx.h
> +++ b/x86/vmx.h
> @@ -895,6 +895,7 @@ bool ept_ad_bits_supported(void);
>  void __enter_guest(u8 abort_flag, struct vmentry_result *result);
>  void enter_guest(void);
>  void enter_guest_with_bad_controls(void);
> +void hypercall(u32 hypercall_no);
>  
>  typedef void (*test_guest_func)(void);
>  typedef void (*test_teardown_func)(void *data);
> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
> index 22f0c7b..1cadc56 100644
> --- a/x86/vmx_tests.c
> +++ b/x86/vmx_tests.c
> @@ -8029,6 +8029,53 @@ static void vmx_guest_state_area_test(void)
>  	enter_guest();
>  }
>  
> +extern void unrestricted_guest_main(void);
> +asm (".code32\n"
> +	"unrestricted_guest_main:\n"
> +	"vmcall\n"
> +	"nop\n"
> +	"mov $1, %edi\n"
> +	"call hypercall\n"
> +	".code64\n");
> +
> +static void setup_unrestricted_guest(void)
> +{
> +	vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) & ~(X86_CR0_PG));
> +	vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) & ~ENT_GUEST_64);
> +	vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) & ~EFER_LMA);
> +	vmcs_write(GUEST_RIP, virt_to_phys(unrestricted_guest_main));
> +}
> +
> +static void unsetup_unrestricted_guest(void)
> +{
> +	vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) | X86_CR0_PG);
> +	vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) | ENT_GUEST_64);
> +	vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) | EFER_LMA);
> +	vmcs_write(GUEST_RIP, (u64) phys_to_virt(vmcs_read(GUEST_RIP)));
> +	vmcs_write(GUEST_RSP, (u64) phys_to_virt(vmcs_read(GUEST_RSP)));
> +}
> +
> +/*
> + * If "unrestricted guest" secondary VM-execution control is set, guests
> + * can run in unpaged protected mode.
> + */
> +static void vmentry_unrestricted_guest_test(void)
> +{
> +	test_set_guest(unrestricted_guest_main);
> +	setup_unrestricted_guest();
> +	if (setup_ept(false))
> +		test_skip("EPT not supported");
> +       vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | CPU_URG);
> +       test_guest_state("Unrestricted guest test", false, CPU_URG, "CPU_URG");

Indentation looks funky.

> +
> +	/*
> +	 * Let the guest finish execution as a regular guest
> +	 */
> +	unsetup_unrestricted_guest();
> +	vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) & ~CPU_URG);
> +	enter_guest();
> +}
> +
>  static bool valid_vmcs_for_vmentry(void)
>  {
>  	struct vmcs *current_vmcs = NULL;
> @@ -10234,6 +10281,7 @@ struct vmx_test vmx_tests[] = {
>  	TEST(vmx_host_state_area_test),
>  	TEST(vmx_guest_state_area_test),
>  	TEST(vmentry_movss_shadow_test),
> +	TEST(vmentry_unrestricted_guest_test),
>  	/* APICv tests */
>  	TEST(vmx_eoi_bitmap_ioapic_scan_test),
>  	TEST(vmx_hlt_with_rvi_test),
> -- 
> 2.18.4
>
diff mbox series

Patch

diff --git a/x86/vmx.c b/x86/vmx.c
index 07415b4..1a84a74 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -1699,7 +1699,7 @@  static void test_vmx_caps(void)
 }
 
 /* This function can only be called in guest */
-static void __attribute__((__used__)) hypercall(u32 hypercall_no)
+void __attribute__((__used__)) hypercall(u32 hypercall_no)
 {
 	u64 val = 0;
 	val = (hypercall_no & HYPERCALL_MASK) | HYPERCALL_BIT;
diff --git a/x86/vmx.h b/x86/vmx.h
index d1c2436..e29301e 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -895,6 +895,7 @@  bool ept_ad_bits_supported(void);
 void __enter_guest(u8 abort_flag, struct vmentry_result *result);
 void enter_guest(void);
 void enter_guest_with_bad_controls(void);
+void hypercall(u32 hypercall_no);
 
 typedef void (*test_guest_func)(void);
 typedef void (*test_teardown_func)(void *data);
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 22f0c7b..1cadc56 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -8029,6 +8029,53 @@  static void vmx_guest_state_area_test(void)
 	enter_guest();
 }
 
+extern void unrestricted_guest_main(void);
+asm (".code32\n"
+	"unrestricted_guest_main:\n"
+	"vmcall\n"
+	"nop\n"
+	"mov $1, %edi\n"
+	"call hypercall\n"
+	".code64\n");
+
+static void setup_unrestricted_guest(void)
+{
+	vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) & ~(X86_CR0_PG));
+	vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) & ~ENT_GUEST_64);
+	vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) & ~EFER_LMA);
+	vmcs_write(GUEST_RIP, virt_to_phys(unrestricted_guest_main));
+}
+
+static void unsetup_unrestricted_guest(void)
+{
+	vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) | X86_CR0_PG);
+	vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) | ENT_GUEST_64);
+	vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) | EFER_LMA);
+	vmcs_write(GUEST_RIP, (u64) phys_to_virt(vmcs_read(GUEST_RIP)));
+	vmcs_write(GUEST_RSP, (u64) phys_to_virt(vmcs_read(GUEST_RSP)));
+}
+
+/*
+ * If "unrestricted guest" secondary VM-execution control is set, guests
+ * can run in unpaged protected mode.
+ */
+static void vmentry_unrestricted_guest_test(void)
+{
+	test_set_guest(unrestricted_guest_main);
+	setup_unrestricted_guest();
+	if (setup_ept(false))
+		test_skip("EPT not supported");
+       vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | CPU_URG);
+       test_guest_state("Unrestricted guest test", false, CPU_URG, "CPU_URG");
+
+	/*
+	 * Let the guest finish execution as a regular guest
+	 */
+	unsetup_unrestricted_guest();
+	vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) & ~CPU_URG);
+	enter_guest();
+}
+
 static bool valid_vmcs_for_vmentry(void)
 {
 	struct vmcs *current_vmcs = NULL;
@@ -10234,6 +10281,7 @@  struct vmx_test vmx_tests[] = {
 	TEST(vmx_host_state_area_test),
 	TEST(vmx_guest_state_area_test),
 	TEST(vmentry_movss_shadow_test),
+	TEST(vmentry_unrestricted_guest_test),
 	/* APICv tests */
 	TEST(vmx_eoi_bitmap_ioapic_scan_test),
 	TEST(vmx_hlt_with_rvi_test),