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