Xen Test Framework
main.c
Go to the documentation of this file.
1 
15 #include <xtf.h>
16 
17 const char test_title[] = "User-Mode Instruction Prevention Tests";
18 
19 static unsigned long stub_sgdt(unsigned long force)
20 {
21  unsigned long fault = 0;
22  desc_ptr tmp;
23 
24  asm volatile("testb $1, %b[fep];"
25  "jz 1f;"
27  "1: sgdt %[tmp]; 2:"
28  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
29  : "+a" (fault), [tmp] "=m" (tmp)
30  : [fep] "rm" (force),
31  [rec] "p" (ex_record_fault_eax));
32 
33  return fault;
34 }
35 
36 static unsigned long stub_sidt(unsigned long force)
37 {
38  unsigned long fault = 0;
39  desc_ptr tmp;
40 
41  asm volatile("testb $1, %b[fep];"
42  "jz 1f;"
44  "1: sidt %[tmp]; 2:"
45  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
46  : "+a" (fault), [tmp] "=m" (tmp)
47  : [fep] "rm" (force),
48  [rec] "p" (ex_record_fault_eax));
49 
50  return fault;
51 }
52 
53 static unsigned long stub_sldt(unsigned long force)
54 {
55  unsigned long fault = 0;
56  unsigned int tmp;
57 
58  asm volatile("testb $1, %b[fep];"
59  "jz 1f;"
61  "1: sldt %[tmp]; 2:"
62  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
63  : "+a" (fault), [tmp] "=r" (tmp)
64  : [fep] "rm" (force),
65  [rec] "p" (ex_record_fault_eax));
66 
67  return fault;
68 }
69 
70 static unsigned long stub_str(unsigned long force)
71 {
72  unsigned long fault = 0;
73  unsigned int tmp;
74 
75  asm volatile("testb $1, %b[fep];"
76  "jz 1f;"
78  "1: str %[tmp]; 2:"
79  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
80  : "+a" (fault), [tmp] "=r" (tmp)
81  : [fep] "rm" (force),
82  [rec] "p" (ex_record_fault_eax));
83 
84  return fault;
85 }
86 
87 static unsigned long stub_smsw(unsigned long force)
88 {
89  unsigned long fault = 0;
90  unsigned int tmp;
91 
92  asm volatile("testb $1, %b[fep];"
93  "jz 1f;"
95  "1: smsw %[tmp]; 2:"
96  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
97  : "+a" (fault), [tmp] "=r" (tmp)
98  : [fep] "rm" (force),
99  [rec] "p" (ex_record_fault_eax));
100 
101  return fault;
102 }
103 
104 static unsigned long __user_text stub_user_sgdt(unsigned long force)
105 {
106  unsigned long fault = 0;
107  desc_ptr tmp;
108 
109  asm volatile("testb $1, %b[fep];"
110  "jz 1f;"
112  "1: sgdt %[tmp]; 2:"
113  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
114  : "+a" (fault), [tmp] "=m" (tmp)
115  : [fep] "rm" (force),
116  [rec] "p" (ex_record_fault_eax));
117 
118  return fault;
119 }
120 
121 static unsigned long __user_text stub_user_sidt(unsigned long force)
122 {
123  unsigned long fault = 0;
124  desc_ptr tmp;
125 
126  asm volatile("testb $1, %b[fep];"
127  "jz 1f;"
129  "1: sidt %[tmp]; 2:"
130  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
131  : "+a" (fault), [tmp] "=m" (tmp)
132  : [fep] "rm" (force),
133  [rec] "p" (ex_record_fault_eax));
134 
135  return fault;
136 }
137 
138 static unsigned long __user_text stub_user_sldt(unsigned long force)
139 {
140  unsigned long fault = 0;
141  unsigned int tmp;
142 
143  asm volatile("testb $1, %b[fep];"
144  "jz 1f;"
146  "1: sldt %[tmp]; 2:"
147  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
148  : "+a" (fault), [tmp] "=r" (tmp)
149  : [fep] "rm" (force),
150  [rec] "p" (ex_record_fault_eax));
151 
152  return fault;
153 }
154 
155 static unsigned long __user_text stub_user_str(unsigned long force)
156 {
157  unsigned long fault = 0;
158  unsigned int tmp;
159 
160  asm volatile("testb $1, %b[fep];"
161  "jz 1f;"
163  "1: str %[tmp]; 2:"
164  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
165  : "+a" (fault), [tmp] "=r" (tmp)
166  : [fep] "rm" (force),
167  [rec] "p" (ex_record_fault_eax));
168 
169  return fault;
170 }
171 
172 static unsigned long __user_text stub_user_smsw(unsigned long force)
173 {
174  unsigned long fault = 0;
175  unsigned int tmp;
176 
177  asm volatile("testb $1, %b[fep];"
178  "jz 1f;"
180  "1: smsw %[tmp]; 2:"
181  _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
182  : "+a" (fault), [tmp] "=r" (tmp)
183  : [fep] "rm" (force),
184  [rec] "p" (ex_record_fault_eax));
185 
186  return fault;
187 }
188 
189 static const struct stub {
190  unsigned long (*fn)(unsigned long);
191  unsigned long (*user_fn)(unsigned long);
192  const char *name;
193 } stubs[] = {
194  { stub_sgdt, stub_user_sgdt, "SGDT" },
195  { stub_sidt, stub_user_sidt, "SIDT" },
196  { stub_sldt, stub_user_sldt, "SLDT" },
197  { stub_str, stub_user_str, "STR" },
198  { stub_smsw, stub_user_smsw, "SMSW" },
199 };
200 
201 static void test_insns(bool umip_active, bool force)
202 {
203  unsigned int i;
204  bool user;
205 
206  for ( user = false; ; user = true )
207  {
208  exinfo_t exp = user && umip_active ? EXINFO_SYM(GP, 0) : 0;
209 
210  for ( i = 0; i < ARRAY_SIZE(stubs); i++)
211  {
212  const struct stub *s = &stubs[i];
213  exinfo_t ret;
214 
215  ret = user ? exec_user_param(s->user_fn, force) : s->fn(force);
216 
217  /*
218  * Tolerate the instruction emulator not understanding these
219  * instructions in older releases of Xen.
220  */
221  if ( force && ret == EXINFO_SYM(UD, 0) )
222  {
223  static bool once;
224 
225  if ( !once )
226  {
227  xtf_skip("Skip: Emulator doesn't implement %s\n", s->name);
228  once = true;
229  }
230 
231  continue;
232  }
233 
234  if ( ret != exp )
235  xtf_failure("Fail: %s %s (UMIP%c, FEP%c)\n"
236  " expected %pe\n"
237  " got %pe\n",
238  user ? "user" : "supervisor", s->name,
239  umip_active ? '+' : '-',
240  force ? '+' : '-',
241  _p(exp), _p(ret));
242  }
243 
244  if ( user )
245  break;
246  }
247 }
248 
249 static void test_umip(bool umip_active)
250 {
251  test_insns(umip_active, false);
252 
253  if ( xtf_has_fep )
254  test_insns(umip_active, true);
255 }
256 
257 void test_main(void)
258 {
259  if ( !xtf_has_fep )
260  xtf_skip("FEP support not detected - some tests will be skipped\n");
261 
262  test_umip(false);
263 
264  if ( !cpu_has_umip )
265  {
266  xtf_skip("UMIP is not supported, skip the rest of test\n");
267 
269  xtf_failure("UMIP unsupported, but setting CR4 bit succeeded\n");
270 
271  return;
272  }
273 
274  /* activate UMIP */
276  return xtf_failure("Fail: Unable to activate UMIP\n");
277 
278  test_umip(true);
279 
280  /* deactivate UMIP */
282  return xtf_failure("Fail: Unable to deactivate UMIP\n");
283 
284  test_umip(false);
285 
286  xtf_success(NULL);
287 }
288 
289 /*
290  * Local variables:
291  * mode: C
292  * c-file-style: "BSD"
293  * c-basic-offset: 4
294  * tab-width: 4
295  * indent-tabs-mode: nil
296  * End:
297  */
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
unsigned long exec_user_param(unsigned long(*fn)(unsigned long), unsigned long p1)
Execute fn(p1) at user privilege, passing its return value back.
Definition: main.c:189
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 ARRAY_SIZE(a)
Definition: lib.h:8
static unsigned long stub_user_str(unsigned long force)
Definition: main.c:155
static unsigned long stub_user_sidt(unsigned long force)
Definition: main.c:121
static unsigned long stub_user_smsw(unsigned long force)
Definition: main.c:172
unsigned long(* fn)(unsigned long)
Definition: main.c:190
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use...
Definition: setup.c:276
static unsigned long stub_sldt(unsigned long force)
Definition: main.c:53
static void user(void)
Definition: main.c:43
#define __user_text
Definition: compiler.h:33
const char * name
Definition: main.c:192
#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 X86_CR4_UMIP
Definition: processor.h:55
#define GP
static unsigned long stub_sidt(unsigned long force)
Definition: main.c:36
static unsigned long stub_user_sgdt(unsigned long force)
Definition: main.c:104
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
static unsigned long stub_user_sldt(unsigned long force)
Definition: main.c:138
static unsigned long read_cr4(void)
Definition: lib.h:252
static unsigned long stub_sgdt(unsigned long force)
Definition: main.c:19
static void test_umip(bool umip_active)
Definition: main.c:249
static const struct stub stubs[]
const char test_title[]
The title of the test.
Definition: main.c:14
unsigned long(* user_fn)(unsigned long)
Definition: main.c:191
static unsigned long stub_smsw(unsigned long force)
Definition: main.c:87
static bool write_cr4_safe(unsigned long cr4)
Definition: lib.h:290
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
static unsigned long stub_str(unsigned long force)
Definition: main.c:70
#define cpu_has_umip
Definition: cpuid.h:98
static void test_insns(bool umip_active, bool force)
Definition: main.c:201
#define true
Definition: stdbool.h:10
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38