1 #include "svm.h" 2 #include "libcflat.h" 3 #include "processor.h" 4 #include "desc.h" 5 #include "msr.h" 6 #include "vm.h" 7 #include "smp.h" 8 #include "types.h" 9 #include "alloc_page.h" 10 #include "isr.h" 11 #include "apic.h" 12 #include "delay.h" 13 14 #define SVM_EXIT_MAX_DR_INTERCEPT 0x3f 15 16 static void *scratch_page; 17 18 #define LATENCY_RUNS 1000000 19 20 u64 tsc_start; 21 u64 tsc_end; 22 23 u64 vmrun_sum, vmexit_sum; 24 u64 vmsave_sum, vmload_sum; 25 u64 stgi_sum, clgi_sum; 26 u64 latvmrun_max; 27 u64 latvmrun_min; 28 u64 latvmexit_max; 29 u64 latvmexit_min; 30 u64 latvmload_max; 31 u64 latvmload_min; 32 u64 latvmsave_max; 33 u64 latvmsave_min; 34 u64 latstgi_max; 35 u64 latstgi_min; 36 u64 latclgi_max; 37 u64 latclgi_min; 38 u64 runs; 39 40 static void null_test(struct svm_test *test) 41 { 42 } 43 44 static bool null_check(struct svm_test *test) 45 { 46 return vmcb->control.exit_code == SVM_EXIT_VMMCALL; 47 } 48 49 static void prepare_no_vmrun_int(struct svm_test *test) 50 { 51 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMRUN); 52 } 53 54 static bool check_no_vmrun_int(struct svm_test *test) 55 { 56 return vmcb->control.exit_code == SVM_EXIT_ERR; 57 } 58 59 static void test_vmrun(struct svm_test *test) 60 { 61 asm volatile ("vmrun %0" : : "a"(virt_to_phys(vmcb))); 62 } 63 64 static bool check_vmrun(struct svm_test *test) 65 { 66 return vmcb->control.exit_code == SVM_EXIT_VMRUN; 67 } 68 69 static void prepare_cr3_intercept(struct svm_test *test) 70 { 71 default_prepare(test); 72 vmcb->control.intercept_cr_read |= 1 << 3; 73 } 74 75 static void test_cr3_intercept(struct svm_test *test) 76 { 77 asm volatile ("mov %%cr3, %0" : "=r"(test->scratch) : : "memory"); 78 } 79 80 static bool check_cr3_intercept(struct svm_test *test) 81 { 82 return vmcb->control.exit_code == SVM_EXIT_READ_CR3; 83 } 84 85 static bool check_cr3_nointercept(struct svm_test *test) 86 { 87 return null_check(test) && test->scratch == read_cr3(); 88 } 89 90 static void corrupt_cr3_intercept_bypass(void *_test) 91 { 92 struct svm_test *test = _test; 93 extern volatile u32 mmio_insn; 94 95 while (!__sync_bool_compare_and_swap(&test->scratch, 1, 2)) 96 pause(); 97 pause(); 98 pause(); 99 pause(); 100 mmio_insn = 0x90d8200f; // mov %cr3, %rax; nop 101 } 102 103 static void prepare_cr3_intercept_bypass(struct svm_test *test) 104 { 105 default_prepare(test); 106 vmcb->control.intercept_cr_read |= 1 << 3; 107 on_cpu_async(1, corrupt_cr3_intercept_bypass, test); 108 } 109 110 static void test_cr3_intercept_bypass(struct svm_test *test) 111 { 112 ulong a = 0xa0000; 113 114 test->scratch = 1; 115 while (test->scratch != 2) 116 barrier(); 117 118 asm volatile ("mmio_insn: mov %0, (%0); nop" 119 : "+a"(a) : : "memory"); 120 test->scratch = a; 121 } 122 123 static void prepare_dr_intercept(struct svm_test *test) 124 { 125 default_prepare(test); 126 vmcb->control.intercept_dr_read = 0xff; 127 vmcb->control.intercept_dr_write = 0xff; 128 } 129 130 static void test_dr_intercept(struct svm_test *test) 131 { 132 unsigned int i, failcnt = 0; 133 134 /* Loop testing debug register reads */ 135 for (i = 0; i < 8; i++) { 136 137 switch (i) { 138 case 0: 139 asm volatile ("mov %%dr0, %0" : "=r"(test->scratch) : : "memory"); 140 break; 141 case 1: 142 asm volatile ("mov %%dr1, %0" : "=r"(test->scratch) : : "memory"); 143 break; 144 case 2: 145 asm volatile ("mov %%dr2, %0" : "=r"(test->scratch) : : "memory"); 146 break; 147 case 3: 148 asm volatile ("mov %%dr3, %0" : "=r"(test->scratch) : : "memory"); 149 break; 150 case 4: 151 asm volatile ("mov %%dr4, %0" : "=r"(test->scratch) : : "memory"); 152 break; 153 case 5: 154 asm volatile ("mov %%dr5, %0" : "=r"(test->scratch) : : "memory"); 155 break; 156 case 6: 157 asm volatile ("mov %%dr6, %0" : "=r"(test->scratch) : : "memory"); 158 break; 159 case 7: 160 asm volatile ("mov %%dr7, %0" : "=r"(test->scratch) : : "memory"); 161 break; 162 } 163 164 if (test->scratch != i) { 165 report(false, "dr%u read intercept", i); 166 failcnt++; 167 } 168 } 169 170 /* Loop testing debug register writes */ 171 for (i = 0; i < 8; i++) { 172 173 switch (i) { 174 case 0: 175 asm volatile ("mov %0, %%dr0" : : "r"(test->scratch) : "memory"); 176 break; 177 case 1: 178 asm volatile ("mov %0, %%dr1" : : "r"(test->scratch) : "memory"); 179 break; 180 case 2: 181 asm volatile ("mov %0, %%dr2" : : "r"(test->scratch) : "memory"); 182 break; 183 case 3: 184 asm volatile ("mov %0, %%dr3" : : "r"(test->scratch) : "memory"); 185 break; 186 case 4: 187 asm volatile ("mov %0, %%dr4" : : "r"(test->scratch) : "memory"); 188 break; 189 case 5: 190 asm volatile ("mov %0, %%dr5" : : "r"(test->scratch) : "memory"); 191 break; 192 case 6: 193 asm volatile ("mov %0, %%dr6" : : "r"(test->scratch) : "memory"); 194 break; 195 case 7: 196 asm volatile ("mov %0, %%dr7" : : "r"(test->scratch) : "memory"); 197 break; 198 } 199 200 if (test->scratch != i) { 201 report(false, "dr%u write intercept", i); 202 failcnt++; 203 } 204 } 205 206 test->scratch = failcnt; 207 } 208 209 static bool dr_intercept_finished(struct svm_test *test) 210 { 211 ulong n = (vmcb->control.exit_code - SVM_EXIT_READ_DR0); 212 213 /* Only expect DR intercepts */ 214 if (n > (SVM_EXIT_MAX_DR_INTERCEPT - SVM_EXIT_READ_DR0)) 215 return true; 216 217 /* 218 * Compute debug register number. 219 * Per Appendix C "SVM Intercept Exit Codes" of AMD64 Architecture 220 * Programmer's Manual Volume 2 - System Programming: 221 * http://support.amd.com/TechDocs/24593.pdf 222 * there are 16 VMEXIT codes each for DR read and write. 223 */ 224 test->scratch = (n % 16); 225 226 /* Jump over MOV instruction */ 227 vmcb->save.rip += 3; 228 229 return false; 230 } 231 232 static bool check_dr_intercept(struct svm_test *test) 233 { 234 return !test->scratch; 235 } 236 237 static bool next_rip_supported(void) 238 { 239 return this_cpu_has(X86_FEATURE_NRIPS); 240 } 241 242 static void prepare_next_rip(struct svm_test *test) 243 { 244 vmcb->control.intercept |= (1ULL << INTERCEPT_RDTSC); 245 } 246 247 248 static void test_next_rip(struct svm_test *test) 249 { 250 asm volatile ("rdtsc\n\t" 251 ".globl exp_next_rip\n\t" 252 "exp_next_rip:\n\t" ::: "eax", "edx"); 253 } 254 255 static bool check_next_rip(struct svm_test *test) 256 { 257 extern char exp_next_rip; 258 unsigned long address = (unsigned long)&exp_next_rip; 259 260 return address == vmcb->control.next_rip; 261 } 262 263 extern u8 *msr_bitmap; 264 265 static void prepare_msr_intercept(struct svm_test *test) 266 { 267 default_prepare(test); 268 vmcb->control.intercept |= (1ULL << INTERCEPT_MSR_PROT); 269 vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR); 270 memset(msr_bitmap, 0xff, MSR_BITMAP_SIZE); 271 } 272 273 static void test_msr_intercept(struct svm_test *test) 274 { 275 unsigned long msr_value = 0xef8056791234abcd; /* Arbitrary value */ 276 unsigned long msr_index; 277 278 for (msr_index = 0; msr_index <= 0xc0011fff; msr_index++) { 279 if (msr_index == 0xC0010131 /* MSR_SEV_STATUS */) { 280 /* 281 * Per section 15.34.10 "SEV_STATUS MSR" of AMD64 Architecture 282 * Programmer's Manual volume 2 - System Programming: 283 * http://support.amd.com/TechDocs/24593.pdf 284 * SEV_STATUS MSR (C001_0131) is a non-interceptable MSR. 285 */ 286 continue; 287 } 288 289 /* Skips gaps between supported MSR ranges */ 290 if (msr_index == 0x2000) 291 msr_index = 0xc0000000; 292 else if (msr_index == 0xc0002000) 293 msr_index = 0xc0010000; 294 295 test->scratch = -1; 296 297 rdmsr(msr_index); 298 299 /* Check that a read intercept occurred for MSR at msr_index */ 300 if (test->scratch != msr_index) 301 report(false, "MSR 0x%lx read intercept", msr_index); 302 303 /* 304 * Poor man approach to generate a value that 305 * seems arbitrary each time around the loop. 306 */ 307 msr_value += (msr_value << 1); 308 309 wrmsr(msr_index, msr_value); 310 311 /* Check that a write intercept occurred for MSR with msr_value */ 312 if (test->scratch != msr_value) 313 report(false, "MSR 0x%lx write intercept", msr_index); 314 } 315 316 test->scratch = -2; 317 } 318 319 static bool msr_intercept_finished(struct svm_test *test) 320 { 321 u32 exit_code = vmcb->control.exit_code; 322 u64 exit_info_1; 323 u8 *opcode; 324 325 if (exit_code == SVM_EXIT_MSR) { 326 exit_info_1 = vmcb->control.exit_info_1; 327 } else { 328 /* 329 * If #GP exception occurs instead, check that it was 330 * for RDMSR/WRMSR and set exit_info_1 accordingly. 331 */ 332 333 if (exit_code != (SVM_EXIT_EXCP_BASE + GP_VECTOR)) 334 return true; 335 336 opcode = (u8 *)vmcb->save.rip; 337 if (opcode[0] != 0x0f) 338 return true; 339 340 switch (opcode[1]) { 341 case 0x30: /* WRMSR */ 342 exit_info_1 = 1; 343 break; 344 case 0x32: /* RDMSR */ 345 exit_info_1 = 0; 346 break; 347 default: 348 return true; 349 } 350 351 /* 352 * Warn that #GP exception occured instead. 353 * RCX holds the MSR index. 354 */ 355 printf("%s 0x%lx #GP exception\n", 356 exit_info_1 ? "WRMSR" : "RDMSR", get_regs().rcx); 357 } 358 359 /* Jump over RDMSR/WRMSR instruction */ 360 vmcb->save.rip += 2; 361 362 /* 363 * Test whether the intercept was for RDMSR/WRMSR. 364 * For RDMSR, test->scratch is set to the MSR index; 365 * RCX holds the MSR index. 366 * For WRMSR, test->scratch is set to the MSR value; 367 * RDX holds the upper 32 bits of the MSR value, 368 * while RAX hold its lower 32 bits. 369 */ 370 if (exit_info_1) 371 test->scratch = 372 ((get_regs().rdx << 32) | (vmcb->save.rax & 0xffffffff)); 373 else 374 test->scratch = get_regs().rcx; 375 376 return false; 377 } 378 379 static bool check_msr_intercept(struct svm_test *test) 380 { 381 memset(msr_bitmap, 0, MSR_BITMAP_SIZE); 382 return (test->scratch == -2); 383 } 384 385 static void prepare_mode_switch(struct svm_test *test) 386 { 387 vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR) 388 | (1ULL << UD_VECTOR) 389 | (1ULL << DF_VECTOR) 390 | (1ULL << PF_VECTOR); 391 test->scratch = 0; 392 } 393 394 static void test_mode_switch(struct svm_test *test) 395 { 396 asm volatile(" cli\n" 397 " ljmp *1f\n" /* jump to 32-bit code segment */ 398 "1:\n" 399 " .long 2f\n" 400 " .long " xstr(KERNEL_CS32) "\n" 401 ".code32\n" 402 "2:\n" 403 " movl %%cr0, %%eax\n" 404 " btcl $31, %%eax\n" /* clear PG */ 405 " movl %%eax, %%cr0\n" 406 " movl $0xc0000080, %%ecx\n" /* EFER */ 407 " rdmsr\n" 408 " btcl $8, %%eax\n" /* clear LME */ 409 " wrmsr\n" 410 " movl %%cr4, %%eax\n" 411 " btcl $5, %%eax\n" /* clear PAE */ 412 " movl %%eax, %%cr4\n" 413 " movw %[ds16], %%ax\n" 414 " movw %%ax, %%ds\n" 415 " ljmpl %[cs16], $3f\n" /* jump to 16 bit protected-mode */ 416 ".code16\n" 417 "3:\n" 418 " movl %%cr0, %%eax\n" 419 " btcl $0, %%eax\n" /* clear PE */ 420 " movl %%eax, %%cr0\n" 421 " ljmpl $0, $4f\n" /* jump to real-mode */ 422 "4:\n" 423 " vmmcall\n" 424 " movl %%cr0, %%eax\n" 425 " btsl $0, %%eax\n" /* set PE */ 426 " movl %%eax, %%cr0\n" 427 " ljmpl %[cs32], $5f\n" /* back to protected mode */ 428 ".code32\n" 429 "5:\n" 430 " movl %%cr4, %%eax\n" 431 " btsl $5, %%eax\n" /* set PAE */ 432 " movl %%eax, %%cr4\n" 433 " movl $0xc0000080, %%ecx\n" /* EFER */ 434 " rdmsr\n" 435 " btsl $8, %%eax\n" /* set LME */ 436 " wrmsr\n" 437 " movl %%cr0, %%eax\n" 438 " btsl $31, %%eax\n" /* set PG */ 439 " movl %%eax, %%cr0\n" 440 " ljmpl %[cs64], $6f\n" /* back to long mode */ 441 ".code64\n\t" 442 "6:\n" 443 " vmmcall\n" 444 :: [cs16] "i"(KERNEL_CS16), [ds16] "i"(KERNEL_DS16), 445 [cs32] "i"(KERNEL_CS32), [cs64] "i"(KERNEL_CS64) 446 : "rax", "rbx", "rcx", "rdx", "memory"); 447 } 448 449 static bool mode_switch_finished(struct svm_test *test) 450 { 451 u64 cr0, cr4, efer; 452 453 cr0 = vmcb->save.cr0; 454 cr4 = vmcb->save.cr4; 455 efer = vmcb->save.efer; 456 457 /* Only expect VMMCALL intercepts */ 458 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) 459 return true; 460 461 /* Jump over VMMCALL instruction */ 462 vmcb->save.rip += 3; 463 464 /* Do sanity checks */ 465 switch (test->scratch) { 466 case 0: 467 /* Test should be in real mode now - check for this */ 468 if ((cr0 & 0x80000001) || /* CR0.PG, CR0.PE */ 469 (cr4 & 0x00000020) || /* CR4.PAE */ 470 (efer & 0x00000500)) /* EFER.LMA, EFER.LME */ 471 return true; 472 break; 473 case 2: 474 /* Test should be back in long-mode now - check for this */ 475 if (((cr0 & 0x80000001) != 0x80000001) || /* CR0.PG, CR0.PE */ 476 ((cr4 & 0x00000020) != 0x00000020) || /* CR4.PAE */ 477 ((efer & 0x00000500) != 0x00000500)) /* EFER.LMA, EFER.LME */ 478 return true; 479 break; 480 } 481 482 /* one step forward */ 483 test->scratch += 1; 484 485 return test->scratch == 2; 486 } 487 488 static bool check_mode_switch(struct svm_test *test) 489 { 490 return test->scratch == 2; 491 } 492 493 extern u8 *io_bitmap; 494 495 static void prepare_ioio(struct svm_test *test) 496 { 497 vmcb->control.intercept |= (1ULL << INTERCEPT_IOIO_PROT); 498 test->scratch = 0; 499 memset(io_bitmap, 0, 8192); 500 io_bitmap[8192] = 0xFF; 501 } 502 503 static void test_ioio(struct svm_test *test) 504 { 505 // stage 0, test IO pass 506 inb(0x5000); 507 outb(0x0, 0x5000); 508 if (get_test_stage(test) != 0) 509 goto fail; 510 511 // test IO width, in/out 512 io_bitmap[0] = 0xFF; 513 inc_test_stage(test); 514 inb(0x0); 515 if (get_test_stage(test) != 2) 516 goto fail; 517 518 outw(0x0, 0x0); 519 if (get_test_stage(test) != 3) 520 goto fail; 521 522 inl(0x0); 523 if (get_test_stage(test) != 4) 524 goto fail; 525 526 // test low/high IO port 527 io_bitmap[0x5000 / 8] = (1 << (0x5000 % 8)); 528 inb(0x5000); 529 if (get_test_stage(test) != 5) 530 goto fail; 531 532 io_bitmap[0x9000 / 8] = (1 << (0x9000 % 8)); 533 inw(0x9000); 534 if (get_test_stage(test) != 6) 535 goto fail; 536 537 // test partial pass 538 io_bitmap[0x5000 / 8] = (1 << (0x5000 % 8)); 539 inl(0x4FFF); 540 if (get_test_stage(test) != 7) 541 goto fail; 542 543 // test across pages 544 inc_test_stage(test); 545 inl(0x7FFF); 546 if (get_test_stage(test) != 8) 547 goto fail; 548 549 inc_test_stage(test); 550 io_bitmap[0x8000 / 8] = 1 << (0x8000 % 8); 551 inl(0x7FFF); 552 if (get_test_stage(test) != 10) 553 goto fail; 554 555 io_bitmap[0] = 0; 556 inl(0xFFFF); 557 if (get_test_stage(test) != 11) 558 goto fail; 559 560 io_bitmap[0] = 0xFF; 561 io_bitmap[8192] = 0; 562 inl(0xFFFF); 563 inc_test_stage(test); 564 if (get_test_stage(test) != 12) 565 goto fail; 566 567 return; 568 569 fail: 570 report(false, "stage %d", get_test_stage(test)); 571 test->scratch = -1; 572 } 573 574 static bool ioio_finished(struct svm_test *test) 575 { 576 unsigned port, size; 577 578 /* Only expect IOIO intercepts */ 579 if (vmcb->control.exit_code == SVM_EXIT_VMMCALL) 580 return true; 581 582 if (vmcb->control.exit_code != SVM_EXIT_IOIO) 583 return true; 584 585 /* one step forward */ 586 test->scratch += 1; 587 588 port = vmcb->control.exit_info_1 >> 16; 589 size = (vmcb->control.exit_info_1 >> SVM_IOIO_SIZE_SHIFT) & 7; 590 591 while (size--) { 592 io_bitmap[port / 8] &= ~(1 << (port & 7)); 593 port++; 594 } 595 596 return false; 597 } 598 599 static bool check_ioio(struct svm_test *test) 600 { 601 memset(io_bitmap, 0, 8193); 602 return test->scratch != -1; 603 } 604 605 static void prepare_asid_zero(struct svm_test *test) 606 { 607 vmcb->control.asid = 0; 608 } 609 610 static void test_asid_zero(struct svm_test *test) 611 { 612 asm volatile ("vmmcall\n\t"); 613 } 614 615 static bool check_asid_zero(struct svm_test *test) 616 { 617 return vmcb->control.exit_code == SVM_EXIT_ERR; 618 } 619 620 static void sel_cr0_bug_prepare(struct svm_test *test) 621 { 622 vmcb_ident(vmcb); 623 vmcb->control.intercept |= (1ULL << INTERCEPT_SELECTIVE_CR0); 624 } 625 626 static bool sel_cr0_bug_finished(struct svm_test *test) 627 { 628 return true; 629 } 630 631 static void sel_cr0_bug_test(struct svm_test *test) 632 { 633 unsigned long cr0; 634 635 /* read cr0, clear CD, and write back */ 636 cr0 = read_cr0(); 637 cr0 |= (1UL << 30); 638 write_cr0(cr0); 639 640 /* 641 * If we are here the test failed, not sure what to do now because we 642 * are not in guest-mode anymore so we can't trigger an intercept. 643 * Trigger a tripple-fault for now. 644 */ 645 report(false, "sel_cr0 test. Can not recover from this - exiting"); 646 exit(report_summary()); 647 } 648 649 static bool sel_cr0_bug_check(struct svm_test *test) 650 { 651 return vmcb->control.exit_code == SVM_EXIT_CR0_SEL_WRITE; 652 } 653 654 static void npt_nx_prepare(struct svm_test *test) 655 { 656 657 u64 *pte; 658 659 vmcb_ident(vmcb); 660 pte = npt_get_pte((u64)null_test); 661 662 *pte |= (1ULL << 63); 663 } 664 665 static bool npt_nx_check(struct svm_test *test) 666 { 667 u64 *pte = npt_get_pte((u64)null_test); 668 669 *pte &= ~(1ULL << 63); 670 671 vmcb->save.efer |= (1 << 11); 672 673 return (vmcb->control.exit_code == SVM_EXIT_NPF) 674 && (vmcb->control.exit_info_1 == 0x100000015ULL); 675 } 676 677 static void npt_us_prepare(struct svm_test *test) 678 { 679 u64 *pte; 680 681 scratch_page = alloc_page(); 682 vmcb_ident(vmcb); 683 pte = npt_get_pte((u64)scratch_page); 684 685 *pte &= ~(1ULL << 2); 686 } 687 688 static void npt_us_test(struct svm_test *test) 689 { 690 (void) *(volatile u64 *)scratch_page; 691 } 692 693 static bool npt_us_check(struct svm_test *test) 694 { 695 u64 *pte = npt_get_pte((u64)scratch_page); 696 697 *pte |= (1ULL << 2); 698 699 return (vmcb->control.exit_code == SVM_EXIT_NPF) 700 && (vmcb->control.exit_info_1 == 0x100000005ULL); 701 } 702 703 u64 save_pde; 704 705 static void npt_rsvd_prepare(struct svm_test *test) 706 { 707 u64 *pde; 708 709 vmcb_ident(vmcb); 710 pde = npt_get_pde((u64) null_test); 711 712 save_pde = *pde; 713 *pde = (1ULL << 19) | (1ULL << 7) | 0x27; 714 } 715 716 static bool npt_rsvd_check(struct svm_test *test) 717 { 718 u64 *pde = npt_get_pde((u64) null_test); 719 720 *pde = save_pde; 721 722 return (vmcb->control.exit_code == SVM_EXIT_NPF) 723 && (vmcb->control.exit_info_1 == 0x10000001dULL); 724 } 725 726 static void npt_rw_prepare(struct svm_test *test) 727 { 728 729 u64 *pte; 730 731 vmcb_ident(vmcb); 732 pte = npt_get_pte(0x80000); 733 734 *pte &= ~(1ULL << 1); 735 } 736 737 static void npt_rw_test(struct svm_test *test) 738 { 739 u64 *data = (void*)(0x80000); 740 741 *data = 0; 742 } 743 744 static bool npt_rw_check(struct svm_test *test) 745 { 746 u64 *pte = npt_get_pte(0x80000); 747 748 *pte |= (1ULL << 1); 749 750 return (vmcb->control.exit_code == SVM_EXIT_NPF) 751 && (vmcb->control.exit_info_1 == 0x100000007ULL); 752 } 753 754 static void npt_rw_pfwalk_prepare(struct svm_test *test) 755 { 756 757 u64 *pte; 758 759 vmcb_ident(vmcb); 760 pte = npt_get_pte(read_cr3()); 761 762 *pte &= ~(1ULL << 1); 763 } 764 765 static bool npt_rw_pfwalk_check(struct svm_test *test) 766 { 767 u64 *pte = npt_get_pte(read_cr3()); 768 769 *pte |= (1ULL << 1); 770 771 return (vmcb->control.exit_code == SVM_EXIT_NPF) 772 && (vmcb->control.exit_info_1 == 0x200000006ULL) 773 && (vmcb->control.exit_info_2 == read_cr3()); 774 } 775 776 static void npt_rsvd_pfwalk_prepare(struct svm_test *test) 777 { 778 u64 *pdpe; 779 vmcb_ident(vmcb); 780 781 pdpe = npt_get_pdpe(); 782 pdpe[0] |= (1ULL << 8); 783 } 784 785 static bool npt_rsvd_pfwalk_check(struct svm_test *test) 786 { 787 u64 *pdpe = npt_get_pdpe(); 788 pdpe[0] &= ~(1ULL << 8); 789 790 return (vmcb->control.exit_code == SVM_EXIT_NPF) 791 && (vmcb->control.exit_info_1 == 0x20000000eULL); 792 } 793 794 static void npt_l1mmio_prepare(struct svm_test *test) 795 { 796 vmcb_ident(vmcb); 797 } 798 799 u32 nested_apic_version1; 800 u32 nested_apic_version2; 801 802 static void npt_l1mmio_test(struct svm_test *test) 803 { 804 volatile u32 *data = (volatile void*)(0xfee00030UL); 805 806 nested_apic_version1 = *data; 807 nested_apic_version2 = *data; 808 } 809 810 static bool npt_l1mmio_check(struct svm_test *test) 811 { 812 volatile u32 *data = (volatile void*)(0xfee00030); 813 u32 lvr = *data; 814 815 return nested_apic_version1 == lvr && nested_apic_version2 == lvr; 816 } 817 818 static void npt_rw_l1mmio_prepare(struct svm_test *test) 819 { 820 821 u64 *pte; 822 823 vmcb_ident(vmcb); 824 pte = npt_get_pte(0xfee00080); 825 826 *pte &= ~(1ULL << 1); 827 } 828 829 static void npt_rw_l1mmio_test(struct svm_test *test) 830 { 831 volatile u32 *data = (volatile void*)(0xfee00080); 832 833 *data = *data; 834 } 835 836 static bool npt_rw_l1mmio_check(struct svm_test *test) 837 { 838 u64 *pte = npt_get_pte(0xfee00080); 839 840 *pte |= (1ULL << 1); 841 842 return (vmcb->control.exit_code == SVM_EXIT_NPF) 843 && (vmcb->control.exit_info_1 == 0x100000007ULL); 844 } 845 846 #define TSC_ADJUST_VALUE (1ll << 32) 847 #define TSC_OFFSET_VALUE (-1ll << 48) 848 static bool ok; 849 850 static void tsc_adjust_prepare(struct svm_test *test) 851 { 852 default_prepare(test); 853 vmcb->control.tsc_offset = TSC_OFFSET_VALUE; 854 855 wrmsr(MSR_IA32_TSC_ADJUST, -TSC_ADJUST_VALUE); 856 int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); 857 ok = adjust == -TSC_ADJUST_VALUE; 858 } 859 860 static void tsc_adjust_test(struct svm_test *test) 861 { 862 int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); 863 ok &= adjust == -TSC_ADJUST_VALUE; 864 865 uint64_t l1_tsc = rdtsc() - TSC_OFFSET_VALUE; 866 wrmsr(MSR_IA32_TSC, l1_tsc - TSC_ADJUST_VALUE); 867 868 adjust = rdmsr(MSR_IA32_TSC_ADJUST); 869 ok &= adjust <= -2 * TSC_ADJUST_VALUE; 870 871 uint64_t l1_tsc_end = rdtsc() - TSC_OFFSET_VALUE; 872 ok &= (l1_tsc_end + TSC_ADJUST_VALUE - l1_tsc) < TSC_ADJUST_VALUE; 873 874 uint64_t l1_tsc_msr = rdmsr(MSR_IA32_TSC) - TSC_OFFSET_VALUE; 875 ok &= (l1_tsc_msr + TSC_ADJUST_VALUE - l1_tsc) < TSC_ADJUST_VALUE; 876 } 877 878 static bool tsc_adjust_check(struct svm_test *test) 879 { 880 int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); 881 882 wrmsr(MSR_IA32_TSC_ADJUST, 0); 883 return ok && adjust <= -2 * TSC_ADJUST_VALUE; 884 } 885 886 static void latency_prepare(struct svm_test *test) 887 { 888 default_prepare(test); 889 runs = LATENCY_RUNS; 890 latvmrun_min = latvmexit_min = -1ULL; 891 latvmrun_max = latvmexit_max = 0; 892 vmrun_sum = vmexit_sum = 0; 893 tsc_start = rdtsc(); 894 } 895 896 static void latency_test(struct svm_test *test) 897 { 898 u64 cycles; 899 900 start: 901 tsc_end = rdtsc(); 902 903 cycles = tsc_end - tsc_start; 904 905 if (cycles > latvmrun_max) 906 latvmrun_max = cycles; 907 908 if (cycles < latvmrun_min) 909 latvmrun_min = cycles; 910 911 vmrun_sum += cycles; 912 913 tsc_start = rdtsc(); 914 915 asm volatile ("vmmcall" : : : "memory"); 916 goto start; 917 } 918 919 static bool latency_finished(struct svm_test *test) 920 { 921 u64 cycles; 922 923 tsc_end = rdtsc(); 924 925 cycles = tsc_end - tsc_start; 926 927 if (cycles > latvmexit_max) 928 latvmexit_max = cycles; 929 930 if (cycles < latvmexit_min) 931 latvmexit_min = cycles; 932 933 vmexit_sum += cycles; 934 935 vmcb->save.rip += 3; 936 937 runs -= 1; 938 939 tsc_end = rdtsc(); 940 941 return runs == 0; 942 } 943 944 static bool latency_check(struct svm_test *test) 945 { 946 printf(" Latency VMRUN : max: %ld min: %ld avg: %ld\n", latvmrun_max, 947 latvmrun_min, vmrun_sum / LATENCY_RUNS); 948 printf(" Latency VMEXIT: max: %ld min: %ld avg: %ld\n", latvmexit_max, 949 latvmexit_min, vmexit_sum / LATENCY_RUNS); 950 return true; 951 } 952 953 static void lat_svm_insn_prepare(struct svm_test *test) 954 { 955 default_prepare(test); 956 runs = LATENCY_RUNS; 957 latvmload_min = latvmsave_min = latstgi_min = latclgi_min = -1ULL; 958 latvmload_max = latvmsave_max = latstgi_max = latclgi_max = 0; 959 vmload_sum = vmsave_sum = stgi_sum = clgi_sum; 960 } 961 962 static bool lat_svm_insn_finished(struct svm_test *test) 963 { 964 u64 vmcb_phys = virt_to_phys(vmcb); 965 u64 cycles; 966 967 for ( ; runs != 0; runs--) { 968 tsc_start = rdtsc(); 969 asm volatile("vmload %0\n\t" : : "a"(vmcb_phys) : "memory"); 970 cycles = rdtsc() - tsc_start; 971 if (cycles > latvmload_max) 972 latvmload_max = cycles; 973 if (cycles < latvmload_min) 974 latvmload_min = cycles; 975 vmload_sum += cycles; 976 977 tsc_start = rdtsc(); 978 asm volatile("vmsave %0\n\t" : : "a"(vmcb_phys) : "memory"); 979 cycles = rdtsc() - tsc_start; 980 if (cycles > latvmsave_max) 981 latvmsave_max = cycles; 982 if (cycles < latvmsave_min) 983 latvmsave_min = cycles; 984 vmsave_sum += cycles; 985 986 tsc_start = rdtsc(); 987 asm volatile("stgi\n\t"); 988 cycles = rdtsc() - tsc_start; 989 if (cycles > latstgi_max) 990 latstgi_max = cycles; 991 if (cycles < latstgi_min) 992 latstgi_min = cycles; 993 stgi_sum += cycles; 994 995 tsc_start = rdtsc(); 996 asm volatile("clgi\n\t"); 997 cycles = rdtsc() - tsc_start; 998 if (cycles > latclgi_max) 999 latclgi_max = cycles; 1000 if (cycles < latclgi_min) 1001 latclgi_min = cycles; 1002 clgi_sum += cycles; 1003 } 1004 1005 tsc_end = rdtsc(); 1006 1007 return true; 1008 } 1009 1010 static bool lat_svm_insn_check(struct svm_test *test) 1011 { 1012 printf(" Latency VMLOAD: max: %ld min: %ld avg: %ld\n", latvmload_max, 1013 latvmload_min, vmload_sum / LATENCY_RUNS); 1014 printf(" Latency VMSAVE: max: %ld min: %ld avg: %ld\n", latvmsave_max, 1015 latvmsave_min, vmsave_sum / LATENCY_RUNS); 1016 printf(" Latency STGI: max: %ld min: %ld avg: %ld\n", latstgi_max, 1017 latstgi_min, stgi_sum / LATENCY_RUNS); 1018 printf(" Latency CLGI: max: %ld min: %ld avg: %ld\n", latclgi_max, 1019 latclgi_min, clgi_sum / LATENCY_RUNS); 1020 return true; 1021 } 1022 1023 bool pending_event_ipi_fired; 1024 bool pending_event_guest_run; 1025 1026 static void pending_event_ipi_isr(isr_regs_t *regs) 1027 { 1028 pending_event_ipi_fired = true; 1029 eoi(); 1030 } 1031 1032 static void pending_event_prepare(struct svm_test *test) 1033 { 1034 int ipi_vector = 0xf1; 1035 1036 default_prepare(test); 1037 1038 pending_event_ipi_fired = false; 1039 1040 handle_irq(ipi_vector, pending_event_ipi_isr); 1041 1042 pending_event_guest_run = false; 1043 1044 vmcb->control.intercept |= (1ULL << INTERCEPT_INTR); 1045 vmcb->control.int_ctl |= V_INTR_MASKING_MASK; 1046 1047 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | 1048 APIC_DM_FIXED | ipi_vector, 0); 1049 1050 set_test_stage(test, 0); 1051 } 1052 1053 static void pending_event_test(struct svm_test *test) 1054 { 1055 pending_event_guest_run = true; 1056 } 1057 1058 static bool pending_event_finished(struct svm_test *test) 1059 { 1060 switch (get_test_stage(test)) { 1061 case 0: 1062 if (vmcb->control.exit_code != SVM_EXIT_INTR) { 1063 report(false, "VMEXIT not due to pending interrupt. Exit reason 0x%x", 1064 vmcb->control.exit_code); 1065 return true; 1066 } 1067 1068 vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR); 1069 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 1070 1071 if (pending_event_guest_run) { 1072 report(false, "Guest ran before host received IPI\n"); 1073 return true; 1074 } 1075 1076 irq_enable(); 1077 asm volatile ("nop"); 1078 irq_disable(); 1079 1080 if (!pending_event_ipi_fired) { 1081 report(false, "Pending interrupt not dispatched after IRQ enabled\n"); 1082 return true; 1083 } 1084 break; 1085 1086 case 1: 1087 if (!pending_event_guest_run) { 1088 report(false, "Guest did not resume when no interrupt\n"); 1089 return true; 1090 } 1091 break; 1092 } 1093 1094 inc_test_stage(test); 1095 1096 return get_test_stage(test) == 2; 1097 } 1098 1099 static bool pending_event_check(struct svm_test *test) 1100 { 1101 return get_test_stage(test) == 2; 1102 } 1103 1104 static void pending_event_cli_prepare(struct svm_test *test) 1105 { 1106 default_prepare(test); 1107 1108 pending_event_ipi_fired = false; 1109 1110 handle_irq(0xf1, pending_event_ipi_isr); 1111 1112 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | 1113 APIC_DM_FIXED | 0xf1, 0); 1114 1115 set_test_stage(test, 0); 1116 } 1117 1118 static void pending_event_cli_prepare_gif_clear(struct svm_test *test) 1119 { 1120 asm("cli"); 1121 } 1122 1123 static void pending_event_cli_test(struct svm_test *test) 1124 { 1125 if (pending_event_ipi_fired == true) { 1126 set_test_stage(test, -1); 1127 report(false, "Interrupt preceeded guest"); 1128 vmmcall(); 1129 } 1130 1131 /* VINTR_MASKING is zero. This should cause the IPI to fire. */ 1132 irq_enable(); 1133 asm volatile ("nop"); 1134 irq_disable(); 1135 1136 if (pending_event_ipi_fired != true) { 1137 set_test_stage(test, -1); 1138 report(false, "Interrupt not triggered by guest"); 1139 } 1140 1141 vmmcall(); 1142 1143 /* 1144 * Now VINTR_MASKING=1, but no interrupt is pending so 1145 * the VINTR interception should be clear in VMCB02. Check 1146 * that L0 did not leave a stale VINTR in the VMCB. 1147 */ 1148 irq_enable(); 1149 asm volatile ("nop"); 1150 irq_disable(); 1151 } 1152 1153 static bool pending_event_cli_finished(struct svm_test *test) 1154 { 1155 if ( vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1156 report(false, "VM_EXIT return to host is not EXIT_VMMCALL exit reason 0x%x", 1157 vmcb->control.exit_code); 1158 return true; 1159 } 1160 1161 switch (get_test_stage(test)) { 1162 case 0: 1163 vmcb->save.rip += 3; 1164 1165 pending_event_ipi_fired = false; 1166 1167 vmcb->control.int_ctl |= V_INTR_MASKING_MASK; 1168 1169 /* Now entering again with VINTR_MASKING=1. */ 1170 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | 1171 APIC_DM_FIXED | 0xf1, 0); 1172 1173 break; 1174 1175 case 1: 1176 if (pending_event_ipi_fired == true) { 1177 report(false, "Interrupt triggered by guest"); 1178 return true; 1179 } 1180 1181 irq_enable(); 1182 asm volatile ("nop"); 1183 irq_disable(); 1184 1185 if (pending_event_ipi_fired != true) { 1186 report(false, "Interrupt not triggered by host"); 1187 return true; 1188 } 1189 1190 break; 1191 1192 default: 1193 return true; 1194 } 1195 1196 inc_test_stage(test); 1197 1198 return get_test_stage(test) == 2; 1199 } 1200 1201 static bool pending_event_cli_check(struct svm_test *test) 1202 { 1203 return get_test_stage(test) == 2; 1204 } 1205 1206 #define TIMER_VECTOR 222 1207 1208 static volatile bool timer_fired; 1209 1210 static void timer_isr(isr_regs_t *regs) 1211 { 1212 timer_fired = true; 1213 apic_write(APIC_EOI, 0); 1214 } 1215 1216 static void interrupt_prepare(struct svm_test *test) 1217 { 1218 default_prepare(test); 1219 handle_irq(TIMER_VECTOR, timer_isr); 1220 timer_fired = false; 1221 set_test_stage(test, 0); 1222 } 1223 1224 static void interrupt_test(struct svm_test *test) 1225 { 1226 long long start, loops; 1227 1228 apic_write(APIC_LVTT, TIMER_VECTOR); 1229 irq_enable(); 1230 apic_write(APIC_TMICT, 1); //Timer Initial Count Register 0x380 one-shot 1231 for (loops = 0; loops < 10000000 && !timer_fired; loops++) 1232 asm volatile ("nop"); 1233 1234 report(timer_fired, "direct interrupt while running guest"); 1235 1236 if (!timer_fired) { 1237 set_test_stage(test, -1); 1238 vmmcall(); 1239 } 1240 1241 apic_write(APIC_TMICT, 0); 1242 irq_disable(); 1243 vmmcall(); 1244 1245 timer_fired = false; 1246 apic_write(APIC_TMICT, 1); 1247 for (loops = 0; loops < 10000000 && !timer_fired; loops++) 1248 asm volatile ("nop"); 1249 1250 report(timer_fired, "intercepted interrupt while running guest"); 1251 1252 if (!timer_fired) { 1253 set_test_stage(test, -1); 1254 vmmcall(); 1255 } 1256 1257 irq_enable(); 1258 apic_write(APIC_TMICT, 0); 1259 irq_disable(); 1260 1261 timer_fired = false; 1262 start = rdtsc(); 1263 apic_write(APIC_TMICT, 1000000); 1264 asm volatile ("sti; hlt"); 1265 1266 report(rdtsc() - start > 10000 && timer_fired, 1267 "direct interrupt + hlt"); 1268 1269 if (!timer_fired) { 1270 set_test_stage(test, -1); 1271 vmmcall(); 1272 } 1273 1274 apic_write(APIC_TMICT, 0); 1275 irq_disable(); 1276 vmmcall(); 1277 1278 timer_fired = false; 1279 start = rdtsc(); 1280 apic_write(APIC_TMICT, 1000000); 1281 asm volatile ("hlt"); 1282 1283 report(rdtsc() - start > 10000 && timer_fired, 1284 "intercepted interrupt + hlt"); 1285 1286 if (!timer_fired) { 1287 set_test_stage(test, -1); 1288 vmmcall(); 1289 } 1290 1291 apic_write(APIC_TMICT, 0); 1292 irq_disable(); 1293 } 1294 1295 static bool interrupt_finished(struct svm_test *test) 1296 { 1297 switch (get_test_stage(test)) { 1298 case 0: 1299 case 2: 1300 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1301 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 1302 vmcb->control.exit_code); 1303 return true; 1304 } 1305 vmcb->save.rip += 3; 1306 1307 vmcb->control.intercept |= (1ULL << INTERCEPT_INTR); 1308 vmcb->control.int_ctl |= V_INTR_MASKING_MASK; 1309 break; 1310 1311 case 1: 1312 case 3: 1313 if (vmcb->control.exit_code != SVM_EXIT_INTR) { 1314 report(false, "VMEXIT not due to intr intercept. Exit reason 0x%x", 1315 vmcb->control.exit_code); 1316 return true; 1317 } 1318 1319 irq_enable(); 1320 asm volatile ("nop"); 1321 irq_disable(); 1322 1323 vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR); 1324 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 1325 break; 1326 1327 case 4: 1328 break; 1329 1330 default: 1331 return true; 1332 } 1333 1334 inc_test_stage(test); 1335 1336 return get_test_stage(test) == 5; 1337 } 1338 1339 static bool interrupt_check(struct svm_test *test) 1340 { 1341 return get_test_stage(test) == 5; 1342 } 1343 1344 static volatile bool nmi_fired; 1345 1346 static void nmi_handler(isr_regs_t *regs) 1347 { 1348 nmi_fired = true; 1349 apic_write(APIC_EOI, 0); 1350 } 1351 1352 static void nmi_prepare(struct svm_test *test) 1353 { 1354 default_prepare(test); 1355 nmi_fired = false; 1356 handle_irq(NMI_VECTOR, nmi_handler); 1357 set_test_stage(test, 0); 1358 } 1359 1360 static void nmi_test(struct svm_test *test) 1361 { 1362 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0); 1363 1364 report(nmi_fired, "direct NMI while running guest"); 1365 1366 if (!nmi_fired) 1367 set_test_stage(test, -1); 1368 1369 vmmcall(); 1370 1371 nmi_fired = false; 1372 1373 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0); 1374 1375 if (!nmi_fired) { 1376 report(nmi_fired, "intercepted pending NMI not dispatched"); 1377 set_test_stage(test, -1); 1378 } 1379 1380 } 1381 1382 static bool nmi_finished(struct svm_test *test) 1383 { 1384 switch (get_test_stage(test)) { 1385 case 0: 1386 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1387 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 1388 vmcb->control.exit_code); 1389 return true; 1390 } 1391 vmcb->save.rip += 3; 1392 1393 vmcb->control.intercept |= (1ULL << INTERCEPT_NMI); 1394 break; 1395 1396 case 1: 1397 if (vmcb->control.exit_code != SVM_EXIT_NMI) { 1398 report(false, "VMEXIT not due to NMI intercept. Exit reason 0x%x", 1399 vmcb->control.exit_code); 1400 return true; 1401 } 1402 1403 report(true, "NMI intercept while running guest"); 1404 break; 1405 1406 case 2: 1407 break; 1408 1409 default: 1410 return true; 1411 } 1412 1413 inc_test_stage(test); 1414 1415 return get_test_stage(test) == 3; 1416 } 1417 1418 static bool nmi_check(struct svm_test *test) 1419 { 1420 return get_test_stage(test) == 3; 1421 } 1422 1423 #define NMI_DELAY 100000000ULL 1424 1425 static void nmi_message_thread(void *_test) 1426 { 1427 struct svm_test *test = _test; 1428 1429 while (get_test_stage(test) != 1) 1430 pause(); 1431 1432 delay(NMI_DELAY); 1433 1434 apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); 1435 1436 while (get_test_stage(test) != 2) 1437 pause(); 1438 1439 delay(NMI_DELAY); 1440 1441 apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); 1442 } 1443 1444 static void nmi_hlt_test(struct svm_test *test) 1445 { 1446 long long start; 1447 1448 on_cpu_async(1, nmi_message_thread, test); 1449 1450 start = rdtsc(); 1451 1452 set_test_stage(test, 1); 1453 1454 asm volatile ("hlt"); 1455 1456 report((rdtsc() - start > NMI_DELAY) && nmi_fired, 1457 "direct NMI + hlt"); 1458 1459 if (!nmi_fired) 1460 set_test_stage(test, -1); 1461 1462 nmi_fired = false; 1463 1464 vmmcall(); 1465 1466 start = rdtsc(); 1467 1468 set_test_stage(test, 2); 1469 1470 asm volatile ("hlt"); 1471 1472 report((rdtsc() - start > NMI_DELAY) && nmi_fired, 1473 "intercepted NMI + hlt"); 1474 1475 if (!nmi_fired) { 1476 report(nmi_fired, "intercepted pending NMI not dispatched"); 1477 set_test_stage(test, -1); 1478 } 1479 1480 set_test_stage(test, 3); 1481 } 1482 1483 static bool nmi_hlt_finished(struct svm_test *test) 1484 { 1485 switch (get_test_stage(test)) { 1486 case 1: 1487 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1488 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 1489 vmcb->control.exit_code); 1490 return true; 1491 } 1492 vmcb->save.rip += 3; 1493 1494 vmcb->control.intercept |= (1ULL << INTERCEPT_NMI); 1495 break; 1496 1497 case 2: 1498 if (vmcb->control.exit_code != SVM_EXIT_NMI) { 1499 report(false, "VMEXIT not due to NMI intercept. Exit reason 0x%x", 1500 vmcb->control.exit_code); 1501 return true; 1502 } 1503 1504 report(true, "NMI intercept while running guest"); 1505 break; 1506 1507 case 3: 1508 break; 1509 1510 default: 1511 return true; 1512 } 1513 1514 return get_test_stage(test) == 3; 1515 } 1516 1517 static bool nmi_hlt_check(struct svm_test *test) 1518 { 1519 return get_test_stage(test) == 3; 1520 } 1521 1522 static volatile int count_exc = 0; 1523 1524 static void my_isr(struct ex_regs *r) 1525 { 1526 count_exc++; 1527 } 1528 1529 static void exc_inject_prepare(struct svm_test *test) 1530 { 1531 handle_exception(DE_VECTOR, my_isr); 1532 handle_exception(NMI_VECTOR, my_isr); 1533 } 1534 1535 1536 static void exc_inject_test(struct svm_test *test) 1537 { 1538 asm volatile ("vmmcall\n\tvmmcall\n\t"); 1539 } 1540 1541 static bool exc_inject_finished(struct svm_test *test) 1542 { 1543 vmcb->save.rip += 3; 1544 1545 switch (get_test_stage(test)) { 1546 case 0: 1547 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1548 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 1549 vmcb->control.exit_code); 1550 return true; 1551 } 1552 vmcb->control.event_inj = NMI_VECTOR | SVM_EVTINJ_TYPE_EXEPT | SVM_EVTINJ_VALID; 1553 break; 1554 1555 case 1: 1556 if (vmcb->control.exit_code != SVM_EXIT_ERR) { 1557 report(false, "VMEXIT not due to error. Exit reason 0x%x", 1558 vmcb->control.exit_code); 1559 return true; 1560 } 1561 report(count_exc == 0, "exception with vector 2 not injected"); 1562 vmcb->control.event_inj = DE_VECTOR | SVM_EVTINJ_TYPE_EXEPT | SVM_EVTINJ_VALID; 1563 break; 1564 1565 case 2: 1566 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1567 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 1568 vmcb->control.exit_code); 1569 return true; 1570 } 1571 report(count_exc == 1, "divide overflow exception injected"); 1572 report(!(vmcb->control.event_inj & SVM_EVTINJ_VALID), "eventinj.VALID cleared"); 1573 break; 1574 1575 default: 1576 return true; 1577 } 1578 1579 inc_test_stage(test); 1580 1581 return get_test_stage(test) == 3; 1582 } 1583 1584 static bool exc_inject_check(struct svm_test *test) 1585 { 1586 return count_exc == 1 && get_test_stage(test) == 3; 1587 } 1588 1589 #define TEST(name) { #name, .v2 = name } 1590 1591 /* 1592 * v2 tests 1593 */ 1594 1595 static void basic_guest_main(struct svm_test *test) 1596 { 1597 } 1598 1599 static void svm_guest_state_test(void) 1600 { 1601 u64 efer_saved = vmcb->save.efer; 1602 u64 efer = efer_saved; 1603 1604 test_set_guest(basic_guest_main); 1605 report (svm_vmrun() == SVM_EXIT_VMMCALL, "EFER.SVME: %lx", efer); 1606 efer &= ~EFER_SVME; 1607 vmcb->save.efer = efer; 1608 report (svm_vmrun() == SVM_EXIT_ERR, "EFER.SVME: %lx", efer); 1609 vmcb->save.efer = efer_saved; 1610 } 1611 1612 struct svm_test svm_tests[] = { 1613 { "null", default_supported, default_prepare, 1614 default_prepare_gif_clear, null_test, 1615 default_finished, null_check }, 1616 { "vmrun", default_supported, default_prepare, 1617 default_prepare_gif_clear, test_vmrun, 1618 default_finished, check_vmrun }, 1619 { "ioio", default_supported, prepare_ioio, 1620 default_prepare_gif_clear, test_ioio, 1621 ioio_finished, check_ioio }, 1622 { "vmrun intercept check", default_supported, prepare_no_vmrun_int, 1623 default_prepare_gif_clear, null_test, default_finished, 1624 check_no_vmrun_int }, 1625 { "cr3 read intercept", default_supported, 1626 prepare_cr3_intercept, default_prepare_gif_clear, 1627 test_cr3_intercept, default_finished, check_cr3_intercept }, 1628 { "cr3 read nointercept", default_supported, default_prepare, 1629 default_prepare_gif_clear, test_cr3_intercept, default_finished, 1630 check_cr3_nointercept }, 1631 { "cr3 read intercept emulate", smp_supported, 1632 prepare_cr3_intercept_bypass, default_prepare_gif_clear, 1633 test_cr3_intercept_bypass, default_finished, check_cr3_intercept }, 1634 { "dr intercept check", default_supported, prepare_dr_intercept, 1635 default_prepare_gif_clear, test_dr_intercept, dr_intercept_finished, 1636 check_dr_intercept }, 1637 { "next_rip", next_rip_supported, prepare_next_rip, 1638 default_prepare_gif_clear, test_next_rip, 1639 default_finished, check_next_rip }, 1640 { "msr intercept check", default_supported, prepare_msr_intercept, 1641 default_prepare_gif_clear, test_msr_intercept, 1642 msr_intercept_finished, check_msr_intercept }, 1643 { "mode_switch", default_supported, prepare_mode_switch, 1644 default_prepare_gif_clear, test_mode_switch, 1645 mode_switch_finished, check_mode_switch }, 1646 { "asid_zero", default_supported, prepare_asid_zero, 1647 default_prepare_gif_clear, test_asid_zero, 1648 default_finished, check_asid_zero }, 1649 { "sel_cr0_bug", default_supported, sel_cr0_bug_prepare, 1650 default_prepare_gif_clear, sel_cr0_bug_test, 1651 sel_cr0_bug_finished, sel_cr0_bug_check }, 1652 { "npt_nx", npt_supported, npt_nx_prepare, 1653 default_prepare_gif_clear, null_test, 1654 default_finished, npt_nx_check }, 1655 { "npt_us", npt_supported, npt_us_prepare, 1656 default_prepare_gif_clear, npt_us_test, 1657 default_finished, npt_us_check }, 1658 { "npt_rsvd", npt_supported, npt_rsvd_prepare, 1659 default_prepare_gif_clear, null_test, 1660 default_finished, npt_rsvd_check }, 1661 { "npt_rw", npt_supported, npt_rw_prepare, 1662 default_prepare_gif_clear, npt_rw_test, 1663 default_finished, npt_rw_check }, 1664 { "npt_rsvd_pfwalk", npt_supported, npt_rsvd_pfwalk_prepare, 1665 default_prepare_gif_clear, null_test, 1666 default_finished, npt_rsvd_pfwalk_check }, 1667 { "npt_rw_pfwalk", npt_supported, npt_rw_pfwalk_prepare, 1668 default_prepare_gif_clear, null_test, 1669 default_finished, npt_rw_pfwalk_check }, 1670 { "npt_l1mmio", npt_supported, npt_l1mmio_prepare, 1671 default_prepare_gif_clear, npt_l1mmio_test, 1672 default_finished, npt_l1mmio_check }, 1673 { "npt_rw_l1mmio", npt_supported, npt_rw_l1mmio_prepare, 1674 default_prepare_gif_clear, npt_rw_l1mmio_test, 1675 default_finished, npt_rw_l1mmio_check }, 1676 { "tsc_adjust", default_supported, tsc_adjust_prepare, 1677 default_prepare_gif_clear, tsc_adjust_test, 1678 default_finished, tsc_adjust_check }, 1679 { "latency_run_exit", default_supported, latency_prepare, 1680 default_prepare_gif_clear, latency_test, 1681 latency_finished, latency_check }, 1682 { "latency_svm_insn", default_supported, lat_svm_insn_prepare, 1683 default_prepare_gif_clear, null_test, 1684 lat_svm_insn_finished, lat_svm_insn_check }, 1685 { "exc_inject", default_supported, exc_inject_prepare, 1686 default_prepare_gif_clear, exc_inject_test, 1687 exc_inject_finished, exc_inject_check }, 1688 { "pending_event", default_supported, pending_event_prepare, 1689 default_prepare_gif_clear, 1690 pending_event_test, pending_event_finished, pending_event_check }, 1691 { "pending_event_cli", default_supported, pending_event_cli_prepare, 1692 pending_event_cli_prepare_gif_clear, 1693 pending_event_cli_test, pending_event_cli_finished, 1694 pending_event_cli_check }, 1695 { "interrupt", default_supported, interrupt_prepare, 1696 default_prepare_gif_clear, interrupt_test, 1697 interrupt_finished, interrupt_check }, 1698 { "nmi", default_supported, nmi_prepare, 1699 default_prepare_gif_clear, nmi_test, 1700 nmi_finished, nmi_check }, 1701 { "nmi_hlt", smp_supported, nmi_prepare, 1702 default_prepare_gif_clear, nmi_hlt_test, 1703 nmi_hlt_finished, nmi_hlt_check }, 1704 TEST(svm_guest_state_test), 1705 { NULL, NULL, NULL, NULL, NULL, NULL, NULL } 1706 }; 1707