Changeset 53718 in vbox for trunk/src/VBox/Runtime/r0drv
- Timestamp:
- Jan 2, 2015 9:24:23 PM (10 years ago)
- Location:
- trunk/src/VBox/Runtime/r0drv/nt
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
r53456 r53718 58 58 /** HalRequestIpi, introduced in ??. */ 59 59 PFNHALREQUESTIPI g_pfnrtNtHalRequestIpi; 60 /** HalSendSoftwareInterrupt */60 /** HalSendSoftwareInterrupt, introduced in AMD64 version of W2K3. */ 61 61 PFNHALSENDSOFTWAREINTERRUPT g_pfnrtNtHalSendSoftwareInterrupt; 62 /** SendIpi handler based on Windows version*/63 PFNRTSENDIPI g_pfnrt SendIpi;64 /** KeIpiGenericCall - Windows Server 2003+ only*/62 /** Worker for RTMpPokeCpu. */ 63 PFNRTSENDIPI g_pfnrtMpPokeCpuWorker; 64 /** KeIpiGenericCall - Introduced in Windows Server 2003. */ 65 65 PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 66 66 /** RtlGetVersion, introduced in ??. */ … … 386 386 387 387 /* 388 * Special IPI fun. 389 */ 390 g_pfnrtSendIpi = rtMpSendIpiDummy; 388 * Special IPI fun for RTMpPokeCpu. 389 * 390 * On Vista and later the DPC fallback doesn't seem to reliably send IPIs, 391 * so we have to use alternative methods. The NtHalSendSoftwareInterrupt 392 * is preferrable, but if that's not available we'll settle for broadcast 393 * IPIs. 394 */ 395 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingDpc; 391 396 #ifndef IPRT_TARGET_NT4 392 if ( g_pfnrtNtHalRequestIpi 393 && OsVerInfo.uMajorVer == 6 394 && OsVerInfo.uMinorVer == 0) 395 { 396 /* Vista or Windows Server 2008 */ 397 g_pfnrtSendIpi = rtMpSendIpiVista; 398 } 399 else if ( g_pfnrtNtHalSendSoftwareInterrupt 400 && OsVerInfo.uMajorVer == 6 401 && OsVerInfo.uMinorVer == 1) 402 { 403 /* Windows 7 or Windows Server 2008 R2 */ 404 g_pfnrtSendIpi = rtMpSendIpiWin7; 405 } 406 /* Windows XP should send always send an IPI -> VERIFY */ 397 if (g_pfnrtNtHalSendSoftwareInterrupt) 398 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingHalSendSoftwareInterrupt; 399 else if (OsVerInfo.uMajorVer >= 6 && g_pfnrtKeIpiGenericCall) 400 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingBroadcastIpi; 401 /* else: Windows XP should send always send an IPI -> VERIFY */ 407 402 #endif 408 403 -
trunk/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
r53456 r53718 58 58 extern PFNHALREQUESTIPI g_pfnrtNtHalRequestIpi; 59 59 extern PFNHALSENDSOFTWAREINTERRUPT g_pfnrtNtHalSendSoftwareInterrupt; 60 extern PFNRTSENDIPI g_pfnrt SendIpi;60 extern PFNRTSENDIPI g_pfnrtMpPokeCpuWorker; 61 61 extern PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 62 62 extern PFNRTRTLGETVERSION g_pfnrtRtlGetVersion; … … 72 72 73 73 74 int rtMp SendIpiVista(RTCPUID idCpu);75 int rtMp SendIpiWin7(RTCPUID idCpu);76 int rtMp SendIpiDummy(RTCPUID idCpu);74 int rtMpPokeCpuUsingDpc(RTCPUID idCpu); 75 int rtMpPokeCpuUsingBroadcastIpi(RTCPUID idCpu); 76 int rtMpPokeCpuUsingHalSendSoftwareInterrupt(RTCPUID idCpu); 77 77 78 78 RT_C_DECLS_END -
trunk/src/VBox/Runtime/r0drv/nt/mp-r0drv-nt.cpp
r53717 r53718 188 188 189 189 /** 190 * Wrapper between the native nt per-cpu callbacks and PFNRTWORKER 191 * 192 * @param Dpc DPC object 193 * @param DeferredContext Context argument specified by KeInitializeDpc 194 * @param SystemArgument1 Argument specified by KeInsertQueueDpc 195 * @param SystemArgument2 Argument specified by KeInsertQueueDpc 196 */ 197 static VOID rtmpNtDPCWrapper(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 198 { 199 PRTMPARGS pArgs = (PRTMPARGS)DeferredContext; 200 ASMAtomicIncU32(&pArgs->cHits); 201 190 * Wrapper between the native KIPI_BROADCAST_WORKER and IPRT's PFNRTMPWORKER for 191 * the RTMpOnAll case. 192 * 193 * @param uUserCtx The user context argument (PRTMPARGS). 194 */ 195 static ULONG_PTR __stdcall rtmpNtOnAllBroadcastIpiWrapper(ULONG_PTR uUserCtx) 196 { 197 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 198 /*ASMAtomicIncU32(&pArgs->cHits); - not needed */ 202 199 pArgs->pfnWorker(KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2); 203 204 /* Dereference the argument structure. */ 205 int32_t cRefs = ASMAtomicDecS32(&pArgs->cRefs); 206 Assert(cRefs >= 0); 207 if (cRefs == 0) 208 ExFreePool(pArgs); 200 return 0; 209 201 } 210 202 211 203 212 204 /** 213 * Internal worker for the RTMpOn* APIs. 205 * Wrapper between the native KIPI_BROADCAST_WORKER and IPRT's PFNRTMPWORKER for 206 * the RTMpOnOthers case. 207 * 208 * @param uUserCtx The user context argument (PRTMPARGS). 209 */ 210 static ULONG_PTR __stdcall rtmpNtOnOthersBroadcastIpiWrapper(ULONG_PTR uUserCtx) 211 { 212 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 213 RTCPUID idCpu = KeGetCurrentProcessorNumber(); 214 if (pArgs->idCpu != idCpu) 215 { 216 /*ASMAtomicIncU32(&pArgs->cHits); - not needed */ 217 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2); 218 } 219 return 0; 220 } 221 222 223 /** 224 * Wrapper between the native KIPI_BROADCAST_WORKER and IPRT's PFNRTMPWORKER for 225 * the RTMpOnSpecific case. 226 * 227 * @param uUserCtx The user context argument (PRTMPARGS). 228 */ 229 static ULONG_PTR __stdcall rtmpNtOnSpecificBroadcastIpiWrapper(ULONG_PTR uUserCtx) 230 { 231 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 232 RTCPUID idCpu = KeGetCurrentProcessorNumber(); 233 if (pArgs->idCpu == idCpu) 234 { 235 ASMAtomicIncU32(&pArgs->cHits); 236 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2); 237 } 238 return 0; 239 } 240 241 242 /** 243 * Internal worker for the RTMpOn* APIs using KeIpiGenericCall. 214 244 * 215 245 * @returns IPRT status code. … … 220 250 * @param idCpu Used if enmCpuid RT_NT_CPUID_SPECIFIC, otherwise ignored. 221 251 */ 222 static int rtMpCall(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, RT_NT_CPUID enmCpuid, RTCPUID idCpu) 252 static int rtMpCallUsingBroadcastIpi(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, 253 PKIPI_BROADCAST_WORKER pfnNativeWrapper, RTCPUID idCpu) 254 { 255 RTMPARGS Args; 256 Args.pfnWorker = pfnWorker; 257 Args.pvUser1 = pvUser1; 258 Args.pvUser2 = pvUser2; 259 Args.idCpu = idCpu; 260 Args.cRefs = 0; 261 Args.cHits = 0; 262 263 AssertPtr(g_pfnrtKeIpiGenericCall); 264 g_pfnrtKeIpiGenericCall(pfnNativeWrapper, (uintptr_t)&Args); 265 266 if ( pfnNativeWrapper != rtmpNtOnSpecificBroadcastIpiWrapper 267 || Args.cHits > 0) 268 return VINF_SUCCESS; 269 return VERR_CPU_OFFLINE; 270 } 271 272 273 /** 274 * Wrapper between the native nt per-cpu callbacks and PFNRTWORKER 275 * 276 * @param Dpc DPC object 277 * @param DeferredContext Context argument specified by KeInitializeDpc 278 * @param SystemArgument1 Argument specified by KeInsertQueueDpc 279 * @param SystemArgument2 Argument specified by KeInsertQueueDpc 280 */ 281 static VOID __stdcall rtmpNtDPCWrapper(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 282 { 283 PRTMPARGS pArgs = (PRTMPARGS)DeferredContext; 284 ASMAtomicIncU32(&pArgs->cHits); 285 286 pArgs->pfnWorker(KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2); 287 288 /* Dereference the argument structure. */ 289 int32_t cRefs = ASMAtomicDecS32(&pArgs->cRefs); 290 Assert(cRefs >= 0); 291 if (cRefs == 0) 292 ExFreePool(pArgs); 293 } 294 295 296 /** 297 * Internal worker for the RTMpOn* APIs. 298 * 299 * @returns IPRT status code. 300 * @param pfnWorker The callback. 301 * @param pvUser1 User argument 1. 302 * @param pvUser2 User argument 2. 303 * @param enmCpuid What to do / is idCpu valid. 304 * @param idCpu Used if enmCpuid RT_NT_CPUID_SPECIFIC, otherwise ignored. 305 */ 306 static int rtMpCallUsingDpcs(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2, RT_NT_CPUID enmCpuid, RTCPUID idCpu) 223 307 { 224 308 PRTMPARGS pArgs; … … 331 415 RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) 332 416 { 333 return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_ALL, 0); 417 if (g_pfnrtKeIpiGenericCall) 418 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnAllBroadcastIpiWrapper, 0); 419 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_ALL, 0); 334 420 } 335 421 … … 337 423 RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) 338 424 { 339 return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_OTHERS, 0); 425 if (g_pfnrtKeIpiGenericCall) 426 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnOthersBroadcastIpiWrapper, 0); 427 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_OTHERS, 0); 340 428 } 341 429 … … 348 436 : VERR_CPU_OFFLINE; 349 437 350 return rtMpCall(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_SPECIFIC, idCpu); 351 } 352 353 static KDPC aPokeDpcs[MAXIMUM_PROCESSORS] = {0}; 354 static bool fPokeDPCsInitialized = false; 438 if (g_pfnrtKeIpiGenericCall) 439 return rtMpCallUsingBroadcastIpi(pfnWorker, pvUser1, pvUser2, rtmpNtOnSpecificBroadcastIpiWrapper, 0); 440 return rtMpCallUsingDpcs(pfnWorker, pvUser1, pvUser2, RT_NT_CPUID_SPECIFIC, idCpu); 441 } 442 443 444 355 445 356 446 static VOID rtMpNtPokeCpuDummy(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) … … 364 454 #ifndef IPRT_TARGET_NT4 365 455 366 ULONG_PTRrtMpIpiGenericCall(ULONG_PTR Argument)456 static ULONG_PTR __stdcall rtMpIpiGenericCall(ULONG_PTR Argument) 367 457 { 368 458 NOREF(Argument); … … 371 461 372 462 463 int rtMpPokeCpuUsingBroadcastIpi(RTCPUID idCpu) 464 { 465 g_pfnrtKeIpiGenericCall(rtMpIpiGenericCall, 0); 466 return VINF_SUCCESS; 467 } 468 469 # if 0 373 470 int rtMpSendIpiVista(RTCPUID idCpu) 374 471 { 472 /* If we start care about Vista, we should investigate a non-broadcast API. */ 375 473 g_pfnrtKeIpiGenericCall(rtMpIpiGenericCall, 0); 376 474 //// g_pfnrtNtHalRequestIpi(1 << idCpu); 377 475 return VINF_SUCCESS; 378 476 } 379 380 381 int rtMpSendIpiWin7(RTCPUID idCpu) 382 { 383 g_pfnrtKeIpiGenericCall(rtMpIpiGenericCall, 0); 384 ////g_pfnrtNtHalSendSoftwareInterrupt(idCpu, DISPATCH_LEVEL);477 # endif 478 479 480 int rtMpPokeCpuUsingHalSendSoftwareInterrupt(RTCPUID idCpu) 481 { 482 g_pfnrtNtHalSendSoftwareInterrupt(idCpu, DISPATCH_LEVEL); 385 483 return VINF_SUCCESS; 386 484 } … … 389 487 390 488 391 int rtMpSendIpiDummy(RTCPUID idCpu) 392 { 393 return VERR_NOT_IMPLEMENTED; 394 } 395 396 397 RTDECL(int) RTMpPokeCpu(RTCPUID idCpu) 398 { 399 if (!RTMpIsCpuOnline(idCpu)) 400 return !RTMpIsCpuPossible(idCpu) 401 ? VERR_CPU_NOT_FOUND 402 : VERR_CPU_OFFLINE; 403 404 int rc = g_pfnrtSendIpi(idCpu); 405 if (rc == VINF_SUCCESS) 406 return rc; 407 408 /* Fallback. */ 409 if (!fPokeDPCsInitialized) 410 { 411 for (unsigned i = 0; i < RT_ELEMENTS(aPokeDpcs); i++) 489 int rtMpPokeCpuUsingDpc(RTCPUID idCpu) 490 { 491 /* 492 * APC fallback. 493 */ 494 static KDPC s_aPokeDpcs[MAXIMUM_PROCESSORS] = {0}; 495 static bool s_fPokeDPCsInitialized = false; 496 497 if (!s_fPokeDPCsInitialized) 498 { 499 for (unsigned i = 0; i < RT_ELEMENTS(s_aPokeDpcs); i++) 412 500 { 413 KeInitializeDpc(& aPokeDpcs[i], rtMpNtPokeCpuDummy, NULL);414 KeSetImportanceDpc(& aPokeDpcs[i], HighImportance);415 KeSetTargetProcessorDpc(& aPokeDpcs[i], (int)i);501 KeInitializeDpc(&s_aPokeDpcs[i], rtMpNtPokeCpuDummy, NULL); 502 KeSetImportanceDpc(&s_aPokeDpcs[i], HighImportance); 503 KeSetTargetProcessorDpc(&s_aPokeDpcs[i], (int)i); 416 504 } 417 fPokeDPCsInitialized = true;505 s_fPokeDPCsInitialized = true; 418 506 } 419 507 … … 424 512 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); 425 513 426 KeSetImportanceDpc(& aPokeDpcs[idCpu], HighImportance);427 KeSetTargetProcessorDpc(& aPokeDpcs[idCpu], (int)idCpu);514 KeSetImportanceDpc(&s_aPokeDpcs[idCpu], HighImportance); 515 KeSetTargetProcessorDpc(&s_aPokeDpcs[idCpu], (int)idCpu); 428 516 429 517 /* Assuming here that high importance DPCs will be delivered immediately; or at least an IPI will be sent immediately. 430 518 * @note: not true on at least Vista & Windows 7 431 519 */ 432 BOOLEAN bRet = KeInsertQueueDpc(& aPokeDpcs[idCpu], 0, 0);520 BOOLEAN bRet = KeInsertQueueDpc(&s_aPokeDpcs[idCpu], 0, 0); 433 521 434 522 KeLowerIrql(oldIrql); … … 437 525 438 526 527 RTDECL(int) RTMpPokeCpu(RTCPUID idCpu) 528 { 529 if (!RTMpIsCpuOnline(idCpu)) 530 return !RTMpIsCpuPossible(idCpu) 531 ? VERR_CPU_NOT_FOUND 532 : VERR_CPU_OFFLINE; 533 /* Calls rtMpSendIpiFallback, rtMpSendIpiWin7AndLater or rtMpSendIpiVista. */ 534 return g_pfnrtMpPokeCpuWorker(idCpu); 535 } 536 537 439 538 RTDECL(bool) RTMpOnAllIsConcurrentSafe(void) 440 539 {
Note:
See TracChangeset
for help on using the changeset viewer.