[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC][XTF] add split memory access tests



Add tests to verify that accesses crossing the upper address boundary
are being handled similarly with and without the emulator involved.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- /dev/null
+++ b/tests/split-access/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := split-access
+CATEGORY  := utility
+TEST-ENVS := $(HVM_ENVIRONMENTS)
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
--- /dev/null
+++ b/tests/split-access/main.c
@@ -0,0 +1,218 @@
+/**
+ * @file tests/split-access/main.c
+ * @ref test-split-access
+ *
+ * @page test-split-access split-access
+ *
+ * @todo Docs for test-split-access
+ *
+ * @see tests/split-access/main.c
+ */
+#include <xtf.h>
+
+#include <arch/decode.h>
+
+const char test_title[] = "Split memory access insns";
+
+/* Keep the compiler from leveraging undefined behavior. */
+#define touch(x) ({ asm ( "" : "+g" (x) ); })
+
+void do_mov(bool force)
+{
+    const unsigned long *ptr = NULL;
+
+    touch(ptr);
+
+    for ( --ptr; ; )
+    {
+        unsigned long val;
+        exinfo_t fault = 0;
+
+        asm volatile ( "test %[fep], %[fep];"
+                       "jz 1f;"
+                       _ASM_XEN_FEP
+                       "1: mov %[src],%[dst]; 2:"
+                       _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                       : [dst] "=r" (val), "+a" (fault)
+                       : [src] "m" (*ptr), [fep] "q" (force) );
+        if ( fault )
+        {
+            char excstr[16];
+
+            x86_decode_exinfo(excstr, ARRAY_SIZE(excstr), fault);
+            xtf_warning("Got %s for %p'\n", excstr, ptr);
+        }
+        else if ( val != *ptr )
+            xtf_failure("%lx != %lx for %p'\n", val, *ptr, ptr);
+
+        touch(ptr);
+        if ( !ptr )
+            break;
+
+        ptr = (void *)(long)ptr + 1;
+    }
+}
+
+void do_lfs(bool force)
+{
+    const struct __packed { unsigned long off; uint16_t sel; } *ptr = NULL;
+
+    touch(ptr);
+
+    for ( --ptr; ; )
+    {
+        unsigned long off;
+        exinfo_t fault = 0;
+
+        asm volatile ( "test %[fep], %[fep];"
+                       "jz 1f;"
+                       _ASM_XEN_FEP
+                       "1: lfs %[src],%[dst]; 2:"
+                       _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                       : [dst] "=r" (off), "+a" (fault)
+                       : [src] "m" (*ptr), [fep] "q" (force) );
+        if ( fault )
+        {
+            char excstr[16];
+
+            x86_decode_exinfo(excstr, ARRAY_SIZE(excstr), fault);
+            xtf_warning("Got %s for %p'\n", excstr, ptr);
+        }
+        else if ( off != ptr->off )
+            xtf_failure("%lx != %lx for %p'\n", off, ptr->off, ptr);
+
+        touch(ptr);
+        if ( !ptr )
+            break;
+
+        ptr = (void *)(long)ptr + 1;
+    }
+}
+
+void do_lidt(bool force)
+{
+    const desc_ptr *ptr = NULL;
+
+    touch(ptr);
+
+    for ( --ptr; ; )
+    {
+        exinfo_t fault = 0;
+
+        asm volatile ( "test %[fep], %[fep];"
+                       "jz 1f;"
+                       _ASM_XEN_FEP
+                       "1: lidt %[src]; 2:"
+                       _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                       : "+a" (fault)
+                       : [src] "m" (*ptr), [fep] "q" (force) );
+        if ( fault )
+        {
+            char excstr[16];
+
+            x86_decode_exinfo(excstr, ARRAY_SIZE(excstr), fault);
+            xtf_warning("Got %s for %p\n", excstr, ptr);
+        }
+        else
+            asm volatile ( "lidt %0" :: "m" (idt_ptr) );
+
+        touch(ptr);
+        if ( !ptr )
+            break;
+
+        ptr = (void *)(long)ptr + 1;
+    }
+}
+
+#ifndef __x86_64__
+void do_bound(bool force)
+{
+    const struct { unsigned long lo, hi; } *ptr = NULL;
+
+    touch(ptr);
+
+    for ( --ptr; ; )
+    {
+        exinfo_t fault = 0;
+
+        asm volatile ( "test %[fep], %[fep];"
+                       "jz 1f;"
+                       _ASM_XEN_FEP
+                       "1: bound %[off], %[bnd]; 2:"
+                       _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                       : "+a" (fault)
+                       : [bnd] "m" (*ptr), [off] "r" (0), [fep] "q" (force) );
+        if ( fault )
+        {
+            char excstr[16];
+
+            x86_decode_exinfo(excstr, ARRAY_SIZE(excstr), fault);
+            xtf_warning("Got %s for %p\n", excstr, ptr);
+        }
+
+        touch(ptr);
+        if ( !ptr )
+            break;
+
+        ptr = (void *)(long)ptr + 1;
+    }
+}
+#endif
+
+void run_tests(bool force)
+{
+    printk("Testing%s MOV\n", force ? " emulated" : "");
+    do_mov(force);
+
+    printk("Testing%s LFS\n", force ? " emulated" : "");
+    do_lfs(force);
+
+    printk("Testing%s LIDT\n", force ? " emulated" : "");
+    do_lidt(force);
+
+#ifndef __x86_64__
+    printk("Testing%s BOUND\n", force ? " emulated" : "");
+    do_bound(force);
+#endif
+}
+
+void test_main(void)
+{
+#if !defined(__x86_64__) && CONFIG_PAGING_LEVELS > 0
+    /*
+     * To better tell actual hardware behavior, zap the mapping for the last
+     * (large) page below 4Gb. That'll make us see page faults when hardware
+     * when all segmentation checks pass, rather than observing #GP/#SS due to
+     * the emulator being invoked anyway due to accesses touching an unmapped
+     * MMIO range. This matches x86-64 behavior at the 2^^64 boundary.
+     */
+# if CONFIG_PAGING_LEVELS == 2
+    pse_l2_identmap[pse_l2_table_offset(~0UL)] = 0;
+# elif CONFIG_PAGING_LEVELS == 3
+    pae_l2_identmap[pae_l2_table_offset(~0UL)] = 0;
+# else
+#  error Bad 32-bit paging mode!
+# endif
+
+    invlpg((void *)~0UL);
+#endif
+
+    run_tests(false);
+
+    if ( !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+    else
+        run_tests(true);
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.