1*7d36db35SAvi Kivity #include "svm.h" 2*7d36db35SAvi Kivity #include "libcflat.h" 3*7d36db35SAvi Kivity #include "processor.h" 4*7d36db35SAvi Kivity #include "msr.h" 5*7d36db35SAvi Kivity #include "vm.h" 6*7d36db35SAvi Kivity #include "smp.h" 7*7d36db35SAvi Kivity #include "types.h" 8*7d36db35SAvi Kivity 9*7d36db35SAvi Kivity static void setup_svm(void) 10*7d36db35SAvi Kivity { 11*7d36db35SAvi Kivity void *hsave = alloc_page(); 12*7d36db35SAvi Kivity 13*7d36db35SAvi Kivity wrmsr(MSR_VM_HSAVE_PA, virt_to_phys(hsave)); 14*7d36db35SAvi Kivity wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SVME); 15*7d36db35SAvi Kivity } 16*7d36db35SAvi Kivity 17*7d36db35SAvi Kivity static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector, 18*7d36db35SAvi Kivity u64 base, u32 limit, u32 attr) 19*7d36db35SAvi Kivity { 20*7d36db35SAvi Kivity seg->selector = selector; 21*7d36db35SAvi Kivity seg->attrib = attr; 22*7d36db35SAvi Kivity seg->limit = limit; 23*7d36db35SAvi Kivity seg->base = base; 24*7d36db35SAvi Kivity } 25*7d36db35SAvi Kivity 26*7d36db35SAvi Kivity static void vmcb_ident(struct vmcb *vmcb) 27*7d36db35SAvi Kivity { 28*7d36db35SAvi Kivity u64 vmcb_phys = virt_to_phys(vmcb); 29*7d36db35SAvi Kivity struct vmcb_save_area *save = &vmcb->save; 30*7d36db35SAvi Kivity struct vmcb_control_area *ctrl = &vmcb->control; 31*7d36db35SAvi Kivity u32 data_seg_attr = 3 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK 32*7d36db35SAvi Kivity | SVM_SELECTOR_DB_MASK | SVM_SELECTOR_G_MASK; 33*7d36db35SAvi Kivity u32 code_seg_attr = 9 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK 34*7d36db35SAvi Kivity | SVM_SELECTOR_L_MASK | SVM_SELECTOR_G_MASK; 35*7d36db35SAvi Kivity struct descriptor_table_ptr desc_table_ptr; 36*7d36db35SAvi Kivity 37*7d36db35SAvi Kivity memset(vmcb, 0, sizeof(*vmcb)); 38*7d36db35SAvi Kivity asm volatile ("vmsave" : : "a"(vmcb_phys) : "memory"); 39*7d36db35SAvi Kivity vmcb_set_seg(&save->es, read_es(), 0, -1U, data_seg_attr); 40*7d36db35SAvi Kivity vmcb_set_seg(&save->cs, read_cs(), 0, -1U, code_seg_attr); 41*7d36db35SAvi Kivity vmcb_set_seg(&save->ss, read_ss(), 0, -1U, data_seg_attr); 42*7d36db35SAvi Kivity vmcb_set_seg(&save->ds, read_ds(), 0, -1U, data_seg_attr); 43*7d36db35SAvi Kivity sgdt(&desc_table_ptr); 44*7d36db35SAvi Kivity vmcb_set_seg(&save->gdtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0); 45*7d36db35SAvi Kivity sidt(&desc_table_ptr); 46*7d36db35SAvi Kivity vmcb_set_seg(&save->idtr, 0, desc_table_ptr.base, desc_table_ptr.limit, 0); 47*7d36db35SAvi Kivity ctrl->asid = 1; 48*7d36db35SAvi Kivity save->cpl = 0; 49*7d36db35SAvi Kivity save->efer = rdmsr(MSR_EFER); 50*7d36db35SAvi Kivity save->cr4 = read_cr4(); 51*7d36db35SAvi Kivity save->cr3 = read_cr3(); 52*7d36db35SAvi Kivity save->cr0 = read_cr0(); 53*7d36db35SAvi Kivity save->dr7 = read_dr7(); 54*7d36db35SAvi Kivity save->dr6 = read_dr6(); 55*7d36db35SAvi Kivity save->cr2 = read_cr2(); 56*7d36db35SAvi Kivity save->g_pat = rdmsr(MSR_IA32_CR_PAT); 57*7d36db35SAvi Kivity save->dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 58*7d36db35SAvi Kivity ctrl->intercept = (1ULL << INTERCEPT_VMRUN) | (1ULL << INTERCEPT_VMMCALL); 59*7d36db35SAvi Kivity } 60*7d36db35SAvi Kivity 61*7d36db35SAvi Kivity struct test { 62*7d36db35SAvi Kivity const char *name; 63*7d36db35SAvi Kivity bool (*supported)(void); 64*7d36db35SAvi Kivity void (*prepare)(struct test *test); 65*7d36db35SAvi Kivity void (*guest_func)(struct test *test); 66*7d36db35SAvi Kivity bool (*finished)(struct test *test); 67*7d36db35SAvi Kivity bool (*succeeded)(struct test *test); 68*7d36db35SAvi Kivity struct vmcb *vmcb; 69*7d36db35SAvi Kivity int exits; 70*7d36db35SAvi Kivity ulong scratch; 71*7d36db35SAvi Kivity }; 72*7d36db35SAvi Kivity 73*7d36db35SAvi Kivity static void test_thunk(struct test *test) 74*7d36db35SAvi Kivity { 75*7d36db35SAvi Kivity test->guest_func(test); 76*7d36db35SAvi Kivity asm volatile ("vmmcall" : : : "memory"); 77*7d36db35SAvi Kivity } 78*7d36db35SAvi Kivity 79*7d36db35SAvi Kivity static bool test_run(struct test *test, struct vmcb *vmcb) 80*7d36db35SAvi Kivity { 81*7d36db35SAvi Kivity u64 vmcb_phys = virt_to_phys(vmcb); 82*7d36db35SAvi Kivity u64 guest_stack[10000]; 83*7d36db35SAvi Kivity bool success; 84*7d36db35SAvi Kivity 85*7d36db35SAvi Kivity test->vmcb = vmcb; 86*7d36db35SAvi Kivity test->prepare(test); 87*7d36db35SAvi Kivity vmcb->save.rip = (ulong)test_thunk; 88*7d36db35SAvi Kivity vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack)); 89*7d36db35SAvi Kivity do { 90*7d36db35SAvi Kivity asm volatile ( 91*7d36db35SAvi Kivity "clgi \n\t" 92*7d36db35SAvi Kivity "vmload \n\t" 93*7d36db35SAvi Kivity "push %%rbp \n\t" 94*7d36db35SAvi Kivity "push %1 \n\t" 95*7d36db35SAvi Kivity "vmrun \n\t" 96*7d36db35SAvi Kivity "pop %1 \n\t" 97*7d36db35SAvi Kivity "pop %%rbp \n\t" 98*7d36db35SAvi Kivity "vmsave \n\t" 99*7d36db35SAvi Kivity "stgi" 100*7d36db35SAvi Kivity : : "a"(vmcb_phys), "D"(test) 101*7d36db35SAvi Kivity : "rbx", "rcx", "rdx", "rsi", 102*7d36db35SAvi Kivity "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15", 103*7d36db35SAvi Kivity "memory"); 104*7d36db35SAvi Kivity ++test->exits; 105*7d36db35SAvi Kivity } while (!test->finished(test)); 106*7d36db35SAvi Kivity 107*7d36db35SAvi Kivity success = test->succeeded(test); 108*7d36db35SAvi Kivity 109*7d36db35SAvi Kivity printf("%s: %s\n", test->name, success ? "PASS" : "FAIL"); 110*7d36db35SAvi Kivity 111*7d36db35SAvi Kivity return success; 112*7d36db35SAvi Kivity } 113*7d36db35SAvi Kivity 114*7d36db35SAvi Kivity static bool default_supported(void) 115*7d36db35SAvi Kivity { 116*7d36db35SAvi Kivity return true; 117*7d36db35SAvi Kivity } 118*7d36db35SAvi Kivity 119*7d36db35SAvi Kivity static void default_prepare(struct test *test) 120*7d36db35SAvi Kivity { 121*7d36db35SAvi Kivity vmcb_ident(test->vmcb); 122*7d36db35SAvi Kivity cli(); 123*7d36db35SAvi Kivity } 124*7d36db35SAvi Kivity 125*7d36db35SAvi Kivity static bool default_finished(struct test *test) 126*7d36db35SAvi Kivity { 127*7d36db35SAvi Kivity return true; /* one vmexit */ 128*7d36db35SAvi Kivity } 129*7d36db35SAvi Kivity 130*7d36db35SAvi Kivity static void null_test(struct test *test) 131*7d36db35SAvi Kivity { 132*7d36db35SAvi Kivity } 133*7d36db35SAvi Kivity 134*7d36db35SAvi Kivity static bool null_check(struct test *test) 135*7d36db35SAvi Kivity { 136*7d36db35SAvi Kivity return test->vmcb->control.exit_code == SVM_EXIT_VMMCALL; 137*7d36db35SAvi Kivity } 138*7d36db35SAvi Kivity 139*7d36db35SAvi Kivity static void prepare_no_vmrun_int(struct test *test) 140*7d36db35SAvi Kivity { 141*7d36db35SAvi Kivity test->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMRUN); 142*7d36db35SAvi Kivity } 143*7d36db35SAvi Kivity 144*7d36db35SAvi Kivity static bool check_no_vmrun_int(struct test *test) 145*7d36db35SAvi Kivity { 146*7d36db35SAvi Kivity return test->vmcb->control.exit_code == SVM_EXIT_ERR; 147*7d36db35SAvi Kivity } 148*7d36db35SAvi Kivity 149*7d36db35SAvi Kivity static void test_vmrun(struct test *test) 150*7d36db35SAvi Kivity { 151*7d36db35SAvi Kivity asm volatile ("vmrun" : : "a"(virt_to_phys(test->vmcb))); 152*7d36db35SAvi Kivity } 153*7d36db35SAvi Kivity 154*7d36db35SAvi Kivity static bool check_vmrun(struct test *test) 155*7d36db35SAvi Kivity { 156*7d36db35SAvi Kivity return test->vmcb->control.exit_code == SVM_EXIT_VMRUN; 157*7d36db35SAvi Kivity } 158*7d36db35SAvi Kivity 159*7d36db35SAvi Kivity static void prepare_cr3_intercept(struct test *test) 160*7d36db35SAvi Kivity { 161*7d36db35SAvi Kivity default_prepare(test); 162*7d36db35SAvi Kivity test->vmcb->control.intercept_cr_read |= 1 << 3; 163*7d36db35SAvi Kivity } 164*7d36db35SAvi Kivity 165*7d36db35SAvi Kivity static void test_cr3_intercept(struct test *test) 166*7d36db35SAvi Kivity { 167*7d36db35SAvi Kivity asm volatile ("mov %%cr3, %0" : "=r"(test->scratch) : : "memory"); 168*7d36db35SAvi Kivity } 169*7d36db35SAvi Kivity 170*7d36db35SAvi Kivity static bool check_cr3_intercept(struct test *test) 171*7d36db35SAvi Kivity { 172*7d36db35SAvi Kivity return test->vmcb->control.exit_code == SVM_EXIT_READ_CR3; 173*7d36db35SAvi Kivity } 174*7d36db35SAvi Kivity 175*7d36db35SAvi Kivity static bool check_cr3_nointercept(struct test *test) 176*7d36db35SAvi Kivity { 177*7d36db35SAvi Kivity return null_check(test) && test->scratch == read_cr3(); 178*7d36db35SAvi Kivity } 179*7d36db35SAvi Kivity 180*7d36db35SAvi Kivity static void corrupt_cr3_intercept_bypass(void *_test) 181*7d36db35SAvi Kivity { 182*7d36db35SAvi Kivity struct test *test = _test; 183*7d36db35SAvi Kivity extern volatile u32 mmio_insn; 184*7d36db35SAvi Kivity 185*7d36db35SAvi Kivity while (!__sync_bool_compare_and_swap(&test->scratch, 1, 2)) 186*7d36db35SAvi Kivity pause(); 187*7d36db35SAvi Kivity pause(); 188*7d36db35SAvi Kivity pause(); 189*7d36db35SAvi Kivity pause(); 190*7d36db35SAvi Kivity mmio_insn = 0x90d8200f; // mov %cr3, %rax; nop 191*7d36db35SAvi Kivity } 192*7d36db35SAvi Kivity 193*7d36db35SAvi Kivity static void prepare_cr3_intercept_bypass(struct test *test) 194*7d36db35SAvi Kivity { 195*7d36db35SAvi Kivity default_prepare(test); 196*7d36db35SAvi Kivity test->vmcb->control.intercept_cr_read |= 1 << 3; 197*7d36db35SAvi Kivity on_cpu_async(1, corrupt_cr3_intercept_bypass, test); 198*7d36db35SAvi Kivity } 199*7d36db35SAvi Kivity 200*7d36db35SAvi Kivity static void test_cr3_intercept_bypass(struct test *test) 201*7d36db35SAvi Kivity { 202*7d36db35SAvi Kivity ulong a = 0xa0000; 203*7d36db35SAvi Kivity 204*7d36db35SAvi Kivity test->scratch = 1; 205*7d36db35SAvi Kivity while (test->scratch != 2) 206*7d36db35SAvi Kivity barrier(); 207*7d36db35SAvi Kivity 208*7d36db35SAvi Kivity asm volatile ("mmio_insn: mov %0, (%0); nop" 209*7d36db35SAvi Kivity : "+a"(a) : : "memory"); 210*7d36db35SAvi Kivity test->scratch = a; 211*7d36db35SAvi Kivity } 212*7d36db35SAvi Kivity 213*7d36db35SAvi Kivity static bool next_rip_supported(void) 214*7d36db35SAvi Kivity { 215*7d36db35SAvi Kivity return (cpuid(SVM_CPUID_FUNC).d & 8); 216*7d36db35SAvi Kivity } 217*7d36db35SAvi Kivity 218*7d36db35SAvi Kivity static void prepare_next_rip(struct test *test) 219*7d36db35SAvi Kivity { 220*7d36db35SAvi Kivity test->vmcb->control.intercept |= (1ULL << INTERCEPT_RDTSC); 221*7d36db35SAvi Kivity } 222*7d36db35SAvi Kivity 223*7d36db35SAvi Kivity 224*7d36db35SAvi Kivity static void test_next_rip(struct test *test) 225*7d36db35SAvi Kivity { 226*7d36db35SAvi Kivity asm volatile ("rdtsc\n\t" 227*7d36db35SAvi Kivity ".globl exp_next_rip\n\t" 228*7d36db35SAvi Kivity "exp_next_rip:\n\t" ::: "eax", "edx"); 229*7d36db35SAvi Kivity } 230*7d36db35SAvi Kivity 231*7d36db35SAvi Kivity static bool check_next_rip(struct test *test) 232*7d36db35SAvi Kivity { 233*7d36db35SAvi Kivity extern char exp_next_rip; 234*7d36db35SAvi Kivity unsigned long address = (unsigned long)&exp_next_rip; 235*7d36db35SAvi Kivity 236*7d36db35SAvi Kivity return address == test->vmcb->control.next_rip; 237*7d36db35SAvi Kivity } 238*7d36db35SAvi Kivity 239*7d36db35SAvi Kivity static void prepare_mode_switch(struct test *test) 240*7d36db35SAvi Kivity { 241*7d36db35SAvi Kivity test->vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR) 242*7d36db35SAvi Kivity | (1ULL << UD_VECTOR) 243*7d36db35SAvi Kivity | (1ULL << DF_VECTOR) 244*7d36db35SAvi Kivity | (1ULL << PF_VECTOR); 245*7d36db35SAvi Kivity test->scratch = 0; 246*7d36db35SAvi Kivity } 247*7d36db35SAvi Kivity 248*7d36db35SAvi Kivity static void test_mode_switch(struct test *test) 249*7d36db35SAvi Kivity { 250*7d36db35SAvi Kivity asm volatile(" cli\n" 251*7d36db35SAvi Kivity " ljmp *1f\n" /* jump to 32-bit code segment */ 252*7d36db35SAvi Kivity "1:\n" 253*7d36db35SAvi Kivity " .long 2f\n" 254*7d36db35SAvi Kivity " .long 40\n" 255*7d36db35SAvi Kivity ".code32\n" 256*7d36db35SAvi Kivity "2:\n" 257*7d36db35SAvi Kivity " movl %%cr0, %%eax\n" 258*7d36db35SAvi Kivity " btcl $31, %%eax\n" /* clear PG */ 259*7d36db35SAvi Kivity " movl %%eax, %%cr0\n" 260*7d36db35SAvi Kivity " movl $0xc0000080, %%ecx\n" /* EFER */ 261*7d36db35SAvi Kivity " rdmsr\n" 262*7d36db35SAvi Kivity " btcl $8, %%eax\n" /* clear LME */ 263*7d36db35SAvi Kivity " wrmsr\n" 264*7d36db35SAvi Kivity " movl %%cr4, %%eax\n" 265*7d36db35SAvi Kivity " btcl $5, %%eax\n" /* clear PAE */ 266*7d36db35SAvi Kivity " movl %%eax, %%cr4\n" 267*7d36db35SAvi Kivity " movw $64, %%ax\n" 268*7d36db35SAvi Kivity " movw %%ax, %%ds\n" 269*7d36db35SAvi Kivity " ljmpl $56, $3f\n" /* jump to 16 bit protected-mode */ 270*7d36db35SAvi Kivity ".code16\n" 271*7d36db35SAvi Kivity "3:\n" 272*7d36db35SAvi Kivity " movl %%cr0, %%eax\n" 273*7d36db35SAvi Kivity " btcl $0, %%eax\n" /* clear PE */ 274*7d36db35SAvi Kivity " movl %%eax, %%cr0\n" 275*7d36db35SAvi Kivity " ljmpl $0, $4f\n" /* jump to real-mode */ 276*7d36db35SAvi Kivity "4:\n" 277*7d36db35SAvi Kivity " vmmcall\n" 278*7d36db35SAvi Kivity " movl %%cr0, %%eax\n" 279*7d36db35SAvi Kivity " btsl $0, %%eax\n" /* set PE */ 280*7d36db35SAvi Kivity " movl %%eax, %%cr0\n" 281*7d36db35SAvi Kivity " ljmpl $40, $5f\n" /* back to protected mode */ 282*7d36db35SAvi Kivity ".code32\n" 283*7d36db35SAvi Kivity "5:\n" 284*7d36db35SAvi Kivity " movl %%cr4, %%eax\n" 285*7d36db35SAvi Kivity " btsl $5, %%eax\n" /* set PAE */ 286*7d36db35SAvi Kivity " movl %%eax, %%cr4\n" 287*7d36db35SAvi Kivity " movl $0xc0000080, %%ecx\n" /* EFER */ 288*7d36db35SAvi Kivity " rdmsr\n" 289*7d36db35SAvi Kivity " btsl $8, %%eax\n" /* set LME */ 290*7d36db35SAvi Kivity " wrmsr\n" 291*7d36db35SAvi Kivity " movl %%cr0, %%eax\n" 292*7d36db35SAvi Kivity " btsl $31, %%eax\n" /* set PG */ 293*7d36db35SAvi Kivity " movl %%eax, %%cr0\n" 294*7d36db35SAvi Kivity " ljmpl $8, $6f\n" /* back to long mode */ 295*7d36db35SAvi Kivity ".code64\n\t" 296*7d36db35SAvi Kivity "6:\n" 297*7d36db35SAvi Kivity " vmmcall\n" 298*7d36db35SAvi Kivity ::: "rax", "rbx", "rcx", "rdx", "memory"); 299*7d36db35SAvi Kivity } 300*7d36db35SAvi Kivity 301*7d36db35SAvi Kivity static bool mode_switch_finished(struct test *test) 302*7d36db35SAvi Kivity { 303*7d36db35SAvi Kivity u64 cr0, cr4, efer; 304*7d36db35SAvi Kivity 305*7d36db35SAvi Kivity cr0 = test->vmcb->save.cr0; 306*7d36db35SAvi Kivity cr4 = test->vmcb->save.cr4; 307*7d36db35SAvi Kivity efer = test->vmcb->save.efer; 308*7d36db35SAvi Kivity 309*7d36db35SAvi Kivity /* Only expect VMMCALL intercepts */ 310*7d36db35SAvi Kivity if (test->vmcb->control.exit_code != SVM_EXIT_VMMCALL) 311*7d36db35SAvi Kivity return true; 312*7d36db35SAvi Kivity 313*7d36db35SAvi Kivity /* Jump over VMMCALL instruction */ 314*7d36db35SAvi Kivity test->vmcb->save.rip += 3; 315*7d36db35SAvi Kivity 316*7d36db35SAvi Kivity /* Do sanity checks */ 317*7d36db35SAvi Kivity switch (test->scratch) { 318*7d36db35SAvi Kivity case 0: 319*7d36db35SAvi Kivity /* Test should be in real mode now - check for this */ 320*7d36db35SAvi Kivity if ((cr0 & 0x80000001) || /* CR0.PG, CR0.PE */ 321*7d36db35SAvi Kivity (cr4 & 0x00000020) || /* CR4.PAE */ 322*7d36db35SAvi Kivity (efer & 0x00000500)) /* EFER.LMA, EFER.LME */ 323*7d36db35SAvi Kivity return true; 324*7d36db35SAvi Kivity break; 325*7d36db35SAvi Kivity case 2: 326*7d36db35SAvi Kivity /* Test should be back in long-mode now - check for this */ 327*7d36db35SAvi Kivity if (((cr0 & 0x80000001) != 0x80000001) || /* CR0.PG, CR0.PE */ 328*7d36db35SAvi Kivity ((cr4 & 0x00000020) != 0x00000020) || /* CR4.PAE */ 329*7d36db35SAvi Kivity ((efer & 0x00000500) != 0x00000500)) /* EFER.LMA, EFER.LME */ 330*7d36db35SAvi Kivity return true; 331*7d36db35SAvi Kivity break; 332*7d36db35SAvi Kivity } 333*7d36db35SAvi Kivity 334*7d36db35SAvi Kivity /* one step forward */ 335*7d36db35SAvi Kivity test->scratch += 1; 336*7d36db35SAvi Kivity 337*7d36db35SAvi Kivity return test->scratch == 2; 338*7d36db35SAvi Kivity } 339*7d36db35SAvi Kivity 340*7d36db35SAvi Kivity static bool check_mode_switch(struct test *test) 341*7d36db35SAvi Kivity { 342*7d36db35SAvi Kivity return test->scratch == 2; 343*7d36db35SAvi Kivity } 344*7d36db35SAvi Kivity 345*7d36db35SAvi Kivity static void prepare_asid_zero(struct test *test) 346*7d36db35SAvi Kivity { 347*7d36db35SAvi Kivity test->vmcb->control.asid = 0; 348*7d36db35SAvi Kivity } 349*7d36db35SAvi Kivity 350*7d36db35SAvi Kivity static void test_asid_zero(struct test *test) 351*7d36db35SAvi Kivity { 352*7d36db35SAvi Kivity asm volatile ("vmmcall\n\t"); 353*7d36db35SAvi Kivity } 354*7d36db35SAvi Kivity 355*7d36db35SAvi Kivity static bool check_asid_zero(struct test *test) 356*7d36db35SAvi Kivity { 357*7d36db35SAvi Kivity return test->vmcb->control.exit_code == SVM_EXIT_ERR; 358*7d36db35SAvi Kivity } 359*7d36db35SAvi Kivity 360*7d36db35SAvi Kivity static struct test tests[] = { 361*7d36db35SAvi Kivity { "null", default_supported, default_prepare, null_test, 362*7d36db35SAvi Kivity default_finished, null_check }, 363*7d36db35SAvi Kivity { "vmrun", default_supported, default_prepare, test_vmrun, 364*7d36db35SAvi Kivity default_finished, check_vmrun }, 365*7d36db35SAvi Kivity { "vmrun intercept check", default_supported, prepare_no_vmrun_int, 366*7d36db35SAvi Kivity null_test, default_finished, check_no_vmrun_int }, 367*7d36db35SAvi Kivity { "cr3 read intercept", default_supported, prepare_cr3_intercept, 368*7d36db35SAvi Kivity test_cr3_intercept, default_finished, check_cr3_intercept }, 369*7d36db35SAvi Kivity { "cr3 read nointercept", default_supported, default_prepare, 370*7d36db35SAvi Kivity test_cr3_intercept, default_finished, check_cr3_nointercept }, 371*7d36db35SAvi Kivity { "cr3 read intercept emulate", default_supported, 372*7d36db35SAvi Kivity prepare_cr3_intercept_bypass, test_cr3_intercept_bypass, 373*7d36db35SAvi Kivity default_finished, check_cr3_intercept }, 374*7d36db35SAvi Kivity { "next_rip", next_rip_supported, prepare_next_rip, test_next_rip, 375*7d36db35SAvi Kivity default_finished, check_next_rip }, 376*7d36db35SAvi Kivity { "mode_switch", default_supported, prepare_mode_switch, test_mode_switch, 377*7d36db35SAvi Kivity mode_switch_finished, check_mode_switch }, 378*7d36db35SAvi Kivity { "asid_zero", default_supported, prepare_asid_zero, test_asid_zero, 379*7d36db35SAvi Kivity default_finished, check_asid_zero }, 380*7d36db35SAvi Kivity 381*7d36db35SAvi Kivity }; 382*7d36db35SAvi Kivity 383*7d36db35SAvi Kivity int main(int ac, char **av) 384*7d36db35SAvi Kivity { 385*7d36db35SAvi Kivity int i, nr, passed, done; 386*7d36db35SAvi Kivity struct vmcb *vmcb; 387*7d36db35SAvi Kivity 388*7d36db35SAvi Kivity setup_vm(); 389*7d36db35SAvi Kivity smp_init(); 390*7d36db35SAvi Kivity 391*7d36db35SAvi Kivity if (!(cpuid(0x80000001).c & 4)) { 392*7d36db35SAvi Kivity printf("SVM not availble\n"); 393*7d36db35SAvi Kivity return 0; 394*7d36db35SAvi Kivity } 395*7d36db35SAvi Kivity 396*7d36db35SAvi Kivity setup_svm(); 397*7d36db35SAvi Kivity 398*7d36db35SAvi Kivity vmcb = alloc_page(); 399*7d36db35SAvi Kivity 400*7d36db35SAvi Kivity nr = ARRAY_SIZE(tests); 401*7d36db35SAvi Kivity passed = done = 0; 402*7d36db35SAvi Kivity for (i = 0; i < nr; ++i) { 403*7d36db35SAvi Kivity if (!tests[i].supported()) 404*7d36db35SAvi Kivity continue; 405*7d36db35SAvi Kivity done += 1; 406*7d36db35SAvi Kivity passed += test_run(&tests[i], vmcb); 407*7d36db35SAvi Kivity } 408*7d36db35SAvi Kivity 409*7d36db35SAvi Kivity printf("\nSUMMARY: %d TESTS, %d FAILURES\n", done, (done - passed)); 410*7d36db35SAvi Kivity return passed == done ? 0 : 1; 411*7d36db35SAvi Kivity } 412