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 
53 #ifdef __i386__
54 # define COND(_32, _64) _32
55 #else
56 # define COND(_32, _64) _64
57 #endif
58 
59 #define EXINFO_TRAP EXINFO_AVAIL0
60 
61 enum mode { KERN, USER };
62 
63 bool ex_record_trap_eax(struct cpu_regs *regs, const struct extable_entry *ex)
64 {
65  regs->ax = EXINFO(regs->entry_vector, regs->error_code) | EXINFO_TRAP;
66  regs->ip = ex->fixup;
67 
68  return true;
69 }
70 
71 struct insn
72 {
73  const char *name;
74  unsigned long (*fn[4])(void);
75  unsigned long (*user_fn[4])(void);
76 };
77 
78 const struct insn int3 = {
79  "int3",
80  {
81  stub_int3,
85  },
86  {
91  },
92 };
93 
94 const struct insn int_0x3 = {
95  "int $3",
96  {
101  },
102  {
107  },
108 };
109 
110 const struct insn icebp = {
111  "icebp",
112  {
113  stub_icebp,
114  stub_icebp_A,
115  stub_icebp_F,
117  },
118  {
123  },
124 };
125 
126 const struct insn int_0x1 = {
127  "int $1",
128  {
129  stub_int_0x1,
133  },
134  {
139  },
140 };
141 
142 const struct insn into = {
143  "into",
144  {
145  stub_into,
146  stub_into_A,
147  stub_into_F,
148  stub_into_FA,
149  },
150  {
155  },
156 };
157 
158 void test_insn(enum mode user, const struct insn *insn, exinfo_t exp)
159 {
160  printk(" Testing %s\n", insn->name);
161 
162  for ( unsigned int i = 0; i < ARRAY_SIZE(insn->fn); ++i )
163  {
164  exinfo_t got;
165 
166  got = user ? exec_user(insn->user_fn[i]) : insn->fn[i]();
167 
168  if ( exp != got )
169  xtf_failure(" Fail (Force%c, Addr%c): expected %pe %s, got %pe %s\n",
170  i & 1 ? '+' : '-',
171  i & 2 ? '+' : '-',
172  _p(exp), exp & EXINFO_TRAP ? "trap" : "fault",
173  _p(got), got & EXINFO_TRAP ? "trap" : "fault");
174 
175  /* Avoid FEP stubs if FEP isn't available. */
176  if ( i == 1 && !xtf_has_fep )
177  break;
178  }
179 }
180 
182 static void set_idt_entries_present(bool present)
183 {
184  idt[X86_EXC_DB].p = present;
185  idt[X86_EXC_BP].p = present;
186  idt[X86_EXC_OF].p = present;
187 }
188 
190 static void set_idt_entries_dpl(unsigned int dpl)
191 {
192  idt[X86_EXC_DB].dpl = dpl;
193  idt[X86_EXC_BP].dpl = dpl;
194  idt[X86_EXC_OF].dpl = dpl;
195 }
196 
197 #define TRAP(V) EXINFO_SYM(V, 0) | EXINFO_TRAP
198 #define FAULT(V) EXINFO_SYM(V, 0)
199 #define FAULT_EC(V, ...) EXINFO_SYM(V, EXC_EC_SYM(__VA_ARGS__))
200 
202 void cpl3_tests(void)
203 {
204  printk("Test cpl3: all perms ok\n");
205  {
206  test_insn(USER, &int3, TRAP(BP));
207  test_insn(USER, &int_0x3, TRAP(BP));
208  test_insn(USER, &icebp, TRAP(DB));
209  test_insn(USER, &int_0x1, TRAP(DB));
210  test_insn(USER, &into, COND(TRAP(OF), FAULT(UD)));
211  }
212 
213  printk("Test cpl3: p=0\n");
214  {
216 
217  test_insn(USER, &int3, FAULT_EC(NP, BP));
218  test_insn(USER, &int_0x3, FAULT_EC(NP, BP));
219  test_insn(USER, &icebp, FAULT_EC(NP, DB, EXT));
220  test_insn(USER, &int_0x1, FAULT_EC(NP, DB));
221  test_insn(USER, &into, COND(FAULT_EC(NP, OF), FAULT(UD)));
222 
224  }
225 
226  printk("Test cpl3: dpl=0\n");
227  {
229 
230  test_insn(USER, &int3, FAULT_EC(GP, BP));
231  test_insn(USER, &int_0x3, FAULT_EC(GP, BP));
232  test_insn(USER, &icebp, TRAP(DB)); /* ICEBP doesn't check DPL. */
233  test_insn(USER, &int_0x1, FAULT_EC(GP, DB));
234  test_insn(USER, &into, COND(FAULT_EC(GP, OF), FAULT(UD)));
235 
237  }
238 }
239 
241 void cpl0_tests(void)
242 {
243  printk("Test cpl0: all perms ok\n");
244  {
245  test_insn(KERN, &int3, TRAP(BP));
246  test_insn(KERN, &int_0x3, TRAP(BP));
247  test_insn(KERN, &icebp, TRAP(DB));
248  test_insn(KERN, &int_0x1, TRAP(DB));
249  test_insn(KERN, &into, COND(TRAP(OF), FAULT(UD)));
250  }
251 
252  printk("Test cpl0: p=0\n");
253  {
255 
256  test_insn(KERN, &int3, FAULT_EC(NP, BP));
257  test_insn(KERN, &int_0x3, FAULT_EC(NP, BP));
258  test_insn(KERN, &icebp, FAULT_EC(NP, DB, EXT));
259  test_insn(KERN, &int_0x1, FAULT_EC(NP, DB));
260  test_insn(KERN, &into, COND(FAULT_EC(NP, OF), FAULT(UD)));
261 
263  }
264 }
265 
266 void test_main(void)
267 {
268  /*
269  * Even if FEP is unavailable, run the tests against real hardware to
270  * check the algorithm, but don't claim overall success.
271  */
272  if ( !xtf_has_fep )
273  xtf_skip("FEP support not detected - some tests will be skipped\n");
274 
277 
278  cpl0_tests();
279  cpl3_tests();
280 
281  xtf_success(NULL);
282 }
283 
284 /*
285  * Local variables:
286  * mode: C
287  * c-file-style: "BSD"
288  * c-basic-offset: 4
289  * tab-width: 4
290  * indent-tabs-mode: nil
291  * End:
292  */
unsigned long stub_user_into_FA(void)
unsigned long(* user_fn)(void)
Definition: main.c:96
unsigned long stub_user_int3(void)
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
unsigned long stub_user_icebp_FA(void)
Definition: main.c:93
void cpl3_tests(void)
Tests run in user mode.
Definition: main.c:202
const struct insn int_0x1
Definition: main.c:126
unsigned long fixup
Fixup address.
Definition: extable.h:67
unsigned long stub_user_int_0x3_F(void)
const struct insn int_0x3
Definition: main.c:94
unsigned long stub_user_into_F(void)
unsigned long stub_into_FA(void)
static void set_idt_entries_dpl(unsigned int dpl)
Modify the descriptor privilege level on the IDT entries under test.
Definition: main.c:190
unsigned long stub_user_int3_F(void)
#define EXINFO(vec, ec)
Definition: exinfo.h:26
unsigned long stub_into(void)
#define ARRAY_SIZE(a)
Definition: lib.h:8
#define X86_EXC_OF
Definition: processor.h:106
unsigned long stub_int_0x1_A(void)
Definition: main.c:102
unsigned long stub_user_int3_FA(void)
unsigned long stub_user_int_0x3_FA(void)
const struct insn int3
Definition: main.c:78
unsigned long stub_into_F(void)
unsigned long stub_user_int3_A(void)
unsigned long stub_user_int_0x1_A(void)
#define FAULT_EC(V,...)
Definition: main.c:199
unsigned long stub_user_icebp(void)
unsigned long stub_int_0x1_F(void)
mode
Definition: main.c:102
void printk(const char *fmt,...)
Definition: console.c:134
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use...
Definition: setup.c:276
unsigned long stub_user_int_0x3_A(void)
unsigned long stub_user_int_0x3(void)
Declarations of stubs and labels in generated in lowlevel.S.
unsigned long stub_int3_FA(void)
#define X86_EXC_BP
Definition: processor.h:105
unsigned long stub_icebp(void)
static void user(void)
Definition: main.c:43
#define EXINFO_TRAP
Definition: main.c:59
Definition: main.c:102
#define NULL
Definition: stddef.h:12
unsigned long stub_int3_A(void)
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
unsigned long stub_int_0x3(void)
unsigned long stub_user_int_0x1_F(void)
unsigned long stub_int3_F(void)
unsigned long stub_int_0x1(void)
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 COND(_32, _64)
Definition: main.c:56
#define GP
Exception table entry.
Definition: extable.h:64
unsigned long stub_user_into(void)
unsigned long stub_user_into_A(void)
bool ex_record_trap_eax(struct cpu_regs *regs, const struct extable_entry *ex)
Definition: main.c:63
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
unsigned long stub_int_0x3_FA(void)
unsigned long stub_int_0x1_FA(void)
const struct insn icebp
Definition: main.c:110
unsigned long stub_int_0x3_A(void)
const char test_title[]
The title of the test.
Definition: main.c:14
void cpl0_tests(void)
Tests run in supervisor mode.
Definition: main.c:241
unsigned long stub_icebp_A(void)
unsigned long stub_user_int_0x1(void)
unsigned long stub_icebp_FA(void)
static unsigned long exec_user(unsigned long(*fn)(void))
Definition: lib.h:62
static void set_idt_entries_present(bool present)
Modify the present flag on the IDT entries under test.
Definition: main.c:182
unsigned long stub_user_icebp_A(void)
const char * name
Definition: main.c:94
unsigned long stub_int3(void)
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define X86_EXC_DB
Definition: processor.h:103
unsigned long stub_icebp_F(void)
unsigned long stub_int_0x3_F(void)
unsigned long stub_into_A(void)
void test_insn(enum mode user, const struct insn *insn, exinfo_t exp)
Definition: main.c:158
unsigned long(* fn)(void)
Definition: main.c:95
const struct insn into
Definition: main.c:142
unsigned long stub_user_icebp_F(void)
#define TRAP(V)
Definition: main.c:197
#define FAULT(V)
Definition: main.c:198
unsigned long stub_user_int_0x1_FA(void)