1 #include "svm.h"
2 #include "vm.h"
3 #include "alloc_page.h"
4 #include "vmalloc.h"
5
6 static void *scratch_page;
7
null_test(struct svm_test * test)8 static void null_test(struct svm_test *test)
9 {
10 }
11
npt_np_prepare(struct svm_test * test)12 static void npt_np_prepare(struct svm_test *test)
13 {
14 u64 *pte;
15
16 scratch_page = alloc_page();
17 pte = npt_get_pte((u64) scratch_page);
18
19 *pte &= ~1ULL;
20 }
21
npt_np_test(struct svm_test * test)22 static void npt_np_test(struct svm_test *test)
23 {
24 (void)*(volatile u64 *)scratch_page;
25 }
26
npt_np_check(struct svm_test * test)27 static bool npt_np_check(struct svm_test *test)
28 {
29 u64 *pte = npt_get_pte((u64) scratch_page);
30
31 *pte |= 1ULL;
32
33 return (vmcb->control.exit_code == SVM_EXIT_NPF)
34 && (vmcb->control.exit_info_1 == 0x100000004ULL);
35 }
36
npt_nx_prepare(struct svm_test * test)37 static void npt_nx_prepare(struct svm_test *test)
38 {
39 u64 *pte;
40
41 test->scratch = rdmsr(MSR_EFER);
42 wrmsr(MSR_EFER, test->scratch | EFER_NX);
43
44 /* Clear the guest's EFER.NX, it should not affect NPT behavior. */
45 vmcb->save.efer &= ~EFER_NX;
46
47 pte = npt_get_pte((u64) null_test);
48
49 *pte |= PT64_NX_MASK;
50 }
51
npt_nx_check(struct svm_test * test)52 static bool npt_nx_check(struct svm_test *test)
53 {
54 u64 *pte = npt_get_pte((u64) null_test);
55
56 wrmsr(MSR_EFER, test->scratch);
57
58 *pte &= ~PT64_NX_MASK;
59
60 return (vmcb->control.exit_code == SVM_EXIT_NPF)
61 && (vmcb->control.exit_info_1 == 0x100000015ULL);
62 }
63
npt_us_prepare(struct svm_test * test)64 static void npt_us_prepare(struct svm_test *test)
65 {
66 u64 *pte;
67
68 scratch_page = alloc_page();
69 pte = npt_get_pte((u64) scratch_page);
70
71 *pte &= ~(1ULL << 2);
72 }
73
npt_us_test(struct svm_test * test)74 static void npt_us_test(struct svm_test *test)
75 {
76 (void)*(volatile u64 *)scratch_page;
77 }
78
npt_us_check(struct svm_test * test)79 static bool npt_us_check(struct svm_test *test)
80 {
81 u64 *pte = npt_get_pte((u64) scratch_page);
82
83 *pte |= (1ULL << 2);
84
85 return (vmcb->control.exit_code == SVM_EXIT_NPF)
86 && (vmcb->control.exit_info_1 == 0x100000005ULL);
87 }
88
npt_rw_prepare(struct svm_test * test)89 static void npt_rw_prepare(struct svm_test *test)
90 {
91
92 u64 *pte;
93
94 pte = npt_get_pte(0x80000);
95
96 *pte &= ~(1ULL << 1);
97 }
98
npt_rw_test(struct svm_test * test)99 static void npt_rw_test(struct svm_test *test)
100 {
101 u64 *data = (void *)(0x80000);
102
103 *data = 0;
104 }
105
npt_rw_check(struct svm_test * test)106 static bool npt_rw_check(struct svm_test *test)
107 {
108 u64 *pte = npt_get_pte(0x80000);
109
110 *pte |= (1ULL << 1);
111
112 return (vmcb->control.exit_code == SVM_EXIT_NPF)
113 && (vmcb->control.exit_info_1 == 0x100000007ULL);
114 }
115
npt_rw_pfwalk_prepare(struct svm_test * test)116 static void npt_rw_pfwalk_prepare(struct svm_test *test)
117 {
118
119 u64 *pte;
120
121 pte = npt_get_pte(read_cr3());
122
123 *pte &= ~(1ULL << 1);
124 }
125
npt_rw_pfwalk_check(struct svm_test * test)126 static bool npt_rw_pfwalk_check(struct svm_test *test)
127 {
128 u64 *pte = npt_get_pte(read_cr3());
129
130 *pte |= (1ULL << 1);
131
132 return (vmcb->control.exit_code == SVM_EXIT_NPF)
133 && (vmcb->control.exit_info_1 == 0x200000007ULL)
134 && (vmcb->control.exit_info_2 == read_cr3());
135 }
136
npt_l1mmio_prepare(struct svm_test * test)137 static void npt_l1mmio_prepare(struct svm_test *test)
138 {
139 }
140
141 u32 nested_apic_version1;
142 u32 nested_apic_version2;
143
npt_l1mmio_test(struct svm_test * test)144 static void npt_l1mmio_test(struct svm_test *test)
145 {
146 volatile u32 *data = (volatile void *)(0xfee00030UL);
147
148 nested_apic_version1 = *data;
149 nested_apic_version2 = *data;
150 }
151
npt_l1mmio_check(struct svm_test * test)152 static bool npt_l1mmio_check(struct svm_test *test)
153 {
154 volatile u32 *data = (volatile void *)(0xfee00030);
155 u32 lvr = *data;
156
157 return nested_apic_version1 == lvr && nested_apic_version2 == lvr;
158 }
159
npt_rw_l1mmio_prepare(struct svm_test * test)160 static void npt_rw_l1mmio_prepare(struct svm_test *test)
161 {
162
163 u64 *pte;
164
165 pte = npt_get_pte(0xfee00080);
166
167 *pte &= ~(1ULL << 1);
168 }
169
npt_rw_l1mmio_test(struct svm_test * test)170 static void npt_rw_l1mmio_test(struct svm_test *test)
171 {
172 volatile u32 *data = (volatile void *)(0xfee00080);
173
174 *data = *data;
175 }
176
npt_rw_l1mmio_check(struct svm_test * test)177 static bool npt_rw_l1mmio_check(struct svm_test *test)
178 {
179 u64 *pte = npt_get_pte(0xfee00080);
180
181 *pte |= (1ULL << 1);
182
183 return (vmcb->control.exit_code == SVM_EXIT_NPF)
184 && (vmcb->control.exit_info_1 == 0x100000007ULL);
185 }
186
basic_guest_main(struct svm_test * test)187 static void basic_guest_main(struct svm_test *test)
188 {
189 }
190
__svm_npt_rsvd_bits_test(u64 * pxe,u64 rsvd_bits,u64 efer,ulong cr4,u64 guest_efer,ulong guest_cr4)191 static void __svm_npt_rsvd_bits_test(u64 * pxe, u64 rsvd_bits, u64 efer,
192 ulong cr4, u64 guest_efer, ulong guest_cr4)
193 {
194 u64 pxe_orig = *pxe;
195 int exit_reason;
196 u64 pfec;
197
198 wrmsr(MSR_EFER, efer);
199 write_cr4(cr4);
200
201 vmcb->save.efer = guest_efer;
202 vmcb->save.cr4 = guest_cr4;
203
204 *pxe |= rsvd_bits;
205
206 exit_reason = svm_vmrun();
207
208 report(exit_reason == SVM_EXIT_NPF,
209 "Wanted #NPF on rsvd bits = 0x%lx, got exit = 0x%x", rsvd_bits,
210 exit_reason);
211
212 if (pxe == npt_get_pdpe((u64) basic_guest_main) || pxe == npt_get_pml4e()) {
213 /*
214 * The guest's page tables will blow up on a bad PDPE/PML4E,
215 * before starting the final walk of the guest page.
216 */
217 pfec = 0x20000000full;
218 } else {
219 /* RSVD #NPF on final walk of guest page. */
220 pfec = 0x10000000dULL;
221
222 /* PFEC.FETCH=1 if NX=1 *or* SMEP=1. */
223 if ((cr4 & X86_CR4_SMEP) || (efer & EFER_NX))
224 pfec |= 0x10;
225
226 }
227
228 report(vmcb->control.exit_info_1 == pfec,
229 "Wanted PFEC = 0x%lx, got PFEC = %lx, PxE = 0x%lx. "
230 "host.NX = %u, host.SMEP = %u, guest.NX = %u, guest.SMEP = %u",
231 pfec, vmcb->control.exit_info_1, *pxe,
232 !!(efer & EFER_NX), !!(cr4 & X86_CR4_SMEP),
233 !!(guest_efer & EFER_NX), !!(guest_cr4 & X86_CR4_SMEP));
234
235 *pxe = pxe_orig;
236 }
237
_svm_npt_rsvd_bits_test(u64 * pxe,u64 pxe_rsvd_bits,u64 efer,ulong cr4,u64 guest_efer,ulong guest_cr4)238 static void _svm_npt_rsvd_bits_test(u64 * pxe, u64 pxe_rsvd_bits, u64 efer,
239 ulong cr4, u64 guest_efer, ulong guest_cr4)
240 {
241 u64 rsvd_bits;
242 int i;
243
244 /*
245 * RDTSC or RDRAND can sometimes fail to generate a valid reserved bits
246 */
247 if (!pxe_rsvd_bits) {
248 report_skip
249 ("svm_npt_rsvd_bits_test: Reserved bits are not valid");
250 return;
251 }
252
253 /*
254 * Test all combinations of guest/host EFER.NX and CR4.SMEP. If host
255 * EFER.NX=0, use NX as the reserved bit, otherwise use the passed in
256 * @pxe_rsvd_bits.
257 */
258 for (i = 0; i < 16; i++) {
259 if (i & 1) {
260 rsvd_bits = pxe_rsvd_bits;
261 efer |= EFER_NX;
262 } else {
263 rsvd_bits = PT64_NX_MASK;
264 efer &= ~EFER_NX;
265 }
266 if (i & 2)
267 cr4 |= X86_CR4_SMEP;
268 else
269 cr4 &= ~X86_CR4_SMEP;
270 if (i & 4)
271 guest_efer |= EFER_NX;
272 else
273 guest_efer &= ~EFER_NX;
274 if (i & 8)
275 guest_cr4 |= X86_CR4_SMEP;
276 else
277 guest_cr4 &= ~X86_CR4_SMEP;
278
279 __svm_npt_rsvd_bits_test(pxe, rsvd_bits, efer, cr4,
280 guest_efer, guest_cr4);
281 }
282 }
283
get_random_bits(u64 hi,u64 low)284 static u64 get_random_bits(u64 hi, u64 low)
285 {
286 unsigned retry = 5;
287 u64 rsvd_bits = 0;
288
289 if (this_cpu_has(X86_FEATURE_RDRAND)) {
290 do {
291 rsvd_bits = (rdrand() << low) & GENMASK_ULL(hi, low);
292 retry--;
293 } while (!rsvd_bits && retry);
294 }
295
296 if (!rsvd_bits) {
297 retry = 5;
298 do {
299 rsvd_bits = (rdtsc() << low) & GENMASK_ULL(hi, low);
300 retry--;
301 } while (!rsvd_bits && retry);
302 }
303
304 return rsvd_bits;
305 }
306
svm_npt_rsvd_bits_test(void)307 static void svm_npt_rsvd_bits_test(void)
308 {
309 u64 saved_efer, host_efer, sg_efer, guest_efer;
310 ulong saved_cr4, host_cr4, sg_cr4, guest_cr4;
311
312 if (!npt_supported()) {
313 report_skip("NPT not supported");
314 return;
315 }
316
317 saved_efer = host_efer = rdmsr(MSR_EFER);
318 saved_cr4 = host_cr4 = read_cr4();
319 sg_efer = guest_efer = vmcb->save.efer;
320 sg_cr4 = guest_cr4 = vmcb->save.cr4;
321
322 test_set_guest(basic_guest_main);
323
324 /*
325 * 4k PTEs don't have reserved bits if MAXPHYADDR >= 52, just skip the
326 * sub-test. The NX test is still valid, but the extra bit of coverage
327 * isn't worth the extra complexity.
328 */
329 if (cpuid_maxphyaddr() >= 52)
330 goto skip_pte_test;
331
332 _svm_npt_rsvd_bits_test(npt_get_pte((u64) basic_guest_main),
333 get_random_bits(51, cpuid_maxphyaddr()),
334 host_efer, host_cr4, guest_efer, guest_cr4);
335
336 skip_pte_test:
337 _svm_npt_rsvd_bits_test(npt_get_pde((u64) basic_guest_main),
338 get_random_bits(20, 13) | PT_PAGE_SIZE_MASK,
339 host_efer, host_cr4, guest_efer, guest_cr4);
340
341 _svm_npt_rsvd_bits_test(npt_get_pdpe((u64) basic_guest_main),
342 PT_PAGE_SIZE_MASK |
343 (this_cpu_has(X86_FEATURE_GBPAGES) ?
344 get_random_bits(29, 13) : 0), host_efer,
345 host_cr4, guest_efer, guest_cr4);
346
347 _svm_npt_rsvd_bits_test(npt_get_pml4e(), BIT_ULL(8),
348 host_efer, host_cr4, guest_efer, guest_cr4);
349
350 wrmsr(MSR_EFER, saved_efer);
351 write_cr4(saved_cr4);
352 vmcb->save.efer = sg_efer;
353 vmcb->save.cr4 = sg_cr4;
354 }
355
356 #define NPT_V1_TEST(name, prepare, guest_code, check) \
357 { #name, npt_supported, prepare, default_prepare_gif_clear, guest_code, \
358 default_finished, check }
359
360 #define NPT_V2_TEST(name) { #name, .v2 = name }
361
362 static struct svm_test npt_tests[] = {
363 NPT_V1_TEST(npt_nx, npt_nx_prepare, null_test, npt_nx_check),
364 NPT_V1_TEST(npt_np, npt_np_prepare, npt_np_test, npt_np_check),
365 NPT_V1_TEST(npt_us, npt_us_prepare, npt_us_test, npt_us_check),
366 NPT_V1_TEST(npt_rw, npt_rw_prepare, npt_rw_test, npt_rw_check),
367 NPT_V1_TEST(npt_rw_pfwalk, npt_rw_pfwalk_prepare, null_test, npt_rw_pfwalk_check),
368 NPT_V1_TEST(npt_l1mmio, npt_l1mmio_prepare, npt_l1mmio_test, npt_l1mmio_check),
369 NPT_V1_TEST(npt_rw_l1mmio, npt_rw_l1mmio_prepare, npt_rw_l1mmio_test, npt_rw_l1mmio_check),
370 NPT_V2_TEST(svm_npt_rsvd_bits_test),
371 { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
372 };
373
main(int ac,char ** av)374 int main(int ac, char **av)
375 {
376 pteval_t opt_mask = 0;
377
378 __setup_vm(&opt_mask);
379 return run_svm_tests(ac, av, npt_tests);
380 }
381