Changeset 1027 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Feb 22, 2007 8:29:35 PM (18 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 1 deleted
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDRV.h
r679 r1027 617 617 /** The GIP DPC object associated with GipTimer. */ 618 618 KDPC GipDpc; 619 /** The GIP DPC objects for updating per-cpu data. */ 620 KDPC aGipCpuDpcs[32]; 619 621 /** Pointer to the MDL for the pGip page. */ 620 622 PMDL pGipMdl; … … 626 628 unsigned long ulLastJiffies; 627 629 /** The last mono time stamp. */ 628 uint64_t 630 uint64_t volatile u64LastMonotime; 629 631 #endif 630 632 } SUPDRVDEVEXT; … … 652 654 void VBOXCALL supdrvOSGipResume(PSUPDRVDEVEXT pDevExt); 653 655 void VBOXCALL supdrvOSGipSuspend(PSUPDRVDEVEXT pDevExt); 656 unsigned VBOXCALL supdrvOSGetCPUCount(void); 654 657 #endif 655 658 … … 671 674 void VBOXCALL supdrvGipTerm(PSUPGLOBALINFOPAGE pGip); 672 675 void VBOXCALL supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS); 676 void VBOXCALL supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, unsigned iCpu); 673 677 674 678 __END_DECLS -
trunk/src/VBox/HostDrivers/Support/SUPDRVIOC.h
r914 r1027 176 176 #define SUPCOOKIE_MAGIC "The Magic Word!" 177 177 /** Current interface version. */ 178 #define SUPDRVIOC_VERSION 0x000 30002178 #define SUPDRVIOC_VERSION 0x00040000 179 179 180 180 /** SUP_IOCTL_COOKIE Output. */ -
trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
r982 r1027 2288 2288 if (pDevExt->cGipUsers == 1) 2289 2289 { 2290 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 2291 unsigned i; 2292 2290 2293 dprintf(("SUPR0GipMap: Resumes GIP updating\n")); 2291 ASMAtomicXchgU32(&pDevExt->pGip->u32TransactionId, 2292 pDevExt->pGip->u32TransactionId & ~(GIP_UPDATEHZ_RECALC_FREQ * 2 - 1)); 2293 ASMAtomicXchgU64(&pDevExt->pGip->u64NanoTSLastUpdateHz, 0); 2294 2295 for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++) 2296 ASMAtomicXchgU32(&pGip->aCPUs[i].u32TransactionId, pGip->aCPUs[i].u32TransactionId & ~(GIP_UPDATEHZ_RECALC_FREQ * 2 - 1)); 2297 ASMAtomicXchgU64(&pGip->u64NanoTSLastUpdateHz, 0); 2298 2294 2299 #ifdef USE_NEW_OS_INTERFACE 2295 rc = RTTimerStart(pDevExt->pGipTimer, 0); AssertRC(rc); rc = 0; 2300 rc = RTTimerStart(pDevExt->pGipTimer, 0); 2301 AssertRC(rc); rc = 0; 2296 2302 #else 2297 2303 supdrvOSGipResume(pDevExt); … … 4005 4011 int VBOXCALL supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz) 4006 4012 { 4013 unsigned i; 4007 4014 dprintf(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz)); 4008 4015 4016 /* 4017 * Initialize the structure. 4018 */ 4009 4019 memset(pGip, 0, PAGE_SIZE); 4010 4020 pGip->u32Magic = SUPGLOBALINFOPAGE_MAGIC; 4021 pGip->u32Mode = SUPGIPMODE_SYNC_TSC; 4011 4022 pGip->u32UpdateHz = uUpdateHz; 4012 4023 pGip->u32UpdateIntervalNS = 1000000000 / uUpdateHz; 4013 pGip->u32TransactionId = 2;4014 pGip->u64NanoTS = u64NanoTS;4015 4024 pGip->u64NanoTSLastUpdateHz = u64NanoTS; 4016 pGip->u64TSC = ASMReadTSC(); 4017 4018 /* 4019 * We don't know the following values until we've executed updates. 4020 * So, we'll just insert very high values. 4021 */ 4022 pGip->u64CpuHz = _4G + 1; 4023 pGip->u32UpdateIntervalTSC = _2G / 4; 4024 pGip->au32TSCHistory[0] = _2G / 4; 4025 pGip->au32TSCHistory[1] = _2G / 4; 4026 pGip->au32TSCHistory[2] = _2G / 4; 4027 pGip->au32TSCHistory[3] = _2G / 4; 4028 pGip->au32TSCHistory[4] = _2G / 4; 4029 pGip->au32TSCHistory[5] = _2G / 4; 4030 pGip->au32TSCHistory[6] = _2G / 4; 4031 pGip->au32TSCHistory[7] = _2G / 4; 4025 4026 for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++) 4027 { 4028 pGip->aCPUs[i].u32TransactionId = 2; 4029 pGip->aCPUs[i].u64NanoTS = u64NanoTS; 4030 pGip->aCPUs[i].u64TSC = ASMReadTSC(); 4031 4032 /* 4033 * We don't know the following values until we've executed updates. 4034 * So, we'll just insert very high values. 4035 */ 4036 pGip->aCPUs[i].u64CpuHz = _4G + 1; 4037 pGip->aCPUs[i].u32UpdateIntervalTSC = _2G / 4; 4038 pGip->aCPUs[i].au32TSCHistory[0] = _2G / 4; 4039 pGip->aCPUs[i].au32TSCHistory[1] = _2G / 4; 4040 pGip->aCPUs[i].au32TSCHistory[2] = _2G / 4; 4041 pGip->aCPUs[i].au32TSCHistory[3] = _2G / 4; 4042 pGip->aCPUs[i].au32TSCHistory[4] = _2G / 4; 4043 pGip->aCPUs[i].au32TSCHistory[5] = _2G / 4; 4044 pGip->aCPUs[i].au32TSCHistory[6] = _2G / 4; 4045 pGip->aCPUs[i].au32TSCHistory[7] = _2G / 4; 4046 } 4032 4047 4033 4048 /* … … 4038 4053 pDevExt->cGipUsers = 0; 4039 4054 4055 /* 4056 * Check if we should switch to async TSC mode. 4057 */ 4058 #if 0 4059 if (supdrvOSGetCPUCount() > 1) 4060 { 4061 ASMCpuId(0, 4062 } 4063 #endif 4064 4040 4065 return 0; 4041 4066 } … … 4049 4074 void VBOXCALL supdrvGipTerm(PSUPGLOBALINFOPAGE pGip) 4050 4075 { 4051 pGip->iTSCHistoryHead = ~0; 4052 pGip->u64NanoTS = 0; 4053 pGip->u64TSC = 0; 4076 unsigned i; 4054 4077 pGip->u32Magic = 0; 4055 pGip->iTSCHistoryHead = 0; 4056 } 4057 4058 4059 /** 4060 * Updates the GIP. 4061 * 4062 * @param pGip Pointer to the GIP. 4063 * @param u64NanoTS The current nanosecond timesamp. 4064 */ 4065 void VBOXCALL supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS) 4078 for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++) 4079 { 4080 pGip->aCPUs[i].u64NanoTS = 0; 4081 pGip->aCPUs[i].u64TSC = 0; 4082 pGip->aCPUs[i].iTSCHistoryHead = 0; 4083 } 4084 } 4085 4086 4087 /** 4088 * Worker routine for supdrvGipUpdate and supdrvGipUpdatePerCpu that 4089 * updates all the per cpu data except the transaction id. 4090 * 4091 * @param pGip The GIP. 4092 * @param pGipCpu Pointer to the per cpu data. 4093 * @param u64NanoTS The current time stamp. 4094 */ 4095 static void supdrvGipDoUpdateCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pGipCpu, uint64_t u64NanoTS) 4066 4096 { 4067 4097 uint64_t u64TSC; … … 4073 4103 4074 4104 /* 4105 * Update the NanoTS. 4106 */ 4107 ASMAtomicXchgU64(&pGipCpu->u64NanoTS, u64NanoTS); 4108 4109 /* 4110 * Calc TSC delta. 4111 */ 4112 /** @todo validate the NanoTS delta, don't trust the OS to call us when it should... */ 4113 u64TSC = ASMReadTSC(); 4114 u64TSCDelta = u64TSC - pGipCpu->u64TSC; 4115 ASMAtomicXchgU64(&pGipCpu->u64TSC, u64TSC); 4116 4117 if (u64TSCDelta >> 32) 4118 { 4119 u64TSCDelta = pGipCpu->u32UpdateIntervalTSC; 4120 pGipCpu->cErrors++; 4121 } 4122 4123 /* 4124 * TSC History. 4125 */ 4126 Assert(ELEMENTS(pGipCpu->au32TSCHistory) == 8); 4127 4128 iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7; 4129 ASMAtomicXchgU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead); 4130 ASMAtomicXchgU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta); 4131 4132 /* 4133 * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ. 4134 */ 4135 if (pGip->u32UpdateHz >= 1000) 4136 { 4137 uint32_t u32; 4138 u32 = pGipCpu->au32TSCHistory[0]; 4139 u32 += pGipCpu->au32TSCHistory[1]; 4140 u32 += pGipCpu->au32TSCHistory[2]; 4141 u32 += pGipCpu->au32TSCHistory[3]; 4142 u32 >>= 2; 4143 u32UpdateIntervalTSC = pGipCpu->au32TSCHistory[4]; 4144 u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[5]; 4145 u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[6]; 4146 u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[7]; 4147 u32UpdateIntervalTSC >>= 2; 4148 u32UpdateIntervalTSC += u32; 4149 u32UpdateIntervalTSC >>= 1; 4150 4151 /* Value choosen for a 2GHz Athlon64 running linux 2.6.10/11, . */ 4152 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 14; 4153 } 4154 else if (pGip->u32UpdateHz >= 90) 4155 { 4156 u32UpdateIntervalTSC = (uint32_t)u64TSCDelta; 4157 u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[(iTSCHistoryHead - 1) & 7]; 4158 u32UpdateIntervalTSC >>= 1; 4159 4160 /* value choosen on a 2GHz thinkpad running windows */ 4161 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 7; 4162 } 4163 else 4164 { 4165 u32UpdateIntervalTSC = (uint32_t)u64TSCDelta; 4166 4167 /* This value hasn't be checked yet.. waiting for OS/2 and 33Hz timers.. :-) */ 4168 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6; 4169 } 4170 ASMAtomicXchgU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack); 4171 4172 /* 4173 * CpuHz. 4174 */ 4175 u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz); 4176 ASMAtomicXchgU64(&pGipCpu->u64CpuHz, u64CpuHz); 4177 } 4178 4179 4180 /** 4181 * Updates the GIP. 4182 * 4183 * @param pGip Pointer to the GIP. 4184 * @param u64NanoTS The current nanosecond timesamp. 4185 */ 4186 void VBOXCALL supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS) 4187 { 4188 /* 4189 * Determin the relevant CPU data. 4190 */ 4191 PSUPGIPCPU pGipCpu; 4192 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC) 4193 pGipCpu = &pGip->aCPUs[0]; 4194 else 4195 { 4196 unsigned iCpu = ASMGetApicId(); 4197 if (RT_LIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs))) 4198 return; 4199 pGipCpu = &pGip->aCPUs[iCpu]; 4200 } 4201 4202 /* 4075 4203 * Start update transaction. 4076 4204 */ 4077 if (!(ASMAtomicIncU32(&pGip ->u32TransactionId) & 1))4205 if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1)) 4078 4206 { 4079 4207 /* this can happen on win32 if we're taking to long and there are more CPUs around. shouldn't happen though. */ 4080 AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGip ->u32TransactionId));4081 ASMAtomicIncU32(&pGip ->u32TransactionId);4082 pGip ->cErrors++;4208 AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId)); 4209 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 4210 pGipCpu->cErrors++; 4083 4211 return; 4084 4212 } 4085 4213 4086 ASMAtomicXchgU64(&pGip->u64NanoTS, u64NanoTS);4087 4088 4214 /* 4089 4215 * Recalc the update frequency every 0x800th time. 4090 4216 */ 4091 if (!(pGip ->u32TransactionId & (GIP_UPDATEHZ_RECALC_FREQ * 2 - 2)))4217 if (!(pGipCpu->u32TransactionId & (GIP_UPDATEHZ_RECALC_FREQ * 2 - 2))) 4092 4218 { 4093 4219 if (pGip->u64NanoTSLastUpdateHz) … … 4107 4233 4108 4234 /* 4109 * Calc TSC delta. 4110 */ 4111 /** @todo validate the NanoTS delta, don't trust the OS to call us when it should... */ 4112 u64TSC = ASMReadTSC(); 4113 u64TSCDelta = u64TSC - pGip->u64TSC; 4114 ASMAtomicXchgU64(&pGip->u64TSC, u64TSC); 4115 4116 if (u64TSCDelta >> 32) 4117 { 4118 u64TSCDelta = pGip->u32UpdateIntervalTSC; 4119 pGip->cErrors++; 4120 } 4121 4122 /* 4123 * TSC History. 4124 */ 4125 Assert(ELEMENTS(pGip->au32TSCHistory) == 8); 4126 4127 iTSCHistoryHead = (pGip->iTSCHistoryHead + 1) & 7; 4128 ASMAtomicXchgU32(&pGip->iTSCHistoryHead, iTSCHistoryHead); 4129 ASMAtomicXchgU32(&pGip->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta); 4130 4131 /* 4132 * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ. 4133 */ 4134 if (pGip->u32UpdateHz >= 1000) 4135 { 4136 uint32_t u32; 4137 u32 = pGip->au32TSCHistory[0]; 4138 u32 += pGip->au32TSCHistory[1]; 4139 u32 += pGip->au32TSCHistory[2]; 4140 u32 += pGip->au32TSCHistory[3]; 4141 u32 >>= 2; 4142 u32UpdateIntervalTSC = pGip->au32TSCHistory[4]; 4143 u32UpdateIntervalTSC += pGip->au32TSCHistory[5]; 4144 u32UpdateIntervalTSC += pGip->au32TSCHistory[6]; 4145 u32UpdateIntervalTSC += pGip->au32TSCHistory[7]; 4146 u32UpdateIntervalTSC >>= 2; 4147 u32UpdateIntervalTSC += u32; 4148 u32UpdateIntervalTSC >>= 1; 4149 4150 /* Value choosen for a 2GHz Athlon64 running linux 2.6.10/11, . */ 4151 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 14; 4152 } 4153 else if (pGip->u32UpdateHz >= 90) 4154 { 4155 u32UpdateIntervalTSC = (uint32_t)u64TSCDelta; 4156 u32UpdateIntervalTSC += pGip->au32TSCHistory[(iTSCHistoryHead - 1) & 7]; 4157 u32UpdateIntervalTSC >>= 1; 4158 4159 /* value choosen on a 2GHz thinkpad running windows */ 4160 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 7; 4161 } 4162 else 4163 { 4164 u32UpdateIntervalTSC = (uint32_t)u64TSCDelta; 4165 4166 /* This value hasn't be checked yet.. waiting for OS/2 and 33Hz timers.. :-) */ 4167 u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6; 4168 } 4169 ASMAtomicXchgU32(&pGip->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack); 4170 4171 /* 4172 * CpuHz. 4173 */ 4174 u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz); 4175 ASMAtomicXchgU64(&pGip->u64CpuHz, u64CpuHz); 4235 * Update the data. 4236 */ 4237 supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS); 4176 4238 4177 4239 /* 4178 4240 * Complete transaction. 4179 4241 */ 4180 ASMAtomicIncU32(&pGip->u32TransactionId); 4242 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 4243 } 4244 4245 4246 /** 4247 * Updates the per cpu GIP data for the calling cpu. 4248 * 4249 * @param pGip Pointer to the GIP. 4250 * @param u64NanoTS The current nanosecond timesamp. 4251 * @param iCpu The CPU index. 4252 */ 4253 void VBOXCALL supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, unsigned iCpu) 4254 { 4255 PSUPGIPCPU pGipCpu; 4256 4257 if (RT_LIKELY(iCpu <= RT_ELEMENTS(pGip->aCPUs))) 4258 { 4259 pGipCpu = &pGip->aCPUs[iCpu]; 4260 4261 /* 4262 * Start update transaction. 4263 */ 4264 if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1)) 4265 { 4266 AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId)); 4267 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 4268 pGipCpu->cErrors++; 4269 return; 4270 } 4271 4272 /* 4273 * Update the data. 4274 */ 4275 supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS); 4276 4277 /* 4278 * Complete transaction. 4279 */ 4280 ASMAtomicIncU32(&pGipCpu->u32TransactionId); 4281 } 4181 4282 } 4182 4283 -
trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
r876 r1027 1361 1361 { 1362 1362 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)ulUser; 1363 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 1363 1364 unsigned long ulNow = jiffies; 1364 1365 unsigned long ulDiff = ulNow - pDevExt->ulLastJiffies; 1366 uint64_t u64Monotime; 1365 1367 pDevExt->ulLastJiffies = ulNow; 1366 1368 #ifdef TICK_NSEC 1367 pDevExt->u64LastMonotime +=ulDiff * TICK_NSEC;1369 u64Monotime = pDevExt->u64LastMonotime + ulDiff * TICK_NSEC; 1368 1370 #else 1369 pDevExt->u64LastMonotime += ulDiff * (1000000 / HZ); 1370 #endif 1371 supdrvGipUpdate(pDevExt->pGip, pDevExt->u64LastMonotime); 1371 u64Monotime = pDevExt->u64LastMonotime + ulDiff * (1000000 / HZ); 1372 #endif 1373 ASMAtomicXchgU64(&pDevExt->u64LastMonotime, u64Monotime); 1374 if (RT_LIKELY(pGip)) 1375 { 1376 #ifdef CONFIG_SMP 1377 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC) 1378 #endif 1379 supdrvGipUpdate(pDevExt->pGip, u64Monotime); 1380 #ifdef CONFIG_SMP 1381 else 1382 { 1383 smp_call_function(VBoxSupDrvGipPerCpu, pDevExt, 0 /* don't retry? */, 0 /* don't wait */); 1384 supdrvGipUpdate(pDevExt->pGip, u64Monotime); 1385 } 1386 #endif 1387 } 1372 1388 mod_timer(&g_GipTimer, jiffies + (HZ <= 1000 ? 0 : ONE_MSEC_IN_JIFFIES)); 1373 1389 } 1390 1391 1392 #ifdef CONFIG_SMP 1393 /** 1394 * smp_call_function callback. 1395 * This is invoked on all the other CPUs. 1396 * 1397 * @param pvUser Pointer to the device extension. 1398 */ 1399 static void VBoxSupDrvGipPerCpu(void *pvUser) 1400 { 1401 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)ulUser; 1402 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 1403 supdrvGipUpdatePerCpu(pGip, pDevExt->u64LastMonotime, ASMGetApicId()); 1404 } 1405 #endif /* CONFIG_SMP */ 1374 1406 1375 1407 … … 1493 1525 if (timer_pending(&g_GipTimer)) 1494 1526 del_timer(&g_GipTimer); 1527 } 1528 1529 1530 /** 1531 * Get the current CPU count. 1532 * @returns Number of cpus. 1533 */ 1534 unsigned VBOXCALL supdrvOSGetCPUCount(void) 1535 { 1536 #ifdef CONFIG_SMP 1537 # ifdef num_present_cpus 1538 return num_present_cpus(); 1539 # else 1540 return smp_num_cpus; 1541 # endif 1542 #else 1543 return 1; 1544 #endif 1495 1545 } 1496 1546 -
trunk/src/VBox/HostDrivers/Support/testcase/Makefile
r1 r1027 65 65 tstPage_SOURCES = $(VBOX_PATH_SUPPORT)/testcase/tstPage.cpp 66 66 67 tstGIP-1_TEMPLATE = VBOXR3TSTEXE68 tstGIP-1_SOURCES = $(VBOX_PATH_SUPPORT)/testcase/tstGIP-1.c69 70 67 tstGIP-2_TEMPLATE = VBOXR3TSTEXE 71 68 tstGIP-2_SOURCES = $(VBOX_PATH_SUPPORT)/testcase/tstGIP-2.cpp -
trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp
r1 r1027 57 57 RTPrintf("tstGIP-2: %2d: %016llx %016llx %08x %d %08x %15llu %08x %08x %08x %08x %08x %08x %08x %08x\n", 58 58 i, 59 g_pSUPGlobalInfoPage-> u64NanoTS,60 g_pSUPGlobalInfoPage-> u64TSC,61 g_pSUPGlobalInfoPage-> u32UpdateIntervalTSC,62 g_pSUPGlobalInfoPage-> iTSCHistoryHead,63 g_pSUPGlobalInfoPage-> u32TransactionId,64 g_pSUPGlobalInfoPage-> u64CpuHz,65 g_pSUPGlobalInfoPage->a u32TSCHistory[0],66 g_pSUPGlobalInfoPage->a u32TSCHistory[1],67 g_pSUPGlobalInfoPage->a u32TSCHistory[2],68 g_pSUPGlobalInfoPage->a u32TSCHistory[3],69 g_pSUPGlobalInfoPage->a u32TSCHistory[4],70 g_pSUPGlobalInfoPage->a u32TSCHistory[5],71 g_pSUPGlobalInfoPage->a u32TSCHistory[6],72 g_pSUPGlobalInfoPage->a u32TSCHistory[7]);59 g_pSUPGlobalInfoPage->aCPUs[0].u64NanoTS, 60 g_pSUPGlobalInfoPage->aCPUs[0].u64TSC, 61 g_pSUPGlobalInfoPage->aCPUs[0].u32UpdateIntervalTSC, 62 g_pSUPGlobalInfoPage->aCPUs[0].iTSCHistoryHead, 63 g_pSUPGlobalInfoPage->aCPUs[0].u32TransactionId, 64 g_pSUPGlobalInfoPage->aCPUs[0].u64CpuHz, 65 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[0], 66 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[1], 67 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[2], 68 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[3], 69 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[4], 70 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[5], 71 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[6], 72 g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[7]); 73 73 RTThreadSleep(9); 74 74 } -
trunk/src/VBox/HostDrivers/Support/win32/SUPDrv-win32.cpp
r390 r1027 70 70 static void VBoxSupDrvGipTerm(PSUPDRVDEVEXT pDevExt); 71 71 static void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2); 72 static void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2); 72 73 73 74 … … 789 790 */ 790 791 KeInitializeTimerEx(&pDevExt->GipTimer, SynchronizationTimer); 791 KeInitializeDpc(&pDevExt->GipDpc, VBoxSupDrvGipTimer, pGip); 792 KeInitializeDpc(&pDevExt->GipDpc, VBoxSupDrvGipTimer, pDevExt); 793 794 /* 795 * Initialize the DPCs we're using to update the per-cpu GIP data. 796 * (Not sure if we need to be this careful with KeSetTargetProcessorDpc...) 797 */ 798 UNICODE_STRING RoutineName; 799 RtlInitUnicodeString(&RoutineName, L"KeSetTargetProcessorDpc"); 800 VOID (*pfnKeSetTargetProcessorDpc)(IN PRKDPC, IN CCHAR) = (VOID (*)(IN PRKDPC, IN CCHAR))MmGetSystemRoutineAddress(&RoutineName); 801 802 for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++) 803 { 804 KeInitializeDpc(&pDevExt->aGipCpuDpcs[i], VBoxSupDrvGipPerCpuDpc, pGip); 805 KeSetImportanceDpc(&pDevExt->aGipCpuDpcs[i], HighImportance); 806 if (pfnKeSetTargetProcessorDpc) 807 pfnKeSetTargetProcessorDpc(&pDevExt->aGipCpuDpcs[i], i); 808 } 809 792 810 dprintf(("VBoxSupDrvGipInit: ulClockFreq=%ld ulClockInterval=%ld ulClockIntervalActual=%ld Phys=%x%08x\n", 793 811 ulClockFreq, ulClockInterval, ulClockIntervalActual, Phys.HighPart, Phys.LowPart)); 794 812 return STATUS_SUCCESS; 795 813 } 796 else 797 { 798 dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip)); 799 rc = STATUS_NO_MEMORY; 800 } 814 815 dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip)); 816 rc = STATUS_NO_MEMORY; 801 817 } 802 818 else … … 863 879 /** 864 880 * Timer callback function. 865 * The ulUser parameter is the GIP pointer. 866 */ 867 static void __stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 881 * The pvUser parameter is the pDevExt pointer. 882 */ 883 static void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 884 { 885 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser; 886 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 887 if (pGip) 888 { 889 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC) 890 supdrvGipUpdate(pGip, supdrvOSMonotime()); 891 else 892 { 893 RTCCUINTREG xFL = ASMGetFlags(); 894 ASMIntDisable(); 895 896 /* 897 * We cannot do other than assume a 1:1 relation ship between the 898 * affinity mask and the process despite the warnings in the docs. 899 * If someone knows a better way to get this done, please let bird know. 900 */ 901 unsigned iSelf = KeGetCurrentProcessorNumber(); 902 KAFFINITY Mask = KeQueryActiveProcessors(); 903 904 for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++) 905 { 906 if ( i != iSelf 907 && (Mask & (1 << i))) 908 KeInsertQueueDpc(&pDevExt->aGipCpuDpcs[i], 0, 0); 909 } 910 911 /* Run the normal update. */ 912 supdrvGipUpdate(pGip, supdrvOSMonotime()); 913 914 ASMSetFlags(xFL); 915 } 916 } 917 } 918 919 920 /** 921 * Per cpu callback callback function. 922 * The pvUser parameter is the pGip pointer. 923 */ 924 static void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 868 925 { 869 926 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser; 870 supdrvGipUpdate (pGip, supdrvOSMonotime());927 supdrvGipUpdatePerCpu(pGip, supdrvOSMonotime(), ASMGetApicId()); 871 928 } 872 929
Note:
See TracChangeset
for help on using the changeset viewer.