Xen Test Framework
main.c
Go to the documentation of this file.
1
42#include <xtf.h>
43
44const char test_title[] = "Debugging facility tests";
45
46static 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
53static 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
60static 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 */
90static 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 */
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
194void test_main(void)
195{
197
198 if ( IS_DEFINED(CONFIG_PV) )
199 {
202 }
203
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 */
bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
Record the current fault in %eax.
Definition: extable.c:8
#define cpu_has_dbext
Definition: cpuid.h:91
static unsigned long read_cr4(void)
Definition: lib.h:252
static void write_cr4(unsigned long cr4)
Definition: lib.h:285
void printk(const char *fmt,...)
Definition: console.c:134
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:110
const char test_title[]
The title of the test.
Definition: main.c:24
static void test_pv_dr7_latch(void)
Definition: main.c:90
static void check_init_msr(const char *name, uint64_t exp, uint64_t got)
Definition: main.c:53
static void test_pv_dr7_io_breakpoints(void)
Definition: main.c:145
static void check_init_dr(unsigned int dr, unsigned long exp, unsigned long got)
Definition: main.c:46
static void test_initial_debug_state(void)
Definition: main.c:60
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
#define PRIx64
Definition: inttypes.h:23
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define GP
#define MSR_DEBUGCTL
Definition: msr-index.h:30
#define MSR_DR0_ADDR_MASK
Definition: msr-index.h:68
#define MSR_DR2_ADDR_MASK
Definition: msr-index.h:70
#define MSR_DR1_ADDR_MASK
Definition: msr-index.h:69
#define MSR_DR3_ADDR_MASK
Definition: msr-index.h:71
static uint64_t rdmsr(uint32_t idx)
Thin wrapper around an rdmsr instruction.
Definition: msr.h:19
name
Definition: mkcfg.py:14
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define X86_CR4_DE
Definition: processor.h:47
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define NULL
Definition: stddef.h:12
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
static unsigned long read_dr3(void)
Definition: x86-dbg-reg.h:144
#define X86_DR6_DEFAULT
Definition: x86-dbg-reg.h:24
static void write_dr0(unsigned long linear)
Definition: x86-dbg-reg.h:111
static unsigned long read_dr6(void)
Definition: x86-dbg-reg.h:158
#define DR7_SYM(bp,...)
Create a partial %dr7 setting for a particular breakpoint based on mnemonics.
Definition: x86-dbg-reg.h:100
static unsigned long read_dr7(void)
Definition: x86-dbg-reg.h:172
static unsigned long read_dr1(void)
Definition: x86-dbg-reg.h:116
#define X86_DR7_GE
Definition: x86-dbg-reg.h:30
#define X86_DR7_DEFAULT
Definition: x86-dbg-reg.h:34
static void write_dr7(unsigned long val)
Definition: x86-dbg-reg.h:181
static unsigned long read_dr2(void)
Definition: x86-dbg-reg.h:130
static void write_dr6(unsigned long val)
Definition: x86-dbg-reg.h:167
static unsigned long read_dr0(void)
Definition: x86-dbg-reg.h:102