Changeset 71293 in vbox
- Timestamp:
- Mar 9, 2018 9:11:20 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
-
include/VBox/vmm/vm.h (modified) (2 diffs)
-
include/VBox/vmm/vm.mac (modified) (1 diff)
-
include/iprt/nt/hyperv.h (modified) (1 diff)
-
src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h (modified) (13 diffs)
-
src/VBox/VMM/VMMR3/EM.cpp (modified) (2 diffs)
-
src/VBox/VMM/VMMR3/EMR3Nem.cpp (modified) (2 diffs)
-
src/VBox/VMM/VMMR3/NEMR3Native-win.cpp (modified) (6 diffs)
-
src/VBox/VMM/include/NEMInternal.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/vm.h
r71129 r71293 178 178 struct NEMCPU s; 179 179 #endif 180 uint8_t padding[ 256]; /* multiple of 64 */180 uint8_t padding[512]; /* multiple of 64 */ 181 181 } nem; 182 182 … … 267 267 268 268 /** Align the following members on page boundary. */ 269 uint8_t abAlignment2[1 848];269 uint8_t abAlignment2[1592]; 270 270 271 271 /** PGM part. */ -
trunk/include/VBox/vmm/vm.mac
r71075 r71293 64 64 .hm resb 5824 65 65 .em resb 1408 66 .nem resb 25666 .nem resb 512 67 67 .trpm resb 128 68 68 .tm resb 384 -
trunk/include/iprt/nt/hyperv.h
r71184 r71293 198 198 HvCallUncommitGpaPages, /**< Happens when VidDestroyGpaRangeCheckSecure/WHvUnmapGpaRange is called. */ 199 199 /* 0xc0..0xcb are unknown */ 200 HvCallVpRunloopRelated = 0xc2, /**< Fast */ 200 201 HvCallQueryVtlProtectionMaskRange = 0xcc, 201 202 HvCallModifyVtlProtectionMaskRange, -
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r71224 r71293 839 839 { 840 840 Log8(("nemHCWinCancelRunVirtualProcessor: Switched %u to canceled state\n", pVCpu->idCpu)); 841 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatCancelChangedState); 841 842 return VINF_SUCCESS; 842 843 } … … 854 855 Assert(rcNt == STATUS_SUCCESS); 855 856 if (NT_SUCCESS(rcNt)) 857 { 858 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatCancelAlertedThread); 856 859 return VINF_SUCCESS; 860 } 857 861 AssertLogRelMsgFailedReturn(("NtAlertThread failed: %#x\n", rcNt), RTErrConvertFromNtStatus(rcNt)); 858 862 } … … 1454 1458 case HvMessageTypeUnmappedGpa: 1455 1459 Assert(pMsg->Header.PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment)); 1460 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitMemUnmapped); 1456 1461 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx, pGVCpu); 1457 1462 1458 1463 case HvMessageTypeGpaIntercept: 1459 1464 Assert(pMsg->Header.PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment)); 1465 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitMemIntercept); 1460 1466 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx, pGVCpu); 1461 1467 1462 1468 case HvMessageTypeX64IoPortIntercept: 1463 1469 Assert(pMsg->Header.PayloadSize == sizeof(pMsg->X64IoPortIntercept)); 1470 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitPortIo); 1464 1471 return nemHCWinHandleMessageIoPort(pVM, pVCpu, &pMsg->X64IoPortIntercept, pCtx, pGVCpu); 1465 1472 1466 1473 case HvMessageTypeX64Halt: 1474 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitHalt); 1467 1475 return VINF_EM_HALT; 1468 1476 … … 1536 1544 { 1537 1545 Log8(("nemHCWinStopCpu: Stopping CPU succeeded (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 1546 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatStopCpuSuccess); 1538 1547 return rcStrict; 1539 1548 } … … 1543 1552 { 1544 1553 Log8(("nemHCWinStopCpu: Stopping CPU succeeded (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 1554 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatStopCpuSuccess); 1545 1555 return rcStrict; 1546 1556 } … … 1560 1570 # endif 1561 1571 Log8(("nemHCWinStopCpu: Stopping CPU pending...\n")); 1572 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatStopCpuPending); 1562 1573 1563 1574 /* … … 1652 1663 1653 1664 /* 1665 * Try switch to NEM runloop state. 1666 */ 1667 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED)) 1668 { /* likely */ } 1669 else 1670 { 1671 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED); 1672 LogFlow(("NEM/%u: returning immediately because canceled\n", pVCpu->idCpu)); 1673 return VINF_SUCCESS; 1674 } 1675 1676 /* 1654 1677 * The run loop. 1655 1678 * … … 1704 1727 } 1705 1728 1706 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED ))1729 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM)) 1707 1730 { 1708 1731 # ifdef IN_RING0 … … 1714 1737 sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext), 1715 1738 NULL, 0); 1716 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED , VMCPUSTATE_STARTED_EXEC_NEM_WAIT);1739 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT); 1717 1740 if (rcNt == STATUS_SUCCESS) 1718 1741 # else 1719 1742 BOOL fRet = VidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, 1720 1743 pVCpu->nem.s.fHandleAndGetFlags, cMillies); 1721 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED , VMCPUSTATE_STARTED_EXEC_NEM_WAIT);1744 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT); 1722 1745 if (fRet) 1723 1746 # endif … … 1733 1756 { 1734 1757 LogFlow(("NEM/%u: breaking: nemHCWinHandleMessage -> %Rrc\n", pVCpu->idCpu, VBOXSTRICTRC_VAL(rcStrict) )); 1758 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnStatus); 1735 1759 break; 1736 1760 } … … 1750 1774 , ("VidMessageSlotHandleAndGetNext failed for CPU #%u: %#x (%u)\n", pVCpu->idCpu, rcNt, rcNt), 1751 1775 VERR_INTERNAL_ERROR_3); 1752 pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; /* exits are likely */ 1776 pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; 1777 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatGetMsgTimeout); 1753 1778 } 1754 1779 … … 1764 1789 LogFlow(("NEM/%u: breaking: pending FF (%#x / %#x)\n", 1765 1790 pVCpu->idCpu, pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions)); 1791 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnFFPost); 1766 1792 } 1767 1793 else 1794 { 1768 1795 LogFlow(("NEM/%u: breaking: canceled %d (pre exec)\n", pVCpu->idCpu, VMCPU_GET_STATE(pVCpu) )); 1796 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnCancel); 1797 } 1769 1798 } 1770 1799 else 1800 { 1771 1801 LogFlow(("NEM/%u: breaking: pending FF (pre exec)\n", pVCpu->idCpu)); 1802 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnFFPre); 1803 } 1772 1804 break; 1773 1805 } /* the run loop */ … … 1784 1816 } 1785 1817 1786 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED); 1818 if (!VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM)) 1819 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED); 1787 1820 1788 1821 if (pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | (CPUMCTX_EXTRN_NEM_WIN_MASK & ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT))) -
trunk/src/VBox/VMM/VMMR3/EM.cpp
r71020 r71293 430 430 EM_REG_PROFILE(&pVCpu->em.s.StatIEMThenREM, "/PROF/CPU%d/EM/IEMThenRem", "Profiling IEM-then-REM instruction execution (by IEM)."); 431 431 EM_REG_PROFILE(&pVCpu->em.s.StatNEMEntry, "/PROF/CPU%d/EM/NEMEnter", "Profiling NEM entry overhead."); 432 #endif /* VBOX_WITH_STATISTICS */ 432 433 EM_REG_PROFILE(&pVCpu->em.s.StatNEMExec, "/PROF/CPU%d/EM/NEMExec", "Profiling NEM execution."); 433 434 EM_REG_COUNTER(&pVCpu->em.s.StatNEMExecuteCalled, "/PROF/CPU%d/EM/NEMExecuteCalled", "Number of times enmR3NEMExecute is called."); 435 #ifdef VBOX_WITH_STATISTICS 434 436 EM_REG_PROFILE(&pVCpu->em.s.StatREMEmu, "/PROF/CPU%d/EM/REMEmuSingle", "Profiling single instruction REM execution."); 435 437 EM_REG_PROFILE(&pVCpu->em.s.StatREMExec, "/PROF/CPU%d/EM/REMExec", "Profiling REM execution."); … … 438 440 EM_REG_PROFILE(&pVCpu->em.s.StatRAWExec, "/PROF/CPU%d/EM/RAWExec", "Profiling Raw Mode execution."); 439 441 EM_REG_PROFILE(&pVCpu->em.s.StatRAWTail, "/PROF/CPU%d/EM/RAWTail", "Profiling Raw Mode tail overhead."); 440 441 442 #endif /* VBOX_WITH_STATISTICS */ 442 443 -
trunk/src/VBox/VMM/VMMR3/EMR3Nem.cpp
r71031 r71293 361 361 *pfFFDone = false; 362 362 363 STAM_ COUNTER_INC(&pVCpu->em.s.StatNEMExecuteCalled);363 STAM_REL_COUNTER_INC(&pVCpu->em.s.StatNEMExecuteCalled); 364 364 365 365 /* … … 421 421 * Execute the code. 422 422 */ 423 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatNEMEntry, a);424 425 423 if (RT_LIKELY(emR3IsExecutionAllowed(pVM, pVCpu))) 426 424 { 427 STAM_PROFILE_START(&pVCpu->em.s.StatNEMExec, x); 425 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatNEMEntry, a); 426 STAM_REL_PROFILE_START(&pVCpu->em.s.StatNEMExec, x); 428 427 rcStrict = NEMR3RunGC(pVM, pVCpu); 429 STAM_ PROFILE_STOP(&pVCpu->em.s.StatNEMExec, x);428 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatNEMExec, x); 430 429 } 431 430 else 432 431 { 433 432 /* Give up this time slice; virtual time continues */ 433 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatNEMEntry, a); 434 434 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatCapped, u); 435 435 RTThreadSleep(5); -
trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
r71289 r71293 1100 1100 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API); 1101 1101 Log(("NEM: Marked active!\n")); 1102 1103 /* Register release statistics */ 1104 for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++) 1105 { 1106 PNEMCPU pNemCpu = &pVM->aCpus[iCpu].nem.s; 1107 STAMR3RegisterF(pVM, &pNemCpu->StatExitPortIo, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of port I/O exits", "/NEM/CPU%u/ExitPortIo", iCpu); 1108 STAMR3RegisterF(pVM, &pNemCpu->StatExitMemUnmapped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of unmapped memory exits", "/NEM/CPU%u/ExitMemUnmapped", iCpu); 1109 STAMR3RegisterF(pVM, &pNemCpu->StatExitMemIntercept, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of intercepted memory exits", "/NEM/CPU%u/ExitMemIntercept", iCpu); 1110 STAMR3RegisterF(pVM, &pNemCpu->StatExitHalt, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of HLT exits", "/NEM/CPU%u/ExitHalt", iCpu); 1111 STAMR3RegisterF(pVM, &pNemCpu->StatGetMsgTimeout, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of get message timeouts/alerts", "/NEM/CPU%u/GetMsgTimeout", iCpu); 1112 STAMR3RegisterF(pVM, &pNemCpu->StatStopCpuSuccess, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of successful CPU stops", "/NEM/CPU%u/StopCpuSuccess", iCpu); 1113 STAMR3RegisterF(pVM, &pNemCpu->StatStopCpuPending, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of pending CPU stops", "/NEM/CPU%u/StopCpuPending", iCpu); 1114 STAMR3RegisterF(pVM, &pNemCpu->StatCancelChangedState, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of cancel changed state", "/NEM/CPU%u/CancelChangedState", iCpu); 1115 STAMR3RegisterF(pVM, &pNemCpu->StatCancelAlertedThread, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of cancel alerted EMT", "/NEM/CPU%u/CancelAlertedEMT", iCpu); 1116 STAMR3RegisterF(pVM, &pNemCpu->StatBreakOnFFPre, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of pre execution FF breaks", "/NEM/CPU%u/BreakOnFFPre", iCpu); 1117 STAMR3RegisterF(pVM, &pNemCpu->StatBreakOnFFPost, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of post execution FF breaks", "/NEM/CPU%u/BreakOnFFPost", iCpu); 1118 STAMR3RegisterF(pVM, &pNemCpu->StatBreakOnCancel, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of cancel execution breaks", "/NEM/CPU%u/BreakOnCancel", iCpu); 1119 STAMR3RegisterF(pVM, &pNemCpu->StatBreakOnStatus, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of status code breaks", "/NEM/CPU%u/BreakOnStatus", iCpu); 1120 } 1102 1121 } 1103 1122 } … … 1275 1294 int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat) 1276 1295 { 1296 //BOOL fRet = SetThreadPriority(GetCurrentThread(), 0); 1297 //AssertLogRel(fRet); 1298 1277 1299 NOREF(pVM); NOREF(enmWhat); 1278 1300 return VINF_SUCCESS; … … 2235 2257 * The CPU creation function boils down to a VidMessageSlotMap call that sets up 2236 2258 * and maps a message buffer into ring-3 for async communication with hyper-V 2237 * and/or the VID.SYS thread actually running the CPU . When for instance a2238 * VMEXIT is encountered, hyper-V sends a message that the2239 * WHvRunVirtualProcessor API retrieves (and later acknowledges) via2240 * VidMessageSlotHandleAndGetNext. It should be noteded that2259 * and/or the VID.SYS thread actually running the CPU thru 2260 * WinHvRunVpDispatchLoop(). When for instance a VMEXIT is encountered, hyper-V 2261 * sends a message that the WHvRunVirtualProcessor API retrieves (and later 2262 * acknowledges) via VidMessageSlotHandleAndGetNext. It should be noteded that 2241 2263 * WHvDeleteVirtualProcessor doesn't do much as there seems to be no partner 2242 2264 * function VidMessagesSlotMap that reverses what it did. … … 2257 2279 * VMEXIT message. Hyper-V / VID.SYS will return information about the message 2258 2280 * in the message buffer mapping, and WHvRunVirtualProcessor will convert that 2259 * into it's own WHV_RUN_VP_EXIT_CONTEXT format.2281 * finto it's own WHV_RUN_VP_EXIT_CONTEXT format. 2260 2282 * 2261 2283 * Other threads can interrupt the execution by using WHvCancelVirtualProcessor, … … 2288 2310 * and 5% for MMIO. 2289 2311 * 2312 * While the tests we've done are using tight tight loops only doing port I/O 2313 * and MMIO, the problem is clearly visible when running regular guest OSes. 2314 * Anything that hammers the VGA device would be suffering, for example: 2315 * 2316 * - Windows 2000 boot screen animation overloads us with MMIO exits 2317 * and won't even boot because all the time is spent in interrupt 2318 * handlers and redrawin the screen. 2319 * 2320 * - DSL 4.4 and its bootmenu logo is slower than molasses in january. 2321 * 2322 * We have not found a workaround for this yet. 2323 * 2324 * Something that might improve the issue a little is to detect blocks with 2325 * excessive MMIO and port I/O exits and emulate instructions to cover 2326 * multiple exits before letting Hyper-V have a go at the guest execution 2327 * again. This will only improve the situation under some circumstances, 2328 * since emulating instructions without recompilation can be expensive, so 2329 * there will only be real gains if the exitting instructions are tightly 2330 * packed. 2331 * 2290 2332 * 2291 2333 * - The WHvCancelVirtualProcessor API schedules a dummy usermode APC callback … … 2417 2459 * 2418 2460 * 2419 * - Why does WINHVR.SYS (or VID.SYS) only query/set 32 registers at the time2420 * thru theHvCallGetVpRegisters and HvCallSetVpRegisters hypercalls?2461 * - Why does VID.SYS only query/set 32 registers at the time thru the 2462 * HvCallGetVpRegisters and HvCallSetVpRegisters hypercalls? 2421 2463 * 2422 2464 * We've not trouble getting/setting all the registers defined by 2423 * WHV_REGISTER_NAME in one hypercall (around 80)... 2465 * WHV_REGISTER_NAME in one hypercall (around 80). Some kind of stack 2466 * buffering or similar? 2424 2467 * 2425 2468 * -
trunk/src/VBox/VMM/include/NEMInternal.h
r71224 r71293 211 211 # endif 212 212 } uIoCtlBuf; 213 214 /** @name Statistics 215 * @{ */ 216 STAMCOUNTER StatExitPortIo; 217 STAMCOUNTER StatExitMemUnmapped; 218 STAMCOUNTER StatExitMemIntercept; 219 STAMCOUNTER StatExitHalt; 220 STAMCOUNTER StatGetMsgTimeout; 221 STAMCOUNTER StatStopCpuSuccess; 222 STAMCOUNTER StatStopCpuPending; 223 STAMCOUNTER StatCancelChangedState; 224 STAMCOUNTER StatCancelAlertedThread; 225 STAMCOUNTER StatBreakOnCancel; 226 STAMCOUNTER StatBreakOnFFPre; 227 STAMCOUNTER StatBreakOnFFPost; 228 STAMCOUNTER StatBreakOnStatus; 229 /** @} */ 213 230 #endif 214 231 } NEMCPU;
Note:
See TracChangeset
for help on using the changeset viewer.

