Changeset 57218 in vbox
- Timestamp:
- Aug 6, 2015 2:53:27 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/sup.h
r57108 r57218 389 389 * can be accessed from ring-3 and raw-mode context. */ 390 390 uint32_t fGetGipCpu; 391 /** GIP flags, see SUPGIP_FLAGS_XXX. */ 392 volatile uint32_t fFlags; 391 393 392 394 /** Padding / reserved space for future data. */ 393 uint32_t au32Padding1[2 5];395 uint32_t au32Padding1[24]; 394 396 395 397 /** Table indexed by the CPU APIC ID to get the CPU table index. */ … … 424 426 * Upper 16 bits is the major version. Major version is only changed with 425 427 * incompatible changes in the GIP. */ 426 #define SUPGLOBALINFOPAGE_VERSION 0x0006000 0428 #define SUPGLOBALINFOPAGE_VERSION 0x00060001 427 429 428 430 /** … … 491 493 SUPDECL(PSUPGLOBALINFOPAGE) SUPGetGIP(void); 492 494 495 /** @name SUPGIP_FLAGS_XXX - SUPR3GipSetFlags flags. 496 * @{ */ 497 /** Enable GIP test mode. */ 498 #define SUPGIP_FLAGS_TESTING_ENABLE RT_BIT_32(0) 499 /** Valid mask of flags that can be set through the ioctl. */ 500 #define SUPGIP_FLAGS_VALID_MASK RT_BIT_32(0) 501 /** GIP test mode needs to be checked (e.g. when enabled or being disabled). */ 502 #define SUPGIP_FLAGS_TESTING RT_BIT_32(24) 503 /** Prepare to start GIP test mode. */ 504 #define SUPGIP_FLAGS_TESTING_START RT_BIT_32(25) 505 /** Prepare to stop GIP test mode. */ 506 #define SUPGIP_FLAGS_TESTING_STOP RT_BIT_32(26) 507 /** @} */ 493 508 494 509 /** @internal */ … … 1708 1723 SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry); 1709 1724 1725 1710 1726 /** 1711 1727 * Reads the delta-adjust TSC value. … … 1718 1734 SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic); 1719 1735 1736 1737 /** 1738 * Sets the GIP flags. 1739 * 1740 * @returns VBox status code. 1741 * @param fOrMask The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX. 1742 * @param fAndMask The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX. 1743 */ 1744 SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask); 1720 1745 /** @} */ 1721 1746 #endif /* IN_RING3 */ -
trunk/include/VBox/sup.mac
r54252 r57218 80 80 .enmUseTscDelta resd 1 81 81 .fGetGipCpu resd 1 82 .au32Padding1 resd 25 82 .fFlags resd 1 83 .au32Padding1 resd 24 83 84 .aiCpuFromApicId resw 256 84 85 .aiCpuFromCpuSetIdx resw 256 -
trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
r57090 r57218 2257 2257 } 2258 2258 2259 case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_GIP_SET_FLAGS): 2260 { 2261 /* validate */ 2262 PSUPGIPSETFLAGS pReq = (PSUPGIPSETFLAGS)pReqHdr; 2263 REQ_CHECK_SIZES(SUP_IOCTL_GIP_SET_FLAGS); 2264 2265 pReqHdr->rc = supdrvIOCtl_GipSetFlags(pDevExt, pSession, pReq->u.In.fOrMask, pReq->u.In.fAndMask); 2266 return 0; 2267 } 2268 2259 2269 default: 2260 2270 Log(("Unknown IOCTL %#lx\n", (long)uIOCtl)); -
trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
r57174 r57218 125 125 static DECLCALLBACK(void) supdrvGipSyncAndInvariantTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 126 126 static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 127 static int supdrvGipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask); 127 128 static void supdrvGipInitCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS, uint64_t uCpuHz); 128 129 static void supdrvTscResetSamples(PSUPDRVDEVEXT pDevExt, bool fClearDeltas); … … 627 628 RTSemFastMutexRequest(pDevExt->mtxGip); 628 629 #endif 630 631 /* 632 * GIP test-mode session? 633 */ 634 if ( pSession->fGipTestMode 635 && pDevExt->pGip) 636 { 637 uint32_t fFlags = pDevExt->pGip->fFlags; 638 fFlags &= ~SUPGIP_FLAGS_TESTING_ENABLE; 639 supdrvGipSetFlags(pDevExt, pSession, 0, fFlags); 640 Assert(!pSession->fGipTestMode); 641 } 629 642 630 643 /* … … 2092 2105 uint32_t u32UpdateIntervalTSCSlack; 2093 2106 unsigned iTSCHistoryHead; 2107 bool fUpdateCpuHz; 2108 uint32_t fGipFlags; 2094 2109 uint64_t u64CpuHz; 2095 2110 uint32_t u32TransactionId; … … 2112 2127 ASMAtomicWriteU64(&pGipCpu->u64TSC, u64TSC); 2113 2128 2129 /* Determine when we need to update the TSC frequency. */ 2130 fUpdateCpuHz = pGip->u32Mode != SUPGIPMODE_INVARIANT_TSC; 2131 2132 /* 2133 * Handle GIP test mode toggle. 2134 */ 2135 fGipFlags = pGip->fFlags; 2136 if (!(fGipFlags & SUPGIP_FLAGS_TESTING)) 2137 { /* likely*/ } 2138 else 2139 { 2140 if (fGipFlags & (SUPGIP_FLAGS_TESTING_ENABLE | SUPGIP_FLAGS_TESTING_START)) 2141 { 2142 if (fGipFlags & SUPGIP_FLAGS_TESTING_START) 2143 { 2144 /* Cache the TSC frequency before forcing updates due to test mode. */ 2145 if (!fUpdateCpuHz) 2146 pDevExt->uGipTestModeInvariantCpuHz = pGip->aCPUs[0].u64CpuHz; 2147 fGipFlags &= ~SUPGIP_FLAGS_TESTING_START; 2148 ASMAtomicWriteU32(&pGip->fFlags, fGipFlags); 2149 } 2150 fUpdateCpuHz = true; 2151 } 2152 else if (fGipFlags & SUPGIP_FLAGS_TESTING_STOP) 2153 { 2154 /* Restore the cached TSC frequency if any. */ 2155 if (!fUpdateCpuHz) 2156 { 2157 Assert(pDevExt->uGipTestModeInvariantCpuHz); 2158 ASMAtomicWriteU64(&pGip->aCPUs[0].u64CpuHz, pDevExt->uGipTestModeInvariantCpuHz); 2159 } 2160 fGipFlags &= ~(SUPGIP_FLAGS_TESTING_STOP | SUPGIP_FLAGS_TESTING); 2161 ASMAtomicWriteU32(&pGip->fFlags, fGipFlags); 2162 } 2163 } 2164 2114 2165 /* 2115 2166 * We don't need to keep realculating the frequency when it's invariant, so 2116 2167 * the remainder of this function is only for the sync and async TSC modes. 2117 2168 */ 2118 if ( pGip->u32Mode != SUPGIPMODE_INVARIANT_TSC)2169 if (fUpdateCpuHz) 2119 2170 { 2120 2171 if (u64TSCDelta >> 32) … … 2980 3031 * eliminate huge deltas when the worker is too early and doesn't by 2981 3032 * itself help produce more accurate deltas. We allow two times the 2982 * computed minimum as an arbi btrary acceptable threshold. Therefore,3033 * computed minimum as an arbitrary acceptable threshold. Therefore, 2983 3034 * it is still possible to get negative deltas where there are none 2984 3035 * when the worker is earlier. As long as these occasional negative 2985 3036 * deltas are lower than the time it takes to exit guest-context and 2986 * the OS to reschedule EMT on a different CPU we won't expose a TSC2987 * that jumped backwards. It is because of the existence of the2988 * negative deltaswe don't recompute the delta with the master and3037 * the OS to reschedule EMT on a different CPU, we won't expose a TSC 3038 * that jumped backwards. It is due to the existence of the negative 3039 * deltas that we don't recompute the delta with the master and 2989 3040 * worker interchanged to eliminate the remaining measurement error. 2990 3041 * … … 4722 4773 } 4723 4774 4775 4776 /** 4777 * Worker for supdrvIOCtl_GipSetFlags. 4778 * 4779 * @returns VBox status code. 4780 * @param pDevExt Pointer to the device instance data. 4781 * @param pSession The support driver session. 4782 * @param fOrMask The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX. 4783 * @param fAndMask The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX. 4784 * 4785 * @remarks This function doesn't validate any of the flags. 4786 */ 4787 static int supdrvGipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask) 4788 { 4789 uint32_t cRefs; 4790 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 4791 4792 /* 4793 * Compute GIP test-mode flags. 4794 */ 4795 if (fOrMask & SUPGIP_FLAGS_TESTING_ENABLE) 4796 { 4797 pSession->fGipTestMode = true; 4798 cRefs = ASMAtomicIncU32(&pDevExt->cGipTestModeRefs); 4799 if (cRefs == 1) 4800 fOrMask |= SUPGIP_FLAGS_TESTING | SUPGIP_FLAGS_TESTING_START; 4801 } 4802 else 4803 { 4804 cRefs = ASMAtomicDecU32(&pDevExt->cGipTestModeRefs); 4805 pSession->fGipTestMode = false; 4806 if (!cRefs) 4807 fOrMask |= SUPGIP_FLAGS_TESTING_STOP; 4808 } 4809 4810 /* 4811 * Commit the flags. 4812 */ 4813 uint32_t fFlags = ASMAtomicUoReadU32(&pGip->fFlags); 4814 fFlags |= fOrMask; 4815 fFlags &= fAndMask; 4816 ASMAtomicWriteU32(&pGip->fFlags, fFlags); 4817 return VINF_SUCCESS; 4818 } 4819 4820 4821 /** 4822 * Sets GIP test mode parameters. 4823 * 4824 * @returns VBox status code. 4825 * @param pDevExt Pointer to the device instance data. 4826 * @param pSession The support driver session. 4827 * @param fOrMask The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX. 4828 * @param fAndMask The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX. 4829 */ 4830 int VBOXCALL supdrvIOCtl_GipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask) 4831 { 4832 PSUPGLOBALINFOPAGE pGip; 4833 4834 /* 4835 * Validate. We require the client to have mapped GIP (no asserting on 4836 * ring-3 preconditions). 4837 */ 4838 AssertPtr(pDevExt); AssertPtr(pSession); /* paranoia^2 */ 4839 if (pSession->GipMapObjR3 == NIL_RTR0MEMOBJ) 4840 return VERR_WRONG_ORDER; 4841 pGip = pDevExt->pGip; 4842 AssertReturn(pGip, VERR_INTERNAL_ERROR_3); 4843 4844 if (fOrMask & ~SUPGIP_FLAGS_VALID_MASK) 4845 return VERR_INVALID_PARAMETER; 4846 if ((fAndMask & ~SUPGIP_FLAGS_VALID_MASK) != ~SUPGIP_FLAGS_VALID_MASK) 4847 return VERR_INVALID_PARAMETER; 4848 4849 return supdrvGipSetFlags(pDevExt, pSession, fOrMask, fAndMask); 4850 } 4851 -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r57093 r57218 1523 1523 /** @} */ 1524 1524 1525 1525 1526 /** @name SUP_IOCTL_TSC_READ 1526 1527 * Reads the TSC and apply TSC-delta if applicable, determining the delta if … … 1559 1560 /** @} */ 1560 1561 1562 1563 /** @name SUP_IOCTL_GIP_SET_FLAGS 1564 * Set GIP flags. 1565 * 1566 * @{ 1567 */ 1568 #define SUP_IOCTL_GIP_SET_FLAGS SUP_CTL_CODE_SIZE(39, SUP_IOCTL_GIP_SET_FLAGS_SIZE) 1569 #define SUP_IOCTL_GIP_SET_FLAGS_SIZE sizeof(SUPGIPSETFLAGS) 1570 #define SUP_IOCTL_GIP_SET_FLAGS_SIZE_IN sizeof(SUPGIPSETFLAGS) 1571 #define SUP_IOCTL_GIP_SET_FLAGS_SIZE_OUT sizeof(SUPREQHDR) 1572 typedef struct SUPGIPSETFLAGS 1573 { 1574 /** The header. */ 1575 SUPREQHDR Hdr; 1576 union 1577 { 1578 struct 1579 { 1580 /** The AND flags mask, see SUPGIP_FLAGS_XXX. */ 1581 uint32_t fAndMask; 1582 /** The OR flags mask, see SUPGIP_FLAGS_XXX. */ 1583 uint32_t fOrMask; 1584 } In; 1585 } u; 1586 } SUPGIPSETFLAGS, *PSUPGIPSETFLAGS; 1587 /** @} */ 1588 1561 1589 #pragma pack() /* paranoia */ 1562 1590 -
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r56558 r57218 545 545 /** The user tracepoint module lookup table. */ 546 546 struct SUPDRVTRACERUMOD *apTpLookupTable[32]; 547 /** Whether this is a GIP test-mode client session or not. */ 548 bool fGipTestMode; 547 549 #ifndef SUPDRV_AGNOSTIC 548 550 # if defined(RT_OS_DARWIN) … … 752 754 #endif 753 755 756 /** @name GIP test mode. 757 * @{ */ 758 /** Reference counter for GIP test-mode sessions. */ 759 uint32_t volatile cGipTestModeRefs; 760 /** Cache of TSC frequency before enabling test-mode on invariant GIP systems. */ 761 uint64_t uGipTestModeInvariantCpuHz; 762 /** @} */ 763 754 764 /* 755 765 * Note! The non-agnostic bits must be at the very end of the structure! … … 949 959 int VBOXCALL supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCDELTAMEASURE pReq); 950 960 int VBOXCALL supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCREAD pReq); 961 int VBOXCALL supdrvIOCtl_GipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask); 962 951 963 952 964 /* SUPDrvTracer.cpp */ -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r56293 r57218 2248 2248 } 2249 2249 2250 2251 SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask) 2252 { 2253 AssertMsgReturn(!(fOrMask & ~SUPGIP_FLAGS_VALID_MASK), 2254 ("fOrMask=%#x ValidMask=%#x\n", fOrMask, SUPGIP_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); 2255 AssertMsgReturn((fAndMask & ~SUPGIP_FLAGS_VALID_MASK) == ~SUPGIP_FLAGS_VALID_MASK, 2256 ("fAndMask=%#x ValidMask=%#x\n", fAndMask, SUPGIP_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); 2257 2258 SUPGIPSETFLAGS Req; 2259 Req.Hdr.u32Cookie = g_u32Cookie; 2260 Req.Hdr.u32SessionCookie = g_u32SessionCookie; 2261 Req.Hdr.cbIn = SUP_IOCTL_GIP_SET_FLAGS_SIZE_IN; 2262 Req.Hdr.cbOut = SUP_IOCTL_GIP_SET_FLAGS_SIZE_OUT; 2263 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2264 Req.Hdr.rc = VERR_INTERNAL_ERROR; 2265 2266 Req.u.In.fAndMask = fAndMask; 2267 Req.u.In.fOrMask = fOrMask; 2268 2269 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_SET_FLAGS, &Req, SUP_IOCTL_GIP_SET_FLAGS_SIZE); 2270 if (RT_SUCCESS(rc)) 2271 rc = Req.Hdr.rc; 2272 return rc; 2273 } 2274 -
trunk/src/VBox/HostDrivers/Support/SUPLibAll.cpp
r57097 r57218 288 288 /* Arbitrary tolerance threshold, tweak later if required, perhaps 289 289 more tolerance on lower frequencies and less tolerance on higher. */ 290 uint16_t uThr = !fRelax ? 666 /* 0.15% */ : 125 /* 0.8% */; 291 uint64_t uLo = uBaseCpuHz / uThr; 292 uint64_t uHi = uBaseCpuHz + (uBaseCpuHz - uLo); 290 uint16_t uFact = !fRelax ? 666 /* 0.15% */ : 125 /* 0.8% */; 291 uint64_t uThr = uBaseCpuHz / uFact; 292 uint64_t uLo = uBaseCpuHz - uThr; 293 uint64_t uHi = uBaseCpuHz + uThr; 293 294 if ( uCpuHz < uLo 294 295 || uCpuHz > uHi) -
trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp
r57060 r57218 41 41 #include <iprt/x86.h> 42 42 43 44 /**45 * Checks whether the CPU advertises an invariant TSC or not.46 *47 * @returns true if invariant, false otherwise.48 */49 bool tstIsInvariantTsc(void)50 {51 if (ASMHasCpuId())52 {53 uint32_t uEax, uEbx, uEcx, uEdx;54 ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);55 if (uEax >= 0x80000007)56 {57 ASMCpuId(0x80000007, &uEax, &uEbx, &uEcx, &uEdx);58 if (uEdx & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)59 return true;60 }61 }62 return false;63 }64 65 66 43 int main(int argc, char **argv) 67 44 { … … 79 56 { "--reference", 'r', RTGETOPT_REQ_UINT64 }, /* reference value of CpuHz, display the 80 57 * CpuHz deviation in a separate column. */ 58 { "--notestmode", 't', RTGETOPT_REQ_NOTHING } /* don't run GIP in test-mode (atm, test-mode 59 * implies updating GIP CpuHz even when invariant) */ 81 60 }; 82 61 … … 85 64 bool fSpin = false; 86 65 bool fCompat = true; 66 bool fTestMode = true; 87 67 int ch; 88 uint64_t uCpuHzRef = 0;68 uint64_t uCpuHzRef = UINT64_MAX; 89 69 uint64_t uCpuHzOverallDeviation = 0; 90 70 uint32_t cCpuHzNotCompat = 0; … … 118 98 break; 119 99 100 case 't': 101 fTestMode = false; 102 break; 103 120 104 default: 121 105 return RTGetOptPrintError(ch, &ValueUnion); … … 132 116 if (g_pSUPGlobalInfoPage) 133 117 { 118 /* Pick current CpuHz as the reference if none was specified. */ 119 if (uCpuHzRef == UINT64_MAX) 120 uCpuHzRef = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage); 121 122 if ( fTestMode 123 && g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC) 124 SUPR3GipSetFlags(SUPGIP_FLAGS_TESTING_ENABLE, UINT32_MAX); 125 134 126 RTPrintf("tstGIP-2: cCpus=%d u32UpdateHz=%RU32 u32UpdateIntervalNS=%RU32 u64NanoTSLastUpdateHz=%RX64 u64CpuHz=%RU64 uCpuHzRef=%RU64 u32Mode=%d (%s) u32Version=%#x\n", 135 127 g_pSUPGlobalInfoPage->cCpus, … … 147 139 uCpuHzRef ? " CpuHz deviation Compat " : ""); 148 140 static SUPGIPCPU s_aaCPUs[2][256]; 141 149 142 for (uint32_t i = 0; i < cIterations; i++) 150 143 { … … 170 163 { 171 164 /* Wait until the history validation code takes effect. */ 165 bool fCurHzCompat = true; 172 166 if (pCpu->u32TransactionId > 23 + (8 * 2) + 1) 173 167 { … … 176 170 uCpuHzOverallDeviation += uCpuHzDeviation; 177 171 cCpuHzOverallDevCnt++; 172 fCurHzCompat = SUPIsTscFreqCompatibleEx(uCpuHzRef, pCpu->u64CpuHz, false /* fRelax */); 178 173 } 179 bool fCurHzCompat = SUPIsTscFreqCompatibleEx(uCpuHzRef, pCpu->u64CpuHz, false /* fRelax */);180 174 uint32_t uPct = (uint32_t)(uCpuHzDeviation * 100000 / uCpuHzRef + 5); 181 175 RTStrPrintf(szCpuHzDeviation, sizeof(szCpuHzDeviation), "%10RI64%3d.%02d%% %RTbool ", … … 271 265 RTPrintf("tstGIP-2: CpuHz compatibility: %RTbool (incompatible %u of %u times w/ %RU64 Hz)\n", fCompat, 272 266 cCpuHzNotCompat, cIterations * g_pSUPGlobalInfoPage->cCpus, uCpuHzRef); 267 268 if ( !fCompat 269 && g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC) 270 rc = -1; 273 271 } 272 273 /* Disable GIP test mode. */ 274 if (fTestMode) 275 SUPR3GipSetFlags(0, ~SUPGIP_FLAGS_TESTING_ENABLE); 274 276 } 275 277 else
Note:
See TracChangeset
for help on using the changeset viewer.