Xen Test Framework
main.c
Go to the documentation of this file.
1
15#include <xtf.h>
16
17const char test_title[] = "User-Mode Instruction Prevention Tests";
18
19static 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
36static 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
53static 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
70static 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
87static 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
104static 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
121static 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
138static 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
155static 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
172static 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
189static 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" },
200
201static 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
249static 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
257void 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
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 */
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
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 cpu_has_umip
Definition: cpuid.h:99
static unsigned long read_cr4(void)
Definition: lib.h:252
static bool write_cr4_safe(unsigned long cr4)
Definition: lib.h:290
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use.
Definition: setup.c:276
#define __user_text
Definition: compiler.h:33
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:110
const char test_title[]
The title of the test.
Definition: main.c:24
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
#define ARRAY_SIZE(a)
Definition: lib.h:8
unsigned long exec_user_param(unsigned long(*fn)(unsigned long), unsigned long p1)
Execute fn(p1) at user privilege, passing its return value back.
static void user(void)
Definition: main.c:43
#define GP
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define X86_CR4_UMIP
Definition: processor.h:55
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define true
Definition: stdbool.h:10
#define NULL
Definition: stddef.h:12
Definition: main.c:189
const char * name
Definition: main.c:192
unsigned long(* user_fn)(unsigned long)
Definition: main.c:191
unsigned long(* fn)(unsigned long)
Definition: main.c:190
static unsigned long stub_str(unsigned long force)
Definition: main.c:70
static unsigned long stub_sgdt(unsigned long force)
Definition: main.c:19
static unsigned long stub_user_sgdt(unsigned long force)
Definition: main.c:104
static unsigned long stub_sldt(unsigned long force)
Definition: main.c:53
static void test_umip(bool umip_active)
Definition: main.c:249
static unsigned long stub_sidt(unsigned long force)
Definition: main.c:36
static unsigned long stub_smsw(unsigned long force)
Definition: main.c:87
static unsigned long stub_user_str(unsigned long force)
Definition: main.c:155
static unsigned long stub_user_sldt(unsigned long force)
Definition: main.c:138
static void test_insns(bool umip_active, bool force)
Definition: main.c:201
static unsigned long stub_user_smsw(unsigned long force)
Definition: main.c:172
static const struct stub stubs[]
static unsigned long stub_user_sidt(unsigned long force)
Definition: main.c:121