Xen Test Framework
main.c
Go to the documentation of this file.
1 
42 #include <xtf.h>
43 
44 const char test_title[] = "Debugging facility tests";
45 
46 static void check_init_dr(unsigned int dr, unsigned long exp, unsigned long got)
47 {
48  if ( got != exp )
49  xtf_failure(" Fail: %%dr%u expected %p, got %p\n",
50  dr, _p(exp), _p(got));
51 }
52 
53 static void check_init_msr(const char *name, uint64_t exp, uint64_t got)
54 {
55  if ( got != exp )
56  xtf_failure(" Fail: %s expected %08"PRIx64", got %08"PRIx64"\n",
57  name, exp, got);
58 }
59 
60 static void test_initial_debug_state(void)
61 {
62  printk("Test initial debug state\n");
63 
64  if ( read_cr4() & X86_CR4_DE )
65  xtf_failure(" Fail: %%cr4.de expected to be clear\n");
66 
67  check_init_dr(0, 0, read_dr0());
68  check_init_dr(1, 0, read_dr1());
69  check_init_dr(2, 0, read_dr2());
70  check_init_dr(3, 0, read_dr3());
73 
74  check_init_msr("MSR_DEBUGCTL", 0, rdmsr(MSR_DEBUGCTL));
75 
76  if ( cpu_has_dbext )
77  {
78  check_init_msr("MSR_DR0_ADDR_MASK", 0, rdmsr(MSR_DR0_ADDR_MASK));
79  check_init_msr("MSR_DR1_ADDR_MASK", 0, rdmsr(MSR_DR1_ADDR_MASK));
80  check_init_msr("MSR_DR2_ADDR_MASK", 0, rdmsr(MSR_DR2_ADDR_MASK));
81  check_init_msr("MSR_DR3_ADDR_MASK", 0, rdmsr(MSR_DR3_ADDR_MASK));
82  }
83 }
84 
85 /*
86  * Attempt to detect a failure to latch %dr7. A full vcpu context switch, or
87  * a second write to %dr7 will latch the correct value even in the presence of
88  * the bug.
89  */
90 static void test_pv_dr7_latch(void)
91 {
92  unsigned int dummy, i;
93  unsigned long dr7;
94 
95  printk("Test PV %%dr7 latch\n");
96 
97  /* Reset any latched %dr7 content. */
98  write_dr7(0);
99  write_dr7(0);
100 
101  /* Point %dr0 at dummy, %dr7 set with %dr0 enabled. */
102  write_dr0(_u(&dummy));
103  dr7 = X86_DR7_GE | DR7_SYM(0, G, RW, 32);
104 
105  /*
106  * We can race with the Xen scheduler, which may mask the latching bug.
107  * Repeat 10 times, or until we positively see buggy behaviour.
108  */
109  for ( i = 0; i < 10; ++i )
110  {
111  exinfo_t fault = 0;
112 
113  asm volatile ("mov %[dr7], %%dr7;"
114  "movl $0, %[ptr]; 1:"
115  _ASM_EXTABLE_HANDLER(1b, 1b, %P[rec])
116  : "+a" (fault),
117  [ptr] "=m" (dummy)
118  : [dr7] "r" (dr7), [rec] "p" (ex_record_fault_eax));
119 
120  /* Reset any latched %dr7 content. */
121  write_dr7(0);
122  write_dr7(0);
123 
124  if ( fault == 0 )
125  {
126  xtf_failure(" Fail: Single write to %%dr7 failed to latch\n");
127  break;
128  }
129  else if ( fault != EXINFO_SYM(DB, 0) )
130  {
131  xtf_error(" Error: Unexpected fault %#x, %pe\n",
132  fault, _p(fault));
133  break;
134  }
135  }
136 
137  /* Reset other state. */
138  write_dr0(0);
140 }
141 
142 /*
143  * Detect both bugs with shadow IO breakpoint state handling.
144  */
145 static void test_pv_dr7_io_breakpoints(void)
146 {
147  unsigned long io0, io1, dr7, cr4 = read_cr4();
148 
149  printk("Test PV %%dr7 IO breakpoints\n");
150 
151  if ( !(cr4 & X86_CR4_DE) )
152  write_cr4(cr4 | X86_CR4_DE);
153 
154  /* Active IO breakpoint in %dr0. */
155  io0 = DR7_SYM(0, G, IO, 32) | X86_DR7_GE | X86_DR7_DEFAULT;
156  write_dr7(io0);
157 
158  if ( (dr7 = read_dr7()) != io0 )
159  xtf_failure(" Fail: dr7 %#lx != io0 %#lx\n",
160  dr7, io0);
161 
162  /* Inactive IO breakpoint in %dr1. */
163  io1 = DR7_SYM(1, G, IO, 32) | X86_DR7_DEFAULT;
164  write_dr7(io1);
165 
166  /* Bug 1. Old %dr0 configuration still visible in %dr7. */
167  if ( (dr7 = read_dr7()) != io1 )
168  xtf_failure(" Fail: dr7 %#lx != io1 %#lx\n",
169  dr7, io1);
170 
171  /* Reload active configuration. */
172  write_dr7(io0);
173 
174  /* Clear %cr4.de, after which IO breakpoints are invalid. */
175  write_cr4(cr4);
176 
177  /* Attempt to reload an IO breakpoint in %dr0, which should fail ... */
178  exinfo_t fault = 0;
179  asm volatile ("1: mov %[val], %%dr7; 2:"
180  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
181  : "+a" (fault)
182  : [val] "r" (io0),
183  [rec] "p" (ex_record_fault_eax));
184 
185  if ( fault != EXINFO_SYM(GP, 0) )
186  xtf_error("Error: Unexpected fault %pe\n", _p(fault));
187 
188  /* Bug 2. ... but may drop the existing %dr7 configuration. */
189  if ( (dr7 = read_dr7()) != io0 )
190  xtf_failure(" Fail: dr7 %#lx != io0 %#lx\n",
191  dr7, io0);
192 }
193 
194 void test_main(void)
195 {
197 
198  if ( IS_DEFINED(CONFIG_PV) )
199  {
202  }
203 
204  xtf_success(NULL);
205 }
206 
207 /*
208  * Local variables:
209  * mode: C
210  * c-file-style: "BSD"
211  * c-basic-offset: 4
212  * tab-width: 4
213  * indent-tabs-mode: nil
214  * End:
215  */
static void check_init_dr(unsigned int dr, unsigned long exp, unsigned long got)
Definition: main.c:46
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
static uint64_t rdmsr(uint32_t idx)
Thin wrapper around an rdmsr instruction.
Definition: msr.h:19
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
name
Definition: mkcfg.py:14
static unsigned long read_dr2(void)
Definition: x86-dbg-reg.h:130
bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
Record the current fault in %eax.
Definition: extable.c:8
static unsigned long read_dr1(void)
Definition: x86-dbg-reg.h:116
#define MSR_DR2_ADDR_MASK
Definition: msr-index.h:70
#define X86_DR7_DEFAULT
Definition: x86-dbg-reg.h:34
#define X86_CR4_DE
Definition: processor.h:47
#define MSR_DEBUGCTL
Definition: msr-index.h:30
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
void printk(const char *fmt,...)
Definition: console.c:134
static void write_dr6(unsigned long val)
Definition: x86-dbg-reg.h:167
#define MSR_DR1_ADDR_MASK
Definition: msr-index.h:69
static void test_initial_debug_state(void)
Definition: main.c:60
#define PRIx64
Definition: inttypes.h:23
static unsigned long read_dr3(void)
Definition: x86-dbg-reg.h:144
static void write_dr7(unsigned long val)
Definition: x86-dbg-reg.h:181
#define NULL
Definition: stddef.h:12
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
static unsigned long read_dr7(void)
Definition: x86-dbg-reg.h:172
#define MSR_DR0_ADDR_MASK
Definition: msr-index.h:68
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:137
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
#define GP
#define DR7_SYM(bp,...)
Create a partial %dr7 setting for a particular breakpoint based on mnemonics.
Definition: x86-dbg-reg.h:100
#define cpu_has_dbext
Definition: cpuid.h:90
static unsigned long read_cr4(void)
Definition: lib.h:252
static void test_pv_dr7_io_breakpoints(void)
Definition: main.c:145
const char test_title[]
The title of the test.
Definition: main.c:14
static void check_init_msr(const char *name, uint64_t exp, uint64_t got)
Definition: main.c:53
static unsigned long read_dr0(void)
Definition: x86-dbg-reg.h:102
#define X86_DR6_DEFAULT
Definition: x86-dbg-reg.h:24
static unsigned long read_dr6(void)
Definition: x86-dbg-reg.h:158
#define MSR_DR3_ADDR_MASK
Definition: msr-index.h:71
static void write_cr4(unsigned long cr4)
Definition: lib.h:285
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
#define X86_DR7_GE
Definition: x86-dbg-reg.h:30
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
static void write_dr0(unsigned long linear)
Definition: x86-dbg-reg.h:111
static void test_pv_dr7_latch(void)
Definition: main.c:90
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38