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 #define LATENCY_RUNS 1000000 17 18 u64 tsc_start; 19 u64 tsc_end; 20 21 u64 vmrun_sum, vmexit_sum; 22 u64 vmsave_sum, vmload_sum; 23 u64 stgi_sum, clgi_sum; 24 u64 latvmrun_max; 25 u64 latvmrun_min; 26 u64 latvmexit_max; 27 u64 latvmexit_min; 28 u64 latvmload_max; 29 u64 latvmload_min; 30 u64 latvmsave_max; 31 u64 latvmsave_min; 32 u64 latstgi_max; 33 u64 latstgi_min; 34 u64 latclgi_max; 35 u64 latclgi_min; 36 u64 runs; 37 38 static void null_test(struct svm_test *test) 39 { 40 } 41 42 static bool null_check(struct svm_test *test) 43 { 44 return vmcb->control.exit_code == SVM_EXIT_VMMCALL; 45 } 46 47 static void prepare_no_vmrun_int(struct svm_test *test) 48 { 49 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMRUN); 50 } 51 52 static bool check_no_vmrun_int(struct svm_test *test) 53 { 54 return vmcb->control.exit_code == SVM_EXIT_ERR; 55 } 56 57 static void test_vmrun(struct svm_test *test) 58 { 59 asm volatile ("vmrun %0" : : "a"(virt_to_phys(vmcb))); 60 } 61 62 static bool check_vmrun(struct svm_test *test) 63 { 64 return vmcb->control.exit_code == SVM_EXIT_VMRUN; 65 } 66 67 static void prepare_rsm_intercept(struct svm_test *test) 68 { 69 default_prepare(test); 70 vmcb->control.intercept |= 1 << INTERCEPT_RSM; 71 vmcb->control.intercept_exceptions |= (1ULL << UD_VECTOR); 72 } 73 74 static void test_rsm_intercept(struct svm_test *test) 75 { 76 asm volatile ("rsm" : : : "memory"); 77 } 78 79 static bool check_rsm_intercept(struct svm_test *test) 80 { 81 return get_test_stage(test) == 2; 82 } 83 84 static bool finished_rsm_intercept(struct svm_test *test) 85 { 86 switch (get_test_stage(test)) { 87 case 0: 88 if (vmcb->control.exit_code != SVM_EXIT_RSM) { 89 report_fail("VMEXIT not due to rsm. Exit reason 0x%x", 90 vmcb->control.exit_code); 91 return true; 92 } 93 vmcb->control.intercept &= ~(1 << INTERCEPT_RSM); 94 inc_test_stage(test); 95 break; 96 97 case 1: 98 if (vmcb->control.exit_code != SVM_EXIT_EXCP_BASE + UD_VECTOR) { 99 report_fail("VMEXIT not due to #UD. Exit reason 0x%x", 100 vmcb->control.exit_code); 101 return true; 102 } 103 vmcb->save.rip += 2; 104 inc_test_stage(test); 105 break; 106 107 default: 108 return true; 109 } 110 return get_test_stage(test) == 2; 111 } 112 113 static void prepare_cr3_intercept(struct svm_test *test) 114 { 115 default_prepare(test); 116 vmcb->control.intercept_cr_read |= 1 << 3; 117 } 118 119 static void test_cr3_intercept(struct svm_test *test) 120 { 121 asm volatile ("mov %%cr3, %0" : "=r"(test->scratch) : : "memory"); 122 } 123 124 static bool check_cr3_intercept(struct svm_test *test) 125 { 126 return vmcb->control.exit_code == SVM_EXIT_READ_CR3; 127 } 128 129 static bool check_cr3_nointercept(struct svm_test *test) 130 { 131 return null_check(test) && test->scratch == read_cr3(); 132 } 133 134 static void corrupt_cr3_intercept_bypass(void *_test) 135 { 136 struct svm_test *test = _test; 137 extern volatile u32 mmio_insn; 138 139 while (!__sync_bool_compare_and_swap(&test->scratch, 1, 2)) 140 pause(); 141 pause(); 142 pause(); 143 pause(); 144 mmio_insn = 0x90d8200f; // mov %cr3, %rax; nop 145 } 146 147 static void prepare_cr3_intercept_bypass(struct svm_test *test) 148 { 149 default_prepare(test); 150 vmcb->control.intercept_cr_read |= 1 << 3; 151 on_cpu_async(1, corrupt_cr3_intercept_bypass, test); 152 } 153 154 static void test_cr3_intercept_bypass(struct svm_test *test) 155 { 156 ulong a = 0xa0000; 157 158 test->scratch = 1; 159 while (test->scratch != 2) 160 barrier(); 161 162 asm volatile ("mmio_insn: mov %0, (%0); nop" 163 : "+a"(a) : : "memory"); 164 test->scratch = a; 165 } 166 167 static void prepare_dr_intercept(struct svm_test *test) 168 { 169 default_prepare(test); 170 vmcb->control.intercept_dr_read = 0xff; 171 vmcb->control.intercept_dr_write = 0xff; 172 } 173 174 static void test_dr_intercept(struct svm_test *test) 175 { 176 unsigned int i, failcnt = 0; 177 178 /* Loop testing debug register reads */ 179 for (i = 0; i < 8; i++) { 180 181 switch (i) { 182 case 0: 183 asm volatile ("mov %%dr0, %0" : "=r"(test->scratch) : : "memory"); 184 break; 185 case 1: 186 asm volatile ("mov %%dr1, %0" : "=r"(test->scratch) : : "memory"); 187 break; 188 case 2: 189 asm volatile ("mov %%dr2, %0" : "=r"(test->scratch) : : "memory"); 190 break; 191 case 3: 192 asm volatile ("mov %%dr3, %0" : "=r"(test->scratch) : : "memory"); 193 break; 194 case 4: 195 asm volatile ("mov %%dr4, %0" : "=r"(test->scratch) : : "memory"); 196 break; 197 case 5: 198 asm volatile ("mov %%dr5, %0" : "=r"(test->scratch) : : "memory"); 199 break; 200 case 6: 201 asm volatile ("mov %%dr6, %0" : "=r"(test->scratch) : : "memory"); 202 break; 203 case 7: 204 asm volatile ("mov %%dr7, %0" : "=r"(test->scratch) : : "memory"); 205 break; 206 } 207 208 if (test->scratch != i) { 209 report_fail("dr%u read intercept", i); 210 failcnt++; 211 } 212 } 213 214 /* Loop testing debug register writes */ 215 for (i = 0; i < 8; i++) { 216 217 switch (i) { 218 case 0: 219 asm volatile ("mov %0, %%dr0" : : "r"(test->scratch) : "memory"); 220 break; 221 case 1: 222 asm volatile ("mov %0, %%dr1" : : "r"(test->scratch) : "memory"); 223 break; 224 case 2: 225 asm volatile ("mov %0, %%dr2" : : "r"(test->scratch) : "memory"); 226 break; 227 case 3: 228 asm volatile ("mov %0, %%dr3" : : "r"(test->scratch) : "memory"); 229 break; 230 case 4: 231 asm volatile ("mov %0, %%dr4" : : "r"(test->scratch) : "memory"); 232 break; 233 case 5: 234 asm volatile ("mov %0, %%dr5" : : "r"(test->scratch) : "memory"); 235 break; 236 case 6: 237 asm volatile ("mov %0, %%dr6" : : "r"(test->scratch) : "memory"); 238 break; 239 case 7: 240 asm volatile ("mov %0, %%dr7" : : "r"(test->scratch) : "memory"); 241 break; 242 } 243 244 if (test->scratch != i) { 245 report_fail("dr%u write intercept", i); 246 failcnt++; 247 } 248 } 249 250 test->scratch = failcnt; 251 } 252 253 static bool dr_intercept_finished(struct svm_test *test) 254 { 255 ulong n = (vmcb->control.exit_code - SVM_EXIT_READ_DR0); 256 257 /* Only expect DR intercepts */ 258 if (n > (SVM_EXIT_MAX_DR_INTERCEPT - SVM_EXIT_READ_DR0)) 259 return true; 260 261 /* 262 * Compute debug register number. 263 * Per Appendix C "SVM Intercept Exit Codes" of AMD64 Architecture 264 * Programmer's Manual Volume 2 - System Programming: 265 * http://support.amd.com/TechDocs/24593.pdf 266 * there are 16 VMEXIT codes each for DR read and write. 267 */ 268 test->scratch = (n % 16); 269 270 /* Jump over MOV instruction */ 271 vmcb->save.rip += 3; 272 273 return false; 274 } 275 276 static bool check_dr_intercept(struct svm_test *test) 277 { 278 return !test->scratch; 279 } 280 281 static bool next_rip_supported(void) 282 { 283 return this_cpu_has(X86_FEATURE_NRIPS); 284 } 285 286 static void prepare_next_rip(struct svm_test *test) 287 { 288 vmcb->control.intercept |= (1ULL << INTERCEPT_RDTSC); 289 } 290 291 292 static void test_next_rip(struct svm_test *test) 293 { 294 asm volatile ("rdtsc\n\t" 295 ".globl exp_next_rip\n\t" 296 "exp_next_rip:\n\t" ::: "eax", "edx"); 297 } 298 299 static bool check_next_rip(struct svm_test *test) 300 { 301 extern char exp_next_rip; 302 unsigned long address = (unsigned long)&exp_next_rip; 303 304 return address == vmcb->control.next_rip; 305 } 306 307 extern u8 *msr_bitmap; 308 309 static void prepare_msr_intercept(struct svm_test *test) 310 { 311 default_prepare(test); 312 vmcb->control.intercept |= (1ULL << INTERCEPT_MSR_PROT); 313 vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR); 314 memset(msr_bitmap, 0xff, MSR_BITMAP_SIZE); 315 } 316 317 static void test_msr_intercept(struct svm_test *test) 318 { 319 unsigned long msr_value = 0xef8056791234abcd; /* Arbitrary value */ 320 unsigned long msr_index; 321 322 for (msr_index = 0; msr_index <= 0xc0011fff; msr_index++) { 323 if (msr_index == 0xC0010131 /* MSR_SEV_STATUS */) { 324 /* 325 * Per section 15.34.10 "SEV_STATUS MSR" of AMD64 Architecture 326 * Programmer's Manual volume 2 - System Programming: 327 * http://support.amd.com/TechDocs/24593.pdf 328 * SEV_STATUS MSR (C001_0131) is a non-interceptable MSR. 329 */ 330 continue; 331 } 332 333 /* Skips gaps between supported MSR ranges */ 334 if (msr_index == 0x2000) 335 msr_index = 0xc0000000; 336 else if (msr_index == 0xc0002000) 337 msr_index = 0xc0010000; 338 339 test->scratch = -1; 340 341 rdmsr(msr_index); 342 343 /* Check that a read intercept occurred for MSR at msr_index */ 344 if (test->scratch != msr_index) 345 report_fail("MSR 0x%lx read intercept", msr_index); 346 347 /* 348 * Poor man approach to generate a value that 349 * seems arbitrary each time around the loop. 350 */ 351 msr_value += (msr_value << 1); 352 353 wrmsr(msr_index, msr_value); 354 355 /* Check that a write intercept occurred for MSR with msr_value */ 356 if (test->scratch != msr_value) 357 report_fail("MSR 0x%lx write intercept", msr_index); 358 } 359 360 test->scratch = -2; 361 } 362 363 static bool msr_intercept_finished(struct svm_test *test) 364 { 365 u32 exit_code = vmcb->control.exit_code; 366 u64 exit_info_1; 367 u8 *opcode; 368 369 if (exit_code == SVM_EXIT_MSR) { 370 exit_info_1 = vmcb->control.exit_info_1; 371 } else { 372 /* 373 * If #GP exception occurs instead, check that it was 374 * for RDMSR/WRMSR and set exit_info_1 accordingly. 375 */ 376 377 if (exit_code != (SVM_EXIT_EXCP_BASE + GP_VECTOR)) 378 return true; 379 380 opcode = (u8 *)vmcb->save.rip; 381 if (opcode[0] != 0x0f) 382 return true; 383 384 switch (opcode[1]) { 385 case 0x30: /* WRMSR */ 386 exit_info_1 = 1; 387 break; 388 case 0x32: /* RDMSR */ 389 exit_info_1 = 0; 390 break; 391 default: 392 return true; 393 } 394 395 /* 396 * Warn that #GP exception occured instead. 397 * RCX holds the MSR index. 398 */ 399 printf("%s 0x%lx #GP exception\n", 400 exit_info_1 ? "WRMSR" : "RDMSR", get_regs().rcx); 401 } 402 403 /* Jump over RDMSR/WRMSR instruction */ 404 vmcb->save.rip += 2; 405 406 /* 407 * Test whether the intercept was for RDMSR/WRMSR. 408 * For RDMSR, test->scratch is set to the MSR index; 409 * RCX holds the MSR index. 410 * For WRMSR, test->scratch is set to the MSR value; 411 * RDX holds the upper 32 bits of the MSR value, 412 * while RAX hold its lower 32 bits. 413 */ 414 if (exit_info_1) 415 test->scratch = 416 ((get_regs().rdx << 32) | (vmcb->save.rax & 0xffffffff)); 417 else 418 test->scratch = get_regs().rcx; 419 420 return false; 421 } 422 423 static bool check_msr_intercept(struct svm_test *test) 424 { 425 memset(msr_bitmap, 0, MSR_BITMAP_SIZE); 426 return (test->scratch == -2); 427 } 428 429 static void prepare_mode_switch(struct svm_test *test) 430 { 431 vmcb->control.intercept_exceptions |= (1ULL << GP_VECTOR) 432 | (1ULL << UD_VECTOR) 433 | (1ULL << DF_VECTOR) 434 | (1ULL << PF_VECTOR); 435 test->scratch = 0; 436 } 437 438 static void test_mode_switch(struct svm_test *test) 439 { 440 asm volatile(" cli\n" 441 " ljmp *1f\n" /* jump to 32-bit code segment */ 442 "1:\n" 443 " .long 2f\n" 444 " .long " xstr(KERNEL_CS32) "\n" 445 ".code32\n" 446 "2:\n" 447 " movl %%cr0, %%eax\n" 448 " btcl $31, %%eax\n" /* clear PG */ 449 " movl %%eax, %%cr0\n" 450 " movl $0xc0000080, %%ecx\n" /* EFER */ 451 " rdmsr\n" 452 " btcl $8, %%eax\n" /* clear LME */ 453 " wrmsr\n" 454 " movl %%cr4, %%eax\n" 455 " btcl $5, %%eax\n" /* clear PAE */ 456 " movl %%eax, %%cr4\n" 457 " movw %[ds16], %%ax\n" 458 " movw %%ax, %%ds\n" 459 " ljmpl %[cs16], $3f\n" /* jump to 16 bit protected-mode */ 460 ".code16\n" 461 "3:\n" 462 " movl %%cr0, %%eax\n" 463 " btcl $0, %%eax\n" /* clear PE */ 464 " movl %%eax, %%cr0\n" 465 " ljmpl $0, $4f\n" /* jump to real-mode */ 466 "4:\n" 467 " vmmcall\n" 468 " movl %%cr0, %%eax\n" 469 " btsl $0, %%eax\n" /* set PE */ 470 " movl %%eax, %%cr0\n" 471 " ljmpl %[cs32], $5f\n" /* back to protected mode */ 472 ".code32\n" 473 "5:\n" 474 " movl %%cr4, %%eax\n" 475 " btsl $5, %%eax\n" /* set PAE */ 476 " movl %%eax, %%cr4\n" 477 " movl $0xc0000080, %%ecx\n" /* EFER */ 478 " rdmsr\n" 479 " btsl $8, %%eax\n" /* set LME */ 480 " wrmsr\n" 481 " movl %%cr0, %%eax\n" 482 " btsl $31, %%eax\n" /* set PG */ 483 " movl %%eax, %%cr0\n" 484 " ljmpl %[cs64], $6f\n" /* back to long mode */ 485 ".code64\n\t" 486 "6:\n" 487 " vmmcall\n" 488 :: [cs16] "i"(KERNEL_CS16), [ds16] "i"(KERNEL_DS16), 489 [cs32] "i"(KERNEL_CS32), [cs64] "i"(KERNEL_CS64) 490 : "rax", "rbx", "rcx", "rdx", "memory"); 491 } 492 493 static bool mode_switch_finished(struct svm_test *test) 494 { 495 u64 cr0, cr4, efer; 496 497 cr0 = vmcb->save.cr0; 498 cr4 = vmcb->save.cr4; 499 efer = vmcb->save.efer; 500 501 /* Only expect VMMCALL intercepts */ 502 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) 503 return true; 504 505 /* Jump over VMMCALL instruction */ 506 vmcb->save.rip += 3; 507 508 /* Do sanity checks */ 509 switch (test->scratch) { 510 case 0: 511 /* Test should be in real mode now - check for this */ 512 if ((cr0 & 0x80000001) || /* CR0.PG, CR0.PE */ 513 (cr4 & 0x00000020) || /* CR4.PAE */ 514 (efer & 0x00000500)) /* EFER.LMA, EFER.LME */ 515 return true; 516 break; 517 case 2: 518 /* Test should be back in long-mode now - check for this */ 519 if (((cr0 & 0x80000001) != 0x80000001) || /* CR0.PG, CR0.PE */ 520 ((cr4 & 0x00000020) != 0x00000020) || /* CR4.PAE */ 521 ((efer & 0x00000500) != 0x00000500)) /* EFER.LMA, EFER.LME */ 522 return true; 523 break; 524 } 525 526 /* one step forward */ 527 test->scratch += 1; 528 529 return test->scratch == 2; 530 } 531 532 static bool check_mode_switch(struct svm_test *test) 533 { 534 return test->scratch == 2; 535 } 536 537 extern u8 *io_bitmap; 538 539 static void prepare_ioio(struct svm_test *test) 540 { 541 vmcb->control.intercept |= (1ULL << INTERCEPT_IOIO_PROT); 542 test->scratch = 0; 543 memset(io_bitmap, 0, 8192); 544 io_bitmap[8192] = 0xFF; 545 } 546 547 static void test_ioio(struct svm_test *test) 548 { 549 // stage 0, test IO pass 550 inb(0x5000); 551 outb(0x0, 0x5000); 552 if (get_test_stage(test) != 0) 553 goto fail; 554 555 // test IO width, in/out 556 io_bitmap[0] = 0xFF; 557 inc_test_stage(test); 558 inb(0x0); 559 if (get_test_stage(test) != 2) 560 goto fail; 561 562 outw(0x0, 0x0); 563 if (get_test_stage(test) != 3) 564 goto fail; 565 566 inl(0x0); 567 if (get_test_stage(test) != 4) 568 goto fail; 569 570 // test low/high IO port 571 io_bitmap[0x5000 / 8] = (1 << (0x5000 % 8)); 572 inb(0x5000); 573 if (get_test_stage(test) != 5) 574 goto fail; 575 576 io_bitmap[0x9000 / 8] = (1 << (0x9000 % 8)); 577 inw(0x9000); 578 if (get_test_stage(test) != 6) 579 goto fail; 580 581 // test partial pass 582 io_bitmap[0x5000 / 8] = (1 << (0x5000 % 8)); 583 inl(0x4FFF); 584 if (get_test_stage(test) != 7) 585 goto fail; 586 587 // test across pages 588 inc_test_stage(test); 589 inl(0x7FFF); 590 if (get_test_stage(test) != 8) 591 goto fail; 592 593 inc_test_stage(test); 594 io_bitmap[0x8000 / 8] = 1 << (0x8000 % 8); 595 inl(0x7FFF); 596 if (get_test_stage(test) != 10) 597 goto fail; 598 599 io_bitmap[0] = 0; 600 inl(0xFFFF); 601 if (get_test_stage(test) != 11) 602 goto fail; 603 604 io_bitmap[0] = 0xFF; 605 io_bitmap[8192] = 0; 606 inl(0xFFFF); 607 inc_test_stage(test); 608 if (get_test_stage(test) != 12) 609 goto fail; 610 611 return; 612 613 fail: 614 report_fail("stage %d", get_test_stage(test)); 615 test->scratch = -1; 616 } 617 618 static bool ioio_finished(struct svm_test *test) 619 { 620 unsigned port, size; 621 622 /* Only expect IOIO intercepts */ 623 if (vmcb->control.exit_code == SVM_EXIT_VMMCALL) 624 return true; 625 626 if (vmcb->control.exit_code != SVM_EXIT_IOIO) 627 return true; 628 629 /* one step forward */ 630 test->scratch += 1; 631 632 port = vmcb->control.exit_info_1 >> 16; 633 size = (vmcb->control.exit_info_1 >> SVM_IOIO_SIZE_SHIFT) & 7; 634 635 while (size--) { 636 io_bitmap[port / 8] &= ~(1 << (port & 7)); 637 port++; 638 } 639 640 return false; 641 } 642 643 static bool check_ioio(struct svm_test *test) 644 { 645 memset(io_bitmap, 0, 8193); 646 return test->scratch != -1; 647 } 648 649 static void prepare_asid_zero(struct svm_test *test) 650 { 651 vmcb->control.asid = 0; 652 } 653 654 static void test_asid_zero(struct svm_test *test) 655 { 656 asm volatile ("vmmcall\n\t"); 657 } 658 659 static bool check_asid_zero(struct svm_test *test) 660 { 661 return vmcb->control.exit_code == SVM_EXIT_ERR; 662 } 663 664 static void sel_cr0_bug_prepare(struct svm_test *test) 665 { 666 vmcb->control.intercept |= (1ULL << INTERCEPT_SELECTIVE_CR0); 667 } 668 669 static bool sel_cr0_bug_finished(struct svm_test *test) 670 { 671 return true; 672 } 673 674 static void sel_cr0_bug_test(struct svm_test *test) 675 { 676 unsigned long cr0; 677 678 /* read cr0, clear CD, and write back */ 679 cr0 = read_cr0(); 680 cr0 |= (1UL << 30); 681 write_cr0(cr0); 682 683 /* 684 * If we are here the test failed, not sure what to do now because we 685 * are not in guest-mode anymore so we can't trigger an intercept. 686 * Trigger a tripple-fault for now. 687 */ 688 report_fail("sel_cr0 test. Can not recover from this - exiting"); 689 exit(report_summary()); 690 } 691 692 static bool sel_cr0_bug_check(struct svm_test *test) 693 { 694 return vmcb->control.exit_code == SVM_EXIT_CR0_SEL_WRITE; 695 } 696 697 #define TSC_ADJUST_VALUE (1ll << 32) 698 #define TSC_OFFSET_VALUE (~0ull << 48) 699 static bool ok; 700 701 static bool tsc_adjust_supported(void) 702 { 703 return this_cpu_has(X86_FEATURE_TSC_ADJUST); 704 } 705 706 static void tsc_adjust_prepare(struct svm_test *test) 707 { 708 default_prepare(test); 709 vmcb->control.tsc_offset = TSC_OFFSET_VALUE; 710 711 wrmsr(MSR_IA32_TSC_ADJUST, -TSC_ADJUST_VALUE); 712 int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); 713 ok = adjust == -TSC_ADJUST_VALUE; 714 } 715 716 static void tsc_adjust_test(struct svm_test *test) 717 { 718 int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); 719 ok &= adjust == -TSC_ADJUST_VALUE; 720 721 uint64_t l1_tsc = rdtsc() - TSC_OFFSET_VALUE; 722 wrmsr(MSR_IA32_TSC, l1_tsc - TSC_ADJUST_VALUE); 723 724 adjust = rdmsr(MSR_IA32_TSC_ADJUST); 725 ok &= adjust <= -2 * TSC_ADJUST_VALUE; 726 727 uint64_t l1_tsc_end = rdtsc() - TSC_OFFSET_VALUE; 728 ok &= (l1_tsc_end + TSC_ADJUST_VALUE - l1_tsc) < TSC_ADJUST_VALUE; 729 730 uint64_t l1_tsc_msr = rdmsr(MSR_IA32_TSC) - TSC_OFFSET_VALUE; 731 ok &= (l1_tsc_msr + TSC_ADJUST_VALUE - l1_tsc) < TSC_ADJUST_VALUE; 732 } 733 734 static bool tsc_adjust_check(struct svm_test *test) 735 { 736 int64_t adjust = rdmsr(MSR_IA32_TSC_ADJUST); 737 738 wrmsr(MSR_IA32_TSC_ADJUST, 0); 739 return ok && adjust <= -2 * TSC_ADJUST_VALUE; 740 } 741 742 743 static u64 guest_tsc_delay_value; 744 /* number of bits to shift tsc right for stable result */ 745 #define TSC_SHIFT 24 746 #define TSC_SCALE_ITERATIONS 10 747 748 static void svm_tsc_scale_guest(struct svm_test *test) 749 { 750 u64 start_tsc = rdtsc(); 751 752 while (rdtsc() - start_tsc < guest_tsc_delay_value) 753 cpu_relax(); 754 } 755 756 static void svm_tsc_scale_run_testcase(u64 duration, 757 double tsc_scale, u64 tsc_offset) 758 { 759 u64 start_tsc, actual_duration; 760 761 guest_tsc_delay_value = (duration << TSC_SHIFT) * tsc_scale; 762 763 test_set_guest(svm_tsc_scale_guest); 764 vmcb->control.tsc_offset = tsc_offset; 765 wrmsr(MSR_AMD64_TSC_RATIO, (u64)(tsc_scale * (1ULL << 32))); 766 767 start_tsc = rdtsc(); 768 769 if (svm_vmrun() != SVM_EXIT_VMMCALL) 770 report_fail("unexpected vm exit code 0x%x", vmcb->control.exit_code); 771 772 actual_duration = (rdtsc() - start_tsc) >> TSC_SHIFT; 773 774 report(duration == actual_duration, "tsc delay (expected: %lu, actual: %lu)", 775 duration, actual_duration); 776 } 777 778 static void svm_tsc_scale_test(void) 779 { 780 int i; 781 782 if (!tsc_scale_supported()) { 783 report_skip("TSC scale not supported in the guest"); 784 return; 785 } 786 787 report(rdmsr(MSR_AMD64_TSC_RATIO) == TSC_RATIO_DEFAULT, 788 "initial TSC scale ratio"); 789 790 for (i = 0 ; i < TSC_SCALE_ITERATIONS; i++) { 791 792 double tsc_scale = (double)(rdrand() % 100 + 1) / 10; 793 int duration = rdrand() % 50 + 1; 794 u64 tsc_offset = rdrand(); 795 796 report_info("duration=%d, tsc_scale=%d, tsc_offset=%ld", 797 duration, (int)(tsc_scale * 100), tsc_offset); 798 799 svm_tsc_scale_run_testcase(duration, tsc_scale, tsc_offset); 800 } 801 802 svm_tsc_scale_run_testcase(50, 255, rdrand()); 803 svm_tsc_scale_run_testcase(50, 0.0001, rdrand()); 804 } 805 806 static void latency_prepare(struct svm_test *test) 807 { 808 default_prepare(test); 809 runs = LATENCY_RUNS; 810 latvmrun_min = latvmexit_min = -1ULL; 811 latvmrun_max = latvmexit_max = 0; 812 vmrun_sum = vmexit_sum = 0; 813 tsc_start = rdtsc(); 814 } 815 816 static void latency_test(struct svm_test *test) 817 { 818 u64 cycles; 819 820 start: 821 tsc_end = rdtsc(); 822 823 cycles = tsc_end - tsc_start; 824 825 if (cycles > latvmrun_max) 826 latvmrun_max = cycles; 827 828 if (cycles < latvmrun_min) 829 latvmrun_min = cycles; 830 831 vmrun_sum += cycles; 832 833 tsc_start = rdtsc(); 834 835 asm volatile ("vmmcall" : : : "memory"); 836 goto start; 837 } 838 839 static bool latency_finished(struct svm_test *test) 840 { 841 u64 cycles; 842 843 tsc_end = rdtsc(); 844 845 cycles = tsc_end - tsc_start; 846 847 if (cycles > latvmexit_max) 848 latvmexit_max = cycles; 849 850 if (cycles < latvmexit_min) 851 latvmexit_min = cycles; 852 853 vmexit_sum += cycles; 854 855 vmcb->save.rip += 3; 856 857 runs -= 1; 858 859 tsc_end = rdtsc(); 860 861 return runs == 0; 862 } 863 864 static bool latency_finished_clean(struct svm_test *test) 865 { 866 vmcb->control.clean = VMCB_CLEAN_ALL; 867 return latency_finished(test); 868 } 869 870 static bool latency_check(struct svm_test *test) 871 { 872 printf(" Latency VMRUN : max: %ld min: %ld avg: %ld\n", latvmrun_max, 873 latvmrun_min, vmrun_sum / LATENCY_RUNS); 874 printf(" Latency VMEXIT: max: %ld min: %ld avg: %ld\n", latvmexit_max, 875 latvmexit_min, vmexit_sum / LATENCY_RUNS); 876 return true; 877 } 878 879 static void lat_svm_insn_prepare(struct svm_test *test) 880 { 881 default_prepare(test); 882 runs = LATENCY_RUNS; 883 latvmload_min = latvmsave_min = latstgi_min = latclgi_min = -1ULL; 884 latvmload_max = latvmsave_max = latstgi_max = latclgi_max = 0; 885 vmload_sum = vmsave_sum = stgi_sum = clgi_sum; 886 } 887 888 static bool lat_svm_insn_finished(struct svm_test *test) 889 { 890 u64 vmcb_phys = virt_to_phys(vmcb); 891 u64 cycles; 892 893 for ( ; runs != 0; runs--) { 894 tsc_start = rdtsc(); 895 asm volatile("vmload %0\n\t" : : "a"(vmcb_phys) : "memory"); 896 cycles = rdtsc() - tsc_start; 897 if (cycles > latvmload_max) 898 latvmload_max = cycles; 899 if (cycles < latvmload_min) 900 latvmload_min = cycles; 901 vmload_sum += cycles; 902 903 tsc_start = rdtsc(); 904 asm volatile("vmsave %0\n\t" : : "a"(vmcb_phys) : "memory"); 905 cycles = rdtsc() - tsc_start; 906 if (cycles > latvmsave_max) 907 latvmsave_max = cycles; 908 if (cycles < latvmsave_min) 909 latvmsave_min = cycles; 910 vmsave_sum += cycles; 911 912 tsc_start = rdtsc(); 913 asm volatile("stgi\n\t"); 914 cycles = rdtsc() - tsc_start; 915 if (cycles > latstgi_max) 916 latstgi_max = cycles; 917 if (cycles < latstgi_min) 918 latstgi_min = cycles; 919 stgi_sum += cycles; 920 921 tsc_start = rdtsc(); 922 asm volatile("clgi\n\t"); 923 cycles = rdtsc() - tsc_start; 924 if (cycles > latclgi_max) 925 latclgi_max = cycles; 926 if (cycles < latclgi_min) 927 latclgi_min = cycles; 928 clgi_sum += cycles; 929 } 930 931 tsc_end = rdtsc(); 932 933 return true; 934 } 935 936 static bool lat_svm_insn_check(struct svm_test *test) 937 { 938 printf(" Latency VMLOAD: max: %ld min: %ld avg: %ld\n", latvmload_max, 939 latvmload_min, vmload_sum / LATENCY_RUNS); 940 printf(" Latency VMSAVE: max: %ld min: %ld avg: %ld\n", latvmsave_max, 941 latvmsave_min, vmsave_sum / LATENCY_RUNS); 942 printf(" Latency STGI: max: %ld min: %ld avg: %ld\n", latstgi_max, 943 latstgi_min, stgi_sum / LATENCY_RUNS); 944 printf(" Latency CLGI: max: %ld min: %ld avg: %ld\n", latclgi_max, 945 latclgi_min, clgi_sum / LATENCY_RUNS); 946 return true; 947 } 948 949 bool pending_event_ipi_fired; 950 bool pending_event_guest_run; 951 952 static void pending_event_ipi_isr(isr_regs_t *regs) 953 { 954 pending_event_ipi_fired = true; 955 eoi(); 956 } 957 958 static void pending_event_prepare(struct svm_test *test) 959 { 960 int ipi_vector = 0xf1; 961 962 default_prepare(test); 963 964 pending_event_ipi_fired = false; 965 966 handle_irq(ipi_vector, pending_event_ipi_isr); 967 968 pending_event_guest_run = false; 969 970 vmcb->control.intercept |= (1ULL << INTERCEPT_INTR); 971 vmcb->control.int_ctl |= V_INTR_MASKING_MASK; 972 973 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | 974 APIC_DM_FIXED | ipi_vector, 0); 975 976 set_test_stage(test, 0); 977 } 978 979 static void pending_event_test(struct svm_test *test) 980 { 981 pending_event_guest_run = true; 982 } 983 984 static bool pending_event_finished(struct svm_test *test) 985 { 986 switch (get_test_stage(test)) { 987 case 0: 988 if (vmcb->control.exit_code != SVM_EXIT_INTR) { 989 report_fail("VMEXIT not due to pending interrupt. Exit reason 0x%x", 990 vmcb->control.exit_code); 991 return true; 992 } 993 994 vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR); 995 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 996 997 if (pending_event_guest_run) { 998 report_fail("Guest ran before host received IPI\n"); 999 return true; 1000 } 1001 1002 irq_enable(); 1003 asm volatile ("nop"); 1004 irq_disable(); 1005 1006 if (!pending_event_ipi_fired) { 1007 report_fail("Pending interrupt not dispatched after IRQ enabled\n"); 1008 return true; 1009 } 1010 break; 1011 1012 case 1: 1013 if (!pending_event_guest_run) { 1014 report_fail("Guest did not resume when no interrupt\n"); 1015 return true; 1016 } 1017 break; 1018 } 1019 1020 inc_test_stage(test); 1021 1022 return get_test_stage(test) == 2; 1023 } 1024 1025 static bool pending_event_check(struct svm_test *test) 1026 { 1027 return get_test_stage(test) == 2; 1028 } 1029 1030 static void pending_event_cli_prepare(struct svm_test *test) 1031 { 1032 default_prepare(test); 1033 1034 pending_event_ipi_fired = false; 1035 1036 handle_irq(0xf1, pending_event_ipi_isr); 1037 1038 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | 1039 APIC_DM_FIXED | 0xf1, 0); 1040 1041 set_test_stage(test, 0); 1042 } 1043 1044 static void pending_event_cli_prepare_gif_clear(struct svm_test *test) 1045 { 1046 asm("cli"); 1047 } 1048 1049 static void pending_event_cli_test(struct svm_test *test) 1050 { 1051 if (pending_event_ipi_fired == true) { 1052 set_test_stage(test, -1); 1053 report_fail("Interrupt preceeded guest"); 1054 vmmcall(); 1055 } 1056 1057 /* VINTR_MASKING is zero. This should cause the IPI to fire. */ 1058 irq_enable(); 1059 asm volatile ("nop"); 1060 irq_disable(); 1061 1062 if (pending_event_ipi_fired != true) { 1063 set_test_stage(test, -1); 1064 report_fail("Interrupt not triggered by guest"); 1065 } 1066 1067 vmmcall(); 1068 1069 /* 1070 * Now VINTR_MASKING=1, but no interrupt is pending so 1071 * the VINTR interception should be clear in VMCB02. Check 1072 * that L0 did not leave a stale VINTR in the VMCB. 1073 */ 1074 irq_enable(); 1075 asm volatile ("nop"); 1076 irq_disable(); 1077 } 1078 1079 static bool pending_event_cli_finished(struct svm_test *test) 1080 { 1081 if ( vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1082 report_fail("VM_EXIT return to host is not EXIT_VMMCALL exit reason 0x%x", 1083 vmcb->control.exit_code); 1084 return true; 1085 } 1086 1087 switch (get_test_stage(test)) { 1088 case 0: 1089 vmcb->save.rip += 3; 1090 1091 pending_event_ipi_fired = false; 1092 1093 vmcb->control.int_ctl |= V_INTR_MASKING_MASK; 1094 1095 /* Now entering again with VINTR_MASKING=1. */ 1096 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | 1097 APIC_DM_FIXED | 0xf1, 0); 1098 1099 break; 1100 1101 case 1: 1102 if (pending_event_ipi_fired == true) { 1103 report_fail("Interrupt triggered by guest"); 1104 return true; 1105 } 1106 1107 irq_enable(); 1108 asm volatile ("nop"); 1109 irq_disable(); 1110 1111 if (pending_event_ipi_fired != true) { 1112 report_fail("Interrupt not triggered by host"); 1113 return true; 1114 } 1115 1116 break; 1117 1118 default: 1119 return true; 1120 } 1121 1122 inc_test_stage(test); 1123 1124 return get_test_stage(test) == 2; 1125 } 1126 1127 static bool pending_event_cli_check(struct svm_test *test) 1128 { 1129 return get_test_stage(test) == 2; 1130 } 1131 1132 #define TIMER_VECTOR 222 1133 1134 static volatile bool timer_fired; 1135 1136 static void timer_isr(isr_regs_t *regs) 1137 { 1138 timer_fired = true; 1139 apic_write(APIC_EOI, 0); 1140 } 1141 1142 static void interrupt_prepare(struct svm_test *test) 1143 { 1144 default_prepare(test); 1145 handle_irq(TIMER_VECTOR, timer_isr); 1146 timer_fired = false; 1147 set_test_stage(test, 0); 1148 } 1149 1150 static void interrupt_test(struct svm_test *test) 1151 { 1152 long long start, loops; 1153 1154 apic_write(APIC_LVTT, TIMER_VECTOR); 1155 irq_enable(); 1156 apic_write(APIC_TMICT, 1); //Timer Initial Count Register 0x380 one-shot 1157 for (loops = 0; loops < 10000000 && !timer_fired; loops++) 1158 asm volatile ("nop"); 1159 1160 report(timer_fired, "direct interrupt while running guest"); 1161 1162 if (!timer_fired) { 1163 set_test_stage(test, -1); 1164 vmmcall(); 1165 } 1166 1167 apic_write(APIC_TMICT, 0); 1168 irq_disable(); 1169 vmmcall(); 1170 1171 timer_fired = false; 1172 apic_write(APIC_TMICT, 1); 1173 for (loops = 0; loops < 10000000 && !timer_fired; loops++) 1174 asm volatile ("nop"); 1175 1176 report(timer_fired, "intercepted interrupt while running guest"); 1177 1178 if (!timer_fired) { 1179 set_test_stage(test, -1); 1180 vmmcall(); 1181 } 1182 1183 irq_enable(); 1184 apic_write(APIC_TMICT, 0); 1185 irq_disable(); 1186 1187 timer_fired = false; 1188 start = rdtsc(); 1189 apic_write(APIC_TMICT, 1000000); 1190 safe_halt(); 1191 1192 report(rdtsc() - start > 10000 && timer_fired, 1193 "direct interrupt + hlt"); 1194 1195 if (!timer_fired) { 1196 set_test_stage(test, -1); 1197 vmmcall(); 1198 } 1199 1200 apic_write(APIC_TMICT, 0); 1201 irq_disable(); 1202 vmmcall(); 1203 1204 timer_fired = false; 1205 start = rdtsc(); 1206 apic_write(APIC_TMICT, 1000000); 1207 asm volatile ("hlt"); 1208 1209 report(rdtsc() - start > 10000 && timer_fired, 1210 "intercepted interrupt + hlt"); 1211 1212 if (!timer_fired) { 1213 set_test_stage(test, -1); 1214 vmmcall(); 1215 } 1216 1217 apic_write(APIC_TMICT, 0); 1218 irq_disable(); 1219 } 1220 1221 static bool interrupt_finished(struct svm_test *test) 1222 { 1223 switch (get_test_stage(test)) { 1224 case 0: 1225 case 2: 1226 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1227 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1228 vmcb->control.exit_code); 1229 return true; 1230 } 1231 vmcb->save.rip += 3; 1232 1233 vmcb->control.intercept |= (1ULL << INTERCEPT_INTR); 1234 vmcb->control.int_ctl |= V_INTR_MASKING_MASK; 1235 break; 1236 1237 case 1: 1238 case 3: 1239 if (vmcb->control.exit_code != SVM_EXIT_INTR) { 1240 report_fail("VMEXIT not due to intr intercept. Exit reason 0x%x", 1241 vmcb->control.exit_code); 1242 return true; 1243 } 1244 1245 irq_enable(); 1246 asm volatile ("nop"); 1247 irq_disable(); 1248 1249 vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR); 1250 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 1251 break; 1252 1253 case 4: 1254 break; 1255 1256 default: 1257 return true; 1258 } 1259 1260 inc_test_stage(test); 1261 1262 return get_test_stage(test) == 5; 1263 } 1264 1265 static bool interrupt_check(struct svm_test *test) 1266 { 1267 return get_test_stage(test) == 5; 1268 } 1269 1270 static volatile bool nmi_fired; 1271 1272 static void nmi_handler(struct ex_regs *regs) 1273 { 1274 nmi_fired = true; 1275 } 1276 1277 static void nmi_prepare(struct svm_test *test) 1278 { 1279 default_prepare(test); 1280 nmi_fired = false; 1281 handle_exception(NMI_VECTOR, nmi_handler); 1282 set_test_stage(test, 0); 1283 } 1284 1285 static void nmi_test(struct svm_test *test) 1286 { 1287 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0); 1288 1289 report(nmi_fired, "direct NMI while running guest"); 1290 1291 if (!nmi_fired) 1292 set_test_stage(test, -1); 1293 1294 vmmcall(); 1295 1296 nmi_fired = false; 1297 1298 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0); 1299 1300 if (!nmi_fired) { 1301 report(nmi_fired, "intercepted pending NMI not dispatched"); 1302 set_test_stage(test, -1); 1303 } 1304 1305 } 1306 1307 static bool nmi_finished(struct svm_test *test) 1308 { 1309 switch (get_test_stage(test)) { 1310 case 0: 1311 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1312 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1313 vmcb->control.exit_code); 1314 return true; 1315 } 1316 vmcb->save.rip += 3; 1317 1318 vmcb->control.intercept |= (1ULL << INTERCEPT_NMI); 1319 break; 1320 1321 case 1: 1322 if (vmcb->control.exit_code != SVM_EXIT_NMI) { 1323 report_fail("VMEXIT not due to NMI intercept. Exit reason 0x%x", 1324 vmcb->control.exit_code); 1325 return true; 1326 } 1327 1328 report_pass("NMI intercept while running guest"); 1329 break; 1330 1331 case 2: 1332 break; 1333 1334 default: 1335 return true; 1336 } 1337 1338 inc_test_stage(test); 1339 1340 return get_test_stage(test) == 3; 1341 } 1342 1343 static bool nmi_check(struct svm_test *test) 1344 { 1345 return get_test_stage(test) == 3; 1346 } 1347 1348 #define NMI_DELAY 100000000ULL 1349 1350 static void nmi_message_thread(void *_test) 1351 { 1352 struct svm_test *test = _test; 1353 1354 while (get_test_stage(test) != 1) 1355 pause(); 1356 1357 delay(NMI_DELAY); 1358 1359 apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); 1360 1361 while (get_test_stage(test) != 2) 1362 pause(); 1363 1364 delay(NMI_DELAY); 1365 1366 apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); 1367 } 1368 1369 static void nmi_hlt_test(struct svm_test *test) 1370 { 1371 long long start; 1372 1373 on_cpu_async(1, nmi_message_thread, test); 1374 1375 start = rdtsc(); 1376 1377 set_test_stage(test, 1); 1378 1379 asm volatile ("hlt"); 1380 1381 report((rdtsc() - start > NMI_DELAY) && nmi_fired, 1382 "direct NMI + hlt"); 1383 1384 if (!nmi_fired) 1385 set_test_stage(test, -1); 1386 1387 nmi_fired = false; 1388 1389 vmmcall(); 1390 1391 start = rdtsc(); 1392 1393 set_test_stage(test, 2); 1394 1395 asm volatile ("hlt"); 1396 1397 report((rdtsc() - start > NMI_DELAY) && nmi_fired, 1398 "intercepted NMI + hlt"); 1399 1400 if (!nmi_fired) { 1401 report(nmi_fired, "intercepted pending NMI not dispatched"); 1402 set_test_stage(test, -1); 1403 vmmcall(); 1404 } 1405 1406 set_test_stage(test, 3); 1407 } 1408 1409 static bool nmi_hlt_finished(struct svm_test *test) 1410 { 1411 switch (get_test_stage(test)) { 1412 case 1: 1413 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1414 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1415 vmcb->control.exit_code); 1416 return true; 1417 } 1418 vmcb->save.rip += 3; 1419 1420 vmcb->control.intercept |= (1ULL << INTERCEPT_NMI); 1421 break; 1422 1423 case 2: 1424 if (vmcb->control.exit_code != SVM_EXIT_NMI) { 1425 report_fail("VMEXIT not due to NMI intercept. Exit reason 0x%x", 1426 vmcb->control.exit_code); 1427 return true; 1428 } 1429 1430 report_pass("NMI intercept while running guest"); 1431 break; 1432 1433 case 3: 1434 break; 1435 1436 default: 1437 return true; 1438 } 1439 1440 return get_test_stage(test) == 3; 1441 } 1442 1443 static bool nmi_hlt_check(struct svm_test *test) 1444 { 1445 return get_test_stage(test) == 3; 1446 } 1447 1448 static volatile int count_exc = 0; 1449 1450 static void my_isr(struct ex_regs *r) 1451 { 1452 count_exc++; 1453 } 1454 1455 static void exc_inject_prepare(struct svm_test *test) 1456 { 1457 default_prepare(test); 1458 handle_exception(DE_VECTOR, my_isr); 1459 handle_exception(NMI_VECTOR, my_isr); 1460 } 1461 1462 1463 static void exc_inject_test(struct svm_test *test) 1464 { 1465 asm volatile ("vmmcall\n\tvmmcall\n\t"); 1466 } 1467 1468 static bool exc_inject_finished(struct svm_test *test) 1469 { 1470 switch (get_test_stage(test)) { 1471 case 0: 1472 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1473 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1474 vmcb->control.exit_code); 1475 return true; 1476 } 1477 vmcb->save.rip += 3; 1478 vmcb->control.event_inj = NMI_VECTOR | SVM_EVTINJ_TYPE_EXEPT | SVM_EVTINJ_VALID; 1479 break; 1480 1481 case 1: 1482 if (vmcb->control.exit_code != SVM_EXIT_ERR) { 1483 report_fail("VMEXIT not due to error. Exit reason 0x%x", 1484 vmcb->control.exit_code); 1485 return true; 1486 } 1487 report(count_exc == 0, "exception with vector 2 not injected"); 1488 vmcb->control.event_inj = DE_VECTOR | SVM_EVTINJ_TYPE_EXEPT | SVM_EVTINJ_VALID; 1489 break; 1490 1491 case 2: 1492 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1493 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1494 vmcb->control.exit_code); 1495 return true; 1496 } 1497 vmcb->save.rip += 3; 1498 report(count_exc == 1, "divide overflow exception injected"); 1499 report(!(vmcb->control.event_inj & SVM_EVTINJ_VALID), "eventinj.VALID cleared"); 1500 break; 1501 1502 default: 1503 return true; 1504 } 1505 1506 inc_test_stage(test); 1507 1508 return get_test_stage(test) == 3; 1509 } 1510 1511 static bool exc_inject_check(struct svm_test *test) 1512 { 1513 return count_exc == 1 && get_test_stage(test) == 3; 1514 } 1515 1516 static volatile bool virq_fired; 1517 1518 static void virq_isr(isr_regs_t *regs) 1519 { 1520 virq_fired = true; 1521 } 1522 1523 static void virq_inject_prepare(struct svm_test *test) 1524 { 1525 handle_irq(0xf1, virq_isr); 1526 default_prepare(test); 1527 vmcb->control.int_ctl = V_INTR_MASKING_MASK | V_IRQ_MASK | 1528 (0x0f << V_INTR_PRIO_SHIFT); // Set to the highest priority 1529 vmcb->control.int_vector = 0xf1; 1530 virq_fired = false; 1531 set_test_stage(test, 0); 1532 } 1533 1534 static void virq_inject_test(struct svm_test *test) 1535 { 1536 if (virq_fired) { 1537 report_fail("virtual interrupt fired before L2 sti"); 1538 set_test_stage(test, -1); 1539 vmmcall(); 1540 } 1541 1542 irq_enable(); 1543 asm volatile ("nop"); 1544 irq_disable(); 1545 1546 if (!virq_fired) { 1547 report_fail("virtual interrupt not fired after L2 sti"); 1548 set_test_stage(test, -1); 1549 } 1550 1551 vmmcall(); 1552 1553 if (virq_fired) { 1554 report_fail("virtual interrupt fired before L2 sti after VINTR intercept"); 1555 set_test_stage(test, -1); 1556 vmmcall(); 1557 } 1558 1559 irq_enable(); 1560 asm volatile ("nop"); 1561 irq_disable(); 1562 1563 if (!virq_fired) { 1564 report_fail("virtual interrupt not fired after return from VINTR intercept"); 1565 set_test_stage(test, -1); 1566 } 1567 1568 vmmcall(); 1569 1570 irq_enable(); 1571 asm volatile ("nop"); 1572 irq_disable(); 1573 1574 if (virq_fired) { 1575 report_fail("virtual interrupt fired when V_IRQ_PRIO less than V_TPR"); 1576 set_test_stage(test, -1); 1577 } 1578 1579 vmmcall(); 1580 vmmcall(); 1581 } 1582 1583 static bool virq_inject_finished(struct svm_test *test) 1584 { 1585 vmcb->save.rip += 3; 1586 1587 switch (get_test_stage(test)) { 1588 case 0: 1589 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1590 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1591 vmcb->control.exit_code); 1592 return true; 1593 } 1594 if (vmcb->control.int_ctl & V_IRQ_MASK) { 1595 report_fail("V_IRQ not cleared on VMEXIT after firing"); 1596 return true; 1597 } 1598 virq_fired = false; 1599 vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR); 1600 vmcb->control.int_ctl = V_INTR_MASKING_MASK | V_IRQ_MASK | 1601 (0x0f << V_INTR_PRIO_SHIFT); 1602 break; 1603 1604 case 1: 1605 if (vmcb->control.exit_code != SVM_EXIT_VINTR) { 1606 report_fail("VMEXIT not due to vintr. Exit reason 0x%x", 1607 vmcb->control.exit_code); 1608 return true; 1609 } 1610 if (virq_fired) { 1611 report_fail("V_IRQ fired before SVM_EXIT_VINTR"); 1612 return true; 1613 } 1614 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VINTR); 1615 break; 1616 1617 case 2: 1618 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1619 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1620 vmcb->control.exit_code); 1621 return true; 1622 } 1623 virq_fired = false; 1624 // Set irq to lower priority 1625 vmcb->control.int_ctl = V_INTR_MASKING_MASK | V_IRQ_MASK | 1626 (0x08 << V_INTR_PRIO_SHIFT); 1627 // Raise guest TPR 1628 vmcb->control.int_ctl |= 0x0a & V_TPR_MASK; 1629 break; 1630 1631 case 3: 1632 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1633 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1634 vmcb->control.exit_code); 1635 return true; 1636 } 1637 vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR); 1638 break; 1639 1640 case 4: 1641 // INTERCEPT_VINTR should be ignored because V_INTR_PRIO < V_TPR 1642 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1643 report_fail("VMEXIT not due to vmmcall. Exit reason 0x%x", 1644 vmcb->control.exit_code); 1645 return true; 1646 } 1647 break; 1648 1649 default: 1650 return true; 1651 } 1652 1653 inc_test_stage(test); 1654 1655 return get_test_stage(test) == 5; 1656 } 1657 1658 static bool virq_inject_check(struct svm_test *test) 1659 { 1660 return get_test_stage(test) == 5; 1661 } 1662 1663 /* 1664 * Detect nested guest RIP corruption as explained in kernel commit 1665 * b6162e82aef19fee9c32cb3fe9ac30d9116a8c73 1666 * 1667 * In the assembly loop below 'ins' is executed while IO instructions 1668 * are not intercepted; the instruction is emulated by L0. 1669 * 1670 * At the same time we are getting interrupts from the local APIC timer, 1671 * and we do intercept them in L1 1672 * 1673 * If the interrupt happens on the insb instruction, L0 will VMexit, emulate 1674 * the insb instruction and then it will inject the interrupt to L1 through 1675 * a nested VMexit. Due to a bug, it would leave pre-emulation values of RIP, 1676 * RAX and RSP in the VMCB. 1677 * 1678 * In our intercept handler we detect the bug by checking that RIP is that of 1679 * the insb instruction, but its memory operand has already been written. 1680 * This means that insb was already executed. 1681 */ 1682 1683 static volatile int isr_cnt = 0; 1684 static volatile uint8_t io_port_var = 0xAA; 1685 extern const char insb_instruction_label[]; 1686 1687 static void reg_corruption_isr(isr_regs_t *regs) 1688 { 1689 isr_cnt++; 1690 apic_write(APIC_EOI, 0); 1691 } 1692 1693 static void reg_corruption_prepare(struct svm_test *test) 1694 { 1695 default_prepare(test); 1696 set_test_stage(test, 0); 1697 1698 vmcb->control.int_ctl = V_INTR_MASKING_MASK; 1699 vmcb->control.intercept |= (1ULL << INTERCEPT_INTR); 1700 1701 handle_irq(TIMER_VECTOR, reg_corruption_isr); 1702 1703 /* set local APIC to inject external interrupts */ 1704 apic_write(APIC_TMICT, 0); 1705 apic_write(APIC_TDCR, 0); 1706 apic_write(APIC_LVTT, TIMER_VECTOR | APIC_LVT_TIMER_PERIODIC); 1707 apic_write(APIC_TMICT, 1000); 1708 } 1709 1710 static void reg_corruption_test(struct svm_test *test) 1711 { 1712 /* this is endless loop, which is interrupted by the timer interrupt */ 1713 asm volatile ( 1714 "1:\n\t" 1715 "movw $0x4d0, %%dx\n\t" // IO port 1716 "lea %[io_port_var], %%rdi\n\t" 1717 "movb $0xAA, %[io_port_var]\n\t" 1718 "insb_instruction_label:\n\t" 1719 "insb\n\t" 1720 "jmp 1b\n\t" 1721 1722 : [io_port_var] "=m" (io_port_var) 1723 : /* no inputs*/ 1724 : "rdx", "rdi" 1725 ); 1726 } 1727 1728 static bool reg_corruption_finished(struct svm_test *test) 1729 { 1730 if (isr_cnt == 10000) { 1731 report_pass("No RIP corruption detected after %d timer interrupts", 1732 isr_cnt); 1733 set_test_stage(test, 1); 1734 goto cleanup; 1735 } 1736 1737 if (vmcb->control.exit_code == SVM_EXIT_INTR) { 1738 1739 void* guest_rip = (void*)vmcb->save.rip; 1740 1741 irq_enable(); 1742 asm volatile ("nop"); 1743 irq_disable(); 1744 1745 if (guest_rip == insb_instruction_label && io_port_var != 0xAA) { 1746 report_fail("RIP corruption detected after %d timer interrupts", 1747 isr_cnt); 1748 goto cleanup; 1749 } 1750 1751 } 1752 return false; 1753 cleanup: 1754 apic_write(APIC_LVTT, APIC_LVT_TIMER_MASK); 1755 apic_write(APIC_TMICT, 0); 1756 return true; 1757 1758 } 1759 1760 static bool reg_corruption_check(struct svm_test *test) 1761 { 1762 return get_test_stage(test) == 1; 1763 } 1764 1765 static void get_tss_entry(void *data) 1766 { 1767 *((gdt_entry_t **)data) = get_tss_descr(); 1768 } 1769 1770 static int orig_cpu_count; 1771 1772 static void init_startup_prepare(struct svm_test *test) 1773 { 1774 gdt_entry_t *tss_entry; 1775 int i; 1776 1777 on_cpu(1, get_tss_entry, &tss_entry); 1778 1779 orig_cpu_count = atomic_read(&cpu_online_count); 1780 1781 apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT, 1782 id_map[1]); 1783 1784 delay(100000000ULL); 1785 1786 atomic_dec(&cpu_online_count); 1787 1788 tss_entry->type &= ~DESC_BUSY; 1789 1790 apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_STARTUP, id_map[1]); 1791 1792 for (i = 0; i < 5 && atomic_read(&cpu_online_count) < orig_cpu_count; i++) 1793 delay(100000000ULL); 1794 } 1795 1796 static bool init_startup_finished(struct svm_test *test) 1797 { 1798 return true; 1799 } 1800 1801 static bool init_startup_check(struct svm_test *test) 1802 { 1803 return atomic_read(&cpu_online_count) == orig_cpu_count; 1804 } 1805 1806 static volatile bool init_intercept; 1807 1808 static void init_intercept_prepare(struct svm_test *test) 1809 { 1810 init_intercept = false; 1811 vmcb->control.intercept |= (1ULL << INTERCEPT_INIT); 1812 } 1813 1814 static void init_intercept_test(struct svm_test *test) 1815 { 1816 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT, 0); 1817 } 1818 1819 static bool init_intercept_finished(struct svm_test *test) 1820 { 1821 vmcb->save.rip += 3; 1822 1823 if (vmcb->control.exit_code != SVM_EXIT_INIT) { 1824 report_fail("VMEXIT not due to init intercept. Exit reason 0x%x", 1825 vmcb->control.exit_code); 1826 1827 return true; 1828 } 1829 1830 init_intercept = true; 1831 1832 report_pass("INIT to vcpu intercepted"); 1833 1834 return true; 1835 } 1836 1837 static bool init_intercept_check(struct svm_test *test) 1838 { 1839 return init_intercept; 1840 } 1841 1842 /* 1843 * Setting host EFLAGS.TF causes a #DB trap after the VMRUN completes on the 1844 * host side (i.e., after the #VMEXIT from the guest). 1845 * 1846 * Setting host EFLAGS.RF suppresses any potential instruction breakpoint 1847 * match on the VMRUN and completion of the VMRUN instruction clears the 1848 * host EFLAGS.RF bit. 1849 * 1850 * [AMD APM] 1851 */ 1852 static volatile u8 host_rflags_guest_main_flag = 0; 1853 static volatile u8 host_rflags_db_handler_flag = 0; 1854 static volatile bool host_rflags_ss_on_vmrun = false; 1855 static volatile bool host_rflags_vmrun_reached = false; 1856 static volatile bool host_rflags_set_tf = false; 1857 static volatile bool host_rflags_set_rf = false; 1858 static u64 rip_detected; 1859 1860 extern u64 *vmrun_rip; 1861 1862 static void host_rflags_db_handler(struct ex_regs *r) 1863 { 1864 if (host_rflags_ss_on_vmrun) { 1865 if (host_rflags_vmrun_reached) { 1866 if (!host_rflags_set_rf) { 1867 r->rflags &= ~X86_EFLAGS_TF; 1868 rip_detected = r->rip; 1869 } else { 1870 r->rflags |= X86_EFLAGS_RF; 1871 ++host_rflags_db_handler_flag; 1872 } 1873 } else { 1874 if (r->rip == (u64)&vmrun_rip) { 1875 host_rflags_vmrun_reached = true; 1876 1877 if (host_rflags_set_rf) { 1878 host_rflags_guest_main_flag = 0; 1879 rip_detected = r->rip; 1880 r->rflags &= ~X86_EFLAGS_TF; 1881 1882 /* Trigger #DB via debug registers */ 1883 write_dr0((void *)&vmrun_rip); 1884 write_dr7(0x403); 1885 } 1886 } 1887 } 1888 } else { 1889 r->rflags &= ~X86_EFLAGS_TF; 1890 } 1891 } 1892 1893 static void host_rflags_prepare(struct svm_test *test) 1894 { 1895 default_prepare(test); 1896 handle_exception(DB_VECTOR, host_rflags_db_handler); 1897 set_test_stage(test, 0); 1898 } 1899 1900 static void host_rflags_prepare_gif_clear(struct svm_test *test) 1901 { 1902 if (host_rflags_set_tf) 1903 write_rflags(read_rflags() | X86_EFLAGS_TF); 1904 } 1905 1906 static void host_rflags_test(struct svm_test *test) 1907 { 1908 while (1) { 1909 if (get_test_stage(test) > 0) { 1910 if ((host_rflags_set_tf && !host_rflags_ss_on_vmrun && !host_rflags_db_handler_flag) || 1911 (host_rflags_set_rf && host_rflags_db_handler_flag == 1)) 1912 host_rflags_guest_main_flag = 1; 1913 } 1914 1915 if (get_test_stage(test) == 4) 1916 break; 1917 vmmcall(); 1918 } 1919 } 1920 1921 static bool host_rflags_finished(struct svm_test *test) 1922 { 1923 switch (get_test_stage(test)) { 1924 case 0: 1925 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 1926 report_fail("Unexpected VMEXIT. Exit reason 0x%x", 1927 vmcb->control.exit_code); 1928 return true; 1929 } 1930 vmcb->save.rip += 3; 1931 /* 1932 * Setting host EFLAGS.TF not immediately before VMRUN, causes 1933 * #DB trap before first guest instruction is executed 1934 */ 1935 host_rflags_set_tf = true; 1936 break; 1937 case 1: 1938 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL || 1939 host_rflags_guest_main_flag != 1) { 1940 report_fail("Unexpected VMEXIT or #DB handler" 1941 " invoked before guest main. Exit reason 0x%x", 1942 vmcb->control.exit_code); 1943 return true; 1944 } 1945 vmcb->save.rip += 3; 1946 /* 1947 * Setting host EFLAGS.TF immediately before VMRUN, causes #DB 1948 * trap after VMRUN completes on the host side (i.e., after 1949 * VMEXIT from guest). 1950 */ 1951 host_rflags_ss_on_vmrun = true; 1952 break; 1953 case 2: 1954 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL || 1955 rip_detected != (u64)&vmrun_rip + 3) { 1956 report_fail("Unexpected VMEXIT or RIP mismatch." 1957 " Exit reason 0x%x, RIP actual: %lx, RIP expected: " 1958 "%lx", vmcb->control.exit_code, 1959 (u64)&vmrun_rip + 3, rip_detected); 1960 return true; 1961 } 1962 host_rflags_set_rf = true; 1963 host_rflags_guest_main_flag = 0; 1964 host_rflags_vmrun_reached = false; 1965 vmcb->save.rip += 3; 1966 break; 1967 case 3: 1968 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL || 1969 rip_detected != (u64)&vmrun_rip || 1970 host_rflags_guest_main_flag != 1 || 1971 host_rflags_db_handler_flag > 1 || 1972 read_rflags() & X86_EFLAGS_RF) { 1973 report_fail("Unexpected VMEXIT or RIP mismatch or " 1974 "EFLAGS.RF not cleared." 1975 " Exit reason 0x%x, RIP actual: %lx, RIP expected: " 1976 "%lx", vmcb->control.exit_code, 1977 (u64)&vmrun_rip, rip_detected); 1978 return true; 1979 } 1980 host_rflags_set_tf = false; 1981 host_rflags_set_rf = false; 1982 vmcb->save.rip += 3; 1983 break; 1984 default: 1985 return true; 1986 } 1987 inc_test_stage(test); 1988 return get_test_stage(test) == 5; 1989 } 1990 1991 static bool host_rflags_check(struct svm_test *test) 1992 { 1993 return get_test_stage(test) == 4; 1994 } 1995 1996 #define TEST(name) { #name, .v2 = name } 1997 1998 /* 1999 * v2 tests 2000 */ 2001 2002 /* 2003 * Ensure that kvm recalculates the L1 guest's CPUID.01H:ECX.OSXSAVE 2004 * after VM-exit from an L2 guest that sets CR4.OSXSAVE to a different 2005 * value than in L1. 2006 */ 2007 2008 static void svm_cr4_osxsave_test_guest(struct svm_test *test) 2009 { 2010 write_cr4(read_cr4() & ~X86_CR4_OSXSAVE); 2011 } 2012 2013 static void svm_cr4_osxsave_test(void) 2014 { 2015 if (!this_cpu_has(X86_FEATURE_XSAVE)) { 2016 report_skip("XSAVE not detected"); 2017 return; 2018 } 2019 2020 if (!(read_cr4() & X86_CR4_OSXSAVE)) { 2021 unsigned long cr4 = read_cr4() | X86_CR4_OSXSAVE; 2022 2023 write_cr4(cr4); 2024 vmcb->save.cr4 = cr4; 2025 } 2026 2027 report(cpuid_osxsave(), "CPUID.01H:ECX.XSAVE set before VMRUN"); 2028 2029 test_set_guest(svm_cr4_osxsave_test_guest); 2030 report(svm_vmrun() == SVM_EXIT_VMMCALL, 2031 "svm_cr4_osxsave_test_guest finished with VMMCALL"); 2032 2033 report(cpuid_osxsave(), "CPUID.01H:ECX.XSAVE set after VMRUN"); 2034 } 2035 2036 static void basic_guest_main(struct svm_test *test) 2037 { 2038 } 2039 2040 2041 #define SVM_TEST_REG_RESERVED_BITS(start, end, inc, str_name, reg, val, \ 2042 resv_mask) \ 2043 { \ 2044 u64 tmp, mask; \ 2045 int i; \ 2046 \ 2047 for (i = start; i <= end; i = i + inc) { \ 2048 mask = 1ull << i; \ 2049 if (!(mask & resv_mask)) \ 2050 continue; \ 2051 tmp = val | mask; \ 2052 reg = tmp; \ 2053 report(svm_vmrun() == SVM_EXIT_ERR, "Test %s %d:%d: %lx", \ 2054 str_name, end, start, tmp); \ 2055 } \ 2056 } 2057 2058 #define SVM_TEST_CR_RESERVED_BITS(start, end, inc, cr, val, resv_mask, \ 2059 exit_code, test_name) \ 2060 { \ 2061 u64 tmp, mask; \ 2062 u32 r; \ 2063 int i; \ 2064 \ 2065 for (i = start; i <= end; i = i + inc) { \ 2066 mask = 1ull << i; \ 2067 if (!(mask & resv_mask)) \ 2068 continue; \ 2069 tmp = val | mask; \ 2070 switch (cr) { \ 2071 case 0: \ 2072 vmcb->save.cr0 = tmp; \ 2073 break; \ 2074 case 3: \ 2075 vmcb->save.cr3 = tmp; \ 2076 break; \ 2077 case 4: \ 2078 vmcb->save.cr4 = tmp; \ 2079 } \ 2080 r = svm_vmrun(); \ 2081 report(r == exit_code, "Test CR%d %s%d:%d: %lx, wanted exit 0x%x, got 0x%x", \ 2082 cr, test_name, end, start, tmp, exit_code, r); \ 2083 } \ 2084 } 2085 2086 static void test_efer(void) 2087 { 2088 /* 2089 * Un-setting EFER.SVME is illegal 2090 */ 2091 u64 efer_saved = vmcb->save.efer; 2092 u64 efer = efer_saved; 2093 2094 report (svm_vmrun() == SVM_EXIT_VMMCALL, "EFER.SVME: %lx", efer); 2095 efer &= ~EFER_SVME; 2096 vmcb->save.efer = efer; 2097 report (svm_vmrun() == SVM_EXIT_ERR, "EFER.SVME: %lx", efer); 2098 vmcb->save.efer = efer_saved; 2099 2100 /* 2101 * EFER MBZ bits: 63:16, 9 2102 */ 2103 efer_saved = vmcb->save.efer; 2104 2105 SVM_TEST_REG_RESERVED_BITS(8, 9, 1, "EFER", vmcb->save.efer, 2106 efer_saved, SVM_EFER_RESERVED_MASK); 2107 SVM_TEST_REG_RESERVED_BITS(16, 63, 4, "EFER", vmcb->save.efer, 2108 efer_saved, SVM_EFER_RESERVED_MASK); 2109 2110 /* 2111 * EFER.LME and CR0.PG are both set and CR4.PAE is zero. 2112 */ 2113 u64 cr0_saved = vmcb->save.cr0; 2114 u64 cr0; 2115 u64 cr4_saved = vmcb->save.cr4; 2116 u64 cr4; 2117 2118 efer = efer_saved | EFER_LME; 2119 vmcb->save.efer = efer; 2120 cr0 = cr0_saved | X86_CR0_PG | X86_CR0_PE; 2121 vmcb->save.cr0 = cr0; 2122 cr4 = cr4_saved & ~X86_CR4_PAE; 2123 vmcb->save.cr4 = cr4; 2124 report(svm_vmrun() == SVM_EXIT_ERR, "EFER.LME=1 (%lx), " 2125 "CR0.PG=1 (%lx) and CR4.PAE=0 (%lx)", efer, cr0, cr4); 2126 2127 /* 2128 * EFER.LME and CR0.PG are both set and CR0.PE is zero. 2129 * CR4.PAE needs to be set as we otherwise cannot 2130 * determine if CR4.PAE=0 or CR0.PE=0 triggered the 2131 * SVM_EXIT_ERR. 2132 */ 2133 cr4 = cr4_saved | X86_CR4_PAE; 2134 vmcb->save.cr4 = cr4; 2135 cr0 &= ~X86_CR0_PE; 2136 vmcb->save.cr0 = cr0; 2137 report(svm_vmrun() == SVM_EXIT_ERR, "EFER.LME=1 (%lx), " 2138 "CR0.PG=1 and CR0.PE=0 (%lx)", efer, cr0); 2139 2140 /* 2141 * EFER.LME, CR0.PG, CR4.PAE, CS.L, and CS.D are all non-zero. 2142 */ 2143 u32 cs_attrib_saved = vmcb->save.cs.attrib; 2144 u32 cs_attrib; 2145 2146 cr0 |= X86_CR0_PE; 2147 vmcb->save.cr0 = cr0; 2148 cs_attrib = cs_attrib_saved | SVM_SELECTOR_L_MASK | 2149 SVM_SELECTOR_DB_MASK; 2150 vmcb->save.cs.attrib = cs_attrib; 2151 report(svm_vmrun() == SVM_EXIT_ERR, "EFER.LME=1 (%lx), " 2152 "CR0.PG=1 (%lx), CR4.PAE=1 (%lx), CS.L=1 and CS.D=1 (%x)", 2153 efer, cr0, cr4, cs_attrib); 2154 2155 vmcb->save.cr0 = cr0_saved; 2156 vmcb->save.cr4 = cr4_saved; 2157 vmcb->save.efer = efer_saved; 2158 vmcb->save.cs.attrib = cs_attrib_saved; 2159 } 2160 2161 static void test_cr0(void) 2162 { 2163 /* 2164 * Un-setting CR0.CD and setting CR0.NW is illegal combination 2165 */ 2166 u64 cr0_saved = vmcb->save.cr0; 2167 u64 cr0 = cr0_saved; 2168 2169 cr0 |= X86_CR0_CD; 2170 cr0 &= ~X86_CR0_NW; 2171 vmcb->save.cr0 = cr0; 2172 report (svm_vmrun() == SVM_EXIT_VMMCALL, "Test CR0 CD=1,NW=0: %lx", 2173 cr0); 2174 cr0 |= X86_CR0_NW; 2175 vmcb->save.cr0 = cr0; 2176 report (svm_vmrun() == SVM_EXIT_VMMCALL, "Test CR0 CD=1,NW=1: %lx", 2177 cr0); 2178 cr0 &= ~X86_CR0_NW; 2179 cr0 &= ~X86_CR0_CD; 2180 vmcb->save.cr0 = cr0; 2181 report (svm_vmrun() == SVM_EXIT_VMMCALL, "Test CR0 CD=0,NW=0: %lx", 2182 cr0); 2183 cr0 |= X86_CR0_NW; 2184 vmcb->save.cr0 = cr0; 2185 report (svm_vmrun() == SVM_EXIT_ERR, "Test CR0 CD=0,NW=1: %lx", 2186 cr0); 2187 vmcb->save.cr0 = cr0_saved; 2188 2189 /* 2190 * CR0[63:32] are not zero 2191 */ 2192 cr0 = cr0_saved; 2193 2194 SVM_TEST_REG_RESERVED_BITS(32, 63, 4, "CR0", vmcb->save.cr0, cr0_saved, 2195 SVM_CR0_RESERVED_MASK); 2196 vmcb->save.cr0 = cr0_saved; 2197 } 2198 2199 static void test_cr3(void) 2200 { 2201 /* 2202 * CR3 MBZ bits based on different modes: 2203 * [63:52] - long mode 2204 */ 2205 u64 cr3_saved = vmcb->save.cr3; 2206 2207 SVM_TEST_CR_RESERVED_BITS(0, 63, 1, 3, cr3_saved, 2208 SVM_CR3_LONG_MBZ_MASK, SVM_EXIT_ERR, ""); 2209 2210 vmcb->save.cr3 = cr3_saved & ~SVM_CR3_LONG_MBZ_MASK; 2211 report(svm_vmrun() == SVM_EXIT_VMMCALL, "Test CR3 63:0: %lx", 2212 vmcb->save.cr3); 2213 2214 /* 2215 * CR3 non-MBZ reserved bits based on different modes: 2216 * [11:5] [2:0] - long mode (PCIDE=0) 2217 * [2:0] - PAE legacy mode 2218 */ 2219 u64 cr4_saved = vmcb->save.cr4; 2220 u64 *pdpe = npt_get_pml4e(); 2221 2222 /* 2223 * Long mode 2224 */ 2225 if (this_cpu_has(X86_FEATURE_PCID)) { 2226 vmcb->save.cr4 = cr4_saved | X86_CR4_PCIDE; 2227 SVM_TEST_CR_RESERVED_BITS(0, 11, 1, 3, cr3_saved, 2228 SVM_CR3_LONG_RESERVED_MASK, SVM_EXIT_VMMCALL, "(PCIDE=1) "); 2229 2230 vmcb->save.cr3 = cr3_saved & ~SVM_CR3_LONG_RESERVED_MASK; 2231 report(svm_vmrun() == SVM_EXIT_VMMCALL, "Test CR3 63:0: %lx", 2232 vmcb->save.cr3); 2233 } 2234 2235 vmcb->save.cr4 = cr4_saved & ~X86_CR4_PCIDE; 2236 2237 if (!npt_supported()) 2238 goto skip_npt_only; 2239 2240 /* Clear P (Present) bit in NPT in order to trigger #NPF */ 2241 pdpe[0] &= ~1ULL; 2242 2243 SVM_TEST_CR_RESERVED_BITS(0, 11, 1, 3, cr3_saved, 2244 SVM_CR3_LONG_RESERVED_MASK, SVM_EXIT_NPF, "(PCIDE=0) "); 2245 2246 pdpe[0] |= 1ULL; 2247 vmcb->save.cr3 = cr3_saved; 2248 2249 /* 2250 * PAE legacy 2251 */ 2252 pdpe[0] &= ~1ULL; 2253 vmcb->save.cr4 = cr4_saved | X86_CR4_PAE; 2254 SVM_TEST_CR_RESERVED_BITS(0, 2, 1, 3, cr3_saved, 2255 SVM_CR3_PAE_LEGACY_RESERVED_MASK, SVM_EXIT_NPF, "(PAE) "); 2256 2257 pdpe[0] |= 1ULL; 2258 2259 skip_npt_only: 2260 vmcb->save.cr3 = cr3_saved; 2261 vmcb->save.cr4 = cr4_saved; 2262 } 2263 2264 /* Test CR4 MBZ bits based on legacy or long modes */ 2265 static void test_cr4(void) 2266 { 2267 u64 cr4_saved = vmcb->save.cr4; 2268 u64 efer_saved = vmcb->save.efer; 2269 u64 efer = efer_saved; 2270 2271 efer &= ~EFER_LME; 2272 vmcb->save.efer = efer; 2273 SVM_TEST_CR_RESERVED_BITS(12, 31, 1, 4, cr4_saved, 2274 SVM_CR4_LEGACY_RESERVED_MASK, SVM_EXIT_ERR, ""); 2275 2276 efer |= EFER_LME; 2277 vmcb->save.efer = efer; 2278 SVM_TEST_CR_RESERVED_BITS(12, 31, 1, 4, cr4_saved, 2279 SVM_CR4_RESERVED_MASK, SVM_EXIT_ERR, ""); 2280 SVM_TEST_CR_RESERVED_BITS(32, 63, 4, 4, cr4_saved, 2281 SVM_CR4_RESERVED_MASK, SVM_EXIT_ERR, ""); 2282 2283 vmcb->save.cr4 = cr4_saved; 2284 vmcb->save.efer = efer_saved; 2285 } 2286 2287 static void test_dr(void) 2288 { 2289 /* 2290 * DR6[63:32] and DR7[63:32] are MBZ 2291 */ 2292 u64 dr_saved = vmcb->save.dr6; 2293 2294 SVM_TEST_REG_RESERVED_BITS(32, 63, 4, "DR6", vmcb->save.dr6, dr_saved, 2295 SVM_DR6_RESERVED_MASK); 2296 vmcb->save.dr6 = dr_saved; 2297 2298 dr_saved = vmcb->save.dr7; 2299 SVM_TEST_REG_RESERVED_BITS(32, 63, 4, "DR7", vmcb->save.dr7, dr_saved, 2300 SVM_DR7_RESERVED_MASK); 2301 2302 vmcb->save.dr7 = dr_saved; 2303 } 2304 2305 /* TODO: verify if high 32-bits are sign- or zero-extended on bare metal */ 2306 #define TEST_BITMAP_ADDR(save_intercept, type, addr, exit_code, \ 2307 msg) { \ 2308 vmcb->control.intercept = saved_intercept | 1ULL << type; \ 2309 if (type == INTERCEPT_MSR_PROT) \ 2310 vmcb->control.msrpm_base_pa = addr; \ 2311 else \ 2312 vmcb->control.iopm_base_pa = addr; \ 2313 report(svm_vmrun() == exit_code, \ 2314 "Test %s address: %lx", msg, addr); \ 2315 } 2316 2317 /* 2318 * If the MSR or IOIO intercept table extends to a physical address that 2319 * is greater than or equal to the maximum supported physical address, the 2320 * guest state is illegal. 2321 * 2322 * The VMRUN instruction ignores the lower 12 bits of the address specified 2323 * in the VMCB. 2324 * 2325 * MSRPM spans 2 contiguous 4KB pages while IOPM spans 2 contiguous 4KB 2326 * pages + 1 byte. 2327 * 2328 * [APM vol 2] 2329 * 2330 * Note: Unallocated MSRPM addresses conforming to consistency checks, generate 2331 * #NPF. 2332 */ 2333 static void test_msrpm_iopm_bitmap_addrs(void) 2334 { 2335 u64 saved_intercept = vmcb->control.intercept; 2336 u64 addr_beyond_limit = 1ull << cpuid_maxphyaddr(); 2337 u64 addr = virt_to_phys(msr_bitmap) & (~((1ull << 12) - 1)); 2338 2339 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_MSR_PROT, 2340 addr_beyond_limit - 2 * PAGE_SIZE, SVM_EXIT_ERR, 2341 "MSRPM"); 2342 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_MSR_PROT, 2343 addr_beyond_limit - 2 * PAGE_SIZE + 1, SVM_EXIT_ERR, 2344 "MSRPM"); 2345 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_MSR_PROT, 2346 addr_beyond_limit - PAGE_SIZE, SVM_EXIT_ERR, 2347 "MSRPM"); 2348 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_MSR_PROT, addr, 2349 SVM_EXIT_VMMCALL, "MSRPM"); 2350 addr |= (1ull << 12) - 1; 2351 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_MSR_PROT, addr, 2352 SVM_EXIT_VMMCALL, "MSRPM"); 2353 2354 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, 2355 addr_beyond_limit - 4 * PAGE_SIZE, SVM_EXIT_VMMCALL, 2356 "IOPM"); 2357 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, 2358 addr_beyond_limit - 3 * PAGE_SIZE, SVM_EXIT_VMMCALL, 2359 "IOPM"); 2360 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, 2361 addr_beyond_limit - 2 * PAGE_SIZE - 2, SVM_EXIT_VMMCALL, 2362 "IOPM"); 2363 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, 2364 addr_beyond_limit - 2 * PAGE_SIZE, SVM_EXIT_ERR, 2365 "IOPM"); 2366 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, 2367 addr_beyond_limit - PAGE_SIZE, SVM_EXIT_ERR, 2368 "IOPM"); 2369 addr = virt_to_phys(io_bitmap) & (~((1ull << 11) - 1)); 2370 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, addr, 2371 SVM_EXIT_VMMCALL, "IOPM"); 2372 addr |= (1ull << 12) - 1; 2373 TEST_BITMAP_ADDR(saved_intercept, INTERCEPT_IOIO_PROT, addr, 2374 SVM_EXIT_VMMCALL, "IOPM"); 2375 2376 vmcb->control.intercept = saved_intercept; 2377 } 2378 2379 /* 2380 * Unlike VMSAVE, VMRUN seems not to update the value of noncanonical 2381 * segment bases in the VMCB. However, VMENTRY succeeds as documented. 2382 */ 2383 #define TEST_CANONICAL_VMRUN(seg_base, msg) \ 2384 saved_addr = seg_base; \ 2385 seg_base = (seg_base & ((1ul << addr_limit) - 1)) | noncanonical_mask; \ 2386 return_value = svm_vmrun(); \ 2387 report(return_value == SVM_EXIT_VMMCALL, \ 2388 "Successful VMRUN with noncanonical %s.base", msg); \ 2389 seg_base = saved_addr; 2390 2391 2392 #define TEST_CANONICAL_VMLOAD(seg_base, msg) \ 2393 saved_addr = seg_base; \ 2394 seg_base = (seg_base & ((1ul << addr_limit) - 1)) | noncanonical_mask; \ 2395 asm volatile ("vmload %0" : : "a"(vmcb_phys) : "memory"); \ 2396 asm volatile ("vmsave %0" : : "a"(vmcb_phys) : "memory"); \ 2397 report(is_canonical(seg_base), \ 2398 "Test %s.base for canonical form: %lx", msg, seg_base); \ 2399 seg_base = saved_addr; 2400 2401 static void test_canonicalization(void) 2402 { 2403 u64 saved_addr; 2404 u64 return_value; 2405 u64 addr_limit; 2406 u64 vmcb_phys = virt_to_phys(vmcb); 2407 2408 addr_limit = (this_cpu_has(X86_FEATURE_LA57)) ? 57 : 48; 2409 u64 noncanonical_mask = NONCANONICAL & ~((1ul << addr_limit) - 1); 2410 2411 TEST_CANONICAL_VMLOAD(vmcb->save.fs.base, "FS"); 2412 TEST_CANONICAL_VMLOAD(vmcb->save.gs.base, "GS"); 2413 TEST_CANONICAL_VMLOAD(vmcb->save.ldtr.base, "LDTR"); 2414 TEST_CANONICAL_VMLOAD(vmcb->save.tr.base, "TR"); 2415 TEST_CANONICAL_VMLOAD(vmcb->save.kernel_gs_base, "KERNEL GS"); 2416 TEST_CANONICAL_VMRUN(vmcb->save.es.base, "ES"); 2417 TEST_CANONICAL_VMRUN(vmcb->save.cs.base, "CS"); 2418 TEST_CANONICAL_VMRUN(vmcb->save.ss.base, "SS"); 2419 TEST_CANONICAL_VMRUN(vmcb->save.ds.base, "DS"); 2420 TEST_CANONICAL_VMRUN(vmcb->save.gdtr.base, "GDTR"); 2421 TEST_CANONICAL_VMRUN(vmcb->save.idtr.base, "IDTR"); 2422 } 2423 2424 /* 2425 * When VMRUN loads a guest value of 1 in EFLAGS.TF, that value does not 2426 * cause a trace trap between the VMRUN and the first guest instruction, but 2427 * rather after completion of the first guest instruction. 2428 * 2429 * [APM vol 2] 2430 */ 2431 u64 guest_rflags_test_trap_rip; 2432 2433 static void guest_rflags_test_db_handler(struct ex_regs *r) 2434 { 2435 guest_rflags_test_trap_rip = r->rip; 2436 r->rflags &= ~X86_EFLAGS_TF; 2437 } 2438 2439 static void svm_guest_state_test(void) 2440 { 2441 test_set_guest(basic_guest_main); 2442 test_efer(); 2443 test_cr0(); 2444 test_cr3(); 2445 test_cr4(); 2446 test_dr(); 2447 test_msrpm_iopm_bitmap_addrs(); 2448 test_canonicalization(); 2449 } 2450 2451 extern void guest_rflags_test_guest(struct svm_test *test); 2452 extern u64 *insn2; 2453 extern u64 *guest_end; 2454 2455 asm("guest_rflags_test_guest:\n\t" 2456 "push %rbp\n\t" 2457 ".global insn2\n\t" 2458 "insn2:\n\t" 2459 "mov %rsp,%rbp\n\t" 2460 "vmmcall\n\t" 2461 "vmmcall\n\t" 2462 ".global guest_end\n\t" 2463 "guest_end:\n\t" 2464 "vmmcall\n\t" 2465 "pop %rbp\n\t" 2466 "ret"); 2467 2468 static void svm_test_singlestep(void) 2469 { 2470 handle_exception(DB_VECTOR, guest_rflags_test_db_handler); 2471 2472 /* 2473 * Trap expected after completion of first guest instruction 2474 */ 2475 vmcb->save.rflags |= X86_EFLAGS_TF; 2476 report (__svm_vmrun((u64)guest_rflags_test_guest) == SVM_EXIT_VMMCALL && 2477 guest_rflags_test_trap_rip == (u64)&insn2, 2478 "Test EFLAGS.TF on VMRUN: trap expected after completion of first guest instruction"); 2479 /* 2480 * No trap expected 2481 */ 2482 guest_rflags_test_trap_rip = 0; 2483 vmcb->save.rip += 3; 2484 vmcb->save.rflags |= X86_EFLAGS_TF; 2485 report (__svm_vmrun(vmcb->save.rip) == SVM_EXIT_VMMCALL && 2486 guest_rflags_test_trap_rip == 0, "Test EFLAGS.TF on VMRUN: trap not expected"); 2487 2488 /* 2489 * Let guest finish execution 2490 */ 2491 vmcb->save.rip += 3; 2492 report (__svm_vmrun(vmcb->save.rip) == SVM_EXIT_VMMCALL && 2493 vmcb->save.rip == (u64)&guest_end, "Test EFLAGS.TF on VMRUN: guest execution completion"); 2494 } 2495 2496 static bool volatile svm_errata_reproduced = false; 2497 static unsigned long volatile physical = 0; 2498 2499 2500 /* 2501 * 2502 * Test the following errata: 2503 * If the VMRUN/VMSAVE/VMLOAD are attempted by the nested guest, 2504 * the CPU would first check the EAX against host reserved memory 2505 * regions (so far only SMM_ADDR/SMM_MASK are known to cause it), 2506 * and only then signal #VMexit 2507 * 2508 * Try to reproduce this by trying vmsave on each possible 4K aligned memory 2509 * address in the low 4G where the SMM area has to reside. 2510 */ 2511 2512 static void gp_isr(struct ex_regs *r) 2513 { 2514 svm_errata_reproduced = true; 2515 /* skip over the vmsave instruction*/ 2516 r->rip += 3; 2517 } 2518 2519 static void svm_vmrun_errata_test(void) 2520 { 2521 unsigned long *last_page = NULL; 2522 2523 handle_exception(GP_VECTOR, gp_isr); 2524 2525 while (!svm_errata_reproduced) { 2526 2527 unsigned long *page = alloc_pages(1); 2528 2529 if (!page) { 2530 report_pass("All guest memory tested, no bug found"); 2531 break; 2532 } 2533 2534 physical = virt_to_phys(page); 2535 2536 asm volatile ( 2537 "mov %[_physical], %%rax\n\t" 2538 "vmsave %%rax\n\t" 2539 2540 : [_physical] "=m" (physical) 2541 : /* no inputs*/ 2542 : "rax" /*clobbers*/ 2543 ); 2544 2545 if (svm_errata_reproduced) { 2546 report_fail("Got #GP exception - svm errata reproduced at 0x%lx", 2547 physical); 2548 break; 2549 } 2550 2551 *page = (unsigned long)last_page; 2552 last_page = page; 2553 } 2554 2555 while (last_page) { 2556 unsigned long *page = last_page; 2557 last_page = (unsigned long *)*last_page; 2558 free_pages_by_order(page, 1); 2559 } 2560 } 2561 2562 static void vmload_vmsave_guest_main(struct svm_test *test) 2563 { 2564 u64 vmcb_phys = virt_to_phys(vmcb); 2565 2566 asm volatile ("vmload %0" : : "a"(vmcb_phys)); 2567 asm volatile ("vmsave %0" : : "a"(vmcb_phys)); 2568 } 2569 2570 static void svm_vmload_vmsave(void) 2571 { 2572 u32 intercept_saved = vmcb->control.intercept; 2573 2574 test_set_guest(vmload_vmsave_guest_main); 2575 2576 /* 2577 * Disabling intercept for VMLOAD and VMSAVE doesn't cause 2578 * respective #VMEXIT to host 2579 */ 2580 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMLOAD); 2581 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMSAVE); 2582 svm_vmrun(); 2583 report(vmcb->control.exit_code == SVM_EXIT_VMMCALL, "Test " 2584 "VMLOAD/VMSAVE intercept: Expected VMMCALL #VMEXIT"); 2585 2586 /* 2587 * Enabling intercept for VMLOAD and VMSAVE causes respective 2588 * #VMEXIT to host 2589 */ 2590 vmcb->control.intercept |= (1ULL << INTERCEPT_VMLOAD); 2591 svm_vmrun(); 2592 report(vmcb->control.exit_code == SVM_EXIT_VMLOAD, "Test " 2593 "VMLOAD/VMSAVE intercept: Expected VMLOAD #VMEXIT"); 2594 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMLOAD); 2595 vmcb->control.intercept |= (1ULL << INTERCEPT_VMSAVE); 2596 svm_vmrun(); 2597 report(vmcb->control.exit_code == SVM_EXIT_VMSAVE, "Test " 2598 "VMLOAD/VMSAVE intercept: Expected VMSAVE #VMEXIT"); 2599 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMSAVE); 2600 svm_vmrun(); 2601 report(vmcb->control.exit_code == SVM_EXIT_VMMCALL, "Test " 2602 "VMLOAD/VMSAVE intercept: Expected VMMCALL #VMEXIT"); 2603 2604 vmcb->control.intercept |= (1ULL << INTERCEPT_VMLOAD); 2605 svm_vmrun(); 2606 report(vmcb->control.exit_code == SVM_EXIT_VMLOAD, "Test " 2607 "VMLOAD/VMSAVE intercept: Expected VMLOAD #VMEXIT"); 2608 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMLOAD); 2609 svm_vmrun(); 2610 report(vmcb->control.exit_code == SVM_EXIT_VMMCALL, "Test " 2611 "VMLOAD/VMSAVE intercept: Expected VMMCALL #VMEXIT"); 2612 2613 vmcb->control.intercept |= (1ULL << INTERCEPT_VMSAVE); 2614 svm_vmrun(); 2615 report(vmcb->control.exit_code == SVM_EXIT_VMSAVE, "Test " 2616 "VMLOAD/VMSAVE intercept: Expected VMSAVE #VMEXIT"); 2617 vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMSAVE); 2618 svm_vmrun(); 2619 report(vmcb->control.exit_code == SVM_EXIT_VMMCALL, "Test " 2620 "VMLOAD/VMSAVE intercept: Expected VMMCALL #VMEXIT"); 2621 2622 vmcb->control.intercept = intercept_saved; 2623 } 2624 2625 static void prepare_vgif_enabled(struct svm_test *test) 2626 { 2627 default_prepare(test); 2628 } 2629 2630 static void test_vgif(struct svm_test *test) 2631 { 2632 asm volatile ("vmmcall\n\tstgi\n\tvmmcall\n\tclgi\n\tvmmcall\n\t"); 2633 } 2634 2635 static bool vgif_finished(struct svm_test *test) 2636 { 2637 switch (get_test_stage(test)) 2638 { 2639 case 0: 2640 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 2641 report_fail("VMEXIT not due to vmmcall."); 2642 return true; 2643 } 2644 vmcb->control.int_ctl |= V_GIF_ENABLED_MASK; 2645 vmcb->save.rip += 3; 2646 inc_test_stage(test); 2647 break; 2648 case 1: 2649 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 2650 report_fail("VMEXIT not due to vmmcall."); 2651 return true; 2652 } 2653 if (!(vmcb->control.int_ctl & V_GIF_MASK)) { 2654 report_fail("Failed to set VGIF when executing STGI."); 2655 vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK; 2656 return true; 2657 } 2658 report_pass("STGI set VGIF bit."); 2659 vmcb->save.rip += 3; 2660 inc_test_stage(test); 2661 break; 2662 case 2: 2663 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 2664 report_fail("VMEXIT not due to vmmcall."); 2665 return true; 2666 } 2667 if (vmcb->control.int_ctl & V_GIF_MASK) { 2668 report_fail("Failed to clear VGIF when executing CLGI."); 2669 vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK; 2670 return true; 2671 } 2672 report_pass("CLGI cleared VGIF bit."); 2673 vmcb->save.rip += 3; 2674 inc_test_stage(test); 2675 vmcb->control.int_ctl &= ~V_GIF_ENABLED_MASK; 2676 break; 2677 default: 2678 return true; 2679 break; 2680 } 2681 2682 return get_test_stage(test) == 3; 2683 } 2684 2685 static bool vgif_check(struct svm_test *test) 2686 { 2687 return get_test_stage(test) == 3; 2688 } 2689 2690 2691 static int pause_test_counter; 2692 static int wait_counter; 2693 2694 static void pause_filter_test_guest_main(struct svm_test *test) 2695 { 2696 int i; 2697 for (i = 0 ; i < pause_test_counter ; i++) 2698 pause(); 2699 2700 if (!wait_counter) 2701 return; 2702 2703 for (i = 0; i < wait_counter; i++) 2704 ; 2705 2706 for (i = 0 ; i < pause_test_counter ; i++) 2707 pause(); 2708 2709 } 2710 2711 static void pause_filter_run_test(int pause_iterations, int filter_value, int wait_iterations, int threshold) 2712 { 2713 test_set_guest(pause_filter_test_guest_main); 2714 2715 pause_test_counter = pause_iterations; 2716 wait_counter = wait_iterations; 2717 2718 vmcb->control.pause_filter_count = filter_value; 2719 vmcb->control.pause_filter_thresh = threshold; 2720 svm_vmrun(); 2721 2722 if (filter_value <= pause_iterations || wait_iterations < threshold) 2723 report(vmcb->control.exit_code == SVM_EXIT_PAUSE, "expected PAUSE vmexit"); 2724 else 2725 report(vmcb->control.exit_code == SVM_EXIT_VMMCALL, "no expected PAUSE vmexit"); 2726 } 2727 2728 static void pause_filter_test(void) 2729 { 2730 if (!pause_filter_supported()) { 2731 report_skip("PAUSE filter not supported in the guest"); 2732 return; 2733 } 2734 2735 vmcb->control.intercept |= (1 << INTERCEPT_PAUSE); 2736 2737 // filter count more that pause count - no VMexit 2738 pause_filter_run_test(10, 9, 0, 0); 2739 2740 // filter count smaller pause count - no VMexit 2741 pause_filter_run_test(20, 21, 0, 0); 2742 2743 2744 if (pause_threshold_supported()) { 2745 // filter count smaller pause count - no VMexit + large enough threshold 2746 // so that filter counter resets 2747 pause_filter_run_test(20, 21, 1000, 10); 2748 2749 // filter count smaller pause count - no VMexit + small threshold 2750 // so that filter doesn't reset 2751 pause_filter_run_test(20, 21, 10, 1000); 2752 } else { 2753 report_skip("PAUSE threshold not supported in the guest"); 2754 return; 2755 } 2756 } 2757 2758 2759 static int of_test_counter; 2760 2761 static void guest_test_of_handler(struct ex_regs *r) 2762 { 2763 of_test_counter++; 2764 } 2765 2766 static void svm_of_test_guest(struct svm_test *test) 2767 { 2768 struct far_pointer32 fp = { 2769 .offset = (uintptr_t)&&into, 2770 .selector = KERNEL_CS32, 2771 }; 2772 uintptr_t rsp; 2773 2774 asm volatile ("mov %%rsp, %0" : "=r"(rsp)); 2775 2776 if (fp.offset != (uintptr_t)&&into) { 2777 printf("Codee address too high.\n"); 2778 return; 2779 } 2780 2781 if ((u32)rsp != rsp) { 2782 printf("Stack address too high.\n"); 2783 } 2784 2785 asm goto("lcall *%0" : : "m" (fp) : "rax" : into); 2786 return; 2787 into: 2788 2789 asm volatile (".code32;" 2790 "movl $0x7fffffff, %eax;" 2791 "addl %eax, %eax;" 2792 "into;" 2793 "lret;" 2794 ".code64"); 2795 __builtin_unreachable(); 2796 } 2797 2798 static void svm_into_test(void) 2799 { 2800 handle_exception(OF_VECTOR, guest_test_of_handler); 2801 test_set_guest(svm_of_test_guest); 2802 report(svm_vmrun() == SVM_EXIT_VMMCALL && of_test_counter == 1, 2803 "#OF is generated in L2 exception handler"); 2804 } 2805 2806 static int bp_test_counter; 2807 2808 static void guest_test_bp_handler(struct ex_regs *r) 2809 { 2810 bp_test_counter++; 2811 } 2812 2813 static void svm_bp_test_guest(struct svm_test *test) 2814 { 2815 asm volatile("int3"); 2816 } 2817 2818 static void svm_int3_test(void) 2819 { 2820 handle_exception(BP_VECTOR, guest_test_bp_handler); 2821 test_set_guest(svm_bp_test_guest); 2822 report(svm_vmrun() == SVM_EXIT_VMMCALL && bp_test_counter == 1, 2823 "#BP is handled in L2 exception handler"); 2824 } 2825 2826 static int nm_test_counter; 2827 2828 static void guest_test_nm_handler(struct ex_regs *r) 2829 { 2830 nm_test_counter++; 2831 write_cr0(read_cr0() & ~X86_CR0_TS); 2832 write_cr0(read_cr0() & ~X86_CR0_EM); 2833 } 2834 2835 static void svm_nm_test_guest(struct svm_test *test) 2836 { 2837 asm volatile("fnop"); 2838 } 2839 2840 /* This test checks that: 2841 * 2842 * (a) If CR0.TS is set in L2, #NM is handled by L2 when 2843 * just an L2 handler is registered. 2844 * 2845 * (b) If CR0.TS is cleared and CR0.EM is set, #NM is handled 2846 * by L2 when just an l2 handler is registered. 2847 * 2848 * (c) If CR0.TS and CR0.EM are cleared in L2, no exception 2849 * is generated. 2850 */ 2851 2852 static void svm_nm_test(void) 2853 { 2854 handle_exception(NM_VECTOR, guest_test_nm_handler); 2855 write_cr0(read_cr0() & ~X86_CR0_TS); 2856 test_set_guest(svm_nm_test_guest); 2857 2858 vmcb->save.cr0 = vmcb->save.cr0 | X86_CR0_TS; 2859 report(svm_vmrun() == SVM_EXIT_VMMCALL && nm_test_counter == 1, 2860 "fnop with CR0.TS set in L2, #NM is triggered"); 2861 2862 vmcb->save.cr0 = (vmcb->save.cr0 & ~X86_CR0_TS) | X86_CR0_EM; 2863 report(svm_vmrun() == SVM_EXIT_VMMCALL && nm_test_counter == 2, 2864 "fnop with CR0.EM set in L2, #NM is triggered"); 2865 2866 vmcb->save.cr0 = vmcb->save.cr0 & ~(X86_CR0_TS | X86_CR0_EM); 2867 report(svm_vmrun() == SVM_EXIT_VMMCALL && nm_test_counter == 2, 2868 "fnop with CR0.TS and CR0.EM unset no #NM excpetion"); 2869 } 2870 2871 static bool check_lbr(u64 *from_excepted, u64 *to_expected) 2872 { 2873 u64 from = rdmsr(MSR_IA32_LASTBRANCHFROMIP); 2874 u64 to = rdmsr(MSR_IA32_LASTBRANCHTOIP); 2875 2876 if ((u64)from_excepted != from) { 2877 report(false, "MSR_IA32_LASTBRANCHFROMIP, expected=0x%lx, actual=0x%lx", 2878 (u64)from_excepted, from); 2879 return false; 2880 } 2881 2882 if ((u64)to_expected != to) { 2883 report(false, "MSR_IA32_LASTBRANCHFROMIP, expected=0x%lx, actual=0x%lx", 2884 (u64)from_excepted, from); 2885 return false; 2886 } 2887 2888 return true; 2889 } 2890 2891 static bool check_dbgctl(u64 dbgctl, u64 dbgctl_expected) 2892 { 2893 if (dbgctl != dbgctl_expected) { 2894 report(false, "Unexpected MSR_IA32_DEBUGCTLMSR value 0x%lx", dbgctl); 2895 return false; 2896 } 2897 return true; 2898 } 2899 2900 2901 #define DO_BRANCH(branch_name) \ 2902 asm volatile ( \ 2903 # branch_name "_from:" \ 2904 "jmp " # branch_name "_to\n" \ 2905 "nop\n" \ 2906 "nop\n" \ 2907 # branch_name "_to:" \ 2908 "nop\n" \ 2909 ) 2910 2911 2912 extern u64 guest_branch0_from, guest_branch0_to; 2913 extern u64 guest_branch2_from, guest_branch2_to; 2914 2915 extern u64 host_branch0_from, host_branch0_to; 2916 extern u64 host_branch2_from, host_branch2_to; 2917 extern u64 host_branch3_from, host_branch3_to; 2918 extern u64 host_branch4_from, host_branch4_to; 2919 2920 u64 dbgctl; 2921 2922 static void svm_lbrv_test_guest1(void) 2923 { 2924 /* 2925 * This guest expects the LBR to be already enabled when it starts, 2926 * it does a branch, and then disables the LBR and then checks. 2927 */ 2928 2929 DO_BRANCH(guest_branch0); 2930 2931 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 2932 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 2933 2934 if (dbgctl != DEBUGCTLMSR_LBR) 2935 asm volatile("ud2\n"); 2936 if (rdmsr(MSR_IA32_DEBUGCTLMSR) != 0) 2937 asm volatile("ud2\n"); 2938 if (rdmsr(MSR_IA32_LASTBRANCHFROMIP) != (u64)&guest_branch0_from) 2939 asm volatile("ud2\n"); 2940 if (rdmsr(MSR_IA32_LASTBRANCHTOIP) != (u64)&guest_branch0_to) 2941 asm volatile("ud2\n"); 2942 2943 asm volatile ("vmmcall\n"); 2944 } 2945 2946 static void svm_lbrv_test_guest2(void) 2947 { 2948 /* 2949 * This guest expects the LBR to be disabled when it starts, 2950 * enables it, does a branch, disables it and then checks. 2951 */ 2952 2953 DO_BRANCH(guest_branch1); 2954 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 2955 2956 if (dbgctl != 0) 2957 asm volatile("ud2\n"); 2958 2959 if (rdmsr(MSR_IA32_LASTBRANCHFROMIP) != (u64)&host_branch2_from) 2960 asm volatile("ud2\n"); 2961 if (rdmsr(MSR_IA32_LASTBRANCHTOIP) != (u64)&host_branch2_to) 2962 asm volatile("ud2\n"); 2963 2964 2965 wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); 2966 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 2967 DO_BRANCH(guest_branch2); 2968 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 2969 2970 if (dbgctl != DEBUGCTLMSR_LBR) 2971 asm volatile("ud2\n"); 2972 if (rdmsr(MSR_IA32_LASTBRANCHFROMIP) != (u64)&guest_branch2_from) 2973 asm volatile("ud2\n"); 2974 if (rdmsr(MSR_IA32_LASTBRANCHTOIP) != (u64)&guest_branch2_to) 2975 asm volatile("ud2\n"); 2976 2977 asm volatile ("vmmcall\n"); 2978 } 2979 2980 static void svm_lbrv_test0(void) 2981 { 2982 report(true, "Basic LBR test"); 2983 wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); 2984 DO_BRANCH(host_branch0); 2985 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 2986 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 2987 2988 check_dbgctl(dbgctl, DEBUGCTLMSR_LBR); 2989 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 2990 check_dbgctl(dbgctl, 0); 2991 2992 check_lbr(&host_branch0_from, &host_branch0_to); 2993 } 2994 2995 static void svm_lbrv_test1(void) 2996 { 2997 report(true, "Test that without LBRV enabled, guest LBR state does 'leak' to the host(1)"); 2998 2999 vmcb->save.rip = (ulong)svm_lbrv_test_guest1; 3000 vmcb->control.virt_ext = 0; 3001 3002 wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); 3003 DO_BRANCH(host_branch1); 3004 SVM_BARE_VMRUN; 3005 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 3006 3007 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 3008 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 3009 vmcb->control.exit_code); 3010 return; 3011 } 3012 3013 check_dbgctl(dbgctl, 0); 3014 check_lbr(&guest_branch0_from, &guest_branch0_to); 3015 } 3016 3017 static void svm_lbrv_test2(void) 3018 { 3019 report(true, "Test that without LBRV enabled, guest LBR state does 'leak' to the host(2)"); 3020 3021 vmcb->save.rip = (ulong)svm_lbrv_test_guest2; 3022 vmcb->control.virt_ext = 0; 3023 3024 wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); 3025 DO_BRANCH(host_branch2); 3026 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 3027 SVM_BARE_VMRUN; 3028 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 3029 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 3030 3031 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 3032 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 3033 vmcb->control.exit_code); 3034 return; 3035 } 3036 3037 check_dbgctl(dbgctl, 0); 3038 check_lbr(&guest_branch2_from, &guest_branch2_to); 3039 } 3040 3041 static void svm_lbrv_nested_test1(void) 3042 { 3043 if (!lbrv_supported()) { 3044 report_skip("LBRV not supported in the guest"); 3045 return; 3046 } 3047 3048 report(true, "Test that with LBRV enabled, guest LBR state doesn't leak (1)"); 3049 vmcb->save.rip = (ulong)svm_lbrv_test_guest1; 3050 vmcb->control.virt_ext = LBR_CTL_ENABLE_MASK; 3051 vmcb->save.dbgctl = DEBUGCTLMSR_LBR; 3052 3053 wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); 3054 DO_BRANCH(host_branch3); 3055 SVM_BARE_VMRUN; 3056 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 3057 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 3058 3059 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 3060 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 3061 vmcb->control.exit_code); 3062 return; 3063 } 3064 3065 if (vmcb->save.dbgctl != 0) { 3066 report(false, "unexpected virtual guest MSR_IA32_DEBUGCTLMSR value 0x%lx", vmcb->save.dbgctl); 3067 return; 3068 } 3069 3070 check_dbgctl(dbgctl, DEBUGCTLMSR_LBR); 3071 check_lbr(&host_branch3_from, &host_branch3_to); 3072 } 3073 3074 static void svm_lbrv_nested_test2(void) 3075 { 3076 if (!lbrv_supported()) { 3077 report_skip("LBRV not supported in the guest"); 3078 return; 3079 } 3080 3081 report(true, "Test that with LBRV enabled, guest LBR state doesn't leak (2)"); 3082 vmcb->save.rip = (ulong)svm_lbrv_test_guest2; 3083 vmcb->control.virt_ext = LBR_CTL_ENABLE_MASK; 3084 3085 vmcb->save.dbgctl = 0; 3086 vmcb->save.br_from = (u64)&host_branch2_from; 3087 vmcb->save.br_to = (u64)&host_branch2_to; 3088 3089 wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR); 3090 DO_BRANCH(host_branch4); 3091 SVM_BARE_VMRUN; 3092 dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); 3093 wrmsr(MSR_IA32_DEBUGCTLMSR, 0); 3094 3095 if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { 3096 report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", 3097 vmcb->control.exit_code); 3098 return; 3099 } 3100 3101 check_dbgctl(dbgctl, DEBUGCTLMSR_LBR); 3102 check_lbr(&host_branch4_from, &host_branch4_to); 3103 } 3104 3105 3106 // test that a nested guest which does enable INTR interception 3107 // but doesn't enable virtual interrupt masking works 3108 3109 static volatile int dummy_isr_recevied; 3110 static void dummy_isr(isr_regs_t *regs) 3111 { 3112 dummy_isr_recevied++; 3113 eoi(); 3114 } 3115 3116 3117 static volatile int nmi_recevied; 3118 static void dummy_nmi_handler(struct ex_regs *regs) 3119 { 3120 nmi_recevied++; 3121 } 3122 3123 3124 static void svm_intr_intercept_mix_run_guest(volatile int *counter, int expected_vmexit) 3125 { 3126 if (counter) 3127 *counter = 0; 3128 3129 sti(); // host IF value should not matter 3130 clgi(); // vmrun will set back GI to 1 3131 3132 svm_vmrun(); 3133 3134 if (counter) 3135 report(!*counter, "No interrupt expected"); 3136 3137 stgi(); 3138 3139 if (counter) 3140 report(*counter == 1, "Interrupt is expected"); 3141 3142 report (vmcb->control.exit_code == expected_vmexit, "Test expected VM exit"); 3143 report(vmcb->save.rflags & X86_EFLAGS_IF, "Guest should have EFLAGS.IF set now"); 3144 cli(); 3145 } 3146 3147 3148 // subtest: test that enabling EFLAGS.IF is enought to trigger an interrupt 3149 static void svm_intr_intercept_mix_if_guest(struct svm_test *test) 3150 { 3151 asm volatile("nop;nop;nop;nop"); 3152 report(!dummy_isr_recevied, "No interrupt expected"); 3153 sti(); 3154 asm volatile("nop"); 3155 report(0, "must not reach here"); 3156 } 3157 3158 static void svm_intr_intercept_mix_if(void) 3159 { 3160 // make a physical interrupt to be pending 3161 handle_irq(0x55, dummy_isr); 3162 3163 vmcb->control.intercept |= (1 << INTERCEPT_INTR); 3164 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 3165 vmcb->save.rflags &= ~X86_EFLAGS_IF; 3166 3167 test_set_guest(svm_intr_intercept_mix_if_guest); 3168 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | 0x55, 0); 3169 svm_intr_intercept_mix_run_guest(&dummy_isr_recevied, SVM_EXIT_INTR); 3170 } 3171 3172 3173 // subtest: test that a clever guest can trigger an interrupt by setting GIF 3174 // if GIF is not intercepted 3175 static void svm_intr_intercept_mix_gif_guest(struct svm_test *test) 3176 { 3177 3178 asm volatile("nop;nop;nop;nop"); 3179 report(!dummy_isr_recevied, "No interrupt expected"); 3180 3181 // clear GIF and enable IF 3182 // that should still not cause VM exit 3183 clgi(); 3184 sti(); 3185 asm volatile("nop"); 3186 report(!dummy_isr_recevied, "No interrupt expected"); 3187 3188 stgi(); 3189 asm volatile("nop"); 3190 report(0, "must not reach here"); 3191 } 3192 3193 static void svm_intr_intercept_mix_gif(void) 3194 { 3195 handle_irq(0x55, dummy_isr); 3196 3197 vmcb->control.intercept |= (1 << INTERCEPT_INTR); 3198 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 3199 vmcb->save.rflags &= ~X86_EFLAGS_IF; 3200 3201 test_set_guest(svm_intr_intercept_mix_gif_guest); 3202 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | 0x55, 0); 3203 svm_intr_intercept_mix_run_guest(&dummy_isr_recevied, SVM_EXIT_INTR); 3204 } 3205 3206 // subtest: test that a clever guest can trigger an interrupt by setting GIF 3207 // if GIF is not intercepted and interrupt comes after guest 3208 // started running 3209 static void svm_intr_intercept_mix_gif_guest2(struct svm_test *test) 3210 { 3211 asm volatile("nop;nop;nop;nop"); 3212 report(!dummy_isr_recevied, "No interrupt expected"); 3213 3214 clgi(); 3215 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | 0x55, 0); 3216 report(!dummy_isr_recevied, "No interrupt expected"); 3217 3218 stgi(); 3219 asm volatile("nop"); 3220 report(0, "must not reach here"); 3221 } 3222 3223 static void svm_intr_intercept_mix_gif2(void) 3224 { 3225 handle_irq(0x55, dummy_isr); 3226 3227 vmcb->control.intercept |= (1 << INTERCEPT_INTR); 3228 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 3229 vmcb->save.rflags |= X86_EFLAGS_IF; 3230 3231 test_set_guest(svm_intr_intercept_mix_gif_guest2); 3232 svm_intr_intercept_mix_run_guest(&dummy_isr_recevied, SVM_EXIT_INTR); 3233 } 3234 3235 3236 // subtest: test that pending NMI will be handled when guest enables GIF 3237 static void svm_intr_intercept_mix_nmi_guest(struct svm_test *test) 3238 { 3239 asm volatile("nop;nop;nop;nop"); 3240 report(!nmi_recevied, "No NMI expected"); 3241 cli(); // should have no effect 3242 3243 clgi(); 3244 asm volatile("nop"); 3245 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI, 0); 3246 sti(); // should have no effect 3247 asm volatile("nop"); 3248 report(!nmi_recevied, "No NMI expected"); 3249 3250 stgi(); 3251 asm volatile("nop"); 3252 report(0, "must not reach here"); 3253 } 3254 3255 static void svm_intr_intercept_mix_nmi(void) 3256 { 3257 handle_exception(2, dummy_nmi_handler); 3258 3259 vmcb->control.intercept |= (1 << INTERCEPT_NMI); 3260 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 3261 vmcb->save.rflags |= X86_EFLAGS_IF; 3262 3263 test_set_guest(svm_intr_intercept_mix_nmi_guest); 3264 svm_intr_intercept_mix_run_guest(&nmi_recevied, SVM_EXIT_NMI); 3265 } 3266 3267 // test that pending SMI will be handled when guest enables GIF 3268 // TODO: can't really count #SMIs so just test that guest doesn't hang 3269 // and VMexits on SMI 3270 static void svm_intr_intercept_mix_smi_guest(struct svm_test *test) 3271 { 3272 asm volatile("nop;nop;nop;nop"); 3273 3274 clgi(); 3275 asm volatile("nop"); 3276 apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_SMI, 0); 3277 sti(); // should have no effect 3278 asm volatile("nop"); 3279 stgi(); 3280 asm volatile("nop"); 3281 report(0, "must not reach here"); 3282 } 3283 3284 static void svm_intr_intercept_mix_smi(void) 3285 { 3286 vmcb->control.intercept |= (1 << INTERCEPT_SMI); 3287 vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; 3288 test_set_guest(svm_intr_intercept_mix_smi_guest); 3289 svm_intr_intercept_mix_run_guest(NULL, SVM_EXIT_SMI); 3290 } 3291 3292 struct svm_test svm_tests[] = { 3293 { "null", default_supported, default_prepare, 3294 default_prepare_gif_clear, null_test, 3295 default_finished, null_check }, 3296 { "vmrun", default_supported, default_prepare, 3297 default_prepare_gif_clear, test_vmrun, 3298 default_finished, check_vmrun }, 3299 { "ioio", default_supported, prepare_ioio, 3300 default_prepare_gif_clear, test_ioio, 3301 ioio_finished, check_ioio }, 3302 { "vmrun intercept check", default_supported, prepare_no_vmrun_int, 3303 default_prepare_gif_clear, null_test, default_finished, 3304 check_no_vmrun_int }, 3305 { "rsm", default_supported, 3306 prepare_rsm_intercept, default_prepare_gif_clear, 3307 test_rsm_intercept, finished_rsm_intercept, check_rsm_intercept }, 3308 { "cr3 read intercept", default_supported, 3309 prepare_cr3_intercept, default_prepare_gif_clear, 3310 test_cr3_intercept, default_finished, check_cr3_intercept }, 3311 { "cr3 read nointercept", default_supported, default_prepare, 3312 default_prepare_gif_clear, test_cr3_intercept, default_finished, 3313 check_cr3_nointercept }, 3314 { "cr3 read intercept emulate", smp_supported, 3315 prepare_cr3_intercept_bypass, default_prepare_gif_clear, 3316 test_cr3_intercept_bypass, default_finished, check_cr3_intercept }, 3317 { "dr intercept check", default_supported, prepare_dr_intercept, 3318 default_prepare_gif_clear, test_dr_intercept, dr_intercept_finished, 3319 check_dr_intercept }, 3320 { "next_rip", next_rip_supported, prepare_next_rip, 3321 default_prepare_gif_clear, test_next_rip, 3322 default_finished, check_next_rip }, 3323 { "msr intercept check", default_supported, prepare_msr_intercept, 3324 default_prepare_gif_clear, test_msr_intercept, 3325 msr_intercept_finished, check_msr_intercept }, 3326 { "mode_switch", default_supported, prepare_mode_switch, 3327 default_prepare_gif_clear, test_mode_switch, 3328 mode_switch_finished, check_mode_switch }, 3329 { "asid_zero", default_supported, prepare_asid_zero, 3330 default_prepare_gif_clear, test_asid_zero, 3331 default_finished, check_asid_zero }, 3332 { "sel_cr0_bug", default_supported, sel_cr0_bug_prepare, 3333 default_prepare_gif_clear, sel_cr0_bug_test, 3334 sel_cr0_bug_finished, sel_cr0_bug_check }, 3335 { "tsc_adjust", tsc_adjust_supported, tsc_adjust_prepare, 3336 default_prepare_gif_clear, tsc_adjust_test, 3337 default_finished, tsc_adjust_check }, 3338 { "latency_run_exit", default_supported, latency_prepare, 3339 default_prepare_gif_clear, latency_test, 3340 latency_finished, latency_check }, 3341 { "latency_run_exit_clean", default_supported, latency_prepare, 3342 default_prepare_gif_clear, latency_test, 3343 latency_finished_clean, latency_check }, 3344 { "latency_svm_insn", default_supported, lat_svm_insn_prepare, 3345 default_prepare_gif_clear, null_test, 3346 lat_svm_insn_finished, lat_svm_insn_check }, 3347 { "exc_inject", default_supported, exc_inject_prepare, 3348 default_prepare_gif_clear, exc_inject_test, 3349 exc_inject_finished, exc_inject_check }, 3350 { "pending_event", default_supported, pending_event_prepare, 3351 default_prepare_gif_clear, 3352 pending_event_test, pending_event_finished, pending_event_check }, 3353 { "pending_event_cli", default_supported, pending_event_cli_prepare, 3354 pending_event_cli_prepare_gif_clear, 3355 pending_event_cli_test, pending_event_cli_finished, 3356 pending_event_cli_check }, 3357 { "interrupt", default_supported, interrupt_prepare, 3358 default_prepare_gif_clear, interrupt_test, 3359 interrupt_finished, interrupt_check }, 3360 { "nmi", default_supported, nmi_prepare, 3361 default_prepare_gif_clear, nmi_test, 3362 nmi_finished, nmi_check }, 3363 { "nmi_hlt", smp_supported, nmi_prepare, 3364 default_prepare_gif_clear, nmi_hlt_test, 3365 nmi_hlt_finished, nmi_hlt_check }, 3366 { "virq_inject", default_supported, virq_inject_prepare, 3367 default_prepare_gif_clear, virq_inject_test, 3368 virq_inject_finished, virq_inject_check }, 3369 { "reg_corruption", default_supported, reg_corruption_prepare, 3370 default_prepare_gif_clear, reg_corruption_test, 3371 reg_corruption_finished, reg_corruption_check }, 3372 { "svm_init_startup_test", smp_supported, init_startup_prepare, 3373 default_prepare_gif_clear, null_test, 3374 init_startup_finished, init_startup_check }, 3375 { "svm_init_intercept_test", smp_supported, init_intercept_prepare, 3376 default_prepare_gif_clear, init_intercept_test, 3377 init_intercept_finished, init_intercept_check, .on_vcpu = 2 }, 3378 { "host_rflags", default_supported, host_rflags_prepare, 3379 host_rflags_prepare_gif_clear, host_rflags_test, 3380 host_rflags_finished, host_rflags_check }, 3381 { "vgif", vgif_supported, prepare_vgif_enabled, 3382 default_prepare_gif_clear, test_vgif, vgif_finished, 3383 vgif_check }, 3384 TEST(svm_cr4_osxsave_test), 3385 TEST(svm_guest_state_test), 3386 TEST(svm_vmrun_errata_test), 3387 TEST(svm_vmload_vmsave), 3388 TEST(svm_test_singlestep), 3389 TEST(svm_nm_test), 3390 TEST(svm_int3_test), 3391 TEST(svm_into_test), 3392 TEST(svm_lbrv_test0), 3393 TEST(svm_lbrv_test1), 3394 TEST(svm_lbrv_test2), 3395 TEST(svm_lbrv_nested_test1), 3396 TEST(svm_lbrv_nested_test2), 3397 TEST(svm_intr_intercept_mix_if), 3398 TEST(svm_intr_intercept_mix_gif), 3399 TEST(svm_intr_intercept_mix_gif2), 3400 TEST(svm_intr_intercept_mix_nmi), 3401 TEST(svm_intr_intercept_mix_smi), 3402 TEST(svm_tsc_scale_test), 3403 TEST(pause_filter_test), 3404 { NULL, NULL, NULL, NULL, NULL, NULL, NULL } 3405 }; 3406 3407 int main(int ac, char **av) 3408 { 3409 setup_vm(); 3410 return run_svm_tests(ac, av, svm_tests); 3411 } 3412