Xen Test Framework
main.c
Go to the documentation of this file.
1 
12 #include <xtf.h>
13 
14 const char test_title[] = "XTF Selftests";
15 bool has_xenstore = true;
16 
17 static void test_xenstore(void)
18 {
19  printk("Test: Xenstore read\n");
20 
21  const char *domid_str = xenstore_read("domid");
22 
23  if ( !domid_str )
24  return xtf_failure("Fail: No domid value returned\n");
25 
26  if ( domid_str[0] == '\0' )
27  return xtf_failure("Fail: domid value empty\n");
28 
29  unsigned int i;
30  for ( i = 0; domid_str[i]; ++i )
31  {
32  if ( domid_str[i] < '0' || domid_str[i] > '9' )
33  return xtf_failure("Fail: unexpected domid value '%s'\n",
34  domid_str);
35  }
36 
37  printk(" Found domid %s\n", domid_str);
38 }
39 
40 static void test_extable(void)
41 {
42  printk("Test: Exception Table\n");
43 
44  /*
45  * Check that control flow is successfully redirected with a ud2a
46  * instruction and appropriate extable entry.
47  */
48  asm volatile ("1: ud2a; 2:"
49  _ASM_EXTABLE(1b, 2b));
50 }
51 
52 enum {
56 };
57 
58 static unsigned long __user_text test_exec_user_cpl3(void)
59 {
60  return ((read_cs() & 3) == 3) ? USER_seen : USER_bad_cs;
61 }
62 
63 static void test_exec_user(void)
64 {
65  unsigned int res;
66 
67  printk("Test: Userspace execution\n");
68 
70 
71  switch ( res )
72  {
73  case USER_seen:
74  /* Success */
75  break;
76 
77  case USER_bad_cs:
78  xtf_failure("Fail: Not at cpl3\n");
79  break;
80 
81  default:
82  xtf_failure("Fail: Did not execute function\n");
83  break;
84  }
85 }
86 
87 static void test_NULL_unmapped(void)
88 {
89  unsigned int tmp;
90  exinfo_t got = 0;
91 
92  printk("Test: NULL unmapped\n");
93 
94  asm volatile ("1: mov 0, %[tmp]; 2:"
95  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
96  : "+a" (got),
97  [tmp] "=r" (tmp)
98  : [rec] "p" (ex_record_fault_eax));
99 
100  if ( got != EXINFO_SYM(PF, 0) )
101  xtf_failure("Fail: Expected #PF, got %pe\n", _p(got));
102 }
103 
104 static volatile bool test_hook_active;
105 bool do_unhandled_exception(struct cpu_regs *regs)
106 {
107  extern unsigned long hook_fault[], hook_fixup[];
108 
109  if ( !test_hook_active )
110  return false;
111 
112  if ( _p(regs->ip) != hook_fault )
113  {
114  xtf_failure("Fail: Expected fault at %p, got %p\n",
115  hook_fault, _p(regs->ip));
116  return false;
117  }
118 
119  regs->ip = _u(hook_fixup);
120  return true;
121 }
122 
124 {
125  printk("Test: Unhandled Exception Hook\n");
126 
127  /* Check that the hook catches the exception, and fix it up. */
128  test_hook_active = true;
129  asm volatile ("hook_fault: ud2a; hook_fixup:");
130  test_hook_active = false;
131 }
132 
134 static bool test_extable_handler_handler(struct cpu_regs *regs,
135  const struct extable_entry *ex)
136 {
138  regs->ip = ex->fixup;
139  return true;
140 }
141 
142 static void test_extable_handler(void)
143 {
144  printk("Test: Exception Table Handler\n");
145 
146  asm volatile ("1: ud2a; 2:"
147  _ASM_EXTABLE_HANDLER(1b, 2b, %P[hnd])
148  :: [hnd] "p" (test_extable_handler_handler));
149 
151  xtf_failure("Fail: Custom handler didn't run\n");
152 }
153 
154 void test_idte_handler(void);
155 asm ("test_idte_handler:;"
156 #if defined (CONFIG_PV) && defined (CONFIG_64BIT)
157  "pop %rcx; pop %r11;"
158 #endif
159  "mov $0x1e51c0de, %eax;"
160 #if defined (CONFIG_HVM)
161  __ASM_SEL(iretl, iretq) ";"
162 #else /* CONFIG_HVM */
163 #ifdef __x86_64__
164  "push $0;"
165 #endif
166  "jmp HYPERCALL_iret;"
167 #endif
168  );
169 
170 static const struct xtf_idte idte = {
172  /* PV guests need DPL1, HVM need DPL0. */
173  .dpl = IS_DEFINED(CONFIG_PV) ? 1 : 0,
174  .cs = __KERN_CS,
175 };
176 
177 static void test_custom_idte(void)
178 {
179  printk("Test: Custom IDT entry\n");
180 
181  int rc = xtf_set_idte(X86_VEC_AVAIL, &idte);
182 
183  if ( rc )
184  return xtf_failure("Fail: xtf_set_idte() returned %d\n", rc);
185 
186  unsigned int res;
187  asm volatile ("int $%c[vec]"
188  : "=a" (res)
189  : "0" (0),
190  [vec] "i" (X86_VEC_AVAIL));
191 
192  if ( res != 0x1e51c0de )
193  xtf_failure("Fail: Unexpected result %#x\n", res);
194 };
195 
196 static void test_driver_init(void)
197 {
198  int rc;
199 
200  printk("Test: Driver basic initialisation\n");
201 
202  if ( IS_DEFINED(CONFIG_HVM) )
203  {
205 
206  /* Cope with guests which have LAPIC emulation disabled. */
207  if ( rc != -ENODEV )
208  {
209  if ( rc )
210  xtf_failure("Fail: apic_init(XAPIC) returned %d\n", rc);
211 
212  if ( cpu_has_x2apic )
213  {
215 
216  if ( rc )
217  xtf_failure("Fail: apic_init(X2APIC) returned %d\n", rc);
218  }
219  }
220 
221  rc = hpet_init();
222  if ( rc && rc != -ENODEV )
223  xtf_failure("Fail: hpet_init() returned %d\n", rc);
224 
225  rc = ioapic_init();
226  if ( rc && rc != -ENODEV )
227  xtf_failure("Fail: ioapic_init() returned %d\n", rc);
228  }
229 
230  rc = xenstore_init();
231  has_xenstore = !rc;
232  if ( rc && rc != -ENODEV )
233  xtf_failure("Fail: xenstore_init() returned %d\n", rc);
234 
235  rc = xtf_init_grant_table(1);
236  if ( rc )
237  xtf_failure("Fail: xtf_init_grant_table(1) returned %d\n", rc);
238 
239  rc = xtf_init_grant_table(2);
240  if ( rc && rc != -ENODEV )
241  xtf_failure("Fail: xtf_init_grant_table(2) returned %d\n", rc);
242 }
243 
244 static void test_vsnprintf_crlf_one(const char *fmt, ...)
245 {
246  va_list args;
247 
248  char buf[4];
249  int rc;
250 
251  va_start(args, fmt);
252  rc = vsnprintf(buf, sizeof(buf), fmt, args);
253  va_end(args);
254 
255  if ( rc != 1 )
256  return xtf_failure("Fail: '%s', expected length 1, got %d\n", fmt, rc);
257  if ( strcmp(buf, "\n") )
258  return xtf_failure("Fail: '%s', expected \"\\n\", got %*ph\n",
259  fmt, (int)sizeof(buf), buf);
260 
261  va_start(args, fmt);
262  rc = vsnprintf_internal(buf, sizeof(buf), fmt, args, LF_TO_CRLF);
263  va_end(args);
264 
265  if ( rc != 2 )
266  return xtf_failure("Fail: '%s', expected length 2, got %d\n", fmt, rc);
267  if ( strcmp(buf, "\r\n") )
268  return xtf_failure("Fail: '%s', expected \"\\r\\n\", got %*ph\n",
269  fmt, (int)sizeof(buf), buf);
270 }
271 
272 static void test_vsnprintf_crlf(void)
273 {
274  printk("Test: vsnprintf() with CRLF expansion\n");
275 
277  test_vsnprintf_crlf_one("%c", '\n');
278  test_vsnprintf_crlf_one("%s", "\n");
279 }
280 
281 void test_main(void)
282 {
283  /*
284  * Wherever possible, enable SMEP and SMAP to test the safety of the
285  * exec_user infrastructure.
286  */
287  if ( IS_DEFINED(CONFIG_HVM) )
288  {
289  unsigned long cr4 = read_cr4(), ocr4 = cr4;
290 
291  if ( cpu_has_smep )
292  cr4 |= X86_CR4_SMEP;
293  if ( cpu_has_smap )
294  cr4 |= X86_CR4_SMAP;
295 
296  if ( cr4 != ocr4 )
297  write_cr4(cr4);
298  }
299 
300  test_extable();
301  test_exec_user();
302  if ( CONFIG_PAGING_LEVELS > 0 )
309 
310  if ( has_xenstore )
311  test_xenstore();
312 
313  xtf_success(NULL);
314 }
315 
316 /*
317  * Inline assembly checks.
318  *
319  * Needs to be written out into an object file to cause build failures.
320  * Nothing executes the resulting code.
321  *
322  * - push/pop %reg need to use unsigned long types to avoid trying to allocate
323  * 32bit registers, which aren't encodable in 64bit.
324  * - push $imm can't encode 64bit integers (only 32bit sign extended)
325  */
326 static void __used asm_checks(void)
327 {
328  read_flags();
329 
330 #ifdef __x86_64__
331  unsigned long tmp = 0xdead0000c0deULL;
332 
333  write_flags(tmp);
334  write_cs(tmp);
335 #endif
336 }
337 
338 /*
339  * Local variables:
340  * mode: C
341  * c-file-style: "BSD"
342  * c-basic-offset: 4
343  * tab-width: 4
344  * indent-tabs-mode: nil
345  * End:
346  */
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
static void test_extable(void)
Definition: main.c:40
int hpet_init(void)
Discover and initialise the HPET.
Definition: hpet.c:29
unsigned long fixup
Fixup address.
Definition: extable.h:67
static unsigned int read_cs(void)
Definition: lib.h:124
#define cpu_has_smep
Definition: cpuid.h:94
static void test_vsnprintf_crlf_one(const char *fmt,...)
Definition: main.c:244
#define X86_CR4_SMEP
Definition: processor.h:61
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
static bool test_extable_handler_handler(struct cpu_regs *regs, const struct extable_entry *ex)
Definition: main.c:134
bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
Record the current fault in %eax.
Definition: extable.c:8
bool has_xenstore
Definition: main.c:15
static void test_driver_init(void)
Definition: main.c:196
unsigned long addr
Definition: idt.h:28
int vsnprintf_internal(char *buf, size_t size, const char *fmt, va_list args, unsigned int caller_flags)
Definition: vsnprintf.c:276
static void test_unhandled_exception_hook(void)
Definition: main.c:123
#define cpu_has_x2apic
Definition: cpuid.h:80
int xtf_set_idte(unsigned int vector, const struct xtf_idte *idte)
Set up an IDT Entry, in a guest agnostic way.
Definition: traps.c:73
static int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
Definition: libc.h:54
#define LF_TO_CRLF
Definition: libc.h:48
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
Definition: main.c:54
int apic_init(enum apic_mode mode)
Discover and initialise the local APIC to the requested mode.
Definition: apic.c:33
static void asm_checks(void)
Definition: main.c:326
#define __used
Definition: compiler.h:14
void printk(const char *fmt,...)
Definition: console.c:134
static unsigned long test_exec_user_cpl3(void)
Definition: main.c:58
void test_idte_handler(void)
#define va_end(v)
Definition: stdarg.h:11
#define __user_text
Definition: compiler.h:33
static bool test_extable_handler_handler_run
Definition: main.c:133
#define va_start(v, l)
Definition: stdarg.h:10
static void test_exec_user(void)
Definition: main.c:63
int xenstore_init(void)
Initialise XTF ready for xenstore communication.
Definition: xenbus.c:109
#define NULL
Definition: stddef.h:12
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
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
#define cpu_has_smap
Definition: cpuid.h:96
Exception table entry.
Definition: extable.h:64
static void test_xenstore(void)
Definition: main.c:17
#define X86_CR4_SMAP
Definition: processor.h:62
static unsigned long read_cr4(void)
Definition: lib.h:252
static const struct xtf_idte idte
Definition: main.c:170
const char * xenstore_read(const char *path)
Issue a XS_READ operation for key, waiting synchronously for the reply.
Definition: xenbus.c:115
int xtf_init_grant_table(unsigned int version)
Initialise XTF&#39;s grant infrastructure.
Definition: grant_table.c:21
static void write_flags(unsigned long flags)
Definition: lib.h:220
const char test_title[]
The title of the test.
Definition: main.c:14
static unsigned long read_flags(void)
Definition: lib.h:211
static void test_NULL_unmapped(void)
Definition: main.c:87
static volatile bool test_hook_active
Definition: main.c:104
#define ENODEV
Definition: errno.h:32
static void write_cr4(unsigned long cr4)
Definition: lib.h:285
static unsigned long exec_user(unsigned long(*fn)(void))
Definition: lib.h:62
#define strcmp(s1, s2)
Definition: libc.h:27
__builtin_va_list va_list
Definition: stdarg.h:9
#define X86_VEC_AVAIL
Available for test use.
Definition: idt.h:20
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
static void test_vsnprintf_crlf(void)
Definition: main.c:272
A guest agnostic represention of IDT information.
Definition: idt.h:26
#define _ASM_EXTABLE(fault, fixup)
Create an exception table entry.
Definition: extable.h:50
#define __ASM_SEL(c, l)
Definition: asm_macros.h:25
static void test_custom_idte(void)
Definition: main.c:177
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:93
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
static void write_cs(unsigned long cs)
Definition: lib.h:178
int ioapic_init(void)
Discover and initialise the IO-APIC.
Definition: io-apic.c:15
static void test_extable_handler(void)
Definition: main.c:142