Changeset 54489 in vbox for trunk/src/VBox
- Timestamp:
- Feb 25, 2015 1:02:11 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 98597
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
r54480 r54489 2573 2573 * Argument package/state passed by supdrvMeasureTscDeltaOne() to the RTMpOn 2574 2574 * callback worker. 2575 * @todo add 2575 2576 */ 2576 2577 typedef struct SUPDRVGIPTSCDELTARGS … … 2600 2601 PSUPDRVTSCDELTAMETHOD2 pMasterData; 2601 2602 PSUPDRVTSCDELTAMETHOD2 pWorkerData; 2602 uint32_t cHits;2603 bool fLagMaster;2604 bool fLagWorker;2605 2603 } M2; 2606 2604 #endif … … 2617 2615 /** Pointer to the master's synchronization struct (on stack). */ 2618 2616 PSUPTSCDELTASYNC2 volatile pSyncMaster; 2619 /** Verification test TSC values for the master. */ 2620 uint64_t volatile auVerifyMasterTscs[32]; 2617 /** Master data union. */ 2618 union 2619 { 2620 /** Data (master) for delta verification. */ 2621 struct 2622 { 2623 /** Verification test TSC values for the master. */ 2624 uint64_t volatile auTscs[32]; 2625 } Verify; 2626 /** Data (master) for measurement method \#2. */ 2627 struct 2628 { 2629 /** Data and sequence number. */ 2630 SUPDRVTSCDELTAMETHOD2 Data; 2631 /** The lag setting for the next run. */ 2632 bool fLag; 2633 /** Number of hits. */ 2634 uint32_t cHits; 2635 } M2; 2636 } uMaster; 2621 2637 /** The verifier verdict, VINF_SUCCESS if ok, VERR_OUT_OF_RANGE if not, 2622 2638 * VERR_TRY_AGAIN on timeout. */ … … 2638 2654 /** The time the worker spent in the MP worker. */ 2639 2655 uint64_t cElapsedWorkerTscTicks; 2640 /** Verification test TSC values for the worker. */ 2641 uint64_t volatile auVerifyWorkerTscs[32]; 2656 /** Worker data union. */ 2657 union 2658 { 2659 /** Data (worker) for delta verification. */ 2660 struct 2661 { 2662 /** Verification test TSC values for the worker. */ 2663 uint64_t volatile auTscs[32]; 2664 } Verify; 2665 /** Data (worker) for measurement method \#2. */ 2666 struct 2667 { 2668 /** Data and sequence number. */ 2669 SUPDRVTSCDELTAMETHOD2 Data; 2670 /** The lag setting for the next run (set by master). */ 2671 bool fLag; 2672 } M2; 2673 } uWorker; 2642 2674 2643 2675 /** Padding to make sure the above is in its own cache line. */ … … 2953 2985 /** @} */ 2954 2986 2987 2955 2988 #ifdef GIP_TSC_DELTA_METHOD_1 2956 2957 2989 /** 2958 2990 * TSC delta measurment algorithm \#1 (GIP_TSC_DELTA_METHOD_1). … … 3094 3126 ASMAtomicWriteU64(&pGipCpuWorker->u64TSCSample, GIP_TSC_DELTA_RSVD); 3095 3127 } 3096 3097 3098 /**3099 * Initializes the argument/state data belonging to algorithm \#1.3100 *3101 * @returns VBox status code.3102 * @param pArgs The argument/state data.3103 */3104 static int supdrvTscDeltaMethod1Init(PSUPDRVGIPTSCDELTARGS pArgs)3105 {3106 NOREF(pArgs);3107 return VINF_SUCCESS;3108 }3109 3110 3111 /**3112 * Undoes what supdrvTscDeltaMethod1Init() did.3113 *3114 * @param pArgs The argument/state data.3115 */3116 static void supdrvTscDeltaMethod1Delete(PSUPDRVGIPTSCDELTARGS pArgs)3117 {3118 NOREF(pArgs);3119 }3120 3121 3128 #endif /* GIP_TSC_DELTA_METHOD_1 */ 3122 3129 … … 3171 3178 if (cHits > 2) 3172 3179 pArgs->pWorker->i64TSCDelta = iBestDelta; 3173 pArgs-> M2.cHits += cHits;3180 pArgs->uMaster.M2.cHits += cHits; 3174 3181 } 3175 3182 … … 3245 3252 { 3246 3253 /* Lag during the priming to be nice to everyone.. */ 3247 pArgs-> M2.fLagMaster= true;3248 pArgs-> M2.fLagWorker= true;3254 pArgs->uMaster.M2.fLag = true; 3255 pArgs->uWorker.M2.fLag = true; 3249 3256 } 3250 3257 else … … 3253 3260 { 3254 3261 /* 25 % of the body without lagging. */ 3255 pArgs-> M2.fLagMaster= false;3256 pArgs-> M2.fLagWorker= false;3262 pArgs->uMaster.M2.fLag = false; 3263 pArgs->uWorker.M2.fLag = false; 3257 3264 } 3258 3265 else if (iLoop < (GIP_TSC_DELTA_M2_LOOPS - GIP_TSC_DELTA_M2_PRIMER_LOOPS) / 4 * 2) 3259 3266 { 3260 3267 /* 25 % of the body with both lagging. */ 3261 pArgs-> M2.fLagMaster= true;3262 pArgs-> M2.fLagWorker= true;3268 pArgs->uMaster.M2.fLag = true; 3269 pArgs->uWorker.M2.fLag = true; 3263 3270 } 3264 3271 else 3265 3272 { 3266 3273 /* 50% of the body with alternating lag. */ 3267 pArgs-> M2.fLagMaster= (iLoop & 1) == 0;3268 pArgs-> M2.fLagWorker= (iLoop & 1) == 1;3274 pArgs->uMaster.M2.fLag = (iLoop & 1) == 0; 3275 pArgs->uWorker.M2.fLag= (iLoop & 1) == 1; 3269 3276 } 3270 3277 … … 3273 3280 */ 3274 3281 TSCDELTA_MASTER_SYNC_BEFORE(pMySync, pOtherSync, &fEFlags, pArgs); 3275 supdrvTscDeltaMethod2CollectData( pArgs->M2.pMasterData, &pArgs->M2.pWorkerData->iCurSeqNo, pArgs->M2.fLagMaster);3282 supdrvTscDeltaMethod2CollectData(&pArgs->uMaster.M2.Data, &pArgs->uWorker.M2.Data.iCurSeqNo, pArgs->uMaster.M2.fLag); 3276 3283 TSCDELTA_MASTER_SYNC_AFTER(pMySync, pOtherSync, fEFlags); 3277 3284 … … 3292 3299 */ 3293 3300 TSCDELTA_OTHER_SYNC_BEFORE(pMySync, pOtherSync, &fEFlags, pArgs); 3294 supdrvTscDeltaMethod2CollectData( pArgs->M2.pWorkerData, &pArgs->M2.pMasterData->iCurSeqNo, pArgs->M2.fLagWorker);3301 supdrvTscDeltaMethod2CollectData(&pArgs->uWorker.M2.Data, &pArgs->uMaster.M2.Data.iCurSeqNo, pArgs->uWorker.M2.fLag); 3295 3302 TSCDELTA_OTHER_SYNC_AFTER(pMySync, pOtherSync, fEFlags); 3296 3303 } 3297 3304 } 3298 3305 } 3299 3300 3301 /**3302 * Initializes the argument/state data belonging to algorithm \#2.3303 *3304 * @returns VBox status code.3305 * @param pArgs The argument/state data.3306 */3307 static int supdrvTscDeltaMethod2Init(PSUPDRVGIPTSCDELTARGS pArgs)3308 {3309 pArgs->M2.pMasterData = NULL;3310 pArgs->M2.pWorkerData = NULL;3311 3312 uint32_t const fFlags = /*RTMEMALLOCEX_FLAGS_ANY_CTX |*/ RTMEMALLOCEX_FLAGS_ZEROED;3313 int rc = RTMemAllocEx(sizeof(*pArgs->M2.pWorkerData), 0, fFlags, (void **)&pArgs->M2.pWorkerData);3314 if (RT_SUCCESS(rc))3315 rc = RTMemAllocEx(sizeof(*pArgs->M2.pMasterData), 0, fFlags, (void **)&pArgs->M2.pMasterData);3316 return rc;3317 }3318 3319 3320 /**3321 * Undoes what supdrvTscDeltaMethod2Init() did.3322 *3323 * @param pArgs The argument/state data.3324 */3325 static void supdrvTscDeltaMethod2Delete(PSUPDRVGIPTSCDELTARGS pArgs)3326 {3327 RTMemFreeEx(pArgs->M2.pMasterData, sizeof(*pArgs->M2.pMasterData));3328 RTMemFreeEx(pArgs->M2.pWorkerData, sizeof(*pArgs->M2.pWorkerData));3329 # if 03330 SUPR0Printf("cHits=%d m=%d w=%d\n", pArgs->M2.cHits, pArgs->pMaster->idApic, pArgs->pWorker->idApic);3331 # endif3332 }3333 3334 3306 3335 3307 #endif /* GIP_TSC_DELTA_METHOD_2 */ … … 3348 3320 { 3349 3321 RTCCUINTREG fEFlags; 3350 AssertCompile((RT_ELEMENTS(pArgs-> auVerifyMasterTscs) & 1) == 0);3351 AssertCompile(RT_ELEMENTS(pArgs-> auVerifyWorkerTscs) == RT_ELEMENTS(pArgs->auVerifyMasterTscs));3322 AssertCompile((RT_ELEMENTS(pArgs->uMaster.Verify.auTscs) & 1) == 0); 3323 AssertCompile(RT_ELEMENTS(pArgs->uMaster.Verify.auTscs) == RT_ELEMENTS(pArgs->uWorker.Verify.auTscs)); 3352 3324 3353 3325 if (fIsMaster) … … 3359 3331 * Collect TSC, master goes first. 3360 3332 */ 3361 for (i = 0; i < RT_ELEMENTS(pArgs-> auVerifyMasterTscs); i += 2)3333 for (i = 0; i < RT_ELEMENTS(pArgs->uMaster.Verify.auTscs); i += 2) 3362 3334 { 3363 3335 /* Read, kick & wait #1. */ … … 3365 3337 ASMAtomicWriteU32(&pOtherSync->uSyncVar, GIP_TSC_DELTA_SYNC2_GO_GO); 3366 3338 ASMSerializeInstruction(); 3367 pArgs-> auVerifyMasterTscs[i] = uTsc;3339 pArgs->uMaster.Verify.auTscs[i] = uTsc; 3368 3340 TSCDELTA_DBG_START_LOOP(); 3369 3341 while (ASMAtomicReadU32(&pMySync->uSyncVar) == GIP_TSC_DELTA_SYNC2_GO) … … 3377 3349 ASMAtomicWriteU32(&pOtherSync->uSyncVar, GIP_TSC_DELTA_SYNC2_GO); 3378 3350 ASMSerializeInstruction(); 3379 pArgs-> auVerifyMasterTscs[i + 1] = uTsc;3351 pArgs->uMaster.Verify.auTscs[i + 1] = uTsc; 3380 3352 TSCDELTA_DBG_START_LOOP(); 3381 3353 while (ASMAtomicReadU32(&pMySync->uSyncVar) == GIP_TSC_DELTA_SYNC2_GO_GO) … … 3398 3370 ASMAtomicWriteS32(&pArgs->rcVerify, VINF_SUCCESS); 3399 3371 uTscWorker = 0; 3400 for (i = 0; i < RT_ELEMENTS(pArgs-> auVerifyMasterTscs); i++)3372 for (i = 0; i < RT_ELEMENTS(pArgs->uMaster.Verify.auTscs); i++) 3401 3373 { 3402 3374 /* Master vs previous worker entry. */ 3403 uint64_t uTscMaster = pArgs-> auVerifyMasterTscs[i] - pGipCpuMaster->i64TSCDelta;3375 uint64_t uTscMaster = pArgs->uMaster.Verify.auTscs[i] - pGipCpuMaster->i64TSCDelta; 3404 3376 int64_t iDiff; 3405 3377 if (i > 0) … … 3423 3395 3424 3396 /* Worker vs master. */ 3425 uTscWorker = pArgs-> auVerifyWorkerTscs[i] - iWorkerTscDelta;3397 uTscWorker = pArgs->uWorker.Verify.auTscs[i] - iWorkerTscDelta; 3426 3398 iDiff = uTscWorker - uTscMaster; 3427 3399 #ifdef TSCDELTA_VERIFY_WITH_STATS … … 3451 3423 TSCDELTA_OTHER_SYNC_BEFORE(pMySync, pOtherSync, &fEFlags, pArgs); 3452 3424 3453 for (i = 0; i < RT_ELEMENTS(pArgs-> auVerifyWorkerTscs); i += 2)3425 for (i = 0; i < RT_ELEMENTS(pArgs->uWorker.Verify.auTscs); i += 2) 3454 3426 { 3455 3427 uint64_t register uTsc; … … 3465 3437 ASMAtomicWriteU32(&pOtherSync->uSyncVar, GIP_TSC_DELTA_SYNC2_GO_GO); 3466 3438 ASMSerializeInstruction(); 3467 pArgs-> auVerifyWorkerTscs[i] = uTsc;3439 pArgs->uWorker.Verify.auTscs[i] = uTsc; 3468 3440 3469 3441 /* Wait, Read and Kick #2. */ … … 3477 3449 ASMAtomicWriteU32(&pOtherSync->uSyncVar, GIP_TSC_DELTA_SYNC2_GO); 3478 3450 ASMSerializeInstruction(); 3479 pArgs-> auVerifyWorkerTscs[i + 1] = uTsc;3451 pArgs->uWorker.Verify.auTscs[i + 1] = uTsc; 3480 3452 } 3481 3453 … … 3864 3836 pArgs->cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 512; /* 1953 us */ 3865 3837 3866 #ifdef GIP_TSC_DELTA_METHOD_1 3867 rc = supdrvTscDeltaMethod1Init(pArgs); 3868 #elif defined(GIP_TSC_DELTA_METHOD_2) 3869 rc = supdrvTscDeltaMethod2Init(pArgs); 3870 #else 3871 # error "huh?" 3872 #endif 3838 /* 3839 * Do the RTMpOnPair call. We reset i64TSCDelta first so we 3840 * and supdrvMeasureTscDeltaCallback can use it as a success check. 3841 */ 3842 /** @todo Store the i64TSCDelta result in pArgs first? Perhaps deals with 3843 * that when doing the restart loop reorg. */ 3844 ASMAtomicWriteS64(&pGipCpuWorker->i64TSCDelta, INT64_MAX); 3845 rc = RTMpOnPair(pGipCpuMaster->idCpu, pGipCpuWorker->idCpu, RTMPON_F_CONCURRENT_EXEC, 3846 supdrvMeasureTscDeltaCallback, pArgs, NULL); 3873 3847 if (RT_SUCCESS(rc)) 3874 3848 { 3875 /*3876 * Do the RTMpOnPair call. We reset i64TSCDelta first so we3877 * and supdrvMeasureTscDeltaCallback can use it as a success check.3878 */3879 /** @todo Store the i64TSCDelta result in pArgs first? Perhaps deals with3880 * that when doing the restart loop reorg. */3881 ASMAtomicWriteS64(&pGipCpuWorker->i64TSCDelta, INT64_MAX);3882 rc = RTMpOnPair(pGipCpuMaster->idCpu, pGipCpuWorker->idCpu, RTMPON_F_CONCURRENT_EXEC,3883 supdrvMeasureTscDeltaCallback, pArgs, NULL);3884 if (RT_SUCCESS(rc))3885 {3886 3849 #if 0 3887 3888 3889 3850 SUPR0Printf("mponpair ticks: %9llu %9llu max: %9llu iTry: %u%s\n", pArgs->cElapsedMasterTscTicks, 3851 pArgs->cElapsedWorkerTscTicks, pArgs->cMaxTscTicks, pArgs->iTry, 3852 pArgs->fTimedOut ? " timed out" :""); 3890 3853 #endif 3891 3854 #if 0 3892 3893 3855 SUPR0Printf("rcVerify=%d iVerifyBadTscDiff=%lld cMinVerifyTscTicks=%lld cMaxVerifyTscTicks=%lld\n", 3856 pArgs->rcVerify, pArgs->iVerifyBadTscDiff, pArgs->cMinVerifyTscTicks, pArgs->cMaxVerifyTscTicks); 3894 3857 #endif 3895 if (RT_LIKELY(pGipCpuWorker->i64TSCDelta != INT64_MAX)) 3858 if (RT_LIKELY(pGipCpuWorker->i64TSCDelta != INT64_MAX)) 3859 { 3860 /* 3861 * Work the TSC delta applicability rating. It starts 3862 * optimistic in supdrvGipInit, we downgrade it here. 3863 */ 3864 SUPGIPUSETSCDELTA enmRating; 3865 if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO 3866 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO) 3867 enmRating = SUPGIPUSETSCDELTA_NOT_ZERO; 3868 else if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO 3869 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO) 3870 enmRating = SUPGIPUSETSCDELTA_ROUGHLY_ZERO; 3871 else 3872 enmRating = SUPGIPUSETSCDELTA_PRACTICALLY_ZERO; 3873 if (pGip->enmUseTscDelta < enmRating) 3896 3874 { 3897 /* 3898 * Work the TSC delta applicability rating. It starts 3899 * optimistic in supdrvGipInit, we downgrade it here. 3900 */ 3901 SUPGIPUSETSCDELTA enmRating; 3902 if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO 3903 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO) 3904 enmRating = SUPGIPUSETSCDELTA_NOT_ZERO; 3905 else if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO 3906 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO) 3907 enmRating = SUPGIPUSETSCDELTA_ROUGHLY_ZERO; 3908 else 3909 enmRating = SUPGIPUSETSCDELTA_PRACTICALLY_ZERO; 3910 if (pGip->enmUseTscDelta < enmRating) 3911 { 3912 AssertCompile(sizeof(pGip->enmUseTscDelta) == sizeof(uint32_t)); 3913 ASMAtomicWriteU32((uint32_t volatile *)&pGip->enmUseTscDelta, enmRating); 3914 } 3875 AssertCompile(sizeof(pGip->enmUseTscDelta) == sizeof(uint32_t)); 3876 ASMAtomicWriteU32((uint32_t volatile *)&pGip->enmUseTscDelta, enmRating); 3915 3877 } 3916 else3917 rc = VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED;3918 3878 } 3919 /** @todo return try-again if we get an offline CPU error. */ 3879 else 3880 rc = VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED; 3920 3881 } 3921 3922 #ifdef GIP_TSC_DELTA_METHOD_1 3923 supdrvTscDeltaMethod1Delete(pArgs); 3924 #elif defined(GIP_TSC_DELTA_METHOD_2) 3925 supdrvTscDeltaMethod2Delete(pArgs); 3926 #else 3927 # error "huh?" 3928 #endif 3882 /** @todo return try-again if we get an offline CPU error. */ 3883 3929 3884 RTMemFree(pArgs); 3930 3885 }
Note:
See TracChangeset
for help on using the changeset viewer.