Changeset 36254 in vbox for trunk/src/VBox
- Timestamp:
- Mar 10, 2011 5:22:08 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r36239 r36254 131 131 static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick); 132 132 static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser); 133 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz); 133 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, 134 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned cCpus); 135 static DECLCALLBACK(void) supdrvGipInitOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2); 134 136 static void supdrvGipTerm(PSUPGLOBALINFOPAGE pGip); 135 static void supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick); 136 static void supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu, uint64_t iTick); 137 static void supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, RTCPUID idCpu, uint64_t iTick); 138 static void supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, 139 RTCPUID idCpu, uint8_t idApic, uint64_t iTick); 137 140 138 141 … … 289 292 { "RTThreadUserWait", (void *)RTThreadUserWait }, 290 293 { "RTThreadUserWaitNoResume", (void *)RTThreadUserWaitNoResume }, 291 #else 292 /** 293 * @todo: remove me, once above code enabled. 294 * We need RTThreadCreate/RTThreadWait in the PCI driver. 295 */ 296 { "RTThreadCreate", (void *)RTThreadCreate }, 297 { "RTThreadWait", (void *)RTThreadWait }, 294 #else 295 /** 296 * @todo: remove me, once above code enabled. 297 * We need RTThreadCreate/RTThreadWait in the PCI driver. 298 */ 299 { "RTThreadCreate", (void *)RTThreadCreate }, 300 { "RTThreadWait", (void *)RTThreadWait }, 298 301 #endif 299 302 { "RTThreadPreemptIsEnabled", (void *)RTThreadPreemptIsEnabled }, … … 3213 3216 { 3214 3217 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser1; 3218 #ifdef SUP_WITH_LOTS_OF_CPUS 3219 unsigned iCpu = pGip->aiCpuFromApicId[ASMGetApicId()]; 3220 #else 3215 3221 unsigned iCpu = ASMGetApicId(); 3216 3222 #endif 3223 3224 #ifdef SUP_WITH_LOTS_OF_CPUS 3225 if (RT_LIKELY(iCpu < pGip->cCpus && pGip->aCPUs[iCpu].idCpu == idCpu)) 3226 #else 3217 3227 if (RT_LIKELY(iCpu < RT_ELEMENTS(pGip->aCPUs))) 3228 #endif 3218 3229 supdrvGipReInitCpu(&pGip->aCPUs[iCpu], *(uint64_t *)pvUser2); 3219 3230 … … 4807 4818 static int supdrvGipCreate(PSUPDRVDEVEXT pDevExt) 4808 4819 { 4809 PSUPGLOBALINFOPAGE pGip; 4810 RTHCPHYS HCPhysGip; 4811 uint32_t u32SystemResolution; 4812 uint32_t u32Interval; 4813 int rc; 4820 PSUPGLOBALINFOPAGE pGip; 4821 RTHCPHYS HCPhysGip; 4822 uint32_t u32SystemResolution; 4823 uint32_t u32Interval; 4824 unsigned cCpus; 4825 int rc; 4826 4814 4827 4815 4828 LogFlow(("supdrvGipCreate:\n")); … … 4821 4834 4822 4835 /* 4823 * Allocate a suitable page with a default kernel mapping. 4824 */ 4825 rc = RTR0MemObjAllocLow(&pDevExt->GipMemObj, PAGE_SIZE, false); 4836 * Check the CPU count. 4837 */ 4838 cCpus = RTMpGetArraySize(); 4839 #ifdef SUP_WITH_LOTS_OF_CPUS 4840 if ( cCpus > RTCPUSET_MAX_CPUS 4841 || cCpus > 256 /*uint8_t is used for the mappings*/) 4842 #else 4843 if (cCpus > RT_ELEMENTS(pGip->aCPUs)) 4844 #endif 4845 { 4846 #ifdef SUP_WITH_LOTS_OF_CPUS 4847 SUPR0Printf("VBoxDrv: Too many CPUs (%u) for the GIP (max %u)\n", cCpus, RT_MIN(RTCPUSET_MAX_CPUS, 256)); 4848 #else 4849 SUPR0Printf("VBoxDrv: Too many CPUs (%u) for the GIP (max %u)\n", cCpus, RT_MIN(RT_ELEMENTS(pGip->aCPUs), 256)); 4850 #endif 4851 return VERR_TOO_MANY_CPUS; 4852 } 4853 4854 /* 4855 * Allocate a contiguous set of pages with a default kernel mapping. 4856 */ 4857 #ifdef SUP_WITH_LOTS_OF_CPUS 4858 rc = RTR0MemObjAllocCont(&pDevExt->GipMemObj, RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), false /*fExecutable*/); 4859 #else 4860 cCpus = RT_ELEMENTS(pGip->aCPUs); 4861 rc = RTR0MemObjAllocLow(&pDevExt->GipMemObj, PAGE_SIZE, false /*fExecutable*/); 4862 #endif 4826 4863 if (RT_FAILURE(rc)) 4827 4864 { … … 4839 4876 u32Interval += u32SystemResolution; 4840 4877 4841 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/ );4878 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/, cCpus); 4842 4879 4843 4880 /* … … 4858 4895 if (RT_SUCCESS(rc)) 4859 4896 { 4860 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 4861 rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt); 4897 rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt); 4862 4898 if (RT_SUCCESS(rc)) 4863 4899 { 4864 /* 4865 * We're good. 4866 */ 4867 Log(("supdrvGipCreate: %ld ns interval.\n", (long)u32Interval)); 4868 g_pSUPGlobalInfoPage = pGip; 4869 return VINF_SUCCESS; 4870 } 4871 4872 OSDBGPRINT(("supdrvGipCreate: failed register MP event notfication. rc=%d\n", rc)); 4900 rc = RTMpOnAll(supdrvGipInitOnCpu, pDevExt, pGip); 4901 if (RT_SUCCESS(rc)) 4902 { 4903 /* 4904 * We're good. 4905 */ 4906 Log(("supdrvGipCreate: %u ns interval.\n", u32Interval)); 4907 g_pSUPGlobalInfoPage = pGip; 4908 return VINF_SUCCESS; 4909 } 4910 4911 OSDBGPRINT(("supdrvGipCreate: RTMpOnAll failed with rc=%Rrc\n", rc)); 4912 RTMpNotificationDeregister(supdrvGipMpEvent, pDevExt); 4913 4914 } 4915 else 4916 OSDBGPRINT(("supdrvGipCreate: failed to register MP event notfication. rc=%Rrc\n", rc)); 4873 4917 } 4874 4918 else 4875 4919 { 4876 OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at % ld ns interval. rc=%d\n", (long)u32Interval, rc));4920 OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %u ns interval. rc=%Rrc\n", u32Interval, rc)); 4877 4921 Assert(!pDevExt->pGipTimer); 4878 4922 } … … 4945 4989 uint64_t NanoTS = RTTimeSystemNanoTS(); 4946 4990 4947 supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, iTick);4991 supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, NIL_RTCPUID, iTick); 4948 4992 4949 4993 ASMSetFlags(fOldFlags); … … 4966 5010 /** @todo reset the transaction number and whatnot when iTick == 1. */ 4967 5011 if (pDevExt->idGipMaster == idCpu) 4968 supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, i Tick);5012 supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, idCpu, iTick); 4969 5013 else 4970 supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, u64TSC, ASMGetApicId(), iTick);5014 supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, u64TSC, idCpu, ASMGetApicId(), iTick); 4971 5015 4972 5016 ASMSetFlags(fOldFlags); … … 4975 5019 4976 5020 /** 5021 * The calling CPU should be accounted as online, update GIP accordingly. 5022 * 5023 * This is used by supdrvGipMpEvent as well as the supdrvGipCreate. 5024 * 5025 * @param pGip The GIP. 5026 * @param idCpu The CPU ID. 5027 */ 5028 static void supdrvGipMpEventOnline(PSUPGLOBALINFOPAGE pGip, RTCPUID idCpu) 5029 { 5030 #ifdef SUP_WITH_LOTS_OF_CPUS 5031 int iCpuSet; 5032 uint8_t idApic; 5033 uint32_t i; 5034 5035 Assert(idCpu == RTMpCpuId()); 5036 Assert(pGip->cPossibleCpus == RTMpGetCount()); 5037 5038 /* 5039 * Update the globals. 5040 */ 5041 ASMAtomicWriteU32(&pGip->cPresentCpus, RTMpGetPresentCount()); 5042 ASMAtomicWriteU32(&pGip->cOnlineCpus, RTMpGetOnlineCount()); 5043 iCpuSet = RTMpCpuIdToSetIndex(idCpu); 5044 if (iCpuSet >= 0) 5045 { 5046 Assert(RTCpuSetIsMemberByIndex(&pGip->PossibleCpuSet, iCpuSet)); 5047 RTCpuSetAddByIndex(&pGip->OnlineCpuSet, iCpuSet); 5048 RTCpuSetAddByIndex(&pGip->PresentCpuSet, iCpuSet); 5049 } 5050 5051 /* 5052 * Find our entry, or allocate one if not found. 5053 * ASSUMES that CPU IDs are constant. 5054 */ 5055 for (i = 0; i < pGip->cCpus; i++) 5056 if (pGip->aCPUs[i].idCpu == idCpu) 5057 break; 5058 5059 if (i >= pGip->cCpus) 5060 for (i = 0; i < pGip->cCpus; i++) 5061 { 5062 bool fRc; 5063 ASMAtomicCmpXchgSize(&pGip->aCPUs[i].idCpu, idCpu, NIL_RTCPUID, fRc); 5064 if (fRc) 5065 break; 5066 } 5067 5068 AssertReturnVoid(i < pGip->cCpus); 5069 5070 /* 5071 * Update the entry. 5072 */ 5073 idApic = ASMGetApicId(); 5074 ASMAtomicUoWriteU16(&pGip->aCPUs[i].idApic, idApic); 5075 ASMAtomicUoWriteS16(&pGip->aCPUs[i].iCpuSet, (int16_t)iCpuSet); 5076 ASMAtomicUoWriteSize(&pGip->aCPUs[i].idCpu, idCpu); 5077 ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_ONLINE); 5078 5079 /* 5080 * Update the APIC ID and CPU set index mappings. 5081 */ 5082 ASMAtomicWriteU16(&pGip->aiCpuFromApicId[idApic], i); 5083 ASMAtomicWriteU16(&pGip->aiCpuFromCpuSetIdx[iCpuSet], i); 5084 #endif 5085 } 5086 5087 5088 /** 5089 * The CPU should be accounted as offline, update the GIP accordingly. 5090 * 5091 * This is used by supdrvGipMpEvent. 5092 * 5093 * @param pGip The GIP. 5094 * @param idCpu The CPU ID. 5095 */ 5096 static void supdrvGipMpEventOffline(PSUPGLOBALINFOPAGE pGip, RTCPUID idCpu) 5097 { 5098 #ifdef SUP_WITH_LOTS_OF_CPUS 5099 int iCpuSet; 5100 unsigned i; 5101 5102 iCpuSet = RTMpCpuIdToSetIndex(idCpu); 5103 AssertReturnVoid(iCpuSet >= 0); 5104 5105 i = pGip->aiCpuFromCpuSetIdx[iCpuSet]; 5106 AssertReturnVoid(i < pGip->cCpus); 5107 AssertReturnVoid(pGip->aCPUs[i].idCpu == idCpu); 5108 5109 Assert(RTCpuSetIsMemberByIndex(&pGip->PossibleCpuSet, iCpuSet)); 5110 ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_OFFLINE); 5111 RTCpuSetDelByIndex(&pGip->OnlineCpuSet, iCpuSet); 5112 #endif 5113 } 5114 5115 5116 /** 4977 5117 * Multiprocessor event notification callback. 4978 5118 * 4979 * This is used to make su e that the GIP master gets passed on to4980 * another CPU. 5119 * This is used to make sure that the GIP master gets passed on to 5120 * another CPU. It also updates the associated CPU data. 4981 5121 * 4982 5122 * @param enmEvent The event. … … 4986 5126 static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser) 4987 5127 { 4988 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 5128 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 5129 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 5130 5131 /* 5132 * Update the GIP CPU data. 5133 */ 5134 if (pGip) 5135 { 5136 switch (enmEvent) 5137 { 5138 case RTMPEVENT_ONLINE: 5139 supdrvGipMpEventOnline(pGip, idCpu); 5140 break; 5141 case RTMPEVENT_OFFLINE: 5142 supdrvGipMpEventOffline(pGip, idCpu); 5143 break; 5144 5145 } 5146 } 5147 5148 /* 5149 * Make sure there is a master GIP. 5150 */ 4989 5151 if (enmEvent == RTMPEVENT_OFFLINE) 4990 5152 { … … 5184 5346 * @param u64NanoTS The current nanosecond timestamp. 5185 5347 * @param uUpdateHz The update frequency. 5186 */ 5187 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz) 5188 { 5189 unsigned i; 5348 * @param cCpus The CPU count. 5349 */ 5350 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, 5351 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned cCpus) 5352 { 5353 size_t const cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), PAGE_SIZE); 5354 unsigned i; 5190 5355 #ifdef DEBUG_DARWIN_GIP 5191 OSDBGPRINT(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d \n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz));5356 OSDBGPRINT(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d cCpus=%u\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz, cCpus)); 5192 5357 #else 5193 LogFlow(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d \n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz));5358 LogFlow(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d cCpus=%u\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz, cCpus)); 5194 5359 #endif 5195 5360 … … 5197 5362 * Initialize the structure. 5198 5363 */ 5199 memset(pGip, 0, PAGE_SIZE); 5200 pGip->u32Magic = SUPGLOBALINFOPAGE_MAGIC; 5201 pGip->u32Version = SUPGLOBALINFOPAGE_VERSION; 5202 pGip->u32Mode = supdrvGipDeterminTscMode(pDevExt); 5203 pGip->u32UpdateHz = uUpdateHz; 5204 pGip->u32UpdateIntervalNS = 1000000000 / uUpdateHz; 5364 memset(pGip, 0, cbGip); 5365 pGip->u32Magic = SUPGLOBALINFOPAGE_MAGIC; 5366 pGip->u32Version = SUPGLOBALINFOPAGE_VERSION; 5367 pGip->u32Mode = supdrvGipDeterminTscMode(pDevExt); 5368 #ifdef SUP_WITH_LOTS_OF_CPUS 5369 pGip->cCpus = (uint16_t)cCpus; 5370 pGip->cPages = (uint16_t)(cbGip / PAGE_SIZE); 5371 #endif 5372 pGip->u32UpdateHz = uUpdateHz; 5373 pGip->u32UpdateIntervalNS = 1000000000 / uUpdateHz; 5205 5374 pGip->u64NanoTSLastUpdateHz = u64NanoTS; 5206 5207 for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++) 5375 #ifdef SUP_WITH_LOTS_OF_CPUS 5376 RTCpuSetEmpty(&pGip->OnlineCpuSet); 5377 pGip->cOnlineCpus = RTMpGetOnlineCount(); 5378 pGip->cPresentCpus = RTMpGetPresentCount(); 5379 RTCpuSetEmpty(&pGip->PresentCpuSet); 5380 RTMpGetSet(&pGip->PossibleCpuSet); 5381 pGip->cPossibleCpus = RTMpGetCount(); 5382 pGip->idCpuMax = RTMpGetMaxCpuId(); 5383 for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromApicId); i++) 5384 pGip->aiCpuFromApicId[i] = 0; 5385 for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx); i++) 5386 pGip->aiCpuFromCpuSetIdx[i] = UINT16_MAX; 5387 #endif 5388 5389 for (i = 0; i < cCpus; i++) 5208 5390 { 5209 5391 pGip->aCPUs[i].u32TransactionId = 2; 5210 5392 pGip->aCPUs[i].u64NanoTS = u64NanoTS; 5211 5393 pGip->aCPUs[i].u64TSC = ASMReadTSC(); 5394 5395 #ifdef SUP_WITH_LOTS_OF_CPUS 5396 pGip->aCPUs[i].enmState = SUPGIPCPUSTATE_INVALID; 5397 pGip->aCPUs[i].idCpu = NIL_RTCPUID; 5398 pGip->aCPUs[i].iCpuSet = -1; 5399 pGip->aCPUs[i].idApic = UINT8_MAX; 5400 #endif 5212 5401 5213 5402 /* … … 5232 5421 * Link it to the device extension. 5233 5422 */ 5234 pDevExt->pGip = pGip;5423 pDevExt->pGip = pGip; 5235 5424 pDevExt->HCPhysGip = HCPhys; 5236 5425 pDevExt->cGipUsers = 0; 5426 } 5427 5428 5429 /** 5430 * On CPU initialization callback for RTMpOnAll. 5431 * 5432 * @param idCpu The CPU ID. 5433 * @param pvUser1 The device extension. 5434 * @param pvUser2 The GIP. 5435 */ 5436 static DECLCALLBACK(void) supdrvGipInitOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2) 5437 { 5438 /* This is good enough, even though it will update some of the globals a 5439 bit to much. */ 5440 supdrvGipMpEventOnline((PSUPGLOBALINFOPAGE)pvUser2, idCpu); 5237 5441 } 5238 5442 … … 5281 5485 * Update the NanoTS. 5282 5486 */ 5283 ASMAtomic XchgU64(&pGipCpu->u64NanoTS, u64NanoTS);5487 ASMAtomicWriteU64(&pGipCpu->u64NanoTS, u64NanoTS); 5284 5488 5285 5489 /* … … 5288 5492 /** @todo validate the NanoTS delta, don't trust the OS to call us when it should... */ 5289 5493 u64TSCDelta = u64TSC - pGipCpu->u64TSC; 5290 ASMAtomic XchgU64(&pGipCpu->u64TSC, u64TSC);5494 ASMAtomicWriteU64(&pGipCpu->u64TSC, u64TSC); 5291 5495 5292 5496 if (u64TSCDelta >> 32) … … 5318 5522 Assert(RT_ELEMENTS(pGipCpu->au32TSCHistory) == 8); 5319 5523 iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7; 5320 ASMAtomic XchgU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);5321 ASMAtomic XchgU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);5524 ASMAtomicWriteU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead); 5525 ASMAtomicWriteU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta); 5322 5526 5323 5527 /* … … 5359 5563 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6; 5360 5564 } 5361 ASMAtomic XchgU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);5565 ASMAtomicWriteU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack); 5362 5566 5363 5567 /* … … 5365 5569 */ 5366 5570 u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz); 5367 ASMAtomic XchgU64(&pGipCpu->u64CpuHz, u64CpuHz);5571 ASMAtomicWriteU64(&pGipCpu->u64CpuHz, u64CpuHz); 5368 5572 } 5369 5573 … … 5375 5579 * @param u64NanoTS The current nanosecond timesamp. 5376 5580 * @param u64TSC The current TSC timesamp. 5581 * @param idCpu The CPU ID. 5377 5582 * @param iTick The current timer tick. 5378 5583 */ 5379 static void supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick)5584 static void supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, RTCPUID idCpu, uint64_t iTick) 5380 5585 { 5381 5586 /* … … 5387 5592 else 5388 5593 { 5594 #ifdef SUP_WITH_LOTS_OF_CPUS 5595 unsigned iCpu = pGip->aiCpuFromApicId[ASMGetApicId()]; 5596 if (RT_UNLIKELY(iCpu >= pGip->cCpus)) 5597 return; 5598 pGipCpu = &pGip->aCPUs[iCpu]; 5599 if (RT_UNLIKELY(pGipCpu->idCpu != idCpu)) 5600 return; 5601 #else 5389 5602 unsigned iCpu = ASMGetApicId(); 5390 5603 if (RT_UNLIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs))) 5391 5604 return; 5392 5605 pGipCpu = &pGip->aCPUs[iCpu]; 5606 #endif 5393 5607 } 5394 5608 … … 5417 5631 if (u32UpdateHz <= 2000 && u32UpdateHz >= 30) 5418 5632 { 5419 ASMAtomic XchgU32(&pGip->u32UpdateHz, u32UpdateHz);5420 ASMAtomic XchgU32(&pGip->u32UpdateIntervalNS, 1000000000 / u32UpdateHz);5633 ASMAtomicWriteU32(&pGip->u32UpdateHz, u32UpdateHz); 5634 ASMAtomicWriteU32(&pGip->u32UpdateIntervalNS, 1000000000 / u32UpdateHz); 5421 5635 } 5422 5636 #endif 5423 5637 } 5424 ASMAtomic XchgU64(&pGip->u64NanoTSLastUpdateHz, u64NanoTS);5638 ASMAtomicWriteU64(&pGip->u64NanoTSLastUpdateHz, u64NanoTS); 5425 5639 } 5426 5640 … … 5443 5657 * @param u64NanoTS The current nanosecond timesamp. 5444 5658 * @param u64TSC The current TSC timesamp. 5445 * @param iCpu The CPU index. 5659 * @param idCpu The CPU ID. 5660 * @param idApic The APIC id for the CPU index. 5446 5661 * @param iTick The current timer tick. 5447 5662 */ 5448 static void supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu, uint64_t iTick) 5449 { 5450 PSUPGIPCPU pGipCpu; 5663 static void supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, 5664 RTCPUID idCpu, uint8_t idApic, uint64_t iTick) 5665 { 5666 #ifdef SUP_WITH_LOTS_OF_CPUS 5667 unsigned iCpu = pGip->aiCpuFromApicId[idApic]; 5668 5669 if (RT_LIKELY(iCpu < pGip->cCpus)) 5670 #else 5671 unsigned iCpu = idApic; 5451 5672 5452 5673 if (RT_LIKELY(iCpu < RT_ELEMENTS(pGip->aCPUs))) 5453 { 5454 pGipCpu = &pGip->aCPUs[iCpu]; 5455 5456 /* 5457 * Start update transaction. 5458 */ 5459 if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1)) 5460 { 5461 AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId)); 5674 #endif 5675 { 5676 PSUPGIPCPU pGipCpu = &pGip->aCPUs[iCpu]; 5677 #ifdef SUP_WITH_LOTS_OF_CPUS 5678 if (pGipCpu->idCpu == idCpu) 5679 #endif 5680 { 5681 5682 /* 5683 * Start update transaction. 5684 */ 5685 if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1)) 5686 { 5687 AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId)); 5688 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 5689 pGipCpu->cErrors++; 5690 return; 5691 } 5692 5693 /* 5694 * Update the data. 5695 */ 5696 supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC, iTick); 5697 5698 /* 5699 * Complete transaction. 5700 */ 5462 5701 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 5463 pGipCpu->cErrors++; 5464 return; 5465 } 5466 5467 /* 5468 * Update the data. 5469 */ 5470 supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC, iTick); 5471 5472 /* 5473 * Complete transaction. 5474 */ 5475 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 5476 } 5477 } 5702 } 5703 } 5704 } -
trunk/src/VBox/HostDrivers/Support/freebsd/Makefile
r33379 r36254 133 133 RTSemEventMultiWaitNoResume-2-ex-generic.c \ 134 134 RTTimerCreate-generic.c \ 135 timer-generic.c \136 mppresent-generic.c135 mppresent-generic.c \ 136 timer-generic.c 137 137 138 138 .PATH: ${.CURDIR}/r0drv -
trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv
r36190 r36254 158 158 ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \ 159 159 ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \ 160 ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \ 160 161 ${PATH_ROOT}/src/VBox/Runtime/generic/timer-generic.cpp=>generic/timer-generic.c \ 161 ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \162 162 ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.cpp=>r0drv/alloc-r0drv.c \ 163 163 ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.h=>r0drv/alloc-r0drv.h \ -
trunk/src/VBox/HostDrivers/Support/linux/Makefile
r36233 r36254 138 138 generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \ 139 139 generic/RTTimerCreate-generic.o \ 140 generic/mppresent-generic.o \ 140 141 generic/uuid-generic.o \ 141 142 VBox/log-vbox.o -
trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
r36233 r36254 146 146 ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventMultiWaitNoResume-2-ex-generic.c \ 147 147 ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \ 148 ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \ 148 149 ${PATH_ROOT}/src/VBox/Runtime/generic/uuid-generic.cpp=>generic/uuid-generic.c \ 149 150 ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.cpp=>r0drv/alloc-r0drv.c \ -
trunk/src/VBox/Runtime/common/time/timesupA.mac
r36220 r36254 95 95 mov u32ApicIdPlus, ebx 96 96 %endif 97 ; pGipCpu = &pGip->aCPU[ u8ApicId];97 ; pGipCpu = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]]; 98 98 shr ebx, 24 99 %ifdef SUP_WITH_LOTS_OF_CPUS 100 movzx ebx, word [esi + ebx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId] 101 %else 102 and ebx, SUPGLOBALINFOPAGE_CPUS - 1 103 %endif 99 104 mov eax, SUPGIPCPU_size 100 105 mul ebx … … 516 521 mov u32ApicIdPlus, ebx 517 522 %endif 518 ; pGipCpu = &pGip->aCPU[ u8ApicId];523 ; pGipCpu = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]]; 519 524 shr ebx, 24 525 %ifdef SUP_WITH_LOTS_OF_CPUS 526 movzx eax, word [pGip + rbx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId] 527 %else 520 528 mov eax, ebx 521 %if SUPGLOBALINFOPAGE_CPUS < 256522 529 and eax, SUPGLOBALINFOPAGE_CPUS - 1 523 530 %endif -
trunk/src/VBox/Runtime/common/time/timesupref.h
r36220 r36254 63 63 64 64 #ifdef ASYNC_GIP 65 uint8_t u8ApicId = ASMGetApicId();66 # if SUPGLOBALINFOPAGE_CPUS < 25667 PSUPGIPCPU pGipCpu = &pGip->aCPUs[ u8ApicId & SUPGLOBALINFOPAGE_CPUS];65 uint8_t u8ApicId = ASMGetApicId(); 66 # ifdef SUP_WITH_LOTS_OF_CPUS 67 PSUPGIPCPU pGipCpu = &pGip->aCPUs[pGip->aiCpuFromApicId[u8ApicId]]; 68 68 # else 69 PSUPGIPCPU pGipCpu = &pGip->aCPUs[u8ApicId ];69 PSUPGIPCPU pGipCpu = &pGip->aCPUs[u8ApicId & (SUPGLOBALINFOPAGE_CPUS - 1)]; 70 70 # endif 71 71 #else -
trunk/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp
r33676 r36254 5 5 6 6 /* 7 * Copyright (C) 2010 Oracle Corporation7 * Copyright (C) 2010-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 *******************************************************************************/ 31 31 #include <iprt/mp.h> 32 #include "internal/iprt.h" 33 34 #include <iprt/asm.h> 32 35 #include <iprt/cpuset.h> 33 #include "internal/iprt.h"34 36 35 37 36 38 RTDECL(uint32_t) RTMpGetArraySize(void) 37 39 { 38 RTCPUSET CpuSet; 39 return RTCpuLastIndex(RTMpGetSet(&CpuSet)) + 1; 40 /* 41 * Cache the result here. This whole point of this function is that it 42 * will always return the same value, so that should be safe. 43 * 44 * Note! Because RTCPUSET may be to small to represent all the CPUs, we 45 * check with RTMpGetCount() as well. 46 */ 47 static uint32_t s_cMaxCpus = 0; 48 uint32_t cCpus = s_cMaxCpus; 49 if (RT_UNLIKELY(cCpus == 0)) 50 { 51 RTCPUSET CpuSet; 52 uint32_t cCpus1 = RTCpuLastIndex(RTMpGetSet(&CpuSet)) + 1; 53 uint32_t cCpus2 = RTMpGetCount(); 54 uint32_t cCpus = RT_MAX(cCpus1, cCpus2); 55 ASMAtomicCmpXchgU32(&s_cMaxCpus, cCpus, 0); 56 return cCpus; 57 } 58 return s_cMaxCpus; 59 40 60 } 41 61 RT_EXPORT_SYMBOL(RTMpGetArraySize); -
trunk/src/VBox/VMM/VMMR3/TM.cpp
r35346 r36254 122 122 #define LOG_GROUP LOG_GROUP_TM 123 123 #include <VBox/vmm/tm.h> 124 #include <iprt/asm-amd64-x86.h> /* for SUPGetCpuHzFromGIP from sup.h */ 124 125 #include <VBox/vmm/vmm.h> 125 126 #include <VBox/vmm/mm.h> … … 139 140 #include <iprt/asm.h> 140 141 #include <iprt/asm-math.h> 141 #include <iprt/asm-amd64-x86.h>142 142 #include <iprt/assert.h> 143 143 #include <iprt/thread.h> … … 222 222 pVM->tm.s.pvGIPR3 = (void *)g_pSUPGlobalInfoPage; 223 223 AssertMsgReturn(pVM->tm.s.pvGIPR3, ("GIP support is now required!\n"), VERR_INTERNAL_ERROR); 224 AssertMsgReturn((g_pSUPGlobalInfoPage->u32Version >> 16) == (SUPGLOBALINFOPAGE_VERSION >> 16), 225 ("Unsupported GIP version!\n"), VERR_INTERNAL_ERROR); 226 224 227 RTHCPHYS HCPhysGIP; 225 228 rc = SUPR3GipGetPhys(&HCPhysGIP); … … 227 230 228 231 RTGCPTR GCPtr; 232 #ifdef SUP_WITH_LOTS_OF_CPUS 233 rc = MMR3HyperMapHCPhys(pVM, pVM->tm.s.pvGIPR3, NIL_RTR0PTR, HCPhysGIP, (size_t)g_pSUPGlobalInfoPage->cPages * PAGE_SIZE, 234 "GIP", &GCPtr); 235 #else 229 236 rc = MMR3HyperMapHCPhys(pVM, pVM->tm.s.pvGIPR3, NIL_RTR0PTR, HCPhysGIP, PAGE_SIZE, "GIP", &GCPtr); 237 #endif 230 238 if (RT_FAILURE(rc)) 231 239 { … … 795 803 * Use GIP when available present. 796 804 */ 797 uint64_t u64Hz; 798 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; 799 if ( pGip 800 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC) 801 { 802 unsigned iCpu = pGip->u32Mode != SUPGIPMODE_ASYNC_TSC ? 0 : ASMGetApicId(); 803 if (iCpu >= RT_ELEMENTS(pGip->aCPUs)) 804 AssertReleaseMsgFailed(("iCpu=%d - the ApicId is too high. send VBox.log and hardware specs!\n", iCpu)); 805 uint64_t u64Hz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage); 806 if (u64Hz != UINT64_MAX) 807 { 808 if (tmR3HasFixedTSC(pVM)) 809 /* Sleep a bit to get a more reliable CpuHz value. */ 810 RTThreadSleep(32); 805 811 else 806 812 { 807 if (tmR3HasFixedTSC(pVM)) 808 /* Sleep a bit to get a more reliable CpuHz value. */ 809 RTThreadSleep(32); 810 else 811 { 812 /* Spin for 40ms to try push up the CPU frequency and get a more reliable CpuHz value. */ 813 const uint64_t u64 = RTTimeMilliTS(); 814 while ((RTTimeMilliTS() - u64) < 40 /*ms*/) 815 /* nothing */; 816 } 817 818 pGip = g_pSUPGlobalInfoPage; 819 if ( pGip 820 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC 821 && (u64Hz = pGip->aCPUs[iCpu].u64CpuHz) 822 && u64Hz != ~(uint64_t)0) 823 return u64Hz; 813 /* Spin for 40ms to try push up the CPU frequency and get a more reliable CpuHz value. */ 814 const uint64_t u64 = RTTimeMilliTS(); 815 while ((RTTimeMilliTS() - u64) < 40 /*ms*/) 816 /* nothing */; 824 817 } 818 819 u64Hz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage); 820 if (u64Hz != UINT64_MAX) 821 return u64Hz; 825 822 } 826 823
Note:
See TracChangeset
for help on using the changeset viewer.