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