Changeset 54339 in vbox
- Timestamp:
- Feb 20, 2015 6:10:12 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/sup.h
r54333 r54339 1806 1806 SUPR0DECL(bool) SUPR0SuspendVTxOnCpu(void); 1807 1807 SUPR0DECL(void) SUPR0ResumeVTxOnCpu(bool fSuspended); 1808 #define SUP_TSCDELTA_MEASURE_F_FORCE RT_BIT_32(0) 1809 #define SUP_TSCDELTA_MEASURE_F_ASYNC RT_BIT_32(1) 1810 #define SUP_TSCDELTA_MEASURE_F_VALID_MASK UINT32_C(0x00000003) 1811 SUPR0DECL(int) SUPR0TscDeltaMeasureBySetIndex(PSUPDRVSESSION pSession, uint32_t iCpuSet, uint32_t fFlags, 1812 RTMSINTERVAL cMsWaitRetry, RTMSINTERVAL cMsWaitThread, uint32_t cTries); 1808 1813 1809 1814 /** @name Absolute symbols -
trunk/include/VBox/vmm/cpum.h
r53615 r54339 1336 1336 VMMR0_INT_DECL(void) CPUMR0LoadHyperDebugState(PVMCPU pVCpu, bool fDr6); 1337 1337 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI 1338 VMMR0_INT_DECL(void) CPUMR0SetLApic(PVMCPU pVCpu, RTCPUID idHostCpu);1338 VMMR0_INT_DECL(void) CPUMR0SetLApic(PVMCPU pVCpu, uint32_t iHostCpuSet); 1339 1339 #endif 1340 1340 -
trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
r54331 r54339 180 180 { "SUPR0PageFree", (void *)SUPR0PageFree }, 181 181 { "SUPR0Printf", (void *)SUPR0Printf }, 182 { "SUPR0TscDeltaMeasureBySetIndex", (void *)SUPR0TscDeltaMeasureBySetIndex }, 182 183 { "SUPR0TracerDeregisterDrv", (void *)SUPR0TracerDeregisterDrv }, 183 184 { "SUPR0TracerDeregisterImpl", (void *)SUPR0TracerDeregisterImpl }, -
trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
r54334 r54339 2793 2793 * 2794 2794 * @returns VBox status code. 2795 * @retval VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED on pure measurement 2796 * failure. 2795 2797 * @param pDevExt Pointer to the device instance data. 2796 2798 * @param idxWorker The index of the worker CPU from the GIP's array of … … 3403 3405 } 3404 3406 3405 3406 3407 #endif /* SUPDRV_USE_TSC_DELTA_THREAD */ 3408 3409 /** 3410 * Measure the TSC delta for the CPU given by its CPU set index. 3411 * 3412 * @returns VBox status code. 3413 * @retval VERR_INTERRUPTED if interrupted while waiting. 3414 * @retval VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED if we were unable to get a 3415 * measurment. 3416 * @retval VERR_CPU_OFFLINE if the specified CPU is offline. 3417 * @retval VERR_CPU_OFFLINE if the specified CPU is offline. 3418 * 3419 * @param pSession The caller's session. GIP must've been mapped. 3420 * @param iCpuSet The CPU set index of the CPU to measure. 3421 * @param fFlags Flags, SUP_TSCDELTA_MEASURE_F_XXX. 3422 * @param cMsWaitRetry Number of milliseconds to wait between each retry. 3423 * @param cMsWaitThread Number of milliseconds to wait for the thread to get 3424 * ready. 3425 * @param cTries Number of times to try, pass 0 for the default. 3426 */ 3427 SUPR0DECL(int) SUPR0TscDeltaMeasureBySetIndex(PSUPDRVSESSION pSession, uint32_t iCpuSet, uint32_t fFlags, 3428 RTMSINTERVAL cMsWaitRetry, RTMSINTERVAL cMsWaitThread, uint32_t cTries) 3429 { 3430 PSUPDRVDEVEXT pDevExt; 3431 PSUPGLOBALINFOPAGE pGip; 3432 uint16_t iGipCpu; 3433 int rc; 3434 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 3435 uint64_t msTsStartWait; 3436 uint32_t iWaitLoop; 3437 #endif 3438 3439 /* 3440 * Validate and adjust the input. 3441 */ 3442 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER); 3443 if (!pSession->fGipReferenced) 3444 return VERR_WRONG_ORDER; 3445 3446 pDevExt = pSession->pDevExt; 3447 AssertReturn(SUP_IS_DEVEXT_VALID(pDevExt), VERR_INVALID_PARAMETER); 3448 3449 pGip = pDevExt->pGip; 3450 AssertPtrReturn(pGip, VERR_INTERNAL_ERROR_2); 3451 3452 AssertReturn(iCpuSet < RTCPUSET_MAX_CPUS, VERR_INVALID_CPU_INDEX); 3453 AssertReturn(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx), VERR_INVALID_CPU_INDEX); 3454 iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet]; 3455 AssertReturn(iGipCpu < pGip->cCpus, VERR_INVALID_CPU_INDEX); 3456 3457 if (fFlags & ~SUP_TSCDELTA_MEASURE_F_VALID_MASK) 3458 return VERR_INVALID_FLAGS; 3459 3460 if (cTries == 0) 3461 cTries = 12; 3462 else if (cTries > 256) 3463 cTries = 256; 3464 3465 if (cMsWaitRetry > 1000) 3466 cMsWaitRetry = 1000; 3467 3468 /* 3469 * The request is a noop if the TSC delta isn't being used. 3470 */ 3471 if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED) 3472 return VINF_SUCCESS; 3473 3474 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 3475 /* 3476 * Has the TSC already been measured and we're not forced to redo it? 3477 */ 3478 if ( pGip->aCPUs[iGipCpu].i64TSCDelta != INT64_MAX 3479 && !(fFlags & SUP_TSCDELTA_MEASURE_F_FORCE)) 3480 return VINF_SUCCESS; 3481 3482 /* 3483 * Asynchronous request? Forward it to the thread, no waiting. 3484 */ 3485 if (fFlags & SUP_TSCDELTA_MEASURE_F_ASYNC) 3486 { 3487 /** @todo Async. doesn't implement options like retries, waiting. We'll need 3488 * to pass those options to the thread somehow and implement it in the 3489 * thread. Check if anyone uses/needs fAsync before implementing this. */ 3490 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); 3491 RTCpuSetAddByIndex(&pDevExt->TscDeltaCpuSet, iCpuSet); 3492 if ( pDevExt->enmTscDeltaThreadState == kTscDeltaThreadState_Listening 3493 || pDevExt->enmTscDeltaThreadState == kTscDeltaThreadState_Measuring) 3494 { 3495 pDevExt->enmTscDeltaThreadState = kTscDeltaThreadState_WaitAndMeasure; 3496 rc = VINF_SUCCESS; 3497 } 3498 else 3499 rc = VERR_THREAD_IS_DEAD; 3500 RTSpinlockRelease(pDevExt->hTscDeltaSpinlock); 3501 RTThreadUserSignal(pDevExt->hTscDeltaThread); 3502 return VINF_SUCCESS; 3503 } 3504 3505 /* 3506 * If a TSC-delta measurement request is already being serviced by the thread, 3507 * wait 'cTries' times if a retry-timeout is provided, otherwise bail as busy. 3508 */ 3509 msTsStartWait = RTTimeSystemMilliTS(); 3510 for (iWaitLoop = 0;; iWaitLoop++) 3511 { 3512 uint64_t cMsElapsed; 3513 SUPDRVTSCDELTATHREADSTATE enmState; 3514 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); 3515 enmState = pDevExt->enmTscDeltaThreadState; 3516 RTSpinlockRelease(pDevExt->hTscDeltaSpinlock); 3517 3518 if (enmState == kTscDeltaThreadState_Measuring) 3519 { /* Must wait, the thread is busy. */ } 3520 else if (enmState == kTscDeltaThreadState_WaitAndMeasure) 3521 { /* Must wait, this state only says what will happen next. */ } 3522 else if (enmState == kTscDeltaThreadState_Terminating) 3523 { /* Must wait, this state only says what should happen next. */ } 3524 else 3525 break; /* All other states, the thread is either idly listening or dead. */ 3526 3527 /* Wait or fail. */ 3528 if (cMsWaitThread == 0) 3529 return VERR_SUPDRV_TSC_DELTA_MEASUREMENT_BUSY; 3530 cMsElapsed = RTTimeSystemMilliTS() - msTsStartWait; 3531 if (cMsElapsed >= cMsWaitThread) 3532 return VERR_SUPDRV_TSC_DELTA_MEASUREMENT_BUSY; 3533 3534 rc = RTThreadSleep(RT_MIN(cMsWaitThread - cMsElapsed, RT_MIN(iWaitLoop + 1, 10))); 3535 if (rc == VERR_INTERRUPTED) 3536 return rc; 3537 } 3538 #endif /* SUPDRV_USE_TSC_DELTA_THREAD */ 3539 3540 /* 3541 * Try measure the TSC delta the given number of times. 3542 */ 3543 for (;;) 3544 { 3545 /* Unless we're forced to measure the delta, check whether it's done already. */ 3546 if ( !(fFlags & SUP_TSCDELTA_MEASURE_F_FORCE) 3547 && pGip->aCPUs[iGipCpu].i64TSCDelta != INT64_MAX) 3548 { 3549 rc = VINF_SUCCESS; 3550 break; 3551 } 3552 3553 /* Measure it. */ 3554 rc = supdrvMeasureTscDeltaOne(pDevExt, iGipCpu); 3555 if (rc != VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED) 3556 { 3557 Assert(pGip->aCPUs[iGipCpu].i64TSCDelta != INT64_MAX || RT_FAILURE_NP(rc)); 3558 break; 3559 } 3560 3561 /* Retry? */ 3562 if (cTries <= 1) 3563 break; 3564 cTries--; 3565 3566 if (cMsWaitRetry) 3567 { 3568 rc = RTThreadSleep(cMsWaitRetry); 3569 if (rc == VERR_INTERRUPTED) 3570 break; 3571 } 3572 } 3573 3574 return rc; 3575 } 3407 3576 3408 3577 … … 3417 3586 int VBOXCALL supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCDELTAMEASURE pReq) 3418 3587 { 3419 PSUPGLOBALINFOPAGE pGip; 3420 RTCPUID idCpuWorker; 3421 int rc; 3422 int16_t cTries; 3423 RTMSINTERVAL cMsWaitRetry; 3424 uint16_t iCpu; 3425 3426 /* 3427 * Validate. 3588 uint32_t cTries; 3589 uint32_t iCpuSet; 3590 uint32_t fFlags; 3591 RTMSINTERVAL cMsWaitRetry; 3592 3593 /* 3594 * Validate and adjust/resolve the input so they can be passed onto SUPR0TscDeltaMeasureBySetIndex. 3428 3595 */ 3429 3596 AssertPtr(pDevExt); AssertPtr(pSession); AssertPtr(pReq); /* paranoia^2 */ 3430 if (pSession->GipMapObjR3 == NIL_RTR0MEMOBJ) 3431 return VERR_WRONG_ORDER; 3432 pGip = pDevExt->pGip; 3433 AssertReturn(pGip, VERR_INTERNAL_ERROR_2); 3434 3435 idCpuWorker = pReq->u.In.idCpu; 3436 if (idCpuWorker == NIL_RTCPUID) 3597 3598 if (pReq->u.In.idCpu == NIL_RTCPUID) 3437 3599 return VERR_INVALID_CPU_ID; 3438 cTries = RT_MAX(pReq->u.In.cRetries + 1, 10); 3600 iCpuSet = RTMpCpuIdToSetIndex(pReq->u.In.idCpu); 3601 if (iCpuSet >= RTCPUSET_MAX_CPUS) 3602 return VERR_INVALID_CPU_ID; 3603 3604 cTries = pReq->u.In.cRetries == 0 ? 0 : (uint32_t)pReq->u.In.cRetries + 1; 3605 3439 3606 cMsWaitRetry = RT_MAX(pReq->u.In.cMsWaitRetry, 5); 3440 3607 3441 /* 3442 * The request is a noop if the TSC delta isn't being used. 3443 */ 3444 pGip = pDevExt->pGip; 3445 if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED) 3446 return VINF_SUCCESS; 3447 3448 rc = VERR_CPU_NOT_FOUND; 3449 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 3450 { 3451 PSUPGIPCPU pGipCpuWorker = &pGip->aCPUs[iCpu]; 3452 if (pGipCpuWorker->idCpu == idCpuWorker) 3453 { 3454 if ( pGipCpuWorker->i64TSCDelta != INT64_MAX 3455 && !pReq->u.In.fForce) 3456 return VINF_SUCCESS; 3457 3458 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 3459 if (pReq->u.In.fAsync) 3460 { 3461 /** @todo Async. doesn't implement options like retries, waiting. We'll need 3462 * to pass those options to the thread somehow and implement it in the 3463 * thread. Check if anyone uses/needs fAsync before implementing this. */ 3464 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); 3465 RTCpuSetAddByIndex(&pDevExt->TscDeltaCpuSet, pGipCpuWorker->iCpuSet); 3466 if ( pDevExt->enmTscDeltaThreadState == kTscDeltaThreadState_Listening 3467 || pDevExt->enmTscDeltaThreadState == kTscDeltaThreadState_Measuring) 3468 { 3469 pDevExt->enmTscDeltaThreadState = kTscDeltaThreadState_WaitAndMeasure; 3470 } 3471 RTSpinlockRelease(pDevExt->hTscDeltaSpinlock); 3472 RTThreadUserSignal(pDevExt->hTscDeltaThread); 3473 return VINF_SUCCESS; 3474 } 3475 3476 /* 3477 * If a TSC-delta measurement request is already being serviced by the thread, 3478 * wait 'cTries' times if a retry-timeout is provided, otherwise bail as busy. 3479 */ 3480 while (cTries-- > 0) 3481 { 3482 SUPDRVTSCDELTATHREADSTATE enmState; 3483 RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock); 3484 enmState = pDevExt->enmTscDeltaThreadState; 3485 RTSpinlockRelease(pDevExt->hTscDeltaSpinlock); 3486 3487 if ( enmState == kTscDeltaThreadState_Measuring 3488 || enmState == kTscDeltaThreadState_WaitAndMeasure) 3489 { 3490 if ( !cTries 3491 || !cMsWaitRetry) 3492 return VERR_SUPDRV_TSC_DELTA_MEASUREMENT_BUSY; 3493 if (cMsWaitRetry) 3494 RTThreadSleep(cMsWaitRetry); 3495 } 3496 } 3497 cTries = RT_MAX(pReq->u.In.cRetries + 1, 10); 3498 #endif 3499 3500 while (cTries-- > 0) 3501 { 3502 rc = supdrvMeasureTscDeltaOne(pDevExt, iCpu); 3503 if (RT_SUCCESS(rc)) 3504 { 3505 Assert(pGipCpuWorker->i64TSCDelta != INT64_MAX); 3506 break; 3507 } 3508 3509 if (cMsWaitRetry) 3510 RTThreadSleep(cMsWaitRetry); 3511 } 3512 3513 break; 3514 } 3515 } 3516 return rc; 3608 fFlags = 0; 3609 if (pReq->u.In.fAsync) 3610 fFlags |= SUP_TSCDELTA_MEASURE_F_ASYNC; 3611 if (pReq->u.In.fForce) 3612 fFlags |= SUP_TSCDELTA_MEASURE_F_FORCE; 3613 3614 return SUPR0TscDeltaMeasureBySetIndex(pSession, iCpuSet, fFlags, cMsWaitRetry, 3615 cTries == 0 ? 5*RT_MS_1SEC : cMsWaitRetry * cTries /*cMsWaitThread*/, 3616 cTries); 3517 3617 } 3518 3618 -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r54331 r54339 213 213 * 214 214 * @todo Pending work on next major version change: 215 * - Fix SUPTSCREAD padding (#if 0 -> #if 1).216 */ 217 #define SUPDRV_IOC_VERSION 0x001f000 1215 * - (nothing) 216 */ 217 #define SUPDRV_IOC_VERSION 0x001f0002 218 218 219 219 /** SUP_IOCTL_COOKIE. */ -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r54308 r54339 280 280 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION; 281 281 const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001f0000 282 ? 0x001f000 1282 ? 0x001f0002 283 283 : SUPDRV_IOC_VERSION & 0xffff0000; 284 284 CookieReq.u.In.u32MinVersion = uMinVersion; -
trunk/src/VBox/HostDrivers/linux/load.sh
r48952 r54339 24 24 25 25 set -e 26 kmk-C "${MY_DIR}/src/vboxdrv" "$@"26 make -C "${MY_DIR}/src/vboxdrv" "$@" 27 27 sudo make -C "${MY_DIR}/src/" unload 28 28 echo "Installing SUPDrv (aka VBoxDrv/vboxdrv)" -
trunk/src/VBox/VMM/VMMR0/CPUMR0.cpp
r53836 r54339 998 998 * @param pVCpu Pointer to the cross context CPU structure of the 999 999 * calling EMT. 1000 * @param i dHostCpu The IDof the current host CPU.1001 */ 1002 VMMR0_INT_DECL(void) CPUMR0SetLApic(PVMCPU pVCpu, RTCPUID idHostCpu)1003 { 1004 int idxCpu = RTMpCpuIdToSetIndex(idHostCpu);1005 pVCpu->cpum.s.pvApicBase = g_aLApics[i dxCpu].pv;1006 pVCpu->cpum.s.fX2Apic = g_aLApics[i dxCpu].fX2Apic;1000 * @param iHostCpuSet The CPU set index of the current host CPU. 1001 */ 1002 VMMR0_INT_DECL(void) CPUMR0SetLApic(PVMCPU pVCpu, uint32_t iHostCpuSet) 1003 { 1004 Assert(iHostCpuSet <= RT_ELEMENTS(g_aLApics)); 1005 pVCpu->cpum.s.pvApicBase = g_aLApics[iHostCpuSet].pv; 1006 pVCpu->cpum.s.fX2Apic = g_aLApics[iHostCpuSet].fX2Apic; 1007 1007 // Log6(("CPUMR0SetLApic: pvApicBase=%p fX2Apic=%d\n", g_aLApics[idxCpu].pv, g_aLApics[idxCpu].fX2Apic)); 1008 1008 } -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r54256 r54339 566 566 567 567 /* We need to update the VCPU <-> host CPU mapping. */ 568 RTCPUID idHostCpu = RTMpCpuId(); 569 pVCpu->iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 568 RTCPUID idHostCpu = RTMpCpuId(); 569 uint32_t iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 570 pVCpu->iHostCpuSet = iHostCpuSet; 570 571 ASMAtomicWriteU32(&pVCpu->idHostCpu, idHostCpu); 572 573 /* In the very unlikely event that the GIP delta for the CPU we're 574 rescheduled needs calculating, try force a return to ring-3. 575 We unfortunately cannot do the measurements right here. */ 576 if (RT_UNLIKELY(SUPIsTscDeltaAvailableForCpuSetIndex(iHostCpuSet))) 577 VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3); 571 578 572 579 /* Invoke the HM-specific thread-context callback. */ … … 862 869 #endif 863 870 864 /* Disable preemption and update the periodic preemption timer. */ 871 /* 872 * Disable preemption. 873 */ 865 874 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 866 875 RTThreadPreemptDisable(&PreemptState); 867 RTCPUID idHostCpu = RTMpCpuId(); 876 877 /* 878 * Get the host CPU identifiers, make sure they are valid and that 879 * we've got a TSC delta for the CPU. 880 */ 881 RTCPUID idHostCpu = RTMpCpuId(); 882 uint32_t iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 883 if (RT_LIKELY( iHostCpuSet < RTCPUSET_MAX_CPUS 884 && SUPIsTscDeltaAvailableForCpuSetIndex(iHostCpuSet))) 885 { 886 /* 887 * Commit the CPU identifiers and update the periodict preemption timer if it's active. 888 */ 868 889 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI 869 CPUMR0SetLApic(pVCpu, idHostCpu); 870 #endif 871 pVCpu->iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 872 ASMAtomicWriteU32(&pVCpu->idHostCpu, idHostCpu); 873 if (pVM->vmm.s.fUsePeriodicPreemptionTimers) 874 GVMMR0SchedUpdatePeriodicPreemptionTimer(pVM, pVCpu->idHostCpu, TMCalcHostTimerFrequency(pVM, pVCpu)); 875 876 /* We might need to disable VT-x if the active switcher turns off paging. */ 877 bool fVTxDisabled; 878 int rc = HMR0EnterSwitcher(pVM, pVM->vmm.s.enmSwitcher, &fVTxDisabled); 879 if (RT_SUCCESS(rc)) 890 CPUMR0SetLApic(pVCpu, iHostCpuSet); 891 #endif 892 pVCpu->iHostCpuSet = iHostCpuSet; 893 ASMAtomicWriteU32(&pVCpu->idHostCpu, idHostCpu); 894 895 if (pVM->vmm.s.fUsePeriodicPreemptionTimers) 896 GVMMR0SchedUpdatePeriodicPreemptionTimer(pVM, pVCpu->idHostCpu, TMCalcHostTimerFrequency(pVM, pVCpu)); 897 898 /* 899 * We might need to disable VT-x if the active switcher turns off paging. 900 */ 901 bool fVTxDisabled; 902 int rc = HMR0EnterSwitcher(pVM, pVM->vmm.s.enmSwitcher, &fVTxDisabled); 903 if (RT_SUCCESS(rc)) 904 { 905 /* 906 * Disable interrupts and run raw-mode code. The loop is for efficiently 907 * dispatching tracepoints that fired in raw-mode context. 908 */ 909 RTCCUINTREG uFlags = ASMIntDisableFlags(); 910 911 for (;;) 912 { 913 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC); 914 TMNotifyStartOfExecution(pVCpu); 915 916 rc = pVM->vmm.s.pfnR0ToRawMode(pVM); 917 pVCpu->vmm.s.iLastGZRc = rc; 918 919 TMNotifyEndOfExecution(pVCpu); 920 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); 921 922 if (rc != VINF_VMM_CALL_TRACER) 923 break; 924 SUPR0TracerUmodProbeFire(pVM->pSession, &pVCpu->vmm.s.TracerCtx); 925 } 926 927 /* 928 * Re-enable VT-x before we dispatch any pending host interrupts and 929 * re-enables interrupts. 930 */ 931 HMR0LeaveSwitcher(pVM, fVTxDisabled); 932 933 if ( rc == VINF_EM_RAW_INTERRUPT 934 || rc == VINF_EM_RAW_INTERRUPT_HYPER) 935 TRPMR0DispatchHostInterrupt(pVM); 936 937 ASMSetFlags(uFlags); 938 939 /* Fire dtrace probe and collect statistics. */ 940 VBOXVMM_R0_VMM_RETURN_TO_RING3_RC(pVCpu, CPUMQueryGuestCtxPtr(pVCpu), rc); 941 #ifdef VBOX_WITH_STATISTICS 942 STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC); 943 vmmR0RecordRC(pVM, pVCpu, rc); 944 #endif 945 } 946 else 947 pVCpu->vmm.s.iLastGZRc = rc; 948 949 /* 950 * Invalidate the host CPU identifiers as we restore preemption. 951 */ 952 pVCpu->iHostCpuSet = UINT32_MAX; 953 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID); 954 955 RTThreadPreemptRestore(&PreemptState); 956 } 957 /* 958 * Invalid CPU set index or TSC delta in need of measuring. 959 */ 960 else 880 961 { 881 RTCCUINTREG uFlags = ASMIntDisableFlags(); 882 883 for (;;) 962 RTThreadPreemptRestore(&PreemptState); 963 if (iHostCpuSet < RTCPUSET_MAX_CPUS) 884 964 { 885 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC); 886 TMNotifyStartOfExecution(pVCpu); 887 888 rc = pVM->vmm.s.pfnR0ToRawMode(pVM); 889 pVCpu->vmm.s.iLastGZRc = rc; 890 891 TMNotifyEndOfExecution(pVCpu); 892 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); 893 894 if (rc != VINF_VMM_CALL_TRACER) 895 break; 896 SUPR0TracerUmodProbeFire(pVM->pSession, &pVCpu->vmm.s.TracerCtx); 965 int rc = SUPR0TscDeltaMeasureBySetIndex(pVM->pSession, iHostCpuSet, 0 /*fFlags*/, 966 2 /*cMsWaitRetry*/, 5*RT_MS_1SEC /*cMsWaitThread*/, 967 0 /*default cTries*/); 968 if (RT_SUCCESS(rc) || rc == VERR_CPU_OFFLINE) 969 pVCpu->vmm.s.iLastGZRc = VINF_EM_RAW_TO_R3; 970 else 971 pVCpu->vmm.s.iLastGZRc = rc; 897 972 } 898 899 /* Re-enable VT-x if previously turned off. */ 900 HMR0LeaveSwitcher(pVM, fVTxDisabled); 901 902 if ( rc == VINF_EM_RAW_INTERRUPT 903 || rc == VINF_EM_RAW_INTERRUPT_HYPER) 904 TRPMR0DispatchHostInterrupt(pVM); 905 906 ASMSetFlags(uFlags); 907 908 VBOXVMM_R0_VMM_RETURN_TO_RING3_RC(pVCpu, CPUMQueryGuestCtxPtr(pVCpu), rc); 909 #ifdef VBOX_WITH_STATISTICS 910 STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC); 911 vmmR0RecordRC(pVM, pVCpu, rc); 912 #endif 973 else 974 pVCpu->vmm.s.iLastGZRc = VERR_INVALID_CPU_INDEX; 913 975 } 914 else915 pVCpu->vmm.s.iLastGZRc = rc;916 pVCpu->iHostCpuSet = UINT32_MAX;917 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);918 RTThreadPreemptRestore(&PreemptState);919 976 break; 920 977 } … … 925 982 case VMMR0_DO_HM_RUN: 926 983 { 984 /* 985 * Disable preemption. 986 */ 927 987 Assert(!VMMR0ThreadCtxHooksAreRegistered(pVCpu)); 928 988 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER; 929 989 RTThreadPreemptDisable(&PreemptState); 930 990 931 /* Update the VCPU <-> host CPU mapping before doing anything else. */ 932 RTCPUID idHostCpu = RTMpCpuId(); 933 pVCpu->iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 934 ASMAtomicWriteU32(&pVCpu->idHostCpu, idHostCpu); 935 936 if (pVM->vmm.s.fUsePeriodicPreemptionTimers) 937 GVMMR0SchedUpdatePeriodicPreemptionTimer(pVM, pVCpu->idHostCpu, TMCalcHostTimerFrequency(pVM, pVCpu)); 991 /* 992 * Get the host CPU identifiers, make sure they are valid and that 993 * we've got a TSC delta for the CPU. 994 */ 995 RTCPUID idHostCpu = RTMpCpuId(); 996 uint32_t iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 997 if (RT_LIKELY( iHostCpuSet < RTCPUSET_MAX_CPUS 998 && SUPIsTscDeltaAvailableForCpuSetIndex(iHostCpuSet))) 999 { 1000 pVCpu->iHostCpuSet = iHostCpuSet; 1001 ASMAtomicWriteU32(&pVCpu->idHostCpu, idHostCpu); 1002 1003 /* 1004 * Update the periodict preemption timer if it's active. 1005 */ 1006 if (pVM->vmm.s.fUsePeriodicPreemptionTimers) 1007 GVMMR0SchedUpdatePeriodicPreemptionTimer(pVM, pVCpu->idHostCpu, TMCalcHostTimerFrequency(pVM, pVCpu)); 1008 938 1009 #ifdef LOG_ENABLED 939 if (pVCpu->idCpu > 0) 940 { 941 /* Lazy registration of ring 0 loggers. */ 942 PVMMR0LOGGER pR0Logger = pVCpu->vmm.s.pR0LoggerR0; 943 if ( pR0Logger 944 && !pR0Logger->fRegistered) 1010 /* 1011 * Ugly: Lazy registration of ring 0 loggers. 1012 */ 1013 if (pVCpu->idCpu > 0) 945 1014 { 946 RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession); 947 pR0Logger->fRegistered = true; 1015 PVMMR0LOGGER pR0Logger = pVCpu->vmm.s.pR0LoggerR0; 1016 if ( pR0Logger 1017 && RT_UNLIKELY(!pR0Logger->fRegistered)) 1018 { 1019 RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession); 1020 pR0Logger->fRegistered = true; 1021 } 948 1022 } 1023 #endif 1024 1025 int rc; 1026 bool fPreemptRestored = false; 1027 if (!HMR0SuspendPending()) 1028 { 1029 /* 1030 * Register thread-context hooks if required. 1031 */ 1032 if ( VMMR0ThreadCtxHooksAreCreated(pVCpu) 1033 && !VMMR0ThreadCtxHooksAreRegistered(pVCpu)) 1034 { 1035 rc = VMMR0ThreadCtxHooksRegister(pVCpu, vmmR0ThreadCtxCallback); 1036 AssertRC(rc); 1037 } 1038 1039 /* 1040 * Enter HM context. 1041 */ 1042 rc = HMR0Enter(pVM, pVCpu); 1043 if (RT_SUCCESS(rc)) 1044 { 1045 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM); 1046 1047 /* 1048 * When preemption hooks are in place, enable preemption now that 1049 * we're in HM context. 1050 */ 1051 if (VMMR0ThreadCtxHooksAreRegistered(pVCpu)) 1052 { 1053 fPreemptRestored = true; 1054 RTThreadPreemptRestore(&PreemptState); 1055 } 1056 1057 /* 1058 * Setup the longjmp machinery and execute guest code (calls HMR0RunGuestCode). 1059 */ 1060 rc = vmmR0CallRing3SetJmp(&pVCpu->vmm.s.CallRing3JmpBufR0, HMR0RunGuestCode, pVM, pVCpu); 1061 1062 /* 1063 * Assert sanity on the way out. Using manual assertions code here as normal 1064 * assertions are going to panic the host since we're outside the setjmp/longjmp zone. 1065 */ 1066 if (RT_UNLIKELY( VMCPU_GET_STATE(pVCpu) != VMCPUSTATE_STARTED_HM 1067 && RT_SUCCESS_NP(rc) && rc != VINF_VMM_CALL_HOST )) 1068 { 1069 pVM->vmm.s.szRing0AssertMsg1[0] = '\0'; 1070 RTStrPrintf(pVM->vmm.s.szRing0AssertMsg2, sizeof(pVM->vmm.s.szRing0AssertMsg2), 1071 "Got VMCPU state %d expected %d.\n", VMCPU_GET_STATE(pVCpu), VMCPUSTATE_STARTED_HM); 1072 rc = VERR_VMM_WRONG_HM_VMCPU_STATE; 1073 } 1074 else if (RT_UNLIKELY(VMMR0ThreadCtxHooksAreRegistered(pVCpu))) 1075 { 1076 pVM->vmm.s.szRing0AssertMsg1[0] = '\0'; 1077 RTStrPrintf(pVM->vmm.s.szRing0AssertMsg2, sizeof(pVM->vmm.s.szRing0AssertMsg2), 1078 "Thread-context hooks still registered! VCPU=%p Id=%u rc=%d.\n", pVCpu, pVCpu->idCpu, rc); 1079 rc = VERR_INVALID_STATE; 1080 } 1081 1082 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); 1083 } 1084 STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC); 1085 } 1086 /* 1087 * The system is about to go into suspend mode; go back to ring 3. 1088 */ 1089 else 1090 rc = VINF_EM_RAW_INTERRUPT; 1091 1092 pVCpu->vmm.s.iLastGZRc = rc; 1093 1094 /* 1095 * Invalidate the host CPU identifiers as we restore preemption. 1096 */ 1097 pVCpu->iHostCpuSet = UINT32_MAX; 1098 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID); 1099 1100 if (!fPreemptRestored) 1101 RTThreadPreemptRestore(&PreemptState); 1102 1103 /* Fire dtrace probe and collect statistics. */ 1104 VBOXVMM_R0_VMM_RETURN_TO_RING3_HM(pVCpu, CPUMQueryGuestCtxPtr(pVCpu), rc); 1105 #ifdef VBOX_WITH_STATISTICS 1106 vmmR0RecordRC(pVM, pVCpu, rc); 1107 #endif 949 1108 } 950 #endif 951 952 int rc; 953 bool fPreemptRestored = false; 954 if (!HMR0SuspendPending()) 955 { 956 /* Register thread-context hooks if required. */ 957 if ( VMMR0ThreadCtxHooksAreCreated(pVCpu) 958 && !VMMR0ThreadCtxHooksAreRegistered(pVCpu)) 959 { 960 rc = VMMR0ThreadCtxHooksRegister(pVCpu, vmmR0ThreadCtxCallback); 961 AssertRC(rc); 962 } 963 964 /* Enter HM context. */ 965 rc = HMR0Enter(pVM, pVCpu); 966 if (RT_SUCCESS(rc)) 967 { 968 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM); 969 970 /* When preemption hooks are in place, enable preemption now that we're in HM context. */ 971 if (VMMR0ThreadCtxHooksAreRegistered(pVCpu)) 972 { 973 fPreemptRestored = true; 974 RTThreadPreemptRestore(&PreemptState); 975 } 976 977 /* Setup the longjmp machinery and execute guest code. */ 978 rc = vmmR0CallRing3SetJmp(&pVCpu->vmm.s.CallRing3JmpBufR0, HMR0RunGuestCode, pVM, pVCpu); 979 980 /* Manual assert as normal assertions are going to crash in this case. */ 981 if (RT_UNLIKELY( VMCPU_GET_STATE(pVCpu) != VMCPUSTATE_STARTED_HM 982 && RT_SUCCESS_NP(rc) && rc != VINF_VMM_CALL_HOST )) 983 { 984 pVM->vmm.s.szRing0AssertMsg1[0] = '\0'; 985 RTStrPrintf(pVM->vmm.s.szRing0AssertMsg2, sizeof(pVM->vmm.s.szRing0AssertMsg2), 986 "Got VMCPU state %d expected %d.\n", VMCPU_GET_STATE(pVCpu), VMCPUSTATE_STARTED_HM); 987 rc = VERR_VMM_WRONG_HM_VMCPU_STATE; 988 } 989 else if (RT_UNLIKELY(VMMR0ThreadCtxHooksAreRegistered(pVCpu))) 990 { 991 pVM->vmm.s.szRing0AssertMsg1[0] = '\0'; 992 RTStrPrintf(pVM->vmm.s.szRing0AssertMsg2, sizeof(pVM->vmm.s.szRing0AssertMsg2), 993 "Thread-context hooks still registered! VCPU=%p Id=%u rc=%d.\n", pVCpu, pVCpu->idCpu, rc); 994 rc = VERR_INVALID_STATE; 995 } 996 997 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); 998 } 999 STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC); 1000 } 1109 /* 1110 * Invalid CPU set index or TSC delta in need of measuring. 1111 */ 1001 1112 else 1002 1113 { 1003 /* System is about to go into suspend mode; go back to ring 3. */ 1004 rc = VINF_EM_RAW_INTERRUPT; 1114 RTThreadPreemptRestore(&PreemptState); 1115 if (iHostCpuSet < RTCPUSET_MAX_CPUS) 1116 { 1117 int rc = SUPR0TscDeltaMeasureBySetIndex(pVM->pSession, iHostCpuSet, 0 /*fFlags*/, 1118 2 /*cMsWaitRetry*/, 5*RT_MS_1SEC /*cMsWaitThread*/, 1119 0 /*default cTries*/); 1120 if (RT_SUCCESS(rc) || rc == VERR_CPU_OFFLINE) 1121 pVCpu->vmm.s.iLastGZRc = VINF_EM_RAW_TO_R3; 1122 else 1123 pVCpu->vmm.s.iLastGZRc = rc; 1124 } 1125 else 1126 pVCpu->vmm.s.iLastGZRc = VERR_INVALID_CPU_INDEX; 1005 1127 } 1006 pVCpu->vmm.s.iLastGZRc = rc;1007 1008 /* Clear the VCPU <-> host CPU mapping as we've left HM context. */1009 pVCpu->iHostCpuSet = UINT32_MAX;1010 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);1011 1012 if (!fPreemptRestored)1013 RTThreadPreemptRestore(&PreemptState);1014 1015 VBOXVMM_R0_VMM_RETURN_TO_RING3_HM(pVCpu, CPUMQueryGuestCtxPtr(pVCpu), rc);1016 #ifdef VBOX_WITH_STATISTICS1017 vmmR0RecordRC(pVM, pVCpu, rc);1018 #endif1019 /* No special action required for external interrupts, just return. */1020 1128 break; 1021 1129 } … … 1197 1305 case VMMR0_DO_CALL_HYPERVISOR: 1198 1306 { 1199 int rc; 1307 /* 1308 * Validate input / context. 1309 */ 1310 if (RT_UNLIKELY(idCpu != 0)) 1311 return VERR_INVALID_CPU_ID; 1312 if (RT_UNLIKELY(pVM->cCpus != 1)) 1313 return VERR_INVALID_PARAMETER; 1314 PVMCPU pVCpu = &pVM->aCpus[idCpu]; 1315 #ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 1316 if (RT_UNLIKELY(!PGMGetHyperCR3(pVCpu))) 1317 return VERR_PGM_NO_CR3_SHADOW_ROOT; 1318 #endif 1319 1320 /* 1321 * Disable interrupts. 1322 */ 1323 RTCCUINTREG fFlags = ASMIntDisableFlags(); 1324 1325 /* 1326 * Get the host CPU identifiers, make sure they are valid and that 1327 * we've got a TSC delta for the CPU. 1328 */ 1329 RTCPUID idHostCpu = RTMpCpuId(); 1330 uint32_t iHostCpuSet = RTMpCpuIdToSetIndex(idHostCpu); 1331 if (RT_UNLIKELY(iHostCpuSet >= RTCPUSET_MAX_CPUS)) 1332 { 1333 ASMSetFlags(fFlags); 1334 return VERR_INVALID_CPU_INDEX; 1335 } 1336 if (RT_UNLIKELY(!SUPIsTscDeltaAvailableForCpuSetIndex(iHostCpuSet))) 1337 { 1338 ASMSetFlags(fFlags); 1339 int rc = SUPR0TscDeltaMeasureBySetIndex(pVM->pSession, iHostCpuSet, 0 /*fFlags*/, 1340 2 /*cMsWaitRetry*/, 5*RT_MS_1SEC /*cMsWaitThread*/, 1341 0 /*default cTries*/); 1342 if (RT_FAILURE(rc) && rc != VERR_CPU_OFFLINE) 1343 return rc; 1344 } 1345 1346 /* 1347 * Commit the CPU identifiers. 1348 */ 1349 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI 1350 CPUMR0SetLApic(pVCpu, iHostCpuSet); 1351 #endif 1352 pVCpu->iHostCpuSet = iHostCpuSet; 1353 ASMAtomicWriteU32(&pVCpu->idHostCpu, idHostCpu); 1354 1355 /* 1356 * We might need to disable VT-x if the active switcher turns off paging. 1357 */ 1200 1358 bool fVTxDisabled; 1201 1202 #ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 1203 if (RT_UNLIKELY(!PGMGetHyperCR3(VMMGetCpu0(pVM)))) 1204 return VERR_PGM_NO_CR3_SHADOW_ROOT; 1205 #endif 1206 1207 RTCCUINTREG fFlags = ASMIntDisableFlags(); 1208 1209 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI 1210 RTCPUID idHostCpu = RTMpCpuId(); 1211 CPUMR0SetLApic(&pVM->aCpus[0], idHostCpu); 1212 #endif 1213 1214 /* We might need to disable VT-x if the active switcher turns off paging. */ 1215 rc = HMR0EnterSwitcher(pVM, pVM->vmm.s.enmSwitcher, &fVTxDisabled); 1216 if (RT_FAILURE(rc)) 1217 return rc; 1218 1219 rc = pVM->vmm.s.pfnR0ToRawMode(pVM); 1220 1221 /* Re-enable VT-x if previously turned off. */ 1222 HMR0LeaveSwitcher(pVM, fVTxDisabled); 1223 1224 /** @todo dispatch interrupts? */ 1359 int rc = HMR0EnterSwitcher(pVM, pVM->vmm.s.enmSwitcher, &fVTxDisabled); 1360 if (RT_SUCCESS(rc)) 1361 { 1362 /* 1363 * Go through the wormhole... 1364 */ 1365 rc = pVM->vmm.s.pfnR0ToRawMode(pVM); 1366 1367 /* 1368 * Re-enable VT-x before we dispatch any pending host interrupts. 1369 */ 1370 HMR0LeaveSwitcher(pVM, fVTxDisabled); 1371 1372 if ( rc == VINF_EM_RAW_INTERRUPT 1373 || rc == VINF_EM_RAW_INTERRUPT_HYPER) 1374 TRPMR0DispatchHostInterrupt(pVM); 1375 } 1376 1377 /* 1378 * Invalidate the host CPU identifiers as we restore interrupts. 1379 */ 1380 pVCpu->iHostCpuSet = UINT32_MAX; 1381 ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID); 1225 1382 ASMSetFlags(fFlags); 1226 1383 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.