Xen Test Framework
main.c
Go to the documentation of this file.
1 
47 #include <xtf.h>
48 
49 #include "lowlevel.h"
50 
51 const char test_title[] = "Software interrupt emulation";
52 
54 
56 struct single
57 {
58  const char *type;
59  void (*fn)(void);
60  void *trap, *fault;
61 };
62 
64 struct sequence
65 {
66  const char *name;
67  struct single tests[4];
68 };
69 
71 struct sequence int3 =
72 { "int3",
73  {
74  {"regular", stub_int3_reg,
76 
77  {"redundant", stub_int3_red,
79 
80  {"forced", stub_int3_force,
82 
83  {"forced redundant", stub_int3_forcered,
85  },
86 };
87 
89 struct sequence int_0x3 =
90 { "int $3",
91  {
92  {"regular", stub_int_0x3_reg,
94 
95  {"redundant", stub_int_0x3_red,
97 
98  {"forced", stub_int_0x3_force,
100 
101  {"forced redundant", stub_int_0x3_forcered,
103  },
104 };
105 
107 struct sequence icebp =
108 { "icebp",
109  {
110  {"regular", stub_icebp_reg,
112 
113  {"redundant", stub_icebp_red,
115 
116  {"forced", stub_icebp_force,
118 
119  {"forced redundant", stub_icebp_forcered,
121  },
122 };
123 
126 { "int $1",
127  {
128  {"regular", stub_int_0x1_reg,
130 
131  {"redundant", stub_int_0x1_red,
133 
134  {"forced", stub_int_0x1_force,
136 
137  {"forced redundant", stub_int_0x1_forcered,
139  },
140 };
141 
143 struct sequence into =
144 { "into",
145  {
146  {"regular", stub_into_reg,
148 
149  {"redundant", stub_into_red,
151 
152  {"forced", stub_into_force,
154 
155  {"forced redundant", stub_into_forcered,
157  },
158 };
159 
161 static bool user = false;
162 
163 struct expectation {
164  const char *prefix;
165  const void *ip;
166  unsigned int ev, ec;
167 }
168  expectation;
169 
171 void expect(const void *prefix, const void *ip,
172  unsigned int ev, unsigned int ec)
173 {
174  expectation = (struct expectation){prefix, ip, ev, ec};
175  xtf_exlog_reset();
176 }
177 
179 void check(void)
180 {
181  unsigned int entries = xtf_exlog_entries();
182 
183  if ( entries != 1 )
184  {
185  xtf_failure("Fail %s: Expected 1 exception (vec %u at %p), got %u\n",
187  expectation.ip, entries);
189  return;
190  }
191 
192  exlog_entry_t *entry = xtf_exlog_entry(0);
193  if ( !entry )
194  {
195  xtf_failure("Fail %s: Unable to retrieve exception log\n",
197  return;
198  }
199 
200  if ( (_p(entry->ip) != expectation.ip) ||
201  (entry->ev != expectation.ev) ||
202  (entry->ec != expectation.ec) )
203  {
204  xtf_failure("Fail %s:\n"
205  " Expected vec %2u[%04x] at %p\n"
206  " got vec %2u[%04x] at %p\n",
209  entry->ev, entry->ec, _p(entry->ip));
210  return;
211  }
212 }
213 
215 bool do_unhandled_exception(struct cpu_regs *regs)
216 {
217  printk("Unhandled Exception at %p\n", _p(regs));
218  check();
219 
220  return false;
221 }
222 
224 void test_seq(struct sequence *seq, unsigned int vector,
225  unsigned int error, bool fault)
226 {
227  unsigned int i;
228 
229  printk(" Testing %s\n", seq->name);
230 
231  for ( i = 0; i < ARRAY_SIZE(seq->tests); ++i )
232  {
233  struct single *s = &seq->tests[i];
234 
235  expect(s->type,
236  fault ? s->fault : s->trap,
237  vector, error);
238 
239  user ? exec_user_void(s->fn) : s->fn();
240 
241  check();
242 
243  /* Avoid 'force' and 'forcered' stubs if FEP isn't available. */
244  if ( i == 1 && !xtf_has_fep )
245  break;
246  }
247 }
248 
250 static void test_trap(struct sequence *seq, unsigned int vector)
251 {
252  test_seq(seq, vector, 0, false);
253 }
254 
256 static void test_fault(struct sequence *seq,
257  unsigned int vector, unsigned int error)
258 {
259  test_seq(seq, vector, error, true);
260 }
261 
263 static void set_idt_entries_present(bool present)
264 {
265  idt[X86_EXC_DB].p = present;
266  idt[X86_EXC_BP].p = present;
267  idt[X86_EXC_OF].p = present;
268 }
269 
271 static void set_idt_entries_dpl(unsigned int dpl)
272 {
273  idt[X86_EXC_DB].dpl = dpl;
274  idt[X86_EXC_BP].dpl = dpl;
275  idt[X86_EXC_OF].dpl = dpl;
276 }
277 
279 void cpl3_tests(void)
280 {
281  user = true;
282 
283  printk("Test cpl3: all perms ok\n");
284  {
285  test_trap(&int3, X86_EXC_BP);
286  test_trap(&int_0x3, X86_EXC_BP);
287  test_trap(&icebp, X86_EXC_DB);
288  test_trap(&int_0x1, X86_EXC_DB);
289 #ifdef __i386__
290  test_trap(&into, X86_EXC_OF);
291 #else
292  test_fault(&into, X86_EXC_UD, 0);
293 #endif
294  }
295 
296  printk("Test cpl3: p=0\n");
297  {
299 
300  test_fault(&int3, X86_EXC_NP, EXC_EC_SYM(BP));
301  test_fault(&int_0x3, X86_EXC_NP, EXC_EC_SYM(BP));
302  test_fault(&icebp, X86_EXC_NP, EXC_EC_SYM(DB, EXT));
303  test_fault(&int_0x1, X86_EXC_NP, EXC_EC_SYM(DB));
304 #ifdef __i386__
305  test_fault(&into, X86_EXC_NP, EXC_EC_SYM(OF));
306 #else
307  test_fault(&into, X86_EXC_UD, 0);
308 #endif
309 
311  }
312 
313  printk("Test cpl3: dpl=0\n");
314  {
316 
317  test_fault(&int3, X86_EXC_GP, EXC_EC_SYM(BP));
318  test_fault(&int_0x3, X86_EXC_GP, EXC_EC_SYM(BP));
319  /* icebp count as external, so no dpl check. */
320  test_trap (&icebp, X86_EXC_DB);
321  test_fault(&int_0x1, X86_EXC_GP, EXC_EC_SYM(DB));
322 #ifdef __i386__
323  test_fault(&into, X86_EXC_GP, EXC_EC_SYM(OF));
324 #else
325  test_fault(&into, X86_EXC_UD, 0);
326 #endif
327 
329  }
330 
331  user = false;
332 }
333 
335 void cpl0_tests(void)
336 {
337  printk("Test cpl0: all perms ok\n");
338  {
339  test_trap(&int3, X86_EXC_BP);
340  test_trap(&int_0x3, X86_EXC_BP);
341  test_trap(&icebp, X86_EXC_DB);
342  test_trap(&int_0x1, X86_EXC_DB);
343 #ifdef __i386__
344  test_trap(&into, X86_EXC_OF);
345 #else
346  test_fault(&into, X86_EXC_UD, 0);
347 #endif
348  }
349 
350  printk("Test cpl0: p=0\n");
351  {
353 
354  test_fault(&int3, X86_EXC_NP, EXC_EC_SYM(BP));
355  test_fault(&int_0x3, X86_EXC_NP, EXC_EC_SYM(BP));
356  test_fault(&icebp, X86_EXC_NP, EXC_EC_SYM(DB, EXT));
357  test_fault(&int_0x1, X86_EXC_NP, EXC_EC_SYM(DB));
358 #ifdef __i386__
359  test_fault(&into, X86_EXC_NP, EXC_EC_SYM(OF));
360 #else
361  test_fault(&into, X86_EXC_UD, 0);
362 #endif
363 
365  }
366 }
367 
368 void test_main(void)
369 {
370  /*
371  * Even if FEP is unavailable, run the tests against real hardware to
372  * check the algorithm, but don't claim overall success.
373  */
374  if ( !xtf_has_fep )
375  xtf_skip("FEP support not detected - some tests will be skipped\n");
376 
379 
380  xtf_exlog_start();
381 
382  cpl0_tests();
383  cpl3_tests();
384 
385  xtf_exlog_stop();
386 
387  xtf_success(NULL);
388 }
389 
390 /*
391  * Local variables:
392  * mode: C
393  * c-file-style: "BSD"
394  * c-basic-offset: 4
395  * tab-width: 4
396  * indent-tabs-mode: nil
397  * End:
398  */
unsigned long label_int_0x1_red_fault[]
struct sequence int3
Sequence for int3.
Definition: main.c:71
void cpl3_tests(void)
Tests run in user mode.
Definition: main.c:279
unsigned long ip
Definition: exlog.h:13
exlog_entry_t * xtf_exlog_entry(unsigned int idx)
Definition: exlog.c:32
#define EXC_EC_SYM(exc,...)
Create an exception selector based error code using mnemonics, with implicit X86_EC_IDT.
A collection of subs for an instruction.
Definition: main.c:64
void xtf_exlog_dump_log(void)
Definition: exlog.c:63
void stub_int_0x3_reg(void)
static void set_idt_entries_dpl(unsigned int dpl)
Modify the descriptor privilege level on the IDT entries under test.
Definition: main.c:271
unsigned long label_int3_red_trap[]
void * trap
Definition: main.c:60
unsigned long label_int3_force_trap[]
unsigned long label_into_forcered_fault[]
unsigned long label_int_0x3_forcered_trap[]
#define ARRAY_SIZE(a)
Definition: lib.h:8
unsigned long label_int3_reg_trap[]
unsigned long label_int_0x3_forcered_fault[]
unsigned long label_int3_forcered_fault[]
#define X86_EXC_OF
Definition: processor.h:95
void stub_int_0x1_red(void)
static void test_trap(struct sequence *seq, unsigned int vector)
test_seq() wrapper, for caller clarity.
Definition: main.c:250
struct sequence into
Sequence for into.
Definition: main.c:143
unsigned long label_icebp_reg_fault[]
unsigned long label_icebp_red_trap[]
#define X86_EXC_GP
Definition: processor.h:104
unsigned int ec
Definition: main.c:166
unsigned long label_int_0x1_force_trap[]
unsigned long label_int_0x3_reg_fault[]
void stub_into_reg(void)
unsigned long label_icebp_red_fault[]
void printk(const char *fmt,...)
Definition: console.c:134
void stub_icebp_reg(void)
void stub_int_0x1_reg(void)
void stub_int3_red(void)
void check(void)
Check the exception long against the expected details.
Definition: main.c:179
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use...
Definition: setup.c:276
unsigned int xtf_exlog_entries(void)
Definition: exlog.c:27
void stub_int_0x3_forcered(void)
unsigned long label_icebp_forcered_trap[]
void xtf_exlog_reset(void)
Definition: exlog.c:16
Declarations of stubs and labels in generated in lowlevel.S.
void stub_int_0x3_red(void)
struct single tests[4]
Definition: main.c:67
#define X86_EXC_BP
Definition: processor.h:94
Definition: exlog.h:11
unsigned long label_icebp_force_trap[]
unsigned long label_int_0x1_force_fault[]
void stub_into_force(void)
unsigned long label_int3_force_fault[]
Single stub&#39;s worth of information.
Definition: main.c:56
#define NULL
Definition: stddef.h:12
struct expectation expectation
Expected %eip, vector and error code from the stub under test.
unsigned long label_int_0x3_force_trap[]
unsigned long label_icebp_force_fault[]
void stub_int_0x3_force(void)
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
unsigned long label_into_force_fault[]
static void exec_user_void(void(*fn)(void))
Definition: lib.h:70
void stub_icebp_force(void)
void stub_int3_forcered(void)
unsigned long label_int_0x3_force_fault[]
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
unsigned long label_into_red_trap[]
bool test_wants_user_mappings
Boolean indicating whether the test wants user mappings or not.
Definition: main.c:26
const char * name
Definition: main.c:66
unsigned long label_int3_red_fault[]
void stub_int_0x1_forcered(void)
static void test_fault(struct sequence *seq, unsigned int vector, unsigned int error)
test_seq() wrapper, for caller clarity.
Definition: main.c:256
unsigned long label_into_force_trap[]
#define X86_EXC_NP
Definition: processor.h:102
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
void stub_icebp_forcered(void)
const void * ip
Definition: main.c:165
unsigned long label_int_0x3_red_fault[]
static bool user
Whether to run the stub in user or supervisor mode.
Definition: main.c:161
const char test_title[]
The title of the test.
Definition: main.c:14
void * fault
Definition: main.c:60
unsigned long label_into_forcered_trap[]
unsigned long label_into_reg_trap[]
uint16_t ev
Definition: exlog.h:14
void cpl0_tests(void)
Tests run in supervisor mode.
Definition: main.c:335
void stub_into_forcered(void)
#define X86_EXC_UD
Definition: processor.h:97
void stub_int3_force(void)
struct sequence int_0x1
Sequence for int $1.
Definition: main.c:125
void xtf_exlog_stop(void)
Definition: exlog.c:21
static void set_idt_entries_present(bool present)
Modify the present flag on the IDT entries under test.
Definition: main.c:263
unsigned long label_int3_reg_fault[]
unsigned int ev
Definition: main.c:166
unsigned long label_int_0x3_red_trap[]
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define X86_EXC_DB
Definition: processor.h:92
void xtf_exlog_start(void)
Definition: exlog.c:10
void(* fn)(void)
Definition: main.c:59
unsigned long label_icebp_reg_trap[]
void stub_into_red(void)
void test_seq(struct sequence *seq, unsigned int vector, unsigned int error, bool fault)
Test a single sequence of related instructions.
Definition: main.c:224
void stub_int_0x1_force(void)
unsigned long label_int3_forcered_trap[]
void stub_int3_reg(void)
unsigned long label_int_0x1_forcered_trap[]
unsigned long label_int_0x1_red_trap[]
uint16_t ec
Definition: exlog.h:14
struct sequence int_0x3
Sequence for int $3.
Definition: main.c:89
unsigned long label_into_reg_fault[]
void expect(const void *prefix, const void *ip, unsigned int ev, unsigned int ec)
Latch details of the stub under test.
Definition: main.c:171
unsigned long label_int_0x1_reg_trap[]
struct sequence icebp
Sequence for icebp.
Definition: main.c:107
unsigned long label_int_0x3_reg_trap[]
static const struct test tests[]
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:96
unsigned long label_icebp_forcered_fault[]
unsigned long label_int_0x1_forcered_fault[]
unsigned long label_into_red_fault[]
const char * prefix
Definition: main.c:164
unsigned long label_int_0x1_reg_fault[]
const char * type
Definition: main.c:58
void stub_icebp_red(void)