Changeset 54339 in vbox for trunk/src/VBox/HostDrivers/Support
- Timestamp:
- Feb 20, 2015 6:10:12 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 98427
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note:
See TracChangeset
for help on using the changeset viewer.