xref: /kvm-unit-tests/x86/svm.c (revision 6f5ce7c1ee0b08920f64712ce0fe63a4b82216b5)
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"
11*6f5ce7c1SManali Shukla #include "fwcfg.h"
127d36db35SAvi Kivity #include "smp.h"
137d36db35SAvi Kivity #include "types.h"
145aca024eSPaolo Bonzini #include "alloc_page.h"
15306bb7dbSCathy Avery #include "isr.h"
16306bb7dbSCathy Avery #include "apic.h"
177d36db35SAvi Kivity 
181535bf0fSJoerg Roedel /* for the nested page table*/
19ad879127SKrish Sadhukhan u64 *pml4e;
201535bf0fSJoerg Roedel 
21096cf7feSPaolo Bonzini struct vmcb *vmcb;
22096cf7feSPaolo Bonzini 
23ad879127SKrish Sadhukhan u64 *npt_get_pte(u64 address)
241535bf0fSJoerg Roedel {
25*6f5ce7c1SManali Shukla 	return get_pte(npt_get_pml4e(), (void*)address);
261535bf0fSJoerg Roedel }
271535bf0fSJoerg Roedel 
28ad879127SKrish Sadhukhan u64 *npt_get_pde(u64 address)
29f6a2ca45SPaolo Bonzini {
30*6f5ce7c1SManali Shukla 	struct pte_search search;
31*6f5ce7c1SManali Shukla 	search = find_pte_level(npt_get_pml4e(), (void*)address, 2);
32*6f5ce7c1SManali Shukla 	return search.pte;
33f6a2ca45SPaolo Bonzini }
34f6a2ca45SPaolo Bonzini 
35*6f5ce7c1SManali Shukla u64 *npt_get_pdpe(u64 address)
368594b943SJoerg Roedel {
37*6f5ce7c1SManali Shukla 	struct pte_search search;
38*6f5ce7c1SManali Shukla 	search = find_pte_level(npt_get_pml4e(), (void*)address, 3);
39*6f5ce7c1SManali Shukla 	return search.pte;
40ad879127SKrish Sadhukhan }
418594b943SJoerg Roedel 
42c6405e37SNadav Amit u64 *npt_get_pml4e(void)
43c6405e37SNadav Amit {
44c6405e37SNadav Amit 	return pml4e;
45c6405e37SNadav Amit }
46c6405e37SNadav Amit 
47ad879127SKrish Sadhukhan bool smp_supported(void)
48ad879127SKrish Sadhukhan {
49ad879127SKrish Sadhukhan 	return cpu_count() > 1;
50ad879127SKrish Sadhukhan }
518594b943SJoerg Roedel 
52ad879127SKrish Sadhukhan bool default_supported(void)
53ad879127SKrish Sadhukhan {
54ad879127SKrish Sadhukhan     return true;
55ad879127SKrish Sadhukhan }
56ad879127SKrish Sadhukhan 
57f6972bd6SLara Lazier bool vgif_supported(void)
58f6972bd6SLara Lazier {
59f6972bd6SLara Lazier 	return this_cpu_has(X86_FEATURE_VGIF);
60f6972bd6SLara Lazier }
61f6972bd6SLara Lazier 
62537d39dfSMaxim Levitsky bool lbrv_supported(void)
63537d39dfSMaxim Levitsky {
64537d39dfSMaxim Levitsky     return this_cpu_has(X86_FEATURE_LBRV);
65537d39dfSMaxim Levitsky }
66537d39dfSMaxim Levitsky 
67a8503d50SMaxim Levitsky bool tsc_scale_supported(void)
68a8503d50SMaxim Levitsky {
69a8503d50SMaxim Levitsky     return this_cpu_has(X86_FEATURE_TSCRATEMSR);
70a8503d50SMaxim Levitsky }
71a8503d50SMaxim Levitsky 
728650dffeSMaxim Levitsky bool pause_filter_supported(void)
738650dffeSMaxim Levitsky {
748650dffeSMaxim Levitsky     return this_cpu_has(X86_FEATURE_PAUSEFILTER);
758650dffeSMaxim Levitsky }
768650dffeSMaxim Levitsky 
778650dffeSMaxim Levitsky bool pause_threshold_supported(void)
788650dffeSMaxim Levitsky {
798650dffeSMaxim Levitsky     return this_cpu_has(X86_FEATURE_PFTHRESHOLD);
808650dffeSMaxim Levitsky }
818650dffeSMaxim Levitsky 
828650dffeSMaxim Levitsky 
83ad879127SKrish Sadhukhan void default_prepare(struct svm_test *test)
84ad879127SKrish Sadhukhan {
85096cf7feSPaolo Bonzini 	vmcb_ident(vmcb);
86ad879127SKrish Sadhukhan }
87ad879127SKrish Sadhukhan 
88ad879127SKrish Sadhukhan void default_prepare_gif_clear(struct svm_test *test)
89ad879127SKrish Sadhukhan {
90ad879127SKrish Sadhukhan }
91ad879127SKrish Sadhukhan 
92ad879127SKrish Sadhukhan bool default_finished(struct svm_test *test)
93ad879127SKrish Sadhukhan {
94ad879127SKrish Sadhukhan 	return true; /* one vmexit */
95ad879127SKrish Sadhukhan }
96ad879127SKrish Sadhukhan 
97ad879127SKrish Sadhukhan bool npt_supported(void)
98ad879127SKrish Sadhukhan {
99ad879127SKrish Sadhukhan 	return this_cpu_has(X86_FEATURE_NPT);
100ad879127SKrish Sadhukhan }
101ad879127SKrish Sadhukhan 
102ad879127SKrish Sadhukhan int get_test_stage(struct svm_test *test)
103ad879127SKrish Sadhukhan {
104ad879127SKrish Sadhukhan 	barrier();
105ad879127SKrish Sadhukhan 	return test->scratch;
106ad879127SKrish Sadhukhan }
107ad879127SKrish Sadhukhan 
108ad879127SKrish Sadhukhan void set_test_stage(struct svm_test *test, int s)
109ad879127SKrish Sadhukhan {
110ad879127SKrish Sadhukhan 	barrier();
111ad879127SKrish Sadhukhan 	test->scratch = s;
112ad879127SKrish Sadhukhan 	barrier();
113ad879127SKrish Sadhukhan }
114ad879127SKrish Sadhukhan 
115ad879127SKrish Sadhukhan void inc_test_stage(struct svm_test *test)
116ad879127SKrish Sadhukhan {
117ad879127SKrish Sadhukhan 	barrier();
118ad879127SKrish Sadhukhan 	test->scratch++;
119ad879127SKrish Sadhukhan 	barrier();
1208594b943SJoerg Roedel }
1218594b943SJoerg Roedel 
1227d36db35SAvi Kivity static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector,
1237d36db35SAvi Kivity                          u64 base, u32 limit, u32 attr)
1247d36db35SAvi Kivity {
1257d36db35SAvi Kivity 	seg->selector = selector;
1267d36db35SAvi Kivity 	seg->attrib = attr;
1277d36db35SAvi Kivity 	seg->limit = limit;
1287d36db35SAvi Kivity 	seg->base = base;
1297d36db35SAvi Kivity }
1307d36db35SAvi Kivity 
131ad879127SKrish Sadhukhan inline void vmmcall(void)
132ad879127SKrish Sadhukhan {
133ad879127SKrish Sadhukhan 	asm volatile ("vmmcall" : : : "memory");
134ad879127SKrish Sadhukhan }
135ad879127SKrish Sadhukhan 
1368660d1b5SKrish Sadhukhan static test_guest_func guest_main;
1378660d1b5SKrish Sadhukhan 
1388660d1b5SKrish Sadhukhan void test_set_guest(test_guest_func func)
1398660d1b5SKrish Sadhukhan {
1408660d1b5SKrish Sadhukhan 	guest_main = func;
1418660d1b5SKrish Sadhukhan }
1428660d1b5SKrish Sadhukhan 
143ad879127SKrish Sadhukhan static void test_thunk(struct svm_test *test)
144ad879127SKrish Sadhukhan {
1458660d1b5SKrish Sadhukhan 	guest_main(test);
146ad879127SKrish Sadhukhan 	vmmcall();
147ad879127SKrish Sadhukhan }
148ad879127SKrish Sadhukhan 
149ad879127SKrish Sadhukhan u8 *io_bitmap;
150ad879127SKrish Sadhukhan u8 io_bitmap_area[16384];
151ad879127SKrish Sadhukhan 
152ad879127SKrish Sadhukhan u8 *msr_bitmap;
153ad879127SKrish Sadhukhan u8 msr_bitmap_area[MSR_BITMAP_SIZE + PAGE_SIZE];
154ad879127SKrish Sadhukhan 
155ad879127SKrish Sadhukhan void vmcb_ident(struct vmcb *vmcb)
1567d36db35SAvi Kivity {
1577d36db35SAvi Kivity 	u64 vmcb_phys = virt_to_phys(vmcb);
1587d36db35SAvi Kivity 	struct vmcb_save_area *save = &vmcb->save;
1597d36db35SAvi Kivity 	struct vmcb_control_area *ctrl = &vmcb->control;
1607d36db35SAvi Kivity 	u32 data_seg_attr = 3 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
1617d36db35SAvi Kivity 	    | SVM_SELECTOR_DB_MASK | SVM_SELECTOR_G_MASK;
1627d36db35SAvi Kivity 	u32 code_seg_attr = 9 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
1637d36db35SAvi Kivity 	    | SVM_SELECTOR_L_MASK | SVM_SELECTOR_G_MASK;
1647d36db35SAvi Kivity 	struct descriptor_table_ptr desc_table_ptr;
1657d36db35SAvi Kivity 
1667d36db35SAvi Kivity 	memset(vmcb, 0, sizeof(*vmcb));
1672c6589bcSPeter Shier 	asm volatile ("vmsave %0" : : "a"(vmcb_phys) : "memory");
1687d36db35SAvi Kivity 	vmcb_set_seg(&save->es, read_es(), 0, -1U, data_seg_attr);
1697d36db35SAvi Kivity 	vmcb_set_seg(&save->cs, read_cs(), 0, -1U, code_seg_attr);
1707d36db35SAvi Kivity 	vmcb_set_seg(&save->ss, read_ss(), 0, -1U, data_seg_attr);
1717d36db35SAvi Kivity 	vmcb_set_seg(&save->ds, read_ds(), 0, -1U, data_seg_attr);
1727d36db35SAvi Kivity 	sgdt(&desc_table_ptr);
1737d36db35SAvi Kivity 	vmcb_set_seg(&save->gdtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0);
1747d36db35SAvi Kivity 	sidt(&desc_table_ptr);
1757d36db35SAvi Kivity 	vmcb_set_seg(&save->idtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0);
1767d36db35SAvi Kivity 	ctrl->asid = 1;
1777d36db35SAvi Kivity 	save->cpl = 0;
1787d36db35SAvi Kivity 	save->efer = rdmsr(MSR_EFER);
1797d36db35SAvi Kivity 	save->cr4 = read_cr4();
1807d36db35SAvi Kivity 	save->cr3 = read_cr3();
1817d36db35SAvi Kivity 	save->cr0 = read_cr0();
1827d36db35SAvi Kivity 	save->dr7 = read_dr7();
1837d36db35SAvi Kivity 	save->dr6 = read_dr6();
1847d36db35SAvi Kivity 	save->cr2 = read_cr2();
1857d36db35SAvi Kivity 	save->g_pat = rdmsr(MSR_IA32_CR_PAT);
1867d36db35SAvi Kivity 	save->dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR);
187eb8a146bSMaxim Levitsky 	ctrl->intercept = (1ULL << INTERCEPT_VMRUN) |
188eb8a146bSMaxim Levitsky 			  (1ULL << INTERCEPT_VMMCALL) |
189eb8a146bSMaxim Levitsky 			  (1ULL << INTERCEPT_SHUTDOWN);
1903d46571bSPaolo Bonzini 	ctrl->iopm_base_pa = virt_to_phys(io_bitmap);
19106a8c023STambe, William 	ctrl->msrpm_base_pa = virt_to_phys(msr_bitmap);
1921535bf0fSJoerg Roedel 
1931535bf0fSJoerg Roedel 	if (npt_supported()) {
1941535bf0fSJoerg Roedel 		ctrl->nested_ctl = 1;
1951535bf0fSJoerg Roedel 		ctrl->nested_cr3 = (u64)pml4e;
196c803b19bSNadav Amit 		ctrl->tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
1971535bf0fSJoerg Roedel 	}
1987d36db35SAvi Kivity }
1997d36db35SAvi Kivity 
200a43baea0SPaolo Bonzini struct regs regs;
201a43baea0SPaolo Bonzini 
202ad879127SKrish Sadhukhan struct regs get_regs(void)
203ad879127SKrish Sadhukhan {
204ad879127SKrish Sadhukhan 	return regs;
205ad879127SKrish Sadhukhan }
206ad879127SKrish Sadhukhan 
207a43baea0SPaolo Bonzini // rax handled specially below
208a43baea0SPaolo Bonzini 
209a43baea0SPaolo Bonzini 
2108660d1b5SKrish Sadhukhan struct svm_test *v2_test;
2118660d1b5SKrish Sadhukhan 
2128660d1b5SKrish Sadhukhan 
2138660d1b5SKrish Sadhukhan u64 guest_stack[10000];
2148660d1b5SKrish Sadhukhan 
215a6495564SKrish Sadhukhan int __svm_vmrun(u64 rip)
2168660d1b5SKrish Sadhukhan {
217a6495564SKrish Sadhukhan 	vmcb->save.rip = (ulong)rip;
2188660d1b5SKrish Sadhukhan 	vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
2198660d1b5SKrish Sadhukhan 	regs.rdi = (ulong)v2_test;
2208660d1b5SKrish Sadhukhan 
2218660d1b5SKrish Sadhukhan 	asm volatile (
22244480895SKrish Sadhukhan 		ASM_PRE_VMRUN_CMD
22344480895SKrish Sadhukhan                 "vmrun %%rax\n\t"               \
22444480895SKrish Sadhukhan 		ASM_POST_VMRUN_CMD
2258660d1b5SKrish Sadhukhan 		:
2268660d1b5SKrish Sadhukhan 		: "a" (virt_to_phys(vmcb))
2277b87cad0SPaolo Bonzini 		: "memory", "r15");
2288660d1b5SKrish Sadhukhan 
2298660d1b5SKrish Sadhukhan 	return (vmcb->control.exit_code);
2308660d1b5SKrish Sadhukhan }
2318660d1b5SKrish Sadhukhan 
232a6495564SKrish Sadhukhan int svm_vmrun(void)
233a6495564SKrish Sadhukhan {
234a6495564SKrish Sadhukhan 	return __svm_vmrun((u64)test_thunk);
235a6495564SKrish Sadhukhan }
236a6495564SKrish Sadhukhan 
2370c22fd44SPaolo Bonzini extern u8 vmrun_rip;
23844480895SKrish Sadhukhan 
239440c4fc3SBill Wendling static noinline void test_run(struct svm_test *test)
2407d36db35SAvi Kivity {
2417d36db35SAvi Kivity 	u64 vmcb_phys = virt_to_phys(vmcb);
2427d36db35SAvi Kivity 
2431500aca4SPaolo Bonzini 	irq_disable();
244cf851077SSean Christopherson 	vmcb_ident(vmcb);
245cf851077SSean Christopherson 
2467d36db35SAvi Kivity 	test->prepare(test);
2478660d1b5SKrish Sadhukhan 	guest_main = test->guest_func;
2487d36db35SAvi Kivity 	vmcb->save.rip = (ulong)test_thunk;
2497d36db35SAvi Kivity 	vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
250a43baea0SPaolo Bonzini 	regs.rdi = (ulong)test;
2517d36db35SAvi Kivity 	do {
252ad879127SKrish Sadhukhan 		struct svm_test *the_test = test;
253e7bce343SPaolo Bonzini 		u64 the_vmcb = vmcb_phys;
2547d36db35SAvi Kivity 		asm volatile (
2552c6589bcSPeter Shier 			"clgi;\n\t" // semi-colon needed for LLVM compatibility
2562e7dd780SCathy Avery 			"sti \n\t"
257e7bce343SPaolo Bonzini 			"call *%c[PREPARE_GIF_CLEAR](%[test]) \n \t"
258e7bce343SPaolo Bonzini 			"mov %[vmcb_phys], %%rax \n\t"
25944480895SKrish Sadhukhan 			ASM_PRE_VMRUN_CMD
26044480895SKrish Sadhukhan 			".global vmrun_rip\n\t"		\
26144480895SKrish Sadhukhan 			"vmrun_rip: vmrun %%rax\n\t"    \
26244480895SKrish Sadhukhan 			ASM_POST_VMRUN_CMD
2632e7dd780SCathy Avery 			"cli \n\t"
2647d36db35SAvi Kivity 			"stgi"
265e7bce343SPaolo Bonzini 			: // inputs clobbered by the guest:
26686d24fa6SBill Wendling 			"=D" (the_test),            // first argument register
26786d24fa6SBill Wendling 			"=b" (the_vmcb)             // callee save register!
268e7bce343SPaolo Bonzini 			: [test] "0" (the_test),
269e7bce343SPaolo Bonzini 			[vmcb_phys] "1"(the_vmcb),
270ad879127SKrish Sadhukhan 			[PREPARE_GIF_CLEAR] "i" (offsetof(struct svm_test, prepare_gif_clear))
271e7bce343SPaolo Bonzini 			: "rax", "rcx", "rdx", "rsi",
2727d36db35SAvi Kivity 			"r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15",
2737d36db35SAvi Kivity 			"memory");
2747d36db35SAvi Kivity 		++test->exits;
2757d36db35SAvi Kivity 	} while (!test->finished(test));
2761500aca4SPaolo Bonzini 	irq_enable();
2777d36db35SAvi Kivity 
278a299895bSThomas Huth 	report(test->succeeded(test), "%s", test->name);
27948f67910SCathy Avery 
28048f67910SCathy Avery         if (test->on_vcpu)
28148f67910SCathy Avery 	    test->on_vcpu_done = true;
28248f67910SCathy Avery }
28348f67910SCathy Avery 
28448f67910SCathy Avery static void set_additional_vcpu_msr(void *msr_efer)
28548f67910SCathy Avery {
28648f67910SCathy Avery 	void *hsave = alloc_page();
28748f67910SCathy Avery 
28848f67910SCathy Avery 	wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave));
289779fd1faSSean Christopherson 	wrmsr(MSR_EFER, (ulong)msr_efer | EFER_SVME);
2907d36db35SAvi Kivity }
2917d36db35SAvi Kivity 
292*6f5ce7c1SManali Shukla static void setup_npt(void)
293*6f5ce7c1SManali Shukla {
294*6f5ce7c1SManali Shukla 	u64 size = fwcfg_get_u64(FW_CFG_RAM_SIZE);
295*6f5ce7c1SManali Shukla 
296*6f5ce7c1SManali Shukla 	/* Ensure all <4gb is mapped, e.g. if there's no RAM above 4gb. */
297*6f5ce7c1SManali Shukla 	if (size < BIT_ULL(32))
298*6f5ce7c1SManali Shukla 		size = BIT_ULL(32);
299*6f5ce7c1SManali Shukla 
300*6f5ce7c1SManali Shukla 	pml4e = alloc_page();
301*6f5ce7c1SManali Shukla 
302*6f5ce7c1SManali Shukla 	/* NPT accesses are treated as "user" accesses. */
303*6f5ce7c1SManali Shukla 	__setup_mmu_range(pml4e, 0, size, X86_MMU_MAP_USER);
304*6f5ce7c1SManali Shukla }
305*6f5ce7c1SManali Shukla 
306ad879127SKrish Sadhukhan static void setup_svm(void)
307095274b4SPrasad Joshi {
308ad879127SKrish Sadhukhan 	void *hsave = alloc_page();
309*6f5ce7c1SManali Shukla 	int i;
310095274b4SPrasad Joshi 
311ad879127SKrish Sadhukhan 	wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave));
312ad879127SKrish Sadhukhan 	wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SVME);
3137d36db35SAvi Kivity 
31448c13f32SKrish Sadhukhan 	io_bitmap = (void *) ALIGN((ulong)io_bitmap_area, PAGE_SIZE);
3157d36db35SAvi Kivity 
316ad879127SKrish Sadhukhan 	msr_bitmap = (void *) ALIGN((ulong)msr_bitmap_area, PAGE_SIZE);
317e7bce343SPaolo Bonzini 
318ad879127SKrish Sadhukhan 	if (!npt_supported())
319bcd9774aSPaolo Bonzini 		return;
320bcd9774aSPaolo Bonzini 
32148f67910SCathy Avery 	for (i = 1; i < cpu_count(); i++)
32248f67910SCathy Avery 		on_cpu(i, (void *)set_additional_vcpu_msr, (void *)rdmsr(MSR_EFER));
32348f67910SCathy Avery 
324ad879127SKrish Sadhukhan 	printf("NPT detected - running all tests with NPT enabled\n");
3254c8eb156SJoerg Roedel 
3264c8eb156SJoerg Roedel 	/*
327ad879127SKrish Sadhukhan 	* Nested paging supported - Build a nested page table
328ad879127SKrish Sadhukhan 	* Build the page-table bottom-up and map everything with 4k
329ad879127SKrish Sadhukhan 	* pages to get enough granularity for the NPT unit-tests.
3304c8eb156SJoerg Roedel 	*/
3314c8eb156SJoerg Roedel 
332*6f5ce7c1SManali Shukla 	setup_npt();
333ea975120SJoerg Roedel }
334ea975120SJoerg Roedel 
33550d27547SPaolo Bonzini int matched;
33650d27547SPaolo Bonzini 
33750d27547SPaolo Bonzini static bool
33850d27547SPaolo Bonzini test_wanted(const char *name, char *filters[], int filter_count)
33950d27547SPaolo Bonzini {
34050d27547SPaolo Bonzini         int i;
34150d27547SPaolo Bonzini         bool positive = false;
34250d27547SPaolo Bonzini         bool match = false;
34350d27547SPaolo Bonzini         char clean_name[strlen(name) + 1];
34450d27547SPaolo Bonzini         char *c;
34550d27547SPaolo Bonzini         const char *n;
34650d27547SPaolo Bonzini 
34750d27547SPaolo Bonzini         /* Replace spaces with underscores. */
34850d27547SPaolo Bonzini         n = name;
34950d27547SPaolo Bonzini         c = &clean_name[0];
35050d27547SPaolo Bonzini         do *c++ = (*n == ' ') ? '_' : *n;
35150d27547SPaolo Bonzini         while (*n++);
35250d27547SPaolo Bonzini 
35350d27547SPaolo Bonzini         for (i = 0; i < filter_count; i++) {
35450d27547SPaolo Bonzini                 const char *filter = filters[i];
35550d27547SPaolo Bonzini 
35650d27547SPaolo Bonzini                 if (filter[0] == '-') {
35750d27547SPaolo Bonzini                         if (simple_glob(clean_name, filter + 1))
35850d27547SPaolo Bonzini                                 return false;
35950d27547SPaolo Bonzini                 } else {
36050d27547SPaolo Bonzini                         positive = true;
36150d27547SPaolo Bonzini                         match |= simple_glob(clean_name, filter);
36250d27547SPaolo Bonzini                 }
36350d27547SPaolo Bonzini         }
36450d27547SPaolo Bonzini 
36550d27547SPaolo Bonzini         if (!positive || match) {
36650d27547SPaolo Bonzini                 matched++;
36750d27547SPaolo Bonzini                 return true;
36850d27547SPaolo Bonzini         } else {
36950d27547SPaolo Bonzini                 return false;
37050d27547SPaolo Bonzini         }
37150d27547SPaolo Bonzini }
37250d27547SPaolo Bonzini 
373712840d5SManali Shukla int run_svm_tests(int ac, char **av, struct svm_test *svm_tests)
3747d36db35SAvi Kivity {
375ad879127SKrish Sadhukhan 	int i = 0;
3767d36db35SAvi Kivity 
37750d27547SPaolo Bonzini 	ac--;
37850d27547SPaolo Bonzini 	av++;
37950d27547SPaolo Bonzini 
380badc98caSKrish Sadhukhan 	if (!this_cpu_has(X86_FEATURE_SVM)) {
381912c0d72SThomas Huth 		printf("SVM not available\n");
38232b9603cSRadim Krčmář 		return report_summary();
3837d36db35SAvi Kivity 	}
3847d36db35SAvi Kivity 
3857d36db35SAvi Kivity 	setup_svm();
3867d36db35SAvi Kivity 
3877d36db35SAvi Kivity 	vmcb = alloc_page();
3887d36db35SAvi Kivity 
389ad879127SKrish Sadhukhan 	for (; svm_tests[i].name != NULL; i++) {
3908660d1b5SKrish Sadhukhan 		if (!test_wanted(svm_tests[i].name, av, ac))
3917d36db35SAvi Kivity 			continue;
3928660d1b5SKrish Sadhukhan 		if (svm_tests[i].supported && !svm_tests[i].supported())
3938660d1b5SKrish Sadhukhan 			continue;
3948660d1b5SKrish Sadhukhan 		if (svm_tests[i].v2 == NULL) {
39548f67910SCathy Avery 			if (svm_tests[i].on_vcpu) {
39648f67910SCathy Avery 				if (cpu_count() <= svm_tests[i].on_vcpu)
39748f67910SCathy Avery 					continue;
39848f67910SCathy Avery 				on_cpu_async(svm_tests[i].on_vcpu, (void *)test_run, &svm_tests[i]);
39948f67910SCathy Avery 				while (!svm_tests[i].on_vcpu_done)
40048f67910SCathy Avery 					cpu_relax();
40148f67910SCathy Avery 			}
40248f67910SCathy Avery 			else
4038660d1b5SKrish Sadhukhan 				test_run(&svm_tests[i]);
4048660d1b5SKrish Sadhukhan 		} else {
4058660d1b5SKrish Sadhukhan 			vmcb_ident(vmcb);
4068660d1b5SKrish Sadhukhan 			v2_test = &(svm_tests[i]);
4078660d1b5SKrish Sadhukhan 			svm_tests[i].v2();
4088660d1b5SKrish Sadhukhan 		}
4097d36db35SAvi Kivity 	}
4107d36db35SAvi Kivity 
41150d27547SPaolo Bonzini 	if (!matched)
41250d27547SPaolo Bonzini 		report(matched, "command line didn't match any tests!");
41350d27547SPaolo Bonzini 
414a43ed2acSAndrew Jones 	return report_summary();
4157d36db35SAvi Kivity }
416