Changeset 92578 in vbox
- Timestamp:
- Nov 24, 2021 1:51:03 AM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 148460
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/NEMR3Native-linux.cpp
r92555 r92578 34 34 #include <iprt/string.h> 35 35 #include <iprt/system.h> 36 #include <iprt/x86.h> 36 37 37 38 #include <errno.h> … … 417 418 418 419 /* 420 * Enable user space MSRs and let us check everything KVM cannot handle. 421 * We will set up filtering later when ring-3 init has completed. 422 */ 423 struct kvm_enable_cap CapEn = 424 { 425 KVM_CAP_X86_USER_SPACE_MSR, 0, 426 { KVM_MSR_EXIT_REASON_FILTER | KVM_MSR_EXIT_REASON_UNKNOWN | KVM_MSR_EXIT_REASON_INVAL, 0, 0, 0} 427 }; 428 int rcLnx = ioctl(pVM->nem.s.fdVm, KVM_ENABLE_CAP, &CapEn); 429 if (rcLnx == -1) 430 return RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, "Failed to enable KVM_CAP_X86_USER_SPACE_MSR failed: %u", errno); 431 432 /* 419 433 * Create the VCpus. 420 434 */ … … 426 440 pVCpu->nem.s.fdVCpu = ioctl(pVM->nem.s.fdVm, KVM_CREATE_VCPU, (unsigned long)idCpu); 427 441 if (pVCpu->nem.s.fdVCpu < 0) 428 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 429 "KVM_CREATE_VCPU failed for VCpu #%u: %d", idCpu, errno); 442 return RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, "KVM_CREATE_VCPU failed for VCpu #%u: %d", idCpu, errno); 430 443 431 444 /* Map the KVM_RUN area. */ … … 433 446 pVCpu->nem.s.fdVCpu, 0 /*offset*/); 434 447 if ((void *)pVCpu->nem.s.pRun == MAP_FAILED) 435 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, "mmap failed for VCpu #%u: %d", idCpu, errno);448 return RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, "mmap failed for VCpu #%u: %d", idCpu, errno); 436 449 437 450 /* We want all x86 registers and events on each exit. */ … … 672 685 AssertRCReturn(rc, rc); 673 686 } 687 } 688 689 /* 690 * Configure MSRs after ring-3 init is done. 691 * 692 * We only need to tell KVM which MSRs it can handle, as we already 693 * requested KVM_MSR_EXIT_REASON_FILTER, KVM_MSR_EXIT_REASON_UNKNOWN 694 * and KVM_MSR_EXIT_REASON_INVAL in nemR3LnxInitSetupVm, and here we 695 * will use KVM_MSR_FILTER_DEFAULT_DENY. So, all MSRs w/o a 1 in the 696 * bitmaps should be deferred to ring-3. 697 */ 698 if (enmWhat == VMINITCOMPLETED_RING3) 699 { 700 struct kvm_msr_filter MsrFilters = {0}; /* Structure with a couple of implicit paddings on 64-bit systems. */ 701 MsrFilters.flags = KVM_MSR_FILTER_DEFAULT_DENY; 702 703 unsigned iRange = 0; 704 #define MSR_RANGE_BEGIN(a_uBase, a_uEnd, a_fFlags) \ 705 AssertCompile(0x3000 <= KVM_MSR_FILTER_MAX_BITMAP_SIZE * 8); \ 706 uint64_t RT_CONCAT(bm, a_uBase)[0x3000 / 64] = {0}; \ 707 do { \ 708 uint64_t * const pbm = RT_CONCAT(bm, a_uBase); \ 709 uint32_t const uBase = UINT32_C(a_uBase); \ 710 uint32_t const cMsrs = UINT32_C(a_uEnd) - UINT32_C(a_uBase); \ 711 MsrFilters.ranges[iRange].base = UINT32_C(a_uBase); \ 712 MsrFilters.ranges[iRange].nmsrs = cMsrs; \ 713 MsrFilters.ranges[iRange].flags = (a_fFlags); \ 714 MsrFilters.ranges[iRange].bitmap = (uint8_t *)&RT_CONCAT(bm, a_uBase)[0] 715 #define MSR_RANGE_ADD(a_Msr) \ 716 do { Assert((uint32_t)(a_Msr) - uBase < cMsrs); ASMBitSet(pbm, (uint32_t)(a_Msr) - uBase); } while (0) 717 #define MSR_RANGE_END(a_cMinMsrs) \ 718 /* optimize the range size before closing: */ \ 719 uint32_t cBitmap = cMsrs / 64; \ 720 while (cBitmap > ((a_cMinMsrs) + 63 / 64) && pbm[cBitmap - 1] == 0) \ 721 cBitmap -= 1; \ 722 MsrFilters.ranges[iRange].nmsrs = cBitmap * 64; \ 723 iRange++; \ 724 } while (0) 725 726 /* 1st Intel range: 0000_0000 to 0000_3000. */ 727 MSR_RANGE_BEGIN(0x00000000, 0x00003000, KVM_MSR_FILTER_READ | KVM_MSR_FILTER_WRITE); 728 MSR_RANGE_ADD(MSR_IA32_TSC); 729 MSR_RANGE_ADD(MSR_IA32_SYSENTER_CS); 730 MSR_RANGE_ADD(MSR_IA32_SYSENTER_ESP); 731 MSR_RANGE_ADD(MSR_IA32_SYSENTER_EIP); 732 MSR_RANGE_ADD(MSR_IA32_CR_PAT); 733 /** @todo more? */ 734 MSR_RANGE_END(64); 735 736 /* 1st AMD range: c000_0000 to c000_3000 */ 737 MSR_RANGE_BEGIN(0xc0000000, 0xc0003000, KVM_MSR_FILTER_READ | KVM_MSR_FILTER_WRITE); 738 MSR_RANGE_ADD(MSR_K6_EFER); 739 MSR_RANGE_ADD(MSR_K6_STAR); 740 MSR_RANGE_ADD(MSR_K8_GS_BASE); 741 MSR_RANGE_ADD(MSR_K8_KERNEL_GS_BASE); 742 MSR_RANGE_ADD(MSR_K8_LSTAR); 743 MSR_RANGE_ADD(MSR_K8_CSTAR); 744 MSR_RANGE_ADD(MSR_K8_SF_MASK); 745 MSR_RANGE_ADD(MSR_K8_TSC_AUX); 746 /** @todo add more? */ 747 MSR_RANGE_END(64); 748 749 /** @todo Specify other ranges too? Like hyper-V and KVM to make sure we get 750 * the MSR requests instead of KVM. */ 751 752 int rcLnx = ioctl(pVM->nem.s.fdVm, KVM_X86_SET_MSR_FILTER, &MsrFilters); 753 if (rcLnx == -1) 754 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 755 "Failed to enable KVM_X86_SET_MSR_FILTER failed: %u", errno); 674 756 } 675 757 … … 2139 2221 2140 2222 /* 2141 * We cannot actually act on the exit history here, because the I/O port2223 * We cannot easily act on the exit history here, because the I/O port 2142 2224 * exit is stateful and the instruction will be completed in the next 2143 2225 * KVM_RUN call. There seems no way to avoid this. … … 2224 2306 2225 2307 /* 2226 * We cannot actually act on the exit history here, because the MMIO port2308 * We cannot easily act on the exit history here, because the MMIO port 2227 2309 * exit is stateful and the instruction will be completed in the next 2228 2310 * KVM_RUN call. There seems no way to circumvent this. … … 2254 2336 return rcStrict; 2255 2337 } 2338 2339 2340 /** 2341 * Handles KVM_EXIT_RDMSR 2342 */ 2343 static VBOXSTRICTRC nemHCLnxHandleExitRdMsr(PVMCPUCC pVCpu, struct kvm_run *pRun) 2344 { 2345 /* 2346 * Input validation. 2347 */ 2348 Assert( pRun->msr.reason == KVM_MSR_EXIT_REASON_INVAL 2349 || pRun->msr.reason == KVM_MSR_EXIT_REASON_UNKNOWN 2350 || pRun->msr.reason == KVM_MSR_EXIT_REASON_FILTER); 2351 2352 /* 2353 * We cannot easily act on the exit history here, because the MSR exit is 2354 * stateful and the instruction will be completed in the next KVM_RUN call. 2355 * There seems no way to circumvent this. 2356 */ 2357 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ), 2358 pRun->s.regs.regs.rip + pRun->s.regs.sregs.cs.base, ASMReadTSC()); 2359 2360 /* 2361 * Do the requested job. 2362 */ 2363 uint64_t uValue = 0; 2364 VBOXSTRICTRC rcStrict = CPUMQueryGuestMsr(pVCpu, pRun->msr.index, &uValue); 2365 pRun->msr.data = uValue; 2366 if (rcStrict != VERR_CPUM_RAISE_GP_0) 2367 { 2368 Log3(("MsrRead/%u: %04x:%08RX64: msr=%#010x (reason=%#x) -> %#RX64 rcStrict=%Rrc\n", pVCpu->idCpu, 2369 pRun->s.regs.sregs.cs.selector, pRun->s.regs.regs.rip, pRun->msr.index, pRun->msr.reason, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2370 pRun->msr.error = 0; 2371 } 2372 else 2373 { 2374 Log3(("MsrRead/%u: %04x:%08RX64: msr=%#010x (reason%#x)-> %#RX64 rcStrict=#GP!\n", pVCpu->idCpu, 2375 pRun->s.regs.sregs.cs.selector, pRun->s.regs.regs.rip, pRun->msr.index, pRun->msr.reason, uValue)); 2376 pRun->msr.error = 1; 2377 rcStrict = VINF_SUCCESS; 2378 } 2379 return rcStrict; 2380 } 2381 2382 2383 /** 2384 * Handles KVM_EXIT_WRMSR 2385 */ 2386 static VBOXSTRICTRC nemHCLnxHandleExitWrMsr(PVMCPUCC pVCpu, struct kvm_run *pRun) 2387 { 2388 /* 2389 * Input validation. 2390 */ 2391 Assert( pRun->msr.reason == KVM_MSR_EXIT_REASON_INVAL 2392 || pRun->msr.reason == KVM_MSR_EXIT_REASON_UNKNOWN 2393 || pRun->msr.reason == KVM_MSR_EXIT_REASON_FILTER); 2394 2395 /* 2396 * We cannot easily act on the exit history here, because the MSR exit is 2397 * stateful and the instruction will be completed in the next KVM_RUN call. 2398 * There seems no way to circumvent this. 2399 */ 2400 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE), 2401 pRun->s.regs.regs.rip + pRun->s.regs.sregs.cs.base, ASMReadTSC()); 2402 2403 /* 2404 * Do the requested job. 2405 */ 2406 VBOXSTRICTRC rcStrict = CPUMSetGuestMsr(pVCpu, pRun->msr.index, pRun->msr.data); 2407 if (rcStrict != VERR_CPUM_RAISE_GP_0) 2408 { 2409 Log3(("MsrWrite/%u: %04x:%08RX64: msr=%#010x := %#RX64 (reason=%#x) -> rcStrict=%Rrc\n", pVCpu->idCpu, 2410 pRun->s.regs.sregs.cs.selector, pRun->s.regs.regs.rip, pRun->msr.index, pRun->msr.data, pRun->msr.reason, VBOXSTRICTRC_VAL(rcStrict) )); 2411 pRun->msr.error = 0; 2412 } 2413 else 2414 { 2415 Log3(("MsrWrite/%u: %04x:%08RX64: msr=%#010x := %#RX64 (reason%#x)-> rcStrict=#GP!\n", pVCpu->idCpu, 2416 pRun->s.regs.sregs.cs.selector, pRun->s.regs.regs.rip, pRun->msr.index, pRun->msr.data, pRun->msr.reason)); 2417 pRun->msr.error = 1; 2418 rcStrict = VINF_SUCCESS; 2419 } 2420 return rcStrict; 2421 } 2422 2256 2423 2257 2424 … … 2295 2462 case KVM_EXIT_X86_RDMSR: 2296 2463 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitRdMsr); 2297 AssertFailed();2298 break;2464 *pfStatefulExit = true; 2465 return nemHCLnxHandleExitRdMsr(pVCpu, pRun); 2299 2466 2300 2467 case KVM_EXIT_X86_WRMSR: 2301 2468 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitWrMsr); 2302 AssertFailed();2303 break;2469 *pfStatefulExit = true; 2470 return nemHCLnxHandleExitWrMsr(pVCpu, pRun); 2304 2471 2305 2472 case KVM_EXIT_HLT:
Note:
See TracChangeset
for help on using the changeset viewer.