]> xenbits.xensource.com Git - xtf.git/commitdiff
debug-regs: Detect the PV IO shadow handling bugs
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 1 Jun 2018 13:11:35 +0000 (14:11 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 15 Oct 2018 16:29:44 +0000 (17:29 +0100)
Also fix up some poor choice of constant names.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/include/arch/x86-dbg-reg.h
tests/debug-regs/main.c

index a982e39125654aada21ba9c140d9122111517796..da9bd9d46bd7195a0f6093725eb7979306ccef39 100644 (file)
@@ -19,9 +19,9 @@
 #define X86_DR6_BD              (1u << 13)  /* Debug register accessed */
 #define X86_DR6_BS              (1u << 14)  /* Single step             */
 #define X86_DR6_BT              (1u << 15)  /* Task switch             */
-#define X86_DR6_NOT_RTM         (1u << 16)  /* #DB/#BP in RTM region   */
+#define X86_DR6_RTM             (1u << 16)  /* #DB/#BP in RTM region   */
 
-#define X86_DR6_RESET           0xffff0ff0u
+#define X86_DR6_DEFAULT         0xffff0ff0
 
 /*
  * DR7 unique control bits.
@@ -31,6 +31,8 @@
 #define X86_DR7_RTM             (1u << 11)  /* Debugging in RTM regions */
 #define X86_DR7_GD              (1u << 13)  /* General Detect           */
 
+#define X86_DR7_DEFAULT         0x00000400
+
 /*
  * DR7 common control bits.  Intended for use with the DR7_SYM() helper.
  */
index 789a89954a8661b4a5f01eefb03e56635716c42a..2835f216adc2ddf072264b1b42f50a562f02e58e 100644 (file)
@@ -4,7 +4,7 @@
  *
  * @page test-debug-regs Debug register and control tests
  *
- * The following misc tests are implemented:
+ * The following PV tests are implemented:
  *
  * 1.  Xen, between
  *     [65e3554908](http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=65e355490817ac1783c9ef06c13cf980edf05b5b)
  *     context switch of @%dr7 fails to take effect until the next full vcpu
  *     reschedule.
  *
+ * 2.  Xen, before
+ *     [f539ae2706](http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=f539ae27061c6811fd5e80e0755bf0514e22b977)
+ *     (Xen 4.11) had a bug whereby a write which cleared @%dr7.L/G would
+ *     leave stale IO shadow state visible in later reads of @%dr7.
+ *
+ *     Unfortunately, that changset introduced a second bug, fixed by
+ *     [237c31b5a1](http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=237c31b5a1d5aa88cdb59b8c31b1b62eb13e82d1)
+ *     (Xen 4.11), which caused an attempt to set up an IO breakpoint with
+ *     @%cr4.DE clear to clobber an already configured state, despite the
+ *     update failing.
+ *
  * @see tests/debug-regs/main.c
  */
 #include <xtf.h>
@@ -75,18 +86,70 @@ static void test_pv_dr7_latch(void)
         }
     }
 
-    if ( i == 10 )
-        printk("  All ok - %%dr7 seems to work fine\n");
-
     /* Reset other state. */
     write_dr0(0);
-    write_dr6(X86_DR6_RESET);
+    write_dr6(X86_DR6_DEFAULT);
+}
+
+/*
+ * Detect both bugs with shadow IO breakpoint state handling.
+ */
+static void test_pv_dr7_io_breakpoints(void)
+{
+    unsigned long io0, io1, dr7, cr4 = read_cr4();
+
+    printk("Test PV %%dr7 IO breakpoints\n");
+
+    if ( !(cr4 & X86_CR4_DE) )
+        write_cr4(cr4 |= X86_CR4_DE);
+
+    /* Active IO breakpoint in %dr0. */
+    io0 = DR7_SYM(0, G, IO, 32) | X86_DR7_GE | X86_DR7_DEFAULT;
+    write_dr7(io0);
+
+    if ( (dr7 = read_dr7()) != io0 )
+        xtf_failure("  Fail: dr7 %#lx != io0 %#lx\n",
+                    dr7, io0);
+
+    /* Inactive IO breakpoint in %dr1. */
+    io1 = DR7_SYM(1, G, IO, 32) | X86_DR7_DEFAULT;
+    write_dr7(io1);
+
+    /* Bug 1.  Old %dr0 configuration still visible in %dr7. */
+    if ( (dr7 = read_dr7()) != io1 )
+        xtf_failure("  Fail: dr7 %#lx != io1 %#lx\n",
+                    dr7, io1);
+
+    /* Reload active configuration. */
+    write_dr7(io0);
+
+    /* Clear %cr4.de, after which IO breakpoints are invalid. */
+    write_cr4(cr4 &= ~X86_CR4_DE);
+
+    /* Attempt to reload an IO breakpoint in %dr0, which should fail ... */
+    exinfo_t fault = 0;
+    asm volatile ("1: mov %[val], %%dr7; 2:"
+                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
+                  : "+a" (fault)
+                  : [val] "r" (io0),
+                    "X" (ex_record_fault_eax));
+
+    if ( fault != EXINFO_SYM(GP, 0) )
+        xtf_error("Error: Unexpected fault %pe\n", _p(fault));
+
+    /* Bug 2.  ... but may drop the existing %dr7 configuration. */
+    if ( (dr7 = read_dr7()) != io0 )
+        xtf_failure("  Fail: dr7 %#lx != io0 %#lx\n",
+                    dr7, io0);
 }
 
 void test_main(void)
 {
     if ( IS_DEFINED(CONFIG_PV) )
+    {
         test_pv_dr7_latch();
+        test_pv_dr7_io_breakpoints();
+    }
 
     xtf_success(NULL);
 }