kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add a reproducer for the AMD nested virtualization errata
@ 2021-01-14 12:21 Maxim Levitsky
  2021-01-18 17:14 ` Paolo Bonzini
  0 siblings, 1 reply; 2+ messages in thread
From: Maxim Levitsky @ 2021-01-14 12:21 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Wei Huang, Bandan Das, Maxim Levitsky

While this test doesn't test every case of this errata, it should
reproduce it on all systems where the errata is known to exist.

Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 x86/svm_tests.c   | 68 +++++++++++++++++++++++++++++++++++++++++++++++
 x86/unittests.cfg |  2 +-
 2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index dc86efd..0c75400 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -2315,6 +2315,73 @@ static void svm_guest_state_test(void)
 	test_dr();
 }
 
+
+static bool volatile svm_errata_reproduced = false;
+static unsigned long volatile physical = 0;
+
+
+/*
+ *
+ * Test the following errata:
+ * If the VMRUN/VMSAVE/VMLOAD are attempted by the nested guest,
+ * the CPU would first check the EAX against host reserved memory
+ * regions (so far only SMM_ADDR/SMM_MASK are known to cause it),
+ * and only then signal #VMexit
+ *
+ * Try to reproduce this by trying vmsave on each possible 4K aligned memory
+ * address in the low 4G where the SMM area has to reside.
+ */
+
+static void gp_isr(struct ex_regs *r)
+{
+    svm_errata_reproduced = true;
+    /* skip over the vmsave instruction*/
+    r->rip += 3;
+}
+
+static void svm_vmrun_errata_test(void)
+{
+    unsigned long *last_page = NULL;
+
+    handle_exception(GP_VECTOR, gp_isr);
+
+    while (!svm_errata_reproduced) {
+
+        unsigned long *page = alloc_pages(1);
+
+        if (!page) {
+            report(true, "All guest memory tested, no bug found");;
+            break;
+        }
+
+        physical = virt_to_phys(page);
+
+        asm volatile (
+            "mov %[_physical], %%rax\n\t"
+            "vmsave\n\t"
+
+            : [_physical] "=m" (physical)
+            : /* no inputs*/
+            : "rax" /*clobbers*/
+        );
+
+        if (svm_errata_reproduced) {
+            report(false, "Got #GP exception - svm errata reproduced at 0x%lx",
+                   physical);
+            break;
+        }
+
+        *page = (unsigned long)last_page;
+        last_page = page;
+    }
+
+    while (last_page) {
+        unsigned long *page = last_page;
+        last_page = (unsigned long *)*last_page;
+        free_pages_by_order(page, 1);
+    }
+}
+
 struct svm_test svm_tests[] = {
     { "null", default_supported, default_prepare,
       default_prepare_gif_clear, null_test,
@@ -2427,5 +2494,6 @@ struct svm_test svm_tests[] = {
       init_intercept_finished, init_intercept_check, .on_vcpu = 2 },
     TEST(svm_cr4_osxsave_test),
     TEST(svm_guest_state_test),
+    TEST(svm_vmrun_errata_test),
     { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index b48c98b..f4ea370 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -213,7 +213,7 @@ arch = x86_64
 [svm]
 file = svm.flat
 smp = 2
-extra_params = -cpu host,+svm
+extra_params = -cpu host,+svm -m 4g
 arch = x86_64
 
 [taskswitch]
-- 
2.26.2


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Add a reproducer for the AMD nested virtualization errata
  2021-01-14 12:21 [PATCH] Add a reproducer for the AMD nested virtualization errata Maxim Levitsky
@ 2021-01-18 17:14 ` Paolo Bonzini
  0 siblings, 0 replies; 2+ messages in thread
From: Paolo Bonzini @ 2021-01-18 17:14 UTC (permalink / raw)
  To: Maxim Levitsky, kvm; +Cc: Wei Huang, Bandan Das

On 14/01/21 13:21, Maxim Levitsky wrote:
> While this test doesn't test every case of this errata, it should
> reproduce it on all systems where the errata is known to exist.
> 
> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> ---
>   x86/svm_tests.c   | 68 +++++++++++++++++++++++++++++++++++++++++++++++
>   x86/unittests.cfg |  2 +-
>   2 files changed, 69 insertions(+), 1 deletion(-)
> 
> diff --git a/x86/svm_tests.c b/x86/svm_tests.c
> index dc86efd..0c75400 100644
> --- a/x86/svm_tests.c
> +++ b/x86/svm_tests.c
> @@ -2315,6 +2315,73 @@ static void svm_guest_state_test(void)
>   	test_dr();
>   }
>   
> +
> +static bool volatile svm_errata_reproduced = false;
> +static unsigned long volatile physical = 0;
> +
> +
> +/*
> + *
> + * Test the following errata:
> + * If the VMRUN/VMSAVE/VMLOAD are attempted by the nested guest,
> + * the CPU would first check the EAX against host reserved memory
> + * regions (so far only SMM_ADDR/SMM_MASK are known to cause it),
> + * and only then signal #VMexit
> + *
> + * Try to reproduce this by trying vmsave on each possible 4K aligned memory
> + * address in the low 4G where the SMM area has to reside.
> + */
> +
> +static void gp_isr(struct ex_regs *r)
> +{
> +    svm_errata_reproduced = true;
> +    /* skip over the vmsave instruction*/
> +    r->rip += 3;
> +}
> +
> +static void svm_vmrun_errata_test(void)
> +{
> +    unsigned long *last_page = NULL;
> +
> +    handle_exception(GP_VECTOR, gp_isr);
> +
> +    while (!svm_errata_reproduced) {
> +
> +        unsigned long *page = alloc_pages(1);
> +
> +        if (!page) {
> +            report(true, "All guest memory tested, no bug found");;
> +            break;
> +        }
> +
> +        physical = virt_to_phys(page);
> +
> +        asm volatile (
> +            "mov %[_physical], %%rax\n\t"
> +            "vmsave\n\t"
> +
> +            : [_physical] "=m" (physical)
> +            : /* no inputs*/
> +            : "rax" /*clobbers*/
> +        );
> +
> +        if (svm_errata_reproduced) {
> +            report(false, "Got #GP exception - svm errata reproduced at 0x%lx",
> +                   physical);
> +            break;
> +        }
> +
> +        *page = (unsigned long)last_page;
> +        last_page = page;
> +    }
> +
> +    while (last_page) {
> +        unsigned long *page = last_page;
> +        last_page = (unsigned long *)*last_page;
> +        free_pages_by_order(page, 1);
> +    }
> +}
> +
>   struct svm_test svm_tests[] = {
>       { "null", default_supported, default_prepare,
>         default_prepare_gif_clear, null_test,
> @@ -2427,5 +2494,6 @@ struct svm_test svm_tests[] = {
>         init_intercept_finished, init_intercept_check, .on_vcpu = 2 },
>       TEST(svm_cr4_osxsave_test),
>       TEST(svm_guest_state_test),
> +    TEST(svm_vmrun_errata_test),
>       { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
>   };
> diff --git a/x86/unittests.cfg b/x86/unittests.cfg
> index b48c98b..f4ea370 100644
> --- a/x86/unittests.cfg
> +++ b/x86/unittests.cfg
> @@ -213,7 +213,7 @@ arch = x86_64
>   [svm]
>   file = svm.flat
>   smp = 2
> -extra_params = -cpu host,+svm
> +extra_params = -cpu host,+svm -m 4g
>   arch = x86_64
>   
>   [taskswitch]
> 

Queued, thanks.

Paolo


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-01-18 17:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-14 12:21 [PATCH] Add a reproducer for the AMD nested virtualization errata Maxim Levitsky
2021-01-18 17:14 ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).