1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021, Red Hat, Inc. 4 * 5 * Tests for Hyper-V features enablement 6 */ 7 #include <asm/kvm_para.h> 8 #include <linux/kvm_para.h> 9 #include <stdint.h> 10 11 #include "test_util.h" 12 #include "kvm_util.h" 13 #include "processor.h" 14 #include "hyperv.h" 15 16 #define VCPU_ID 0 17 #define LINUX_OS_ID ((u64)0x8100 << 48) 18 19 extern unsigned char rdmsr_start; 20 extern unsigned char rdmsr_end; 21 22 static u64 do_rdmsr(u32 idx) 23 { 24 u32 lo, hi; 25 26 asm volatile("rdmsr_start: rdmsr;" 27 "rdmsr_end:" 28 : "=a"(lo), "=c"(hi) 29 : "c"(idx)); 30 31 return (((u64) hi) << 32) | lo; 32 } 33 34 extern unsigned char wrmsr_start; 35 extern unsigned char wrmsr_end; 36 37 static void do_wrmsr(u32 idx, u64 val) 38 { 39 u32 lo, hi; 40 41 lo = val; 42 hi = val >> 32; 43 44 asm volatile("wrmsr_start: wrmsr;" 45 "wrmsr_end:" 46 : : "a"(lo), "c"(idx), "d"(hi)); 47 } 48 49 static int nr_gp; 50 51 static inline u64 hypercall(u64 control, vm_vaddr_t input_address, 52 vm_vaddr_t output_address) 53 { 54 u64 hv_status; 55 56 asm volatile("mov %3, %%r8\n" 57 "vmcall" 58 : "=a" (hv_status), 59 "+c" (control), "+d" (input_address) 60 : "r" (output_address) 61 : "cc", "memory", "r8", "r9", "r10", "r11"); 62 63 return hv_status; 64 } 65 66 static void guest_gp_handler(struct ex_regs *regs) 67 { 68 unsigned char *rip = (unsigned char *)regs->rip; 69 bool r, w; 70 71 r = rip == &rdmsr_start; 72 w = rip == &wrmsr_start; 73 GUEST_ASSERT(r || w); 74 75 nr_gp++; 76 77 if (r) 78 regs->rip = (uint64_t)&rdmsr_end; 79 else 80 regs->rip = (uint64_t)&wrmsr_end; 81 } 82 83 struct msr_data { 84 uint32_t idx; 85 bool available; 86 bool write; 87 u64 write_val; 88 }; 89 90 struct hcall_data { 91 uint64_t control; 92 uint64_t expect; 93 }; 94 95 static void guest_msr(struct msr_data *msr) 96 { 97 int i = 0; 98 99 while (msr->idx) { 100 WRITE_ONCE(nr_gp, 0); 101 if (!msr->write) 102 do_rdmsr(msr->idx); 103 else 104 do_wrmsr(msr->idx, msr->write_val); 105 106 if (msr->available) 107 GUEST_ASSERT(READ_ONCE(nr_gp) == 0); 108 else 109 GUEST_ASSERT(READ_ONCE(nr_gp) == 1); 110 111 GUEST_SYNC(i++); 112 } 113 114 GUEST_DONE(); 115 } 116 117 static void guest_hcall(vm_vaddr_t pgs_gpa, struct hcall_data *hcall) 118 { 119 int i = 0; 120 121 wrmsr(HV_X64_MSR_GUEST_OS_ID, LINUX_OS_ID); 122 wrmsr(HV_X64_MSR_HYPERCALL, pgs_gpa); 123 124 while (hcall->control) { 125 GUEST_ASSERT(hypercall(hcall->control, pgs_gpa, 126 pgs_gpa + 4096) == hcall->expect); 127 GUEST_SYNC(i++); 128 } 129 130 GUEST_DONE(); 131 } 132 133 static void hv_set_cpuid(struct kvm_vm *vm, struct kvm_cpuid2 *cpuid, 134 struct kvm_cpuid_entry2 *feat, 135 struct kvm_cpuid_entry2 *recomm, 136 struct kvm_cpuid_entry2 *dbg) 137 { 138 TEST_ASSERT(set_cpuid(cpuid, feat), 139 "failed to set KVM_CPUID_FEATURES leaf"); 140 TEST_ASSERT(set_cpuid(cpuid, recomm), 141 "failed to set HYPERV_CPUID_ENLIGHTMENT_INFO leaf"); 142 TEST_ASSERT(set_cpuid(cpuid, dbg), 143 "failed to set HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES leaf"); 144 vcpu_set_cpuid(vm, VCPU_ID, cpuid); 145 } 146 147 static void guest_test_msrs_access(struct kvm_vm *vm, struct msr_data *msr, 148 struct kvm_cpuid2 *best) 149 { 150 struct kvm_run *run; 151 struct ucall uc; 152 int stage = 0, r; 153 struct kvm_cpuid_entry2 feat = { 154 .function = HYPERV_CPUID_FEATURES 155 }; 156 struct kvm_cpuid_entry2 recomm = { 157 .function = HYPERV_CPUID_ENLIGHTMENT_INFO 158 }; 159 struct kvm_cpuid_entry2 dbg = { 160 .function = HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 161 }; 162 struct kvm_enable_cap cap = {0}; 163 164 run = vcpu_state(vm, VCPU_ID); 165 166 while (true) { 167 switch (stage) { 168 case 0: 169 /* 170 * Only available when Hyper-V identification is set 171 */ 172 msr->idx = HV_X64_MSR_GUEST_OS_ID; 173 msr->write = 0; 174 msr->available = 0; 175 break; 176 case 1: 177 msr->idx = HV_X64_MSR_HYPERCALL; 178 msr->write = 0; 179 msr->available = 0; 180 break; 181 case 2: 182 feat.eax |= HV_MSR_HYPERCALL_AVAILABLE; 183 /* 184 * HV_X64_MSR_GUEST_OS_ID has to be written first to make 185 * HV_X64_MSR_HYPERCALL available. 186 */ 187 msr->idx = HV_X64_MSR_GUEST_OS_ID; 188 msr->write = 1; 189 msr->write_val = LINUX_OS_ID; 190 msr->available = 1; 191 break; 192 case 3: 193 msr->idx = HV_X64_MSR_GUEST_OS_ID; 194 msr->write = 0; 195 msr->available = 1; 196 break; 197 case 4: 198 msr->idx = HV_X64_MSR_HYPERCALL; 199 msr->write = 0; 200 msr->available = 1; 201 break; 202 203 case 5: 204 msr->idx = HV_X64_MSR_VP_RUNTIME; 205 msr->write = 0; 206 msr->available = 0; 207 break; 208 case 6: 209 feat.eax |= HV_MSR_VP_RUNTIME_AVAILABLE; 210 msr->write = 0; 211 msr->available = 1; 212 break; 213 case 7: 214 /* Read only */ 215 msr->write = 1; 216 msr->write_val = 1; 217 msr->available = 0; 218 break; 219 220 case 8: 221 msr->idx = HV_X64_MSR_TIME_REF_COUNT; 222 msr->write = 0; 223 msr->available = 0; 224 break; 225 case 9: 226 feat.eax |= HV_MSR_TIME_REF_COUNT_AVAILABLE; 227 msr->write = 0; 228 msr->available = 1; 229 break; 230 case 10: 231 /* Read only */ 232 msr->write = 1; 233 msr->write_val = 1; 234 msr->available = 0; 235 break; 236 237 case 11: 238 msr->idx = HV_X64_MSR_VP_INDEX; 239 msr->write = 0; 240 msr->available = 0; 241 break; 242 case 12: 243 feat.eax |= HV_MSR_VP_INDEX_AVAILABLE; 244 msr->write = 0; 245 msr->available = 1; 246 break; 247 case 13: 248 /* Read only */ 249 msr->write = 1; 250 msr->write_val = 1; 251 msr->available = 0; 252 break; 253 254 case 14: 255 msr->idx = HV_X64_MSR_RESET; 256 msr->write = 0; 257 msr->available = 0; 258 break; 259 case 15: 260 feat.eax |= HV_MSR_RESET_AVAILABLE; 261 msr->write = 0; 262 msr->available = 1; 263 break; 264 case 16: 265 msr->write = 1; 266 msr->write_val = 0; 267 msr->available = 1; 268 break; 269 270 case 17: 271 msr->idx = HV_X64_MSR_REFERENCE_TSC; 272 msr->write = 0; 273 msr->available = 0; 274 break; 275 case 18: 276 feat.eax |= HV_MSR_REFERENCE_TSC_AVAILABLE; 277 msr->write = 0; 278 msr->available = 1; 279 break; 280 case 19: 281 msr->write = 1; 282 msr->write_val = 0; 283 msr->available = 1; 284 break; 285 286 case 20: 287 msr->idx = HV_X64_MSR_EOM; 288 msr->write = 0; 289 msr->available = 0; 290 break; 291 case 21: 292 /* 293 * Remains unavailable even with KVM_CAP_HYPERV_SYNIC2 294 * capability enabled and guest visible CPUID bit unset. 295 */ 296 cap.cap = KVM_CAP_HYPERV_SYNIC2; 297 vcpu_enable_cap(vm, VCPU_ID, &cap); 298 break; 299 case 22: 300 feat.eax |= HV_MSR_SYNIC_AVAILABLE; 301 msr->write = 0; 302 msr->available = 1; 303 break; 304 case 23: 305 msr->write = 1; 306 msr->write_val = 0; 307 msr->available = 1; 308 break; 309 310 case 24: 311 msr->idx = HV_X64_MSR_STIMER0_CONFIG; 312 msr->write = 0; 313 msr->available = 0; 314 break; 315 case 25: 316 feat.eax |= HV_MSR_SYNTIMER_AVAILABLE; 317 msr->write = 0; 318 msr->available = 1; 319 break; 320 case 26: 321 msr->write = 1; 322 msr->write_val = 0; 323 msr->available = 1; 324 break; 325 case 27: 326 /* Direct mode test */ 327 msr->write = 1; 328 msr->write_val = 1 << 12; 329 msr->available = 0; 330 break; 331 case 28: 332 feat.edx |= HV_STIMER_DIRECT_MODE_AVAILABLE; 333 msr->available = 1; 334 break; 335 336 case 29: 337 msr->idx = HV_X64_MSR_EOI; 338 msr->write = 0; 339 msr->available = 0; 340 break; 341 case 30: 342 feat.eax |= HV_MSR_APIC_ACCESS_AVAILABLE; 343 msr->write = 1; 344 msr->write_val = 1; 345 msr->available = 1; 346 break; 347 348 case 31: 349 msr->idx = HV_X64_MSR_TSC_FREQUENCY; 350 msr->write = 0; 351 msr->available = 0; 352 break; 353 case 32: 354 feat.eax |= HV_ACCESS_FREQUENCY_MSRS; 355 msr->write = 0; 356 msr->available = 1; 357 break; 358 case 33: 359 /* Read only */ 360 msr->write = 1; 361 msr->write_val = 1; 362 msr->available = 0; 363 break; 364 365 case 34: 366 msr->idx = HV_X64_MSR_REENLIGHTENMENT_CONTROL; 367 msr->write = 0; 368 msr->available = 0; 369 break; 370 case 35: 371 feat.eax |= HV_ACCESS_REENLIGHTENMENT; 372 msr->write = 0; 373 msr->available = 1; 374 break; 375 case 36: 376 msr->write = 1; 377 msr->write_val = 1; 378 msr->available = 1; 379 break; 380 case 37: 381 /* Can only write '0' */ 382 msr->idx = HV_X64_MSR_TSC_EMULATION_STATUS; 383 msr->write = 1; 384 msr->write_val = 1; 385 msr->available = 0; 386 break; 387 388 case 38: 389 msr->idx = HV_X64_MSR_CRASH_P0; 390 msr->write = 0; 391 msr->available = 0; 392 break; 393 case 39: 394 feat.edx |= HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE; 395 msr->write = 0; 396 msr->available = 1; 397 break; 398 case 40: 399 msr->write = 1; 400 msr->write_val = 1; 401 msr->available = 1; 402 break; 403 404 case 41: 405 msr->idx = HV_X64_MSR_SYNDBG_STATUS; 406 msr->write = 0; 407 msr->available = 0; 408 break; 409 case 42: 410 feat.edx |= HV_FEATURE_DEBUG_MSRS_AVAILABLE; 411 dbg.eax |= HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING; 412 msr->write = 0; 413 msr->available = 1; 414 break; 415 case 43: 416 msr->write = 1; 417 msr->write_val = 0; 418 msr->available = 1; 419 break; 420 421 case 44: 422 /* END */ 423 msr->idx = 0; 424 break; 425 } 426 427 hv_set_cpuid(vm, best, &feat, &recomm, &dbg); 428 429 if (msr->idx) 430 pr_debug("Stage %d: testing msr: 0x%x for %s\n", stage, 431 msr->idx, msr->write ? "write" : "read"); 432 else 433 pr_debug("Stage %d: finish\n", stage); 434 435 r = _vcpu_run(vm, VCPU_ID); 436 TEST_ASSERT(!r, "vcpu_run failed: %d\n", r); 437 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, 438 "unexpected exit reason: %u (%s)", 439 run->exit_reason, exit_reason_str(run->exit_reason)); 440 441 switch (get_ucall(vm, VCPU_ID, &uc)) { 442 case UCALL_SYNC: 443 TEST_ASSERT(uc.args[1] == stage, 444 "Unexpected stage: %ld (%d expected)\n", 445 uc.args[1], stage); 446 break; 447 case UCALL_ABORT: 448 TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0], 449 __FILE__, uc.args[1]); 450 return; 451 case UCALL_DONE: 452 return; 453 } 454 455 stage++; 456 } 457 } 458 459 static void guest_test_hcalls_access(struct kvm_vm *vm, struct hcall_data *hcall, 460 void *input, void *output, struct kvm_cpuid2 *best) 461 { 462 struct kvm_run *run; 463 struct ucall uc; 464 int stage = 0, r; 465 struct kvm_cpuid_entry2 feat = { 466 .function = HYPERV_CPUID_FEATURES, 467 .eax = HV_MSR_HYPERCALL_AVAILABLE 468 }; 469 struct kvm_cpuid_entry2 recomm = { 470 .function = HYPERV_CPUID_ENLIGHTMENT_INFO 471 }; 472 struct kvm_cpuid_entry2 dbg = { 473 .function = HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 474 }; 475 476 run = vcpu_state(vm, VCPU_ID); 477 478 while (true) { 479 switch (stage) { 480 case 0: 481 hcall->control = 0xdeadbeef; 482 hcall->expect = HV_STATUS_INVALID_HYPERCALL_CODE; 483 break; 484 485 case 1: 486 hcall->control = HVCALL_POST_MESSAGE; 487 hcall->expect = HV_STATUS_ACCESS_DENIED; 488 break; 489 case 2: 490 feat.ebx |= HV_POST_MESSAGES; 491 hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT; 492 break; 493 494 case 3: 495 hcall->control = HVCALL_SIGNAL_EVENT; 496 hcall->expect = HV_STATUS_ACCESS_DENIED; 497 break; 498 case 4: 499 feat.ebx |= HV_SIGNAL_EVENTS; 500 hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT; 501 break; 502 503 case 5: 504 hcall->control = HVCALL_RESET_DEBUG_SESSION; 505 hcall->expect = HV_STATUS_INVALID_HYPERCALL_CODE; 506 break; 507 case 6: 508 dbg.eax |= HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING; 509 hcall->expect = HV_STATUS_ACCESS_DENIED; 510 break; 511 case 7: 512 feat.ebx |= HV_DEBUGGING; 513 hcall->expect = HV_STATUS_OPERATION_DENIED; 514 break; 515 516 case 8: 517 hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE; 518 hcall->expect = HV_STATUS_ACCESS_DENIED; 519 break; 520 case 9: 521 recomm.eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED; 522 hcall->expect = HV_STATUS_SUCCESS; 523 break; 524 case 10: 525 hcall->control = HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX; 526 hcall->expect = HV_STATUS_ACCESS_DENIED; 527 break; 528 case 11: 529 recomm.eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED; 530 hcall->expect = HV_STATUS_SUCCESS; 531 break; 532 533 case 12: 534 hcall->control = HVCALL_SEND_IPI; 535 hcall->expect = HV_STATUS_ACCESS_DENIED; 536 break; 537 case 13: 538 recomm.eax |= HV_X64_CLUSTER_IPI_RECOMMENDED; 539 hcall->expect = HV_STATUS_INVALID_HYPERCALL_INPUT; 540 break; 541 case 14: 542 /* Nothing in 'sparse banks' -> success */ 543 hcall->control = HVCALL_SEND_IPI_EX; 544 hcall->expect = HV_STATUS_SUCCESS; 545 break; 546 547 case 15: 548 hcall->control = HVCALL_NOTIFY_LONG_SPIN_WAIT; 549 hcall->expect = HV_STATUS_ACCESS_DENIED; 550 break; 551 case 16: 552 recomm.ebx = 0xfff; 553 hcall->expect = HV_STATUS_SUCCESS; 554 break; 555 556 case 17: 557 /* END */ 558 hcall->control = 0; 559 break; 560 } 561 562 hv_set_cpuid(vm, best, &feat, &recomm, &dbg); 563 564 if (hcall->control) 565 pr_debug("Stage %d: testing hcall: 0x%lx\n", stage, 566 hcall->control); 567 else 568 pr_debug("Stage %d: finish\n", stage); 569 570 r = _vcpu_run(vm, VCPU_ID); 571 TEST_ASSERT(!r, "vcpu_run failed: %d\n", r); 572 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, 573 "unexpected exit reason: %u (%s)", 574 run->exit_reason, exit_reason_str(run->exit_reason)); 575 576 switch (get_ucall(vm, VCPU_ID, &uc)) { 577 case UCALL_SYNC: 578 TEST_ASSERT(uc.args[1] == stage, 579 "Unexpected stage: %ld (%d expected)\n", 580 uc.args[1], stage); 581 break; 582 case UCALL_ABORT: 583 TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0], 584 __FILE__, uc.args[1]); 585 return; 586 case UCALL_DONE: 587 return; 588 } 589 590 stage++; 591 } 592 } 593 594 int main(void) 595 { 596 struct kvm_cpuid2 *best; 597 struct kvm_vm *vm; 598 vm_vaddr_t msr_gva, hcall_page, hcall_params; 599 struct kvm_enable_cap cap = { 600 .cap = KVM_CAP_HYPERV_ENFORCE_CPUID, 601 .args = {1} 602 }; 603 604 /* Test MSRs */ 605 vm = vm_create_default(VCPU_ID, 0, guest_msr); 606 607 msr_gva = vm_vaddr_alloc_page(vm); 608 memset(addr_gva2hva(vm, msr_gva), 0x0, getpagesize()); 609 vcpu_args_set(vm, VCPU_ID, 1, msr_gva); 610 vcpu_enable_cap(vm, VCPU_ID, &cap); 611 612 vcpu_set_hv_cpuid(vm, VCPU_ID); 613 614 best = kvm_get_supported_hv_cpuid(); 615 616 vm_init_descriptor_tables(vm); 617 vcpu_init_descriptor_tables(vm, VCPU_ID); 618 vm_install_exception_handler(vm, GP_VECTOR, guest_gp_handler); 619 620 pr_info("Testing access to Hyper-V specific MSRs\n"); 621 guest_test_msrs_access(vm, addr_gva2hva(vm, msr_gva), 622 best); 623 kvm_vm_free(vm); 624 625 /* Test hypercalls */ 626 vm = vm_create_default(VCPU_ID, 0, guest_hcall); 627 628 /* Hypercall input/output */ 629 hcall_page = vm_vaddr_alloc_pages(vm, 2); 630 memset(addr_gva2hva(vm, hcall_page), 0x0, 2 * getpagesize()); 631 632 hcall_params = vm_vaddr_alloc_page(vm); 633 memset(addr_gva2hva(vm, hcall_params), 0x0, getpagesize()); 634 635 vcpu_args_set(vm, VCPU_ID, 2, addr_gva2gpa(vm, hcall_page), hcall_params); 636 vcpu_enable_cap(vm, VCPU_ID, &cap); 637 638 vcpu_set_hv_cpuid(vm, VCPU_ID); 639 640 best = kvm_get_supported_hv_cpuid(); 641 642 pr_info("Testing access to Hyper-V hypercalls\n"); 643 guest_test_hcalls_access(vm, addr_gva2hva(vm, hcall_params), 644 addr_gva2hva(vm, hcall_page), 645 addr_gva2hva(vm, hcall_page) + getpagesize(), 646 best); 647 648 kvm_vm_free(vm); 649 } 650