xref: /kvm-unit-tests/x86/svm.c (revision eb8a146b2cefa7b8fc30f8e1d6f7250ea673a97b)
1ad879127SKrish Sadhukhan /*
2ad879127SKrish Sadhukhan  * Framework for testing nested virtualization
3ad879127SKrish Sadhukhan  */
4ad879127SKrish Sadhukhan 
57d36db35SAvi Kivity #include "svm.h"
67d36db35SAvi Kivity #include "libcflat.h"
77d36db35SAvi Kivity #include "processor.h"
8b46094b4SPaolo Bonzini #include "desc.h"
97d36db35SAvi Kivity #include "msr.h"
107d36db35SAvi Kivity #include "vm.h"
117d36db35SAvi Kivity #include "smp.h"
127d36db35SAvi Kivity #include "types.h"
135aca024eSPaolo Bonzini #include "alloc_page.h"
14306bb7dbSCathy Avery #include "isr.h"
15306bb7dbSCathy Avery #include "apic.h"
16916635a8SSean Christopherson #include "vmalloc.h"
177d36db35SAvi Kivity 
181535bf0fSJoerg Roedel /* for the nested page table*/
191535bf0fSJoerg Roedel u64 *pte[2048];
20ad879127SKrish Sadhukhan u64 *pde[4];
21ad879127SKrish Sadhukhan u64 *pdpe;
22ad879127SKrish Sadhukhan u64 *pml4e;
231535bf0fSJoerg Roedel 
24096cf7feSPaolo Bonzini struct vmcb *vmcb;
25096cf7feSPaolo Bonzini 
26ad879127SKrish Sadhukhan u64 *npt_get_pte(u64 address)
271535bf0fSJoerg Roedel {
28ad879127SKrish Sadhukhan 	int i1, i2;
29ad879127SKrish Sadhukhan 
30ad879127SKrish Sadhukhan 	address >>= 12;
31ad879127SKrish Sadhukhan 	i1 = (address >> 9) & 0x7ff;
32ad879127SKrish Sadhukhan 	i2 = address & 0x1ff;
33ad879127SKrish Sadhukhan 
34ad879127SKrish Sadhukhan 	return &pte[i1][i2];
351535bf0fSJoerg Roedel }
361535bf0fSJoerg Roedel 
37ad879127SKrish Sadhukhan u64 *npt_get_pde(u64 address)
38f6a2ca45SPaolo Bonzini {
39f6a2ca45SPaolo Bonzini 	int i1, i2;
40f6a2ca45SPaolo Bonzini 
41f6a2ca45SPaolo Bonzini 	address >>= 21;
42f6a2ca45SPaolo Bonzini 	i1 = (address >> 9) & 0x3;
43f6a2ca45SPaolo Bonzini 	i2 = address & 0x1ff;
44f6a2ca45SPaolo Bonzini 
45f6a2ca45SPaolo Bonzini 	return &pde[i1][i2];
46f6a2ca45SPaolo Bonzini }
47f6a2ca45SPaolo Bonzini 
48ad879127SKrish Sadhukhan u64 *npt_get_pdpe(void)
498594b943SJoerg Roedel {
50ad879127SKrish Sadhukhan 	return pdpe;
51ad879127SKrish Sadhukhan }
528594b943SJoerg Roedel 
53c6405e37SNadav Amit u64 *npt_get_pml4e(void)
54c6405e37SNadav Amit {
55c6405e37SNadav Amit 	return pml4e;
56c6405e37SNadav Amit }
57c6405e37SNadav Amit 
58ad879127SKrish Sadhukhan bool smp_supported(void)
59ad879127SKrish Sadhukhan {
60ad879127SKrish Sadhukhan 	return cpu_count() > 1;
61ad879127SKrish Sadhukhan }
628594b943SJoerg Roedel 
63ad879127SKrish Sadhukhan bool default_supported(void)
64ad879127SKrish Sadhukhan {
65ad879127SKrish Sadhukhan     return true;
66ad879127SKrish Sadhukhan }
67ad879127SKrish Sadhukhan 
68f6972bd6SLara Lazier bool vgif_supported(void)
69f6972bd6SLara Lazier {
70f6972bd6SLara Lazier 	return this_cpu_has(X86_FEATURE_VGIF);
71f6972bd6SLara Lazier }
72f6972bd6SLara Lazier 
73ad879127SKrish Sadhukhan void default_prepare(struct svm_test *test)
74ad879127SKrish Sadhukhan {
75096cf7feSPaolo Bonzini 	vmcb_ident(vmcb);
76ad879127SKrish Sadhukhan }
77ad879127SKrish Sadhukhan 
78ad879127SKrish Sadhukhan void default_prepare_gif_clear(struct svm_test *test)
79ad879127SKrish Sadhukhan {
80ad879127SKrish Sadhukhan }
81ad879127SKrish Sadhukhan 
82ad879127SKrish Sadhukhan bool default_finished(struct svm_test *test)
83ad879127SKrish Sadhukhan {
84ad879127SKrish Sadhukhan 	return true; /* one vmexit */
85ad879127SKrish Sadhukhan }
86ad879127SKrish Sadhukhan 
87ad879127SKrish Sadhukhan bool npt_supported(void)
88ad879127SKrish Sadhukhan {
89ad879127SKrish Sadhukhan 	return this_cpu_has(X86_FEATURE_NPT);
90ad879127SKrish Sadhukhan }
91ad879127SKrish Sadhukhan 
92ad879127SKrish Sadhukhan int get_test_stage(struct svm_test *test)
93ad879127SKrish Sadhukhan {
94ad879127SKrish Sadhukhan 	barrier();
95ad879127SKrish Sadhukhan 	return test->scratch;
96ad879127SKrish Sadhukhan }
97ad879127SKrish Sadhukhan 
98ad879127SKrish Sadhukhan void set_test_stage(struct svm_test *test, int s)
99ad879127SKrish Sadhukhan {
100ad879127SKrish Sadhukhan 	barrier();
101ad879127SKrish Sadhukhan 	test->scratch = s;
102ad879127SKrish Sadhukhan 	barrier();
103ad879127SKrish Sadhukhan }
104ad879127SKrish Sadhukhan 
105ad879127SKrish Sadhukhan void inc_test_stage(struct svm_test *test)
106ad879127SKrish Sadhukhan {
107ad879127SKrish Sadhukhan 	barrier();
108ad879127SKrish Sadhukhan 	test->scratch++;
109ad879127SKrish Sadhukhan 	barrier();
1108594b943SJoerg Roedel }
1118594b943SJoerg Roedel 
1127d36db35SAvi Kivity static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector,
1137d36db35SAvi Kivity                          u64 base, u32 limit, u32 attr)
1147d36db35SAvi Kivity {
1157d36db35SAvi Kivity 	seg->selector = selector;
1167d36db35SAvi Kivity 	seg->attrib = attr;
1177d36db35SAvi Kivity 	seg->limit = limit;
1187d36db35SAvi Kivity 	seg->base = base;
1197d36db35SAvi Kivity }
1207d36db35SAvi Kivity 
121ad879127SKrish Sadhukhan inline void vmmcall(void)
122ad879127SKrish Sadhukhan {
123ad879127SKrish Sadhukhan 	asm volatile ("vmmcall" : : : "memory");
124ad879127SKrish Sadhukhan }
125ad879127SKrish Sadhukhan 
1268660d1b5SKrish Sadhukhan static test_guest_func guest_main;
1278660d1b5SKrish Sadhukhan 
1288660d1b5SKrish Sadhukhan void test_set_guest(test_guest_func func)
1298660d1b5SKrish Sadhukhan {
1308660d1b5SKrish Sadhukhan 	guest_main = func;
1318660d1b5SKrish Sadhukhan }
1328660d1b5SKrish Sadhukhan 
133ad879127SKrish Sadhukhan static void test_thunk(struct svm_test *test)
134ad879127SKrish Sadhukhan {
1358660d1b5SKrish Sadhukhan 	guest_main(test);
136ad879127SKrish Sadhukhan 	vmmcall();
137ad879127SKrish Sadhukhan }
138ad879127SKrish Sadhukhan 
139ad879127SKrish Sadhukhan u8 *io_bitmap;
140ad879127SKrish Sadhukhan u8 io_bitmap_area[16384];
141ad879127SKrish Sadhukhan 
142ad879127SKrish Sadhukhan u8 *msr_bitmap;
143ad879127SKrish Sadhukhan u8 msr_bitmap_area[MSR_BITMAP_SIZE + PAGE_SIZE];
144ad879127SKrish Sadhukhan 
145ad879127SKrish Sadhukhan void vmcb_ident(struct vmcb *vmcb)
1467d36db35SAvi Kivity {
1477d36db35SAvi Kivity 	u64 vmcb_phys = virt_to_phys(vmcb);
1487d36db35SAvi Kivity 	struct vmcb_save_area *save = &vmcb->save;
1497d36db35SAvi Kivity 	struct vmcb_control_area *ctrl = &vmcb->control;
1507d36db35SAvi Kivity 	u32 data_seg_attr = 3 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
1517d36db35SAvi Kivity 	    | SVM_SELECTOR_DB_MASK | SVM_SELECTOR_G_MASK;
1527d36db35SAvi Kivity 	u32 code_seg_attr = 9 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
1537d36db35SAvi Kivity 	    | SVM_SELECTOR_L_MASK | SVM_SELECTOR_G_MASK;
1547d36db35SAvi Kivity 	struct descriptor_table_ptr desc_table_ptr;
1557d36db35SAvi Kivity 
1567d36db35SAvi Kivity 	memset(vmcb, 0, sizeof(*vmcb));
1572c6589bcSPeter Shier 	asm volatile ("vmsave %0" : : "a"(vmcb_phys) : "memory");
1587d36db35SAvi Kivity 	vmcb_set_seg(&save->es, read_es(), 0, -1U, data_seg_attr);
1597d36db35SAvi Kivity 	vmcb_set_seg(&save->cs, read_cs(), 0, -1U, code_seg_attr);
1607d36db35SAvi Kivity 	vmcb_set_seg(&save->ss, read_ss(), 0, -1U, data_seg_attr);
1617d36db35SAvi Kivity 	vmcb_set_seg(&save->ds, read_ds(), 0, -1U, data_seg_attr);
1627d36db35SAvi Kivity 	sgdt(&desc_table_ptr);
1637d36db35SAvi Kivity 	vmcb_set_seg(&save->gdtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0);
1647d36db35SAvi Kivity 	sidt(&desc_table_ptr);
1657d36db35SAvi Kivity 	vmcb_set_seg(&save->idtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0);
1667d36db35SAvi Kivity 	ctrl->asid = 1;
1677d36db35SAvi Kivity 	save->cpl = 0;
1687d36db35SAvi Kivity 	save->efer = rdmsr(MSR_EFER);
1697d36db35SAvi Kivity 	save->cr4 = read_cr4();
1707d36db35SAvi Kivity 	save->cr3 = read_cr3();
1717d36db35SAvi Kivity 	save->cr0 = read_cr0();
1727d36db35SAvi Kivity 	save->dr7 = read_dr7();
1737d36db35SAvi Kivity 	save->dr6 = read_dr6();
1747d36db35SAvi Kivity 	save->cr2 = read_cr2();
1757d36db35SAvi Kivity 	save->g_pat = rdmsr(MSR_IA32_CR_PAT);
1767d36db35SAvi Kivity 	save->dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR);
177*eb8a146bSMaxim Levitsky 	ctrl->intercept = (1ULL << INTERCEPT_VMRUN) |
178*eb8a146bSMaxim Levitsky 			  (1ULL << INTERCEPT_VMMCALL) |
179*eb8a146bSMaxim Levitsky 			  (1ULL << INTERCEPT_SHUTDOWN);
1803d46571bSPaolo Bonzini 	ctrl->iopm_base_pa = virt_to_phys(io_bitmap);
18106a8c023STambe, William 	ctrl->msrpm_base_pa = virt_to_phys(msr_bitmap);
1821535bf0fSJoerg Roedel 
1831535bf0fSJoerg Roedel 	if (npt_supported()) {
1841535bf0fSJoerg Roedel 		ctrl->nested_ctl = 1;
1851535bf0fSJoerg Roedel 		ctrl->nested_cr3 = (u64)pml4e;
186c803b19bSNadav Amit 		ctrl->tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
1871535bf0fSJoerg Roedel 	}
1887d36db35SAvi Kivity }
1897d36db35SAvi Kivity 
190a43baea0SPaolo Bonzini struct regs regs;
191a43baea0SPaolo Bonzini 
192ad879127SKrish Sadhukhan struct regs get_regs(void)
193ad879127SKrish Sadhukhan {
194ad879127SKrish Sadhukhan 	return regs;
195ad879127SKrish Sadhukhan }
196ad879127SKrish Sadhukhan 
197a43baea0SPaolo Bonzini // rax handled specially below
198a43baea0SPaolo Bonzini 
199a43baea0SPaolo Bonzini #define SAVE_GPR_C                              \
200a43baea0SPaolo Bonzini         "xchg %%rbx, regs+0x8\n\t"              \
201a43baea0SPaolo Bonzini         "xchg %%rcx, regs+0x10\n\t"             \
202a43baea0SPaolo Bonzini         "xchg %%rdx, regs+0x18\n\t"             \
203a43baea0SPaolo Bonzini         "xchg %%rbp, regs+0x28\n\t"             \
204a43baea0SPaolo Bonzini         "xchg %%rsi, regs+0x30\n\t"             \
205a43baea0SPaolo Bonzini         "xchg %%rdi, regs+0x38\n\t"             \
206a43baea0SPaolo Bonzini         "xchg %%r8, regs+0x40\n\t"              \
207a43baea0SPaolo Bonzini         "xchg %%r9, regs+0x48\n\t"              \
208a43baea0SPaolo Bonzini         "xchg %%r10, regs+0x50\n\t"             \
209a43baea0SPaolo Bonzini         "xchg %%r11, regs+0x58\n\t"             \
210a43baea0SPaolo Bonzini         "xchg %%r12, regs+0x60\n\t"             \
211a43baea0SPaolo Bonzini         "xchg %%r13, regs+0x68\n\t"             \
212a43baea0SPaolo Bonzini         "xchg %%r14, regs+0x70\n\t"             \
213a43baea0SPaolo Bonzini         "xchg %%r15, regs+0x78\n\t"
214a43baea0SPaolo Bonzini 
215a43baea0SPaolo Bonzini #define LOAD_GPR_C      SAVE_GPR_C
216a43baea0SPaolo Bonzini 
2178660d1b5SKrish Sadhukhan struct svm_test *v2_test;
2188660d1b5SKrish Sadhukhan 
21944480895SKrish Sadhukhan #define ASM_PRE_VMRUN_CMD                       \
2208660d1b5SKrish Sadhukhan                 "vmload %%rax\n\t"              \
2218660d1b5SKrish Sadhukhan                 "mov regs+0x80, %%r15\n\t"      \
2228660d1b5SKrish Sadhukhan                 "mov %%r15, 0x170(%%rax)\n\t"   \
2238660d1b5SKrish Sadhukhan                 "mov regs, %%r15\n\t"           \
2248660d1b5SKrish Sadhukhan                 "mov %%r15, 0x1f8(%%rax)\n\t"   \
2258660d1b5SKrish Sadhukhan                 LOAD_GPR_C                      \
22644480895SKrish Sadhukhan 
22744480895SKrish Sadhukhan #define ASM_POST_VMRUN_CMD                      \
2288660d1b5SKrish Sadhukhan                 SAVE_GPR_C                      \
2298660d1b5SKrish Sadhukhan                 "mov 0x170(%%rax), %%r15\n\t"   \
2308660d1b5SKrish Sadhukhan                 "mov %%r15, regs+0x80\n\t"      \
2318660d1b5SKrish Sadhukhan                 "mov 0x1f8(%%rax), %%r15\n\t"   \
2328660d1b5SKrish Sadhukhan                 "mov %%r15, regs\n\t"           \
2338660d1b5SKrish Sadhukhan                 "vmsave %%rax\n\t"              \
2348660d1b5SKrish Sadhukhan 
2358660d1b5SKrish Sadhukhan u64 guest_stack[10000];
2368660d1b5SKrish Sadhukhan 
237a6495564SKrish Sadhukhan int __svm_vmrun(u64 rip)
2388660d1b5SKrish Sadhukhan {
239a6495564SKrish Sadhukhan 	vmcb->save.rip = (ulong)rip;
2408660d1b5SKrish Sadhukhan 	vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
2418660d1b5SKrish Sadhukhan 	regs.rdi = (ulong)v2_test;
2428660d1b5SKrish Sadhukhan 
2438660d1b5SKrish Sadhukhan 	asm volatile (
24444480895SKrish Sadhukhan 		ASM_PRE_VMRUN_CMD
24544480895SKrish Sadhukhan                 "vmrun %%rax\n\t"               \
24644480895SKrish Sadhukhan 		ASM_POST_VMRUN_CMD
2478660d1b5SKrish Sadhukhan 		:
2488660d1b5SKrish Sadhukhan 		: "a" (virt_to_phys(vmcb))
2497b87cad0SPaolo Bonzini 		: "memory", "r15");
2508660d1b5SKrish Sadhukhan 
2518660d1b5SKrish Sadhukhan 	return (vmcb->control.exit_code);
2528660d1b5SKrish Sadhukhan }
2538660d1b5SKrish Sadhukhan 
254a6495564SKrish Sadhukhan int svm_vmrun(void)
255a6495564SKrish Sadhukhan {
256a6495564SKrish Sadhukhan 	return __svm_vmrun((u64)test_thunk);
257a6495564SKrish Sadhukhan }
258a6495564SKrish Sadhukhan 
2590c22fd44SPaolo Bonzini extern u8 vmrun_rip;
26044480895SKrish Sadhukhan 
261440c4fc3SBill Wendling static noinline void test_run(struct svm_test *test)
2627d36db35SAvi Kivity {
2637d36db35SAvi Kivity 	u64 vmcb_phys = virt_to_phys(vmcb);
2647d36db35SAvi Kivity 
2651500aca4SPaolo Bonzini 	irq_disable();
266cf851077SSean Christopherson 	vmcb_ident(vmcb);
267cf851077SSean Christopherson 
2687d36db35SAvi Kivity 	test->prepare(test);
2698660d1b5SKrish Sadhukhan 	guest_main = test->guest_func;
2707d36db35SAvi Kivity 	vmcb->save.rip = (ulong)test_thunk;
2717d36db35SAvi Kivity 	vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
272a43baea0SPaolo Bonzini 	regs.rdi = (ulong)test;
2737d36db35SAvi Kivity 	do {
274ad879127SKrish Sadhukhan 		struct svm_test *the_test = test;
275e7bce343SPaolo Bonzini 		u64 the_vmcb = vmcb_phys;
2767d36db35SAvi Kivity 		asm volatile (
2772c6589bcSPeter Shier 			"clgi;\n\t" // semi-colon needed for LLVM compatibility
2782e7dd780SCathy Avery 			"sti \n\t"
279e7bce343SPaolo Bonzini 			"call *%c[PREPARE_GIF_CLEAR](%[test]) \n \t"
280e7bce343SPaolo Bonzini 			"mov %[vmcb_phys], %%rax \n\t"
28144480895SKrish Sadhukhan 			ASM_PRE_VMRUN_CMD
28244480895SKrish Sadhukhan 			".global vmrun_rip\n\t"		\
28344480895SKrish Sadhukhan 			"vmrun_rip: vmrun %%rax\n\t"    \
28444480895SKrish Sadhukhan 			ASM_POST_VMRUN_CMD
2852e7dd780SCathy Avery 			"cli \n\t"
2867d36db35SAvi Kivity 			"stgi"
287e7bce343SPaolo Bonzini 			: // inputs clobbered by the guest:
28886d24fa6SBill Wendling 			"=D" (the_test),            // first argument register
28986d24fa6SBill Wendling 			"=b" (the_vmcb)             // callee save register!
290e7bce343SPaolo Bonzini 			: [test] "0" (the_test),
291e7bce343SPaolo Bonzini 			[vmcb_phys] "1"(the_vmcb),
292ad879127SKrish Sadhukhan 			[PREPARE_GIF_CLEAR] "i" (offsetof(struct svm_test, prepare_gif_clear))
293e7bce343SPaolo Bonzini 			: "rax", "rcx", "rdx", "rsi",
2947d36db35SAvi Kivity 			"r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15",
2957d36db35SAvi Kivity 			"memory");
2967d36db35SAvi Kivity 		++test->exits;
2977d36db35SAvi Kivity 	} while (!test->finished(test));
2981500aca4SPaolo Bonzini 	irq_enable();
2997d36db35SAvi Kivity 
300a299895bSThomas Huth 	report(test->succeeded(test), "%s", test->name);
30148f67910SCathy Avery 
30248f67910SCathy Avery         if (test->on_vcpu)
30348f67910SCathy Avery 	    test->on_vcpu_done = true;
30448f67910SCathy Avery }
30548f67910SCathy Avery 
30648f67910SCathy Avery static void set_additional_vcpu_msr(void *msr_efer)
30748f67910SCathy Avery {
30848f67910SCathy Avery 	void *hsave = alloc_page();
30948f67910SCathy Avery 
31048f67910SCathy Avery 	wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave));
311779fd1faSSean Christopherson 	wrmsr(MSR_EFER, (ulong)msr_efer | EFER_SVME);
3127d36db35SAvi Kivity }
3137d36db35SAvi Kivity 
314ad879127SKrish Sadhukhan static void setup_svm(void)
315095274b4SPrasad Joshi {
316ad879127SKrish Sadhukhan 	void *hsave = alloc_page();
317ad879127SKrish Sadhukhan 	u64 *page, address;
318ad879127SKrish Sadhukhan 	int i,j;
319095274b4SPrasad Joshi 
320ad879127SKrish Sadhukhan 	wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave));
321ad879127SKrish Sadhukhan 	wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SVME);
3227d36db35SAvi Kivity 
32348c13f32SKrish Sadhukhan 	io_bitmap = (void *) ALIGN((ulong)io_bitmap_area, PAGE_SIZE);
3247d36db35SAvi Kivity 
325ad879127SKrish Sadhukhan 	msr_bitmap = (void *) ALIGN((ulong)msr_bitmap_area, PAGE_SIZE);
326e7bce343SPaolo Bonzini 
327ad879127SKrish Sadhukhan 	if (!npt_supported())
328bcd9774aSPaolo Bonzini 		return;
329bcd9774aSPaolo Bonzini 
33048f67910SCathy Avery 	for (i = 1; i < cpu_count(); i++)
33148f67910SCathy Avery 		on_cpu(i, (void *)set_additional_vcpu_msr, (void *)rdmsr(MSR_EFER));
33248f67910SCathy Avery 
333ad879127SKrish Sadhukhan 	printf("NPT detected - running all tests with NPT enabled\n");
3344c8eb156SJoerg Roedel 
3354c8eb156SJoerg Roedel 	/*
336ad879127SKrish Sadhukhan 	* Nested paging supported - Build a nested page table
337ad879127SKrish Sadhukhan 	* Build the page-table bottom-up and map everything with 4k
338ad879127SKrish Sadhukhan 	* pages to get enough granularity for the NPT unit-tests.
3394c8eb156SJoerg Roedel 	*/
3404c8eb156SJoerg Roedel 
341ad879127SKrish Sadhukhan 	address = 0;
3424c8eb156SJoerg Roedel 
343ad879127SKrish Sadhukhan 	/* PTE level */
344ad879127SKrish Sadhukhan 	for (i = 0; i < 2048; ++i) {
345ad879127SKrish Sadhukhan 		page = alloc_page();
3468594b943SJoerg Roedel 
347ad879127SKrish Sadhukhan 		for (j = 0; j < 512; ++j, address += 4096)
348ad879127SKrish Sadhukhan 	    		page[j] = address | 0x067ULL;
3498594b943SJoerg Roedel 
350ad879127SKrish Sadhukhan 		pte[i] = page;
3518594b943SJoerg Roedel 	}
3528594b943SJoerg Roedel 
353ad879127SKrish Sadhukhan 	/* PDE level */
354ad879127SKrish Sadhukhan 	for (i = 0; i < 4; ++i) {
355ad879127SKrish Sadhukhan 		page = alloc_page();
3568594b943SJoerg Roedel 
357ad879127SKrish Sadhukhan 	for (j = 0; j < 512; ++j)
358ad879127SKrish Sadhukhan 	    page[j] = (u64)pte[(i * 512) + j] | 0x027ULL;
3598594b943SJoerg Roedel 
360ad879127SKrish Sadhukhan 		pde[i] = page;
3618594b943SJoerg Roedel 	}
3628594b943SJoerg Roedel 
363ad879127SKrish Sadhukhan 	/* PDPe level */
364ad879127SKrish Sadhukhan 	pdpe   = alloc_page();
365ad879127SKrish Sadhukhan 	for (i = 0; i < 4; ++i)
366ad879127SKrish Sadhukhan 		pdpe[i] = ((u64)(pde[i])) | 0x27;
367ea975120SJoerg Roedel 
368ad879127SKrish Sadhukhan 	/* PML4e level */
369ad879127SKrish Sadhukhan 	pml4e    = alloc_page();
370ad879127SKrish Sadhukhan 	pml4e[0] = ((u64)pdpe) | 0x27;
371ea975120SJoerg Roedel }
372ea975120SJoerg Roedel 
37350d27547SPaolo Bonzini int matched;
37450d27547SPaolo Bonzini 
37550d27547SPaolo Bonzini static bool
37650d27547SPaolo Bonzini test_wanted(const char *name, char *filters[], int filter_count)
37750d27547SPaolo Bonzini {
37850d27547SPaolo Bonzini         int i;
37950d27547SPaolo Bonzini         bool positive = false;
38050d27547SPaolo Bonzini         bool match = false;
38150d27547SPaolo Bonzini         char clean_name[strlen(name) + 1];
38250d27547SPaolo Bonzini         char *c;
38350d27547SPaolo Bonzini         const char *n;
38450d27547SPaolo Bonzini 
38550d27547SPaolo Bonzini         /* Replace spaces with underscores. */
38650d27547SPaolo Bonzini         n = name;
38750d27547SPaolo Bonzini         c = &clean_name[0];
38850d27547SPaolo Bonzini         do *c++ = (*n == ' ') ? '_' : *n;
38950d27547SPaolo Bonzini         while (*n++);
39050d27547SPaolo Bonzini 
39150d27547SPaolo Bonzini         for (i = 0; i < filter_count; i++) {
39250d27547SPaolo Bonzini                 const char *filter = filters[i];
39350d27547SPaolo Bonzini 
39450d27547SPaolo Bonzini                 if (filter[0] == '-') {
39550d27547SPaolo Bonzini                         if (simple_glob(clean_name, filter + 1))
39650d27547SPaolo Bonzini                                 return false;
39750d27547SPaolo Bonzini                 } else {
39850d27547SPaolo Bonzini                         positive = true;
39950d27547SPaolo Bonzini                         match |= simple_glob(clean_name, filter);
40050d27547SPaolo Bonzini                 }
40150d27547SPaolo Bonzini         }
40250d27547SPaolo Bonzini 
40350d27547SPaolo Bonzini         if (!positive || match) {
40450d27547SPaolo Bonzini                 matched++;
40550d27547SPaolo Bonzini                 return true;
40650d27547SPaolo Bonzini         } else {
40750d27547SPaolo Bonzini                 return false;
40850d27547SPaolo Bonzini         }
40950d27547SPaolo Bonzini }
41050d27547SPaolo Bonzini 
4117d36db35SAvi Kivity int main(int ac, char **av)
4127d36db35SAvi Kivity {
413916635a8SSean Christopherson 	/* Omit PT_USER_MASK to allow tested host.CR4.SMEP=1. */
414916635a8SSean Christopherson 	pteval_t opt_mask = 0;
415ad879127SKrish Sadhukhan 	int i = 0;
4167d36db35SAvi Kivity 
41750d27547SPaolo Bonzini 	ac--;
41850d27547SPaolo Bonzini 	av++;
41950d27547SPaolo Bonzini 
420916635a8SSean Christopherson 	__setup_vm(&opt_mask);
4217d36db35SAvi Kivity 
422badc98caSKrish Sadhukhan 	if (!this_cpu_has(X86_FEATURE_SVM)) {
4237d36db35SAvi Kivity 		printf("SVM not availble\n");
42432b9603cSRadim Krčmář 		return report_summary();
4257d36db35SAvi Kivity 	}
4267d36db35SAvi Kivity 
4277d36db35SAvi Kivity 	setup_svm();
4287d36db35SAvi Kivity 
4297d36db35SAvi Kivity 	vmcb = alloc_page();
4307d36db35SAvi Kivity 
431ad879127SKrish Sadhukhan 	for (; svm_tests[i].name != NULL; i++) {
4328660d1b5SKrish Sadhukhan 		if (!test_wanted(svm_tests[i].name, av, ac))
4337d36db35SAvi Kivity 			continue;
4348660d1b5SKrish Sadhukhan 		if (svm_tests[i].supported && !svm_tests[i].supported())
4358660d1b5SKrish Sadhukhan 			continue;
4368660d1b5SKrish Sadhukhan 		if (svm_tests[i].v2 == NULL) {
43748f67910SCathy Avery 			if (svm_tests[i].on_vcpu) {
43848f67910SCathy Avery 				if (cpu_count() <= svm_tests[i].on_vcpu)
43948f67910SCathy Avery 					continue;
44048f67910SCathy Avery 				on_cpu_async(svm_tests[i].on_vcpu, (void *)test_run, &svm_tests[i]);
44148f67910SCathy Avery 				while (!svm_tests[i].on_vcpu_done)
44248f67910SCathy Avery 					cpu_relax();
44348f67910SCathy Avery 			}
44448f67910SCathy Avery 			else
4458660d1b5SKrish Sadhukhan 				test_run(&svm_tests[i]);
4468660d1b5SKrish Sadhukhan 		} else {
4478660d1b5SKrish Sadhukhan 			vmcb_ident(vmcb);
4488660d1b5SKrish Sadhukhan 			v2_test = &(svm_tests[i]);
4498660d1b5SKrish Sadhukhan 			svm_tests[i].v2();
4508660d1b5SKrish Sadhukhan 		}
4517d36db35SAvi Kivity 	}
4527d36db35SAvi Kivity 
45350d27547SPaolo Bonzini 	if (!matched)
45450d27547SPaolo Bonzini 		report(matched, "command line didn't match any tests!");
45550d27547SPaolo Bonzini 
456a43ed2acSAndrew Jones 	return report_summary();
4577d36db35SAvi Kivity }
458