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"
116f5ce7c1SManali Shukla #include "fwcfg.h"
127d36db35SAvi Kivity #include "smp.h"
135aca024eSPaolo Bonzini #include "alloc_page.h"
14306bb7dbSCathy Avery #include "isr.h"
15306bb7dbSCathy Avery #include "apic.h"
167d36db35SAvi Kivity
171535bf0fSJoerg Roedel /* for the nested page table*/
18ad879127SKrish Sadhukhan u64 *pml4e;
191535bf0fSJoerg Roedel
20096cf7feSPaolo Bonzini struct vmcb *vmcb;
21096cf7feSPaolo Bonzini
npt_get_pte(u64 address)22ad879127SKrish Sadhukhan u64 *npt_get_pte(u64 address)
231535bf0fSJoerg Roedel {
246f5ce7c1SManali Shukla return get_pte(npt_get_pml4e(), (void*)address);
251535bf0fSJoerg Roedel }
261535bf0fSJoerg Roedel
npt_get_pde(u64 address)27ad879127SKrish Sadhukhan u64 *npt_get_pde(u64 address)
28f6a2ca45SPaolo Bonzini {
296f5ce7c1SManali Shukla struct pte_search search;
306f5ce7c1SManali Shukla search = find_pte_level(npt_get_pml4e(), (void*)address, 2);
316f5ce7c1SManali Shukla return search.pte;
32f6a2ca45SPaolo Bonzini }
33f6a2ca45SPaolo Bonzini
npt_get_pdpe(u64 address)346f5ce7c1SManali Shukla u64 *npt_get_pdpe(u64 address)
358594b943SJoerg Roedel {
366f5ce7c1SManali Shukla struct pte_search search;
376f5ce7c1SManali Shukla search = find_pte_level(npt_get_pml4e(), (void*)address, 3);
386f5ce7c1SManali Shukla return search.pte;
39ad879127SKrish Sadhukhan }
408594b943SJoerg Roedel
npt_get_pml4e(void)41c6405e37SNadav Amit u64 *npt_get_pml4e(void)
42c6405e37SNadav Amit {
43c6405e37SNadav Amit return pml4e;
44c6405e37SNadav Amit }
45c6405e37SNadav Amit
smp_supported(void)46ad879127SKrish Sadhukhan bool smp_supported(void)
47ad879127SKrish Sadhukhan {
48ad879127SKrish Sadhukhan return cpu_count() > 1;
49ad879127SKrish Sadhukhan }
508594b943SJoerg Roedel
default_supported(void)51ad879127SKrish Sadhukhan bool default_supported(void)
52ad879127SKrish Sadhukhan {
53ad879127SKrish Sadhukhan return true;
54ad879127SKrish Sadhukhan }
55ad879127SKrish Sadhukhan
vgif_supported(void)56f6972bd6SLara Lazier bool vgif_supported(void)
57f6972bd6SLara Lazier {
58f6972bd6SLara Lazier return this_cpu_has(X86_FEATURE_VGIF);
59f6972bd6SLara Lazier }
60f6972bd6SLara Lazier
lbrv_supported(void)61537d39dfSMaxim Levitsky bool lbrv_supported(void)
62537d39dfSMaxim Levitsky {
63537d39dfSMaxim Levitsky return this_cpu_has(X86_FEATURE_LBRV);
64537d39dfSMaxim Levitsky }
65537d39dfSMaxim Levitsky
tsc_scale_supported(void)66a8503d50SMaxim Levitsky bool tsc_scale_supported(void)
67a8503d50SMaxim Levitsky {
68a8503d50SMaxim Levitsky return this_cpu_has(X86_FEATURE_TSCRATEMSR);
69a8503d50SMaxim Levitsky }
70a8503d50SMaxim Levitsky
pause_filter_supported(void)718650dffeSMaxim Levitsky bool pause_filter_supported(void)
728650dffeSMaxim Levitsky {
738650dffeSMaxim Levitsky return this_cpu_has(X86_FEATURE_PAUSEFILTER);
748650dffeSMaxim Levitsky }
758650dffeSMaxim Levitsky
pause_threshold_supported(void)768650dffeSMaxim Levitsky bool pause_threshold_supported(void)
778650dffeSMaxim Levitsky {
788650dffeSMaxim Levitsky return this_cpu_has(X86_FEATURE_PFTHRESHOLD);
798650dffeSMaxim Levitsky }
808650dffeSMaxim Levitsky
818650dffeSMaxim Levitsky
default_prepare(struct svm_test * test)82ad879127SKrish Sadhukhan void default_prepare(struct svm_test *test)
83ad879127SKrish Sadhukhan {
84096cf7feSPaolo Bonzini vmcb_ident(vmcb);
85ad879127SKrish Sadhukhan }
86ad879127SKrish Sadhukhan
default_prepare_gif_clear(struct svm_test * test)87ad879127SKrish Sadhukhan void default_prepare_gif_clear(struct svm_test *test)
88ad879127SKrish Sadhukhan {
89ad879127SKrish Sadhukhan }
90ad879127SKrish Sadhukhan
default_finished(struct svm_test * test)91ad879127SKrish Sadhukhan bool default_finished(struct svm_test *test)
92ad879127SKrish Sadhukhan {
93ad879127SKrish Sadhukhan return true; /* one vmexit */
94ad879127SKrish Sadhukhan }
95ad879127SKrish Sadhukhan
npt_supported(void)96ad879127SKrish Sadhukhan bool npt_supported(void)
97ad879127SKrish Sadhukhan {
98ad879127SKrish Sadhukhan return this_cpu_has(X86_FEATURE_NPT);
99ad879127SKrish Sadhukhan }
100ad879127SKrish Sadhukhan
vnmi_supported(void)10108200397SSantosh Shukla bool vnmi_supported(void)
10208200397SSantosh Shukla {
10308200397SSantosh Shukla return this_cpu_has(X86_FEATURE_VNMI);
10408200397SSantosh Shukla }
10508200397SSantosh Shukla
get_test_stage(struct svm_test * test)106ad879127SKrish Sadhukhan int get_test_stage(struct svm_test *test)
107ad879127SKrish Sadhukhan {
108ad879127SKrish Sadhukhan barrier();
109ad879127SKrish Sadhukhan return test->scratch;
110ad879127SKrish Sadhukhan }
111ad879127SKrish Sadhukhan
set_test_stage(struct svm_test * test,int s)112ad879127SKrish Sadhukhan void set_test_stage(struct svm_test *test, int s)
113ad879127SKrish Sadhukhan {
114ad879127SKrish Sadhukhan barrier();
115ad879127SKrish Sadhukhan test->scratch = s;
116ad879127SKrish Sadhukhan barrier();
117ad879127SKrish Sadhukhan }
118ad879127SKrish Sadhukhan
inc_test_stage(struct svm_test * test)119ad879127SKrish Sadhukhan void inc_test_stage(struct svm_test *test)
120ad879127SKrish Sadhukhan {
121ad879127SKrish Sadhukhan barrier();
122ad879127SKrish Sadhukhan test->scratch++;
123ad879127SKrish Sadhukhan barrier();
1248594b943SJoerg Roedel }
1258594b943SJoerg Roedel
vmcb_set_seg(struct vmcb_seg * seg,u16 selector,u64 base,u32 limit,u32 attr)1267d36db35SAvi Kivity static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector,
1277d36db35SAvi Kivity u64 base, u32 limit, u32 attr)
1287d36db35SAvi Kivity {
1297d36db35SAvi Kivity seg->selector = selector;
1307d36db35SAvi Kivity seg->attrib = attr;
1317d36db35SAvi Kivity seg->limit = limit;
1327d36db35SAvi Kivity seg->base = base;
1337d36db35SAvi Kivity }
1347d36db35SAvi Kivity
vmmcall(void)135ad879127SKrish Sadhukhan inline void vmmcall(void)
136ad879127SKrish Sadhukhan {
137ad879127SKrish Sadhukhan asm volatile ("vmmcall" : : : "memory");
138ad879127SKrish Sadhukhan }
139ad879127SKrish Sadhukhan
1408660d1b5SKrish Sadhukhan static test_guest_func guest_main;
1418660d1b5SKrish Sadhukhan
test_set_guest(test_guest_func func)1428660d1b5SKrish Sadhukhan void test_set_guest(test_guest_func func)
1438660d1b5SKrish Sadhukhan {
1448660d1b5SKrish Sadhukhan guest_main = func;
1458660d1b5SKrish Sadhukhan }
1468660d1b5SKrish Sadhukhan
test_thunk(struct svm_test * test)147ad879127SKrish Sadhukhan static void test_thunk(struct svm_test *test)
148ad879127SKrish Sadhukhan {
1498660d1b5SKrish Sadhukhan guest_main(test);
150ad879127SKrish Sadhukhan vmmcall();
151ad879127SKrish Sadhukhan }
152ad879127SKrish Sadhukhan
153ad879127SKrish Sadhukhan u8 *io_bitmap;
154ad879127SKrish Sadhukhan u8 io_bitmap_area[16384];
155ad879127SKrish Sadhukhan
156ad879127SKrish Sadhukhan u8 *msr_bitmap;
157ad879127SKrish Sadhukhan u8 msr_bitmap_area[MSR_BITMAP_SIZE + PAGE_SIZE];
158ad879127SKrish Sadhukhan
vmcb_ident(struct vmcb * vmcb)159ad879127SKrish Sadhukhan void vmcb_ident(struct vmcb *vmcb)
1607d36db35SAvi Kivity {
1617d36db35SAvi Kivity u64 vmcb_phys = virt_to_phys(vmcb);
1627d36db35SAvi Kivity struct vmcb_save_area *save = &vmcb->save;
1637d36db35SAvi Kivity struct vmcb_control_area *ctrl = &vmcb->control;
1647d36db35SAvi Kivity u32 data_seg_attr = 3 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
1657d36db35SAvi Kivity | SVM_SELECTOR_DB_MASK | SVM_SELECTOR_G_MASK;
1667d36db35SAvi Kivity u32 code_seg_attr = 9 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
1677d36db35SAvi Kivity | SVM_SELECTOR_L_MASK | SVM_SELECTOR_G_MASK;
1687d36db35SAvi Kivity struct descriptor_table_ptr desc_table_ptr;
1697d36db35SAvi Kivity
1707d36db35SAvi Kivity memset(vmcb, 0, sizeof(*vmcb));
1712c6589bcSPeter Shier asm volatile ("vmsave %0" : : "a"(vmcb_phys) : "memory");
1727d36db35SAvi Kivity vmcb_set_seg(&save->es, read_es(), 0, -1U, data_seg_attr);
1737d36db35SAvi Kivity vmcb_set_seg(&save->cs, read_cs(), 0, -1U, code_seg_attr);
1747d36db35SAvi Kivity vmcb_set_seg(&save->ss, read_ss(), 0, -1U, data_seg_attr);
1757d36db35SAvi Kivity vmcb_set_seg(&save->ds, read_ds(), 0, -1U, data_seg_attr);
1767d36db35SAvi Kivity sgdt(&desc_table_ptr);
1777d36db35SAvi Kivity vmcb_set_seg(&save->gdtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0);
1787d36db35SAvi Kivity sidt(&desc_table_ptr);
1797d36db35SAvi Kivity vmcb_set_seg(&save->idtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0);
1807d36db35SAvi Kivity ctrl->asid = 1;
1817d36db35SAvi Kivity save->cpl = 0;
1827d36db35SAvi Kivity save->efer = rdmsr(MSR_EFER);
1837d36db35SAvi Kivity save->cr4 = read_cr4();
1847d36db35SAvi Kivity save->cr3 = read_cr3();
1857d36db35SAvi Kivity save->cr0 = read_cr0();
1867d36db35SAvi Kivity save->dr7 = read_dr7();
1877d36db35SAvi Kivity save->dr6 = read_dr6();
1887d36db35SAvi Kivity save->cr2 = read_cr2();
1897d36db35SAvi Kivity save->g_pat = rdmsr(MSR_IA32_CR_PAT);
1907d36db35SAvi Kivity save->dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR);
191eb8a146bSMaxim Levitsky ctrl->intercept = (1ULL << INTERCEPT_VMRUN) |
192eb8a146bSMaxim Levitsky (1ULL << INTERCEPT_VMMCALL) |
193eb8a146bSMaxim Levitsky (1ULL << INTERCEPT_SHUTDOWN);
1943d46571bSPaolo Bonzini ctrl->iopm_base_pa = virt_to_phys(io_bitmap);
19506a8c023STambe, William ctrl->msrpm_base_pa = virt_to_phys(msr_bitmap);
1961535bf0fSJoerg Roedel
1971535bf0fSJoerg Roedel if (npt_supported()) {
1981535bf0fSJoerg Roedel ctrl->nested_ctl = 1;
1991535bf0fSJoerg Roedel ctrl->nested_cr3 = (u64)pml4e;
200c803b19bSNadav Amit ctrl->tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
2011535bf0fSJoerg Roedel }
2027d36db35SAvi Kivity }
2037d36db35SAvi Kivity
204a43baea0SPaolo Bonzini struct regs regs;
205a43baea0SPaolo Bonzini
get_regs(void)206ad879127SKrish Sadhukhan struct regs get_regs(void)
207ad879127SKrish Sadhukhan {
208ad879127SKrish Sadhukhan return regs;
209ad879127SKrish Sadhukhan }
210ad879127SKrish Sadhukhan
211a43baea0SPaolo Bonzini // rax handled specially below
212a43baea0SPaolo Bonzini
213a43baea0SPaolo Bonzini
2148660d1b5SKrish Sadhukhan struct svm_test *v2_test;
2158660d1b5SKrish Sadhukhan
2168660d1b5SKrish Sadhukhan
2178660d1b5SKrish Sadhukhan u64 guest_stack[10000];
2188660d1b5SKrish Sadhukhan
svm_setup_vmrun(u64 rip)2195200c1f1SSean Christopherson void svm_setup_vmrun(u64 rip)
2208660d1b5SKrish Sadhukhan {
221a6495564SKrish Sadhukhan vmcb->save.rip = (ulong)rip;
2228660d1b5SKrish Sadhukhan vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
2235200c1f1SSean Christopherson }
2245200c1f1SSean Christopherson
__svm_vmrun(u64 rip)2255200c1f1SSean Christopherson int __svm_vmrun(u64 rip)
2265200c1f1SSean Christopherson {
2275200c1f1SSean Christopherson svm_setup_vmrun(rip);
2288660d1b5SKrish Sadhukhan regs.rdi = (ulong)v2_test;
2298660d1b5SKrish Sadhukhan
2308660d1b5SKrish Sadhukhan asm volatile (
23144480895SKrish Sadhukhan ASM_PRE_VMRUN_CMD
23244480895SKrish Sadhukhan "vmrun %%rax\n\t" \
23344480895SKrish Sadhukhan ASM_POST_VMRUN_CMD
2348660d1b5SKrish Sadhukhan :
2358660d1b5SKrish Sadhukhan : "a" (virt_to_phys(vmcb))
2367b87cad0SPaolo Bonzini : "memory", "r15");
2378660d1b5SKrish Sadhukhan
2388660d1b5SKrish Sadhukhan return (vmcb->control.exit_code);
2398660d1b5SKrish Sadhukhan }
2408660d1b5SKrish Sadhukhan
svm_vmrun(void)241a6495564SKrish Sadhukhan int svm_vmrun(void)
242a6495564SKrish Sadhukhan {
243a6495564SKrish Sadhukhan return __svm_vmrun((u64)test_thunk);
244a6495564SKrish Sadhukhan }
245a6495564SKrish Sadhukhan
2460c22fd44SPaolo Bonzini extern u8 vmrun_rip;
24744480895SKrish Sadhukhan
test_run(struct svm_test * test)248440c4fc3SBill Wendling static noinline void test_run(struct svm_test *test)
2497d36db35SAvi Kivity {
2507d36db35SAvi Kivity u64 vmcb_phys = virt_to_phys(vmcb);
2517d36db35SAvi Kivity
252*787f0aebSMaxim Levitsky cli();
253cf851077SSean Christopherson vmcb_ident(vmcb);
254cf851077SSean Christopherson
2557d36db35SAvi Kivity test->prepare(test);
2568660d1b5SKrish Sadhukhan guest_main = test->guest_func;
2577d36db35SAvi Kivity vmcb->save.rip = (ulong)test_thunk;
2587d36db35SAvi Kivity vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
259a43baea0SPaolo Bonzini regs.rdi = (ulong)test;
2607d36db35SAvi Kivity do {
261ad879127SKrish Sadhukhan struct svm_test *the_test = test;
262e7bce343SPaolo Bonzini u64 the_vmcb = vmcb_phys;
2637d36db35SAvi Kivity asm volatile (
2642c6589bcSPeter Shier "clgi;\n\t" // semi-colon needed for LLVM compatibility
2652e7dd780SCathy Avery "sti \n\t"
266e7bce343SPaolo Bonzini "call *%c[PREPARE_GIF_CLEAR](%[test]) \n \t"
267e7bce343SPaolo Bonzini "mov %[vmcb_phys], %%rax \n\t"
26844480895SKrish Sadhukhan ASM_PRE_VMRUN_CMD
26944480895SKrish Sadhukhan ".global vmrun_rip\n\t" \
27044480895SKrish Sadhukhan "vmrun_rip: vmrun %%rax\n\t" \
27144480895SKrish Sadhukhan ASM_POST_VMRUN_CMD
2722e7dd780SCathy Avery "cli \n\t"
2737d36db35SAvi Kivity "stgi"
274e7bce343SPaolo Bonzini : // inputs clobbered by the guest:
27586d24fa6SBill Wendling "=D" (the_test), // first argument register
27686d24fa6SBill Wendling "=b" (the_vmcb) // callee save register!
277e7bce343SPaolo Bonzini : [test] "0" (the_test),
278e7bce343SPaolo Bonzini [vmcb_phys] "1"(the_vmcb),
279ad879127SKrish Sadhukhan [PREPARE_GIF_CLEAR] "i" (offsetof(struct svm_test, prepare_gif_clear))
280e7bce343SPaolo Bonzini : "rax", "rcx", "rdx", "rsi",
2817d36db35SAvi Kivity "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15",
2827d36db35SAvi Kivity "memory");
2837d36db35SAvi Kivity ++test->exits;
2847d36db35SAvi Kivity } while (!test->finished(test));
285*787f0aebSMaxim Levitsky sti();
2867d36db35SAvi Kivity
287a299895bSThomas Huth report(test->succeeded(test), "%s", test->name);
28848f67910SCathy Avery
28948f67910SCathy Avery if (test->on_vcpu)
29048f67910SCathy Avery test->on_vcpu_done = true;
29148f67910SCathy Avery }
29248f67910SCathy Avery
set_additional_vcpu_msr(void * msr_efer)29348f67910SCathy Avery static void set_additional_vcpu_msr(void *msr_efer)
29448f67910SCathy Avery {
29548f67910SCathy Avery void *hsave = alloc_page();
29648f67910SCathy Avery
29748f67910SCathy Avery wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave));
298779fd1faSSean Christopherson wrmsr(MSR_EFER, (ulong)msr_efer | EFER_SVME);
2997d36db35SAvi Kivity }
3007d36db35SAvi Kivity
setup_npt(void)3016f5ce7c1SManali Shukla static void setup_npt(void)
3026f5ce7c1SManali Shukla {
3036f5ce7c1SManali Shukla u64 size = fwcfg_get_u64(FW_CFG_RAM_SIZE);
3046f5ce7c1SManali Shukla
3056f5ce7c1SManali Shukla /* Ensure all <4gb is mapped, e.g. if there's no RAM above 4gb. */
3066f5ce7c1SManali Shukla if (size < BIT_ULL(32))
3076f5ce7c1SManali Shukla size = BIT_ULL(32);
3086f5ce7c1SManali Shukla
3096f5ce7c1SManali Shukla pml4e = alloc_page();
3106f5ce7c1SManali Shukla
3116f5ce7c1SManali Shukla /* NPT accesses are treated as "user" accesses. */
3126f5ce7c1SManali Shukla __setup_mmu_range(pml4e, 0, size, X86_MMU_MAP_USER);
3136f5ce7c1SManali Shukla }
3146f5ce7c1SManali Shukla
setup_svm(void)315ad879127SKrish Sadhukhan static void setup_svm(void)
316095274b4SPrasad Joshi {
317ad879127SKrish Sadhukhan void *hsave = alloc_page();
3186f5ce7c1SManali Shukla int i;
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
3416f5ce7c1SManali Shukla setup_npt();
342ea975120SJoerg Roedel }
343ea975120SJoerg Roedel
34450d27547SPaolo Bonzini int matched;
34550d27547SPaolo Bonzini
34650d27547SPaolo Bonzini static bool
test_wanted(const char * name,char * filters[],int filter_count)34750d27547SPaolo Bonzini test_wanted(const char *name, char *filters[], int filter_count)
34850d27547SPaolo Bonzini {
34950d27547SPaolo Bonzini int i;
35050d27547SPaolo Bonzini bool positive = false;
35150d27547SPaolo Bonzini bool match = false;
35250d27547SPaolo Bonzini char clean_name[strlen(name) + 1];
35350d27547SPaolo Bonzini char *c;
35450d27547SPaolo Bonzini const char *n;
35550d27547SPaolo Bonzini
35650d27547SPaolo Bonzini /* Replace spaces with underscores. */
35750d27547SPaolo Bonzini n = name;
35850d27547SPaolo Bonzini c = &clean_name[0];
35950d27547SPaolo Bonzini do *c++ = (*n == ' ') ? '_' : *n;
36050d27547SPaolo Bonzini while (*n++);
36150d27547SPaolo Bonzini
36250d27547SPaolo Bonzini for (i = 0; i < filter_count; i++) {
36350d27547SPaolo Bonzini const char *filter = filters[i];
36450d27547SPaolo Bonzini
36550d27547SPaolo Bonzini if (filter[0] == '-') {
36650d27547SPaolo Bonzini if (simple_glob(clean_name, filter + 1))
36750d27547SPaolo Bonzini return false;
36850d27547SPaolo Bonzini } else {
36950d27547SPaolo Bonzini positive = true;
37050d27547SPaolo Bonzini match |= simple_glob(clean_name, filter);
37150d27547SPaolo Bonzini }
37250d27547SPaolo Bonzini }
37350d27547SPaolo Bonzini
37450d27547SPaolo Bonzini if (!positive || match) {
37550d27547SPaolo Bonzini matched++;
37650d27547SPaolo Bonzini return true;
37750d27547SPaolo Bonzini } else {
37850d27547SPaolo Bonzini return false;
37950d27547SPaolo Bonzini }
38050d27547SPaolo Bonzini }
38150d27547SPaolo Bonzini
run_svm_tests(int ac,char ** av,struct svm_test * svm_tests)382712840d5SManali Shukla int run_svm_tests(int ac, char **av, struct svm_test *svm_tests)
3837d36db35SAvi Kivity {
384ad879127SKrish Sadhukhan int i = 0;
3857d36db35SAvi Kivity
38650d27547SPaolo Bonzini ac--;
38750d27547SPaolo Bonzini av++;
38850d27547SPaolo Bonzini
389badc98caSKrish Sadhukhan if (!this_cpu_has(X86_FEATURE_SVM)) {
390912c0d72SThomas Huth printf("SVM not available\n");
39132b9603cSRadim Krčmář return report_summary();
3927d36db35SAvi Kivity }
3937d36db35SAvi Kivity
3947d36db35SAvi Kivity setup_svm();
3957d36db35SAvi Kivity
3967d36db35SAvi Kivity vmcb = alloc_page();
3977d36db35SAvi Kivity
398ad879127SKrish Sadhukhan for (; svm_tests[i].name != NULL; i++) {
3998660d1b5SKrish Sadhukhan if (!test_wanted(svm_tests[i].name, av, ac))
4007d36db35SAvi Kivity continue;
4018660d1b5SKrish Sadhukhan if (svm_tests[i].supported && !svm_tests[i].supported())
4028660d1b5SKrish Sadhukhan continue;
4038660d1b5SKrish Sadhukhan if (svm_tests[i].v2 == NULL) {
40448f67910SCathy Avery if (svm_tests[i].on_vcpu) {
40548f67910SCathy Avery if (cpu_count() <= svm_tests[i].on_vcpu)
40648f67910SCathy Avery continue;
40748f67910SCathy Avery on_cpu_async(svm_tests[i].on_vcpu, (void *)test_run, &svm_tests[i]);
40848f67910SCathy Avery while (!svm_tests[i].on_vcpu_done)
40948f67910SCathy Avery cpu_relax();
41048f67910SCathy Avery }
41148f67910SCathy Avery else
4128660d1b5SKrish Sadhukhan test_run(&svm_tests[i]);
4138660d1b5SKrish Sadhukhan } else {
4148660d1b5SKrish Sadhukhan vmcb_ident(vmcb);
4158660d1b5SKrish Sadhukhan v2_test = &(svm_tests[i]);
4168660d1b5SKrish Sadhukhan svm_tests[i].v2();
4178660d1b5SKrish Sadhukhan }
4187d36db35SAvi Kivity }
4197d36db35SAvi Kivity
42050d27547SPaolo Bonzini if (!matched)
42150d27547SPaolo Bonzini report(matched, "command line didn't match any tests!");
42250d27547SPaolo Bonzini
423a43ed2acSAndrew Jones return report_summary();
4247d36db35SAvi Kivity }
425