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 bool do_unhandled_exception(struct cpu_regs *regs)
105 {
106  extern unsigned long hook_fault[], hook_fixup[];
107 
108  if ( _p(regs->ip) != hook_fault )
109  {
110  xtf_failure("Fail: Expected fault at %p, got %p\n",
111  hook_fault, _p(regs->ip));
112  return false;
113  }
114 
115  regs->ip = _u(hook_fixup);
116  return true;
117 }
118 
120 {
121  printk("Test: Unhandled Exception Hook\n");
122 
123  /* Check that the hook catches the exception, and fix it up. */
124  asm volatile ("hook_fault: ud2a; hook_fixup:");
125 }
126 
128 static bool test_extable_handler_handler(struct cpu_regs *regs,
129  const struct extable_entry *ex)
130 {
132  regs->ip = ex->fixup;
133  return true;
134 }
135 
136 static void test_extable_handler(void)
137 {
138  printk("Test: Exception Table Handler\n");
139 
140  asm volatile ("1: ud2a; 2:"
141  _ASM_EXTABLE_HANDLER(1b, 2b, %P[hnd])
142  :: [hnd] "p" (test_extable_handler_handler));
143 
145  xtf_failure("Fail: Custom handler didn't run\n");
146 }
147 
148 void test_idte_handler(void);
149 asm ("test_idte_handler:;"
150 #if defined (CONFIG_PV) && defined (CONFIG_64BIT)
151  "pop %rcx; pop %r11;"
152 #endif
153  "mov $0x1e51c0de, %eax;"
154 #if defined (CONFIG_HVM)
155  __ASM_SEL(iretl, iretq) ";"
156 #else /* CONFIG_HVM */
157 #ifdef __x86_64__
158  "push $0;"
159 #endif
160  "jmp HYPERCALL_iret;"
161 #endif
162  );
163 
164 static const struct xtf_idte idte = {
166  /* PV guests need DPL1, HVM need DPL0. */
167  .dpl = IS_DEFINED(CONFIG_PV) ? 1 : 0,
168  .cs = __KERN_CS,
169 };
170 
171 static void test_custom_idte(void)
172 {
173  printk("Test: Custom IDT entry\n");
174 
175  int rc = xtf_set_idte(X86_VEC_AVAIL, &idte);
176 
177  if ( rc )
178  return xtf_failure("Fail: xtf_set_idte() returned %d\n", rc);
179 
180  unsigned int res;
181  asm volatile ("int $%c[vec]"
182  : "=a" (res)
183  : "0" (0),
184  [vec] "i" (X86_VEC_AVAIL));
185 
186  if ( res != 0x1e51c0de )
187  xtf_failure("Fail: Unexpected result %#x\n", res);
188 };
189 
190 static void test_driver_init(void)
191 {
192  int rc;
193 
194  printk("Test: Driver basic initialisation\n");
195 
196  if ( IS_DEFINED(CONFIG_HVM) )
197  {
199 
200  /* Cope with guests which have LAPIC emulation disabled. */
201  if ( rc != -ENODEV )
202  {
203  if ( rc )
204  xtf_failure("Fail: apic_init(XAPIC) returned %d\n", rc);
205 
206  if ( cpu_has_x2apic )
207  {
209 
210  if ( rc )
211  xtf_failure("Fail: apic_init(X2APIC) returned %d\n", rc);
212  }
213  }
214 
215  rc = hpet_init();
216  if ( rc && rc != -ENODEV )
217  xtf_failure("Fail: hpet_init() returned %d\n", rc);
218 
219  rc = ioapic_init();
220  if ( rc && rc != -ENODEV )
221  xtf_failure("Fail: ioapic_init() returned %d\n", rc);
222  }
223 
224  rc = xenstore_init();
225  has_xenstore = !rc;
226  if ( rc && rc != -ENODEV )
227  xtf_failure("Fail: xenstore_init() returned %d\n", rc);
228 
229  rc = xtf_init_grant_table(1);
230  if ( rc )
231  xtf_failure("Fail: xtf_init_grant_table(1) returned %d\n", rc);
232 
233  rc = xtf_init_grant_table(2);
234  if ( rc && rc != -ENODEV )
235  xtf_failure("Fail: xtf_init_grant_table(2) returned %d\n", rc);
236 }
237 
238 static void test_vsnprintf_crlf_one(const char *fmt, ...)
239 {
240  va_list args;
241 
242  char buf[4];
243  int rc;
244 
245  va_start(args, fmt);
246  rc = vsnprintf(buf, sizeof(buf), fmt, args);
247  va_end(args);
248 
249  if ( rc != 1 )
250  return xtf_failure("Fail: '%s', expected length 1, got %d\n", fmt, rc);
251  if ( strcmp(buf, "\n") )
252  return xtf_failure("Fail: '%s', expected \"\\n\", got %*ph\n",
253  fmt, (int)sizeof(buf), buf);
254 
255  va_start(args, fmt);
256  rc = vsnprintf_internal(buf, sizeof(buf), fmt, args, LF_TO_CRLF);
257  va_end(args);
258 
259  if ( rc != 2 )
260  return xtf_failure("Fail: '%s', expected length 2, got %d\n", fmt, rc);
261  if ( strcmp(buf, "\r\n") )
262  return xtf_failure("Fail: '%s', expected \"\\r\\n\", got %*ph\n",
263  fmt, (int)sizeof(buf), buf);
264 }
265 
266 static void test_vsnprintf_crlf(void)
267 {
268  printk("Test: vsnprintf() with CRLF expansion\n");
269 
271  test_vsnprintf_crlf_one("%c", '\n');
272  test_vsnprintf_crlf_one("%s", "\n");
273 }
274 
275 void test_main(void)
276 {
277  /*
278  * Wherever possible, enable SMEP and SMAP to test the safety of the
279  * exec_user infrastructure.
280  */
281  if ( IS_DEFINED(CONFIG_HVM) )
282  {
283  unsigned long cr4 = read_cr4(), ocr4 = cr4;
284 
285  if ( cpu_has_smep )
286  cr4 |= X86_CR4_SMEP;
287  if ( cpu_has_smap )
288  cr4 |= X86_CR4_SMAP;
289 
290  if ( cr4 != ocr4 )
291  write_cr4(cr4);
292  }
293 
294  test_extable();
295  test_exec_user();
296  if ( CONFIG_PAGING_LEVELS > 0 )
303 
304  if ( has_xenstore )
305  test_xenstore();
306 
307  xtf_success(NULL);
308 }
309 
310 /*
311  * Inline assembly checks.
312  *
313  * Needs to be written out into an object file to cause build failures.
314  * Nothing executes the resulting code.
315  *
316  * - push/pop %reg need to use unsigned long types to avoid trying to allocate
317  * 32bit registers, which aren't encodable in 64bit.
318  * - push $imm can't encode 64bit integers (only 32bit sign extended)
319  */
320 static void __used asm_checks(void)
321 {
322  read_flags();
323 
324 #ifdef __x86_64__
325  unsigned long tmp = 0xdead0000c0deULL;
326 
327  write_flags(tmp);
328  write_cs(tmp);
329 #endif
330 }
331 
332 /*
333  * Local variables:
334  * mode: C
335  * c-file-style: "BSD"
336  * c-basic-offset: 4
337  * tab-width: 4
338  * indent-tabs-mode: nil
339  * End:
340  */
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:238
#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:128
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:190
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:119
#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:320
#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:127
#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:164
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
#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:266
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:171
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:94
#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:136