xref: /kvm-unit-tests/x86/svm_npt.c (revision 14b54ed754c8a8cae7a22895e4a0b745a3227a4b)
162f5db4bSSean Christopherson #include "svm.h"
262f5db4bSSean Christopherson #include "vm.h"
362f5db4bSSean Christopherson #include "alloc_page.h"
462f5db4bSSean Christopherson #include "vmalloc.h"
562f5db4bSSean Christopherson 
662f5db4bSSean Christopherson static void *scratch_page;
762f5db4bSSean Christopherson 
null_test(struct svm_test * test)862f5db4bSSean Christopherson static void null_test(struct svm_test *test)
962f5db4bSSean Christopherson {
1062f5db4bSSean Christopherson }
1162f5db4bSSean Christopherson 
npt_np_prepare(struct svm_test * test)1262f5db4bSSean Christopherson static void npt_np_prepare(struct svm_test *test)
1362f5db4bSSean Christopherson {
1462f5db4bSSean Christopherson 	u64 *pte;
1562f5db4bSSean Christopherson 
1662f5db4bSSean Christopherson 	scratch_page = alloc_page();
1762f5db4bSSean Christopherson 	pte = npt_get_pte((u64) scratch_page);
1862f5db4bSSean Christopherson 
1962f5db4bSSean Christopherson 	*pte &= ~1ULL;
2062f5db4bSSean Christopherson }
2162f5db4bSSean Christopherson 
npt_np_test(struct svm_test * test)2262f5db4bSSean Christopherson static void npt_np_test(struct svm_test *test)
2362f5db4bSSean Christopherson {
2462f5db4bSSean Christopherson 	(void)*(volatile u64 *)scratch_page;
2562f5db4bSSean Christopherson }
2662f5db4bSSean Christopherson 
npt_np_check(struct svm_test * test)2762f5db4bSSean Christopherson static bool npt_np_check(struct svm_test *test)
2862f5db4bSSean Christopherson {
2962f5db4bSSean Christopherson 	u64 *pte = npt_get_pte((u64) scratch_page);
3062f5db4bSSean Christopherson 
3162f5db4bSSean Christopherson 	*pte |= 1ULL;
3262f5db4bSSean Christopherson 
3362f5db4bSSean Christopherson 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
3462f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_1 == 0x100000004ULL);
3562f5db4bSSean Christopherson }
3662f5db4bSSean Christopherson 
npt_nx_prepare(struct svm_test * test)3762f5db4bSSean Christopherson static void npt_nx_prepare(struct svm_test *test)
3862f5db4bSSean Christopherson {
3962f5db4bSSean Christopherson 	u64 *pte;
4062f5db4bSSean Christopherson 
4162f5db4bSSean Christopherson 	test->scratch = rdmsr(MSR_EFER);
4262f5db4bSSean Christopherson 	wrmsr(MSR_EFER, test->scratch | EFER_NX);
4362f5db4bSSean Christopherson 
4462f5db4bSSean Christopherson 	/* Clear the guest's EFER.NX, it should not affect NPT behavior. */
4562f5db4bSSean Christopherson 	vmcb->save.efer &= ~EFER_NX;
4662f5db4bSSean Christopherson 
4762f5db4bSSean Christopherson 	pte = npt_get_pte((u64) null_test);
4862f5db4bSSean Christopherson 
4962f5db4bSSean Christopherson 	*pte |= PT64_NX_MASK;
5062f5db4bSSean Christopherson }
5162f5db4bSSean Christopherson 
npt_nx_check(struct svm_test * test)5262f5db4bSSean Christopherson static bool npt_nx_check(struct svm_test *test)
5362f5db4bSSean Christopherson {
5462f5db4bSSean Christopherson 	u64 *pte = npt_get_pte((u64) null_test);
5562f5db4bSSean Christopherson 
5662f5db4bSSean Christopherson 	wrmsr(MSR_EFER, test->scratch);
5762f5db4bSSean Christopherson 
5862f5db4bSSean Christopherson 	*pte &= ~PT64_NX_MASK;
5962f5db4bSSean Christopherson 
6062f5db4bSSean Christopherson 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
6162f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_1 == 0x100000015ULL);
6262f5db4bSSean Christopherson }
6362f5db4bSSean Christopherson 
npt_us_prepare(struct svm_test * test)6462f5db4bSSean Christopherson static void npt_us_prepare(struct svm_test *test)
6562f5db4bSSean Christopherson {
6662f5db4bSSean Christopherson 	u64 *pte;
6762f5db4bSSean Christopherson 
6862f5db4bSSean Christopherson 	scratch_page = alloc_page();
6962f5db4bSSean Christopherson 	pte = npt_get_pte((u64) scratch_page);
7062f5db4bSSean Christopherson 
7162f5db4bSSean Christopherson 	*pte &= ~(1ULL << 2);
7262f5db4bSSean Christopherson }
7362f5db4bSSean Christopherson 
npt_us_test(struct svm_test * test)7462f5db4bSSean Christopherson static void npt_us_test(struct svm_test *test)
7562f5db4bSSean Christopherson {
7662f5db4bSSean Christopherson 	(void)*(volatile u64 *)scratch_page;
7762f5db4bSSean Christopherson }
7862f5db4bSSean Christopherson 
npt_us_check(struct svm_test * test)7962f5db4bSSean Christopherson static bool npt_us_check(struct svm_test *test)
8062f5db4bSSean Christopherson {
8162f5db4bSSean Christopherson 	u64 *pte = npt_get_pte((u64) scratch_page);
8262f5db4bSSean Christopherson 
8362f5db4bSSean Christopherson 	*pte |= (1ULL << 2);
8462f5db4bSSean Christopherson 
8562f5db4bSSean Christopherson 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
8662f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_1 == 0x100000005ULL);
8762f5db4bSSean Christopherson }
8862f5db4bSSean Christopherson 
npt_rw_prepare(struct svm_test * test)8962f5db4bSSean Christopherson static void npt_rw_prepare(struct svm_test *test)
9062f5db4bSSean Christopherson {
9162f5db4bSSean Christopherson 
9262f5db4bSSean Christopherson 	u64 *pte;
9362f5db4bSSean Christopherson 
9462f5db4bSSean Christopherson 	pte = npt_get_pte(0x80000);
9562f5db4bSSean Christopherson 
9662f5db4bSSean Christopherson 	*pte &= ~(1ULL << 1);
9762f5db4bSSean Christopherson }
9862f5db4bSSean Christopherson 
npt_rw_test(struct svm_test * test)9962f5db4bSSean Christopherson static void npt_rw_test(struct svm_test *test)
10062f5db4bSSean Christopherson {
10162f5db4bSSean Christopherson 	u64 *data = (void *)(0x80000);
10262f5db4bSSean Christopherson 
10362f5db4bSSean Christopherson 	*data = 0;
10462f5db4bSSean Christopherson }
10562f5db4bSSean Christopherson 
npt_rw_check(struct svm_test * test)10662f5db4bSSean Christopherson static bool npt_rw_check(struct svm_test *test)
10762f5db4bSSean Christopherson {
10862f5db4bSSean Christopherson 	u64 *pte = npt_get_pte(0x80000);
10962f5db4bSSean Christopherson 
11062f5db4bSSean Christopherson 	*pte |= (1ULL << 1);
11162f5db4bSSean Christopherson 
11262f5db4bSSean Christopherson 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
11362f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_1 == 0x100000007ULL);
11462f5db4bSSean Christopherson }
11562f5db4bSSean Christopherson 
npt_rw_pfwalk_prepare(struct svm_test * test)11662f5db4bSSean Christopherson static void npt_rw_pfwalk_prepare(struct svm_test *test)
11762f5db4bSSean Christopherson {
11862f5db4bSSean Christopherson 
11962f5db4bSSean Christopherson 	u64 *pte;
12062f5db4bSSean Christopherson 
12162f5db4bSSean Christopherson 	pte = npt_get_pte(read_cr3());
12262f5db4bSSean Christopherson 
12362f5db4bSSean Christopherson 	*pte &= ~(1ULL << 1);
12462f5db4bSSean Christopherson }
12562f5db4bSSean Christopherson 
npt_rw_pfwalk_check(struct svm_test * test)12662f5db4bSSean Christopherson static bool npt_rw_pfwalk_check(struct svm_test *test)
12762f5db4bSSean Christopherson {
12862f5db4bSSean Christopherson 	u64 *pte = npt_get_pte(read_cr3());
12962f5db4bSSean Christopherson 
13062f5db4bSSean Christopherson 	*pte |= (1ULL << 1);
13162f5db4bSSean Christopherson 
13262f5db4bSSean Christopherson 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
13362f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_1 == 0x200000007ULL)
13462f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_2 == read_cr3());
13562f5db4bSSean Christopherson }
13662f5db4bSSean Christopherson 
npt_l1mmio_prepare(struct svm_test * test)13762f5db4bSSean Christopherson static void npt_l1mmio_prepare(struct svm_test *test)
13862f5db4bSSean Christopherson {
13962f5db4bSSean Christopherson }
14062f5db4bSSean Christopherson 
14162f5db4bSSean Christopherson u32 nested_apic_version1;
14262f5db4bSSean Christopherson u32 nested_apic_version2;
14362f5db4bSSean Christopherson 
npt_l1mmio_test(struct svm_test * test)14462f5db4bSSean Christopherson static void npt_l1mmio_test(struct svm_test *test)
14562f5db4bSSean Christopherson {
14662f5db4bSSean Christopherson 	volatile u32 *data = (volatile void *)(0xfee00030UL);
14762f5db4bSSean Christopherson 
14862f5db4bSSean Christopherson 	nested_apic_version1 = *data;
14962f5db4bSSean Christopherson 	nested_apic_version2 = *data;
15062f5db4bSSean Christopherson }
15162f5db4bSSean Christopherson 
npt_l1mmio_check(struct svm_test * test)15262f5db4bSSean Christopherson static bool npt_l1mmio_check(struct svm_test *test)
15362f5db4bSSean Christopherson {
15462f5db4bSSean Christopherson 	volatile u32 *data = (volatile void *)(0xfee00030);
15562f5db4bSSean Christopherson 	u32 lvr = *data;
15662f5db4bSSean Christopherson 
15762f5db4bSSean Christopherson 	return nested_apic_version1 == lvr && nested_apic_version2 == lvr;
15862f5db4bSSean Christopherson }
15962f5db4bSSean Christopherson 
npt_rw_l1mmio_prepare(struct svm_test * test)16062f5db4bSSean Christopherson static void npt_rw_l1mmio_prepare(struct svm_test *test)
16162f5db4bSSean Christopherson {
16262f5db4bSSean Christopherson 
16362f5db4bSSean Christopherson 	u64 *pte;
16462f5db4bSSean Christopherson 
16562f5db4bSSean Christopherson 	pte = npt_get_pte(0xfee00080);
16662f5db4bSSean Christopherson 
16762f5db4bSSean Christopherson 	*pte &= ~(1ULL << 1);
16862f5db4bSSean Christopherson }
16962f5db4bSSean Christopherson 
npt_rw_l1mmio_test(struct svm_test * test)17062f5db4bSSean Christopherson static void npt_rw_l1mmio_test(struct svm_test *test)
17162f5db4bSSean Christopherson {
17262f5db4bSSean Christopherson 	volatile u32 *data = (volatile void *)(0xfee00080);
17362f5db4bSSean Christopherson 
17462f5db4bSSean Christopherson 	*data = *data;
17562f5db4bSSean Christopherson }
17662f5db4bSSean Christopherson 
npt_rw_l1mmio_check(struct svm_test * test)17762f5db4bSSean Christopherson static bool npt_rw_l1mmio_check(struct svm_test *test)
17862f5db4bSSean Christopherson {
17962f5db4bSSean Christopherson 	u64 *pte = npt_get_pte(0xfee00080);
18062f5db4bSSean Christopherson 
18162f5db4bSSean Christopherson 	*pte |= (1ULL << 1);
18262f5db4bSSean Christopherson 
18362f5db4bSSean Christopherson 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
18462f5db4bSSean Christopherson 	    && (vmcb->control.exit_info_1 == 0x100000007ULL);
18562f5db4bSSean Christopherson }
18662f5db4bSSean Christopherson 
basic_guest_main(struct svm_test * test)18762f5db4bSSean Christopherson static void basic_guest_main(struct svm_test *test)
18862f5db4bSSean Christopherson {
18962f5db4bSSean Christopherson }
19062f5db4bSSean Christopherson 
__svm_npt_rsvd_bits_test(u64 * pxe,u64 rsvd_bits,u64 efer,ulong cr4,u64 guest_efer,ulong guest_cr4)19162f5db4bSSean Christopherson static void __svm_npt_rsvd_bits_test(u64 * pxe, u64 rsvd_bits, u64 efer,
19262f5db4bSSean Christopherson 				     ulong cr4, u64 guest_efer, ulong guest_cr4)
19362f5db4bSSean Christopherson {
19462f5db4bSSean Christopherson 	u64 pxe_orig = *pxe;
19562f5db4bSSean Christopherson 	int exit_reason;
19662f5db4bSSean Christopherson 	u64 pfec;
19762f5db4bSSean Christopherson 
19862f5db4bSSean Christopherson 	wrmsr(MSR_EFER, efer);
19962f5db4bSSean Christopherson 	write_cr4(cr4);
20062f5db4bSSean Christopherson 
20162f5db4bSSean Christopherson 	vmcb->save.efer = guest_efer;
20262f5db4bSSean Christopherson 	vmcb->save.cr4 = guest_cr4;
20362f5db4bSSean Christopherson 
20462f5db4bSSean Christopherson 	*pxe |= rsvd_bits;
20562f5db4bSSean Christopherson 
20662f5db4bSSean Christopherson 	exit_reason = svm_vmrun();
20762f5db4bSSean Christopherson 
20862f5db4bSSean Christopherson 	report(exit_reason == SVM_EXIT_NPF,
20962f5db4bSSean Christopherson 	       "Wanted #NPF on rsvd bits = 0x%lx, got exit = 0x%x", rsvd_bits,
21062f5db4bSSean Christopherson 	       exit_reason);
21162f5db4bSSean Christopherson 
2126f5ce7c1SManali Shukla 	if (pxe == npt_get_pdpe((u64) basic_guest_main) || pxe == npt_get_pml4e()) {
21362f5db4bSSean Christopherson 		/*
21462f5db4bSSean Christopherson 		 * The guest's page tables will blow up on a bad PDPE/PML4E,
21562f5db4bSSean Christopherson 		 * before starting the final walk of the guest page.
21662f5db4bSSean Christopherson 		 */
21762f5db4bSSean Christopherson 		pfec = 0x20000000full;
21862f5db4bSSean Christopherson 	} else {
21962f5db4bSSean Christopherson 		/* RSVD #NPF on final walk of guest page. */
22062f5db4bSSean Christopherson 		pfec = 0x10000000dULL;
22162f5db4bSSean Christopherson 
22262f5db4bSSean Christopherson 		/* PFEC.FETCH=1 if NX=1 *or* SMEP=1. */
22362f5db4bSSean Christopherson 		if ((cr4 & X86_CR4_SMEP) || (efer & EFER_NX))
22462f5db4bSSean Christopherson 			pfec |= 0x10;
22562f5db4bSSean Christopherson 
22662f5db4bSSean Christopherson 	}
22762f5db4bSSean Christopherson 
22862f5db4bSSean Christopherson 	report(vmcb->control.exit_info_1 == pfec,
22962f5db4bSSean Christopherson 	       "Wanted PFEC = 0x%lx, got PFEC = %lx, PxE = 0x%lx.  "
23062f5db4bSSean Christopherson 	       "host.NX = %u, host.SMEP = %u, guest.NX = %u, guest.SMEP = %u",
23162f5db4bSSean Christopherson 	       pfec, vmcb->control.exit_info_1, *pxe,
23262f5db4bSSean Christopherson 	       !!(efer & EFER_NX), !!(cr4 & X86_CR4_SMEP),
23362f5db4bSSean Christopherson 	       !!(guest_efer & EFER_NX), !!(guest_cr4 & X86_CR4_SMEP));
23462f5db4bSSean Christopherson 
23562f5db4bSSean Christopherson 	*pxe = pxe_orig;
23662f5db4bSSean Christopherson }
23762f5db4bSSean Christopherson 
_svm_npt_rsvd_bits_test(u64 * pxe,u64 pxe_rsvd_bits,u64 efer,ulong cr4,u64 guest_efer,ulong guest_cr4)23862f5db4bSSean Christopherson static void _svm_npt_rsvd_bits_test(u64 * pxe, u64 pxe_rsvd_bits, u64 efer,
23962f5db4bSSean Christopherson 				    ulong cr4, u64 guest_efer, ulong guest_cr4)
24062f5db4bSSean Christopherson {
24162f5db4bSSean Christopherson 	u64 rsvd_bits;
24262f5db4bSSean Christopherson 	int i;
24362f5db4bSSean Christopherson 
24462f5db4bSSean Christopherson 	/*
24562f5db4bSSean Christopherson 	 * RDTSC or RDRAND can sometimes fail to generate a valid reserved bits
24662f5db4bSSean Christopherson 	 */
24762f5db4bSSean Christopherson 	if (!pxe_rsvd_bits) {
24862f5db4bSSean Christopherson 		report_skip
24962f5db4bSSean Christopherson 		    ("svm_npt_rsvd_bits_test: Reserved bits are not valid");
25062f5db4bSSean Christopherson 		return;
25162f5db4bSSean Christopherson 	}
25262f5db4bSSean Christopherson 
25362f5db4bSSean Christopherson 	/*
25462f5db4bSSean Christopherson 	 * Test all combinations of guest/host EFER.NX and CR4.SMEP.  If host
25562f5db4bSSean Christopherson 	 * EFER.NX=0, use NX as the reserved bit, otherwise use the passed in
25662f5db4bSSean Christopherson 	 * @pxe_rsvd_bits.
25762f5db4bSSean Christopherson 	 */
25862f5db4bSSean Christopherson 	for (i = 0; i < 16; i++) {
25962f5db4bSSean Christopherson 		if (i & 1) {
26062f5db4bSSean Christopherson 			rsvd_bits = pxe_rsvd_bits;
26162f5db4bSSean Christopherson 			efer |= EFER_NX;
26262f5db4bSSean Christopherson 		} else {
26362f5db4bSSean Christopherson 			rsvd_bits = PT64_NX_MASK;
26462f5db4bSSean Christopherson 			efer &= ~EFER_NX;
26562f5db4bSSean Christopherson 		}
26662f5db4bSSean Christopherson 		if (i & 2)
26762f5db4bSSean Christopherson 			cr4 |= X86_CR4_SMEP;
26862f5db4bSSean Christopherson 		else
26962f5db4bSSean Christopherson 			cr4 &= ~X86_CR4_SMEP;
27062f5db4bSSean Christopherson 		if (i & 4)
27162f5db4bSSean Christopherson 			guest_efer |= EFER_NX;
27262f5db4bSSean Christopherson 		else
27362f5db4bSSean Christopherson 			guest_efer &= ~EFER_NX;
27462f5db4bSSean Christopherson 		if (i & 8)
27562f5db4bSSean Christopherson 			guest_cr4 |= X86_CR4_SMEP;
27662f5db4bSSean Christopherson 		else
27762f5db4bSSean Christopherson 			guest_cr4 &= ~X86_CR4_SMEP;
27862f5db4bSSean Christopherson 
27962f5db4bSSean Christopherson 		__svm_npt_rsvd_bits_test(pxe, rsvd_bits, efer, cr4,
28062f5db4bSSean Christopherson 					 guest_efer, guest_cr4);
28162f5db4bSSean Christopherson 	}
28262f5db4bSSean Christopherson }
28362f5db4bSSean Christopherson 
get_random_bits(u64 hi,u64 low)28462f5db4bSSean Christopherson static u64 get_random_bits(u64 hi, u64 low)
28562f5db4bSSean Christopherson {
28662f5db4bSSean Christopherson 	unsigned retry = 5;
28762f5db4bSSean Christopherson 	u64 rsvd_bits = 0;
28862f5db4bSSean Christopherson 
28962f5db4bSSean Christopherson 	if (this_cpu_has(X86_FEATURE_RDRAND)) {
29062f5db4bSSean Christopherson 		do {
29162f5db4bSSean Christopherson 			rsvd_bits = (rdrand() << low) & GENMASK_ULL(hi, low);
29262f5db4bSSean Christopherson 			retry--;
29362f5db4bSSean Christopherson 		} while (!rsvd_bits && retry);
29462f5db4bSSean Christopherson 	}
29562f5db4bSSean Christopherson 
29662f5db4bSSean Christopherson 	if (!rsvd_bits) {
29762f5db4bSSean Christopherson 		retry = 5;
29862f5db4bSSean Christopherson 		do {
29962f5db4bSSean Christopherson 			rsvd_bits = (rdtsc() << low) & GENMASK_ULL(hi, low);
30062f5db4bSSean Christopherson 			retry--;
30162f5db4bSSean Christopherson 		} while (!rsvd_bits && retry);
30262f5db4bSSean Christopherson 	}
30362f5db4bSSean Christopherson 
30462f5db4bSSean Christopherson 	return rsvd_bits;
30562f5db4bSSean Christopherson }
30662f5db4bSSean Christopherson 
svm_npt_rsvd_bits_test(void)30762f5db4bSSean Christopherson static void svm_npt_rsvd_bits_test(void)
30862f5db4bSSean Christopherson {
30962f5db4bSSean Christopherson 	u64 saved_efer, host_efer, sg_efer, guest_efer;
31062f5db4bSSean Christopherson 	ulong saved_cr4, host_cr4, sg_cr4, guest_cr4;
31162f5db4bSSean Christopherson 
31262f5db4bSSean Christopherson 	if (!npt_supported()) {
31362f5db4bSSean Christopherson 		report_skip("NPT not supported");
31462f5db4bSSean Christopherson 		return;
31562f5db4bSSean Christopherson 	}
31662f5db4bSSean Christopherson 
31762f5db4bSSean Christopherson 	saved_efer = host_efer = rdmsr(MSR_EFER);
31862f5db4bSSean Christopherson 	saved_cr4 = host_cr4 = read_cr4();
31962f5db4bSSean Christopherson 	sg_efer = guest_efer = vmcb->save.efer;
32062f5db4bSSean Christopherson 	sg_cr4 = guest_cr4 = vmcb->save.cr4;
32162f5db4bSSean Christopherson 
32262f5db4bSSean Christopherson 	test_set_guest(basic_guest_main);
32362f5db4bSSean Christopherson 
32462f5db4bSSean Christopherson 	/*
32562f5db4bSSean Christopherson 	 * 4k PTEs don't have reserved bits if MAXPHYADDR >= 52, just skip the
32662f5db4bSSean Christopherson 	 * sub-test.  The NX test is still valid, but the extra bit of coverage
32762f5db4bSSean Christopherson 	 * isn't worth the extra complexity.
32862f5db4bSSean Christopherson 	 */
32962f5db4bSSean Christopherson 	if (cpuid_maxphyaddr() >= 52)
33062f5db4bSSean Christopherson 		goto skip_pte_test;
33162f5db4bSSean Christopherson 
33262f5db4bSSean Christopherson 	_svm_npt_rsvd_bits_test(npt_get_pte((u64) basic_guest_main),
33362f5db4bSSean Christopherson 				get_random_bits(51, cpuid_maxphyaddr()),
33462f5db4bSSean Christopherson 				host_efer, host_cr4, guest_efer, guest_cr4);
33562f5db4bSSean Christopherson 
33662f5db4bSSean Christopherson skip_pte_test:
33762f5db4bSSean Christopherson 	_svm_npt_rsvd_bits_test(npt_get_pde((u64) basic_guest_main),
33862f5db4bSSean Christopherson 				get_random_bits(20, 13) | PT_PAGE_SIZE_MASK,
33962f5db4bSSean Christopherson 				host_efer, host_cr4, guest_efer, guest_cr4);
34062f5db4bSSean Christopherson 
3416f5ce7c1SManali Shukla 	_svm_npt_rsvd_bits_test(npt_get_pdpe((u64) basic_guest_main),
34262f5db4bSSean Christopherson 				PT_PAGE_SIZE_MASK |
34362f5db4bSSean Christopherson 				(this_cpu_has(X86_FEATURE_GBPAGES) ?
34462f5db4bSSean Christopherson 				 get_random_bits(29, 13) : 0), host_efer,
34562f5db4bSSean Christopherson 				host_cr4, guest_efer, guest_cr4);
34662f5db4bSSean Christopherson 
34762f5db4bSSean Christopherson 	_svm_npt_rsvd_bits_test(npt_get_pml4e(), BIT_ULL(8),
34862f5db4bSSean Christopherson 				host_efer, host_cr4, guest_efer, guest_cr4);
34962f5db4bSSean Christopherson 
35062f5db4bSSean Christopherson 	wrmsr(MSR_EFER, saved_efer);
35162f5db4bSSean Christopherson 	write_cr4(saved_cr4);
35262f5db4bSSean Christopherson 	vmcb->save.efer = sg_efer;
35362f5db4bSSean Christopherson 	vmcb->save.cr4 = sg_cr4;
35462f5db4bSSean Christopherson }
35562f5db4bSSean Christopherson 
356*cf75a19cSSean Christopherson #define NPT_V1_TEST(name, prepare, guest_code, check)				\
357*cf75a19cSSean Christopherson 	{ #name, npt_supported, prepare, default_prepare_gif_clear, guest_code,	\
358*cf75a19cSSean Christopherson 	  default_finished, check }
359*cf75a19cSSean Christopherson 
360*cf75a19cSSean Christopherson #define NPT_V2_TEST(name) { #name, .v2 = name }
36162f5db4bSSean Christopherson 
36262f5db4bSSean Christopherson static struct svm_test npt_tests[] = {
363*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_nx, npt_nx_prepare, null_test, npt_nx_check),
364*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_np, npt_np_prepare, npt_np_test, npt_np_check),
365*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_us, npt_us_prepare, npt_us_test, npt_us_check),
366*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_rw, npt_rw_prepare, npt_rw_test, npt_rw_check),
367*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_rw_pfwalk, npt_rw_pfwalk_prepare, null_test, npt_rw_pfwalk_check),
368*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_l1mmio, npt_l1mmio_prepare, npt_l1mmio_test, npt_l1mmio_check),
369*cf75a19cSSean Christopherson 	NPT_V1_TEST(npt_rw_l1mmio, npt_rw_l1mmio_prepare, npt_rw_l1mmio_test, npt_rw_l1mmio_check),
370*cf75a19cSSean Christopherson 	NPT_V2_TEST(svm_npt_rsvd_bits_test),
37162f5db4bSSean Christopherson 	{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
37262f5db4bSSean Christopherson };
37362f5db4bSSean Christopherson 
main(int ac,char ** av)37462f5db4bSSean Christopherson int main(int ac, char **av)
37562f5db4bSSean Christopherson {
37662f5db4bSSean Christopherson 	pteval_t opt_mask = 0;
37762f5db4bSSean Christopherson 
37862f5db4bSSean Christopherson 	__setup_vm(&opt_mask);
37962f5db4bSSean Christopherson 	return run_svm_tests(ac, av, npt_tests);
38062f5db4bSSean Christopherson }
381