Changeset 64234 in vbox
- Timestamp:
- Oct 13, 2016 10:10:42 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 111243
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/err.h
r62473 r64234 951 951 * creating a process as a given user. IQ is also called 'Increase quotas'. */ 952 952 #define VERR_PROC_IQ_PRIV_NOT_HELD (-22413) 953 /** The system has too many CPUs. */ 954 #define VERR_MP_TOO_MANY_CPUS (-22414) 953 955 /** @} */ 954 956 -
trunk/include/iprt/nt/nt.h
r64219 r64234 2431 2431 typedef NTSTATUS (NTAPI *PFNKEGETPROCESSORNUMBERFROMINDEX)(KEPROCESSORINDEX idxProcessor, PPROCESSOR_NUMBER pProcNumber); 2432 2432 typedef KEPROCESSORINDEX (NTAPI *PFNKEGETPROCESSORINDEXFROMNUMBER)(const PROCESSOR_NUMBER *pProcNumber); 2433 typedef NTSTATUS (NTAPI *PFNKEGETPROCESSORNUMBERFROMINDEX)(KEPROCESSORINDEX ProcIndex, PROCESSOR_NUMBER *pProcNumber); 2434 typedef KEPROCESSORINDEX (NTAPI *PFNKEGETCURRENTPROCESSORNUMBEREX)(const PROCESSOR_NUMBER *pProcNumber); 2435 typedef KAFFINITY (NTAPI *PFNKEQUERYACTIVEPROCESSORS)(VOID); 2436 typedef ULONG (NTAPI *PFNKEQUERYMAXIMUMPROCESSORCOUNT)(VOID); 2437 typedef ULONG (NTAPI *PFNKEQUERYMAXIMUMPROCESSORCOUNTEX)(USHORT GroupNumber); 2438 typedef USHORT (NTAPI *PFNKEQUERYMAXIMUMGROUPCOUNT)(VOID); 2439 typedef NTSTATUS (NTAPI *PFNKEQUERYLOGICALPROCESSORRELATIONSHIP)(PROCESSOR_NUMBER *pProcNumber, 2440 LOGICAL_PROCESSOR_RELATIONSHIP RelationShipType, 2441 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pInfo, PULONG pcbInfo); 2442 typedef PVOID (NTAPI *PFNKEREGISTERPROCESSORCHANGECALLBACK)(PPROCESSOR_CALLBACK_FUNCTION pfnCallback, void *pvUser, ULONG fFlags); 2443 typedef VOID (NTAPI *PFNKEDEREGISTERPROCESSORCHANGECALLBACK)(PVOID pvCallback); 2444 typedef NTSTATUS (NTAPI *PFNKESETTARGETPROCESSORDPCEX)(KDPC *pDpc, PROCESSOR_NUMBER *pProcNumber); 2433 2445 2434 2446 NTSYSAPI BOOLEAN NTAPI ObFindHandleForObject(PEPROCESS pProcess, PVOID pvObject, POBJECT_TYPE pObjectType, -
trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
r62477 r64234 33 33 #include <iprt/assert.h> 34 34 #include <iprt/err.h> 35 #include <iprt/mem.h> 35 36 #include <iprt/mp.h> 36 37 #include <iprt/string.h> 37 38 #include "internal/initterm.h" 38 39 #include "internal-r0drv-nt.h" 40 #include "../mp-r0drv.h" 39 41 #include "symdb.h" 40 42 #include "symdbdata.h" … … 51 53 * and update this variable as CPUs comes online. (The code is done already.) 52 54 */ 53 RTCPUSET g_rtMpNtCpuSet; 55 RTCPUSET g_rtMpNtCpuSet; 56 /** Maximum number of processor groups. */ 57 uint32_t g_cRtMpNtMaxGroups; 58 /** Maximum number of processors. */ 59 uint32_t g_cRtMpNtMaxCpus; 60 /** The handle of the rtR0NtMpProcessorChangeCallback registration. */ 61 static PVOID g_pvMpCpuChangeCallback = NULL; 54 62 55 63 /** ExSetTimerResolution, introduced in W2K. */ 56 PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution;64 PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution; 57 65 /** KeFlushQueuedDpcs, introduced in XP. */ 58 PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs;66 PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs; 59 67 /** HalRequestIpi, version introduced with windows 7. */ 60 PFNHALREQUESTIPI_W7PLUS g_pfnrtHalRequestIpiW7Plus;68 PFNHALREQUESTIPI_W7PLUS g_pfnrtHalRequestIpiW7Plus; 61 69 /** HalRequestIpi, version valid up to windows vista?? */ 62 PFNHALREQUESTIPI_PRE_W7 g_pfnrtHalRequestIpiPreW7;70 PFNHALREQUESTIPI_PRE_W7 g_pfnrtHalRequestIpiPreW7; 63 71 /** Worker for RTMpPokeCpu. */ 64 PFNRTSENDIPI g_pfnrtMpPokeCpuWorker;72 PFNRTSENDIPI g_pfnrtMpPokeCpuWorker; 65 73 /** KeIpiGenericCall - Introduced in Windows Server 2003. */ 66 PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 74 PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 75 /** KeSetTargetProcessorDpcEx - Introduced in Windows 7. */ 76 PFNKESETTARGETPROCESSORDPCEX g_pfnrtKeSetTargetProcessorDpcEx; 67 77 /** KeInitializeAffinityEx - Introducted in Windows 7. */ 68 PFNKEINITIALIZEAFFINITYEX g_pfnrtKeInitializeAffinityEx;78 PFNKEINITIALIZEAFFINITYEX g_pfnrtKeInitializeAffinityEx; 69 79 /** KeAddProcessorAffinityEx - Introducted in Windows 7. */ 70 PFNKEADDPROCESSORAFFINITYEX g_pfnrtKeAddProcessorAffinityEx; 71 /** KeGetProcessorIndexFromNumber - Introducted in Windows 7. */ 72 PFNKEGETPROCESSORINDEXFROMNUMBER g_pfnrtKeGetProcessorIndexFromNumber; 80 PFNKEADDPROCESSORAFFINITYEX g_pfnrtKeAddProcessorAffinityEx; 81 /** KeGetProcessorIndexFromNumber - Introducted in Windows 7. */ 82 PFNKEGETPROCESSORINDEXFROMNUMBER g_pfnrtKeGetProcessorIndexFromNumber; 83 /** KeGetProcessorNumberFromIndex - Introducted in Windows 7. */ 84 PFNKEGETPROCESSORNUMBERFROMINDEX g_pfnrtKeGetProcessorNumberFromIndex; 85 /** KeGetCurrentProcessorNumberEx - Introducted in Windows 7. */ 86 PFNKEGETCURRENTPROCESSORNUMBEREX g_pfnrtKeGetCurrentProcessorNumberEx; 87 /** KeQueryActiveProcessors - Introducted in Windows 2000. */ 88 PFNKEQUERYACTIVEPROCESSORS g_pfnrtKeQueryActiveProcessors; 89 /** KeQueryMaximumProcessorCount - Introducted in Vista and obsoleted W7. */ 90 PFNKEQUERYMAXIMUMPROCESSORCOUNT g_pfnrtKeQueryMaximumProcessorCount; 91 /** KeQueryMaximumProcessorCountEx - Introducted in Windows 7. */ 92 PFNKEQUERYMAXIMUMPROCESSORCOUNTEX g_pfnrtKeQueryMaximumProcessorCountEx; 93 /** KeQueryMaximumGroupCount - Introducted in Windows 7. */ 94 PFNKEQUERYMAXIMUMGROUPCOUNT g_pfnrtKeQueryMaximumGroupCount; 95 /** KeQueryLogicalProcessorRelationship - Introducted in Windows 7. */ 96 PFNKEQUERYLOGICALPROCESSORRELATIONSHIP g_pfnrtKeQueryLogicalProcessorRelationship; 97 /** KeRegisterProcessorChangeCallback - Introducted in Windows 7. */ 98 PFNKEREGISTERPROCESSORCHANGECALLBACK g_pfnrtKeRegisterProcessorChangeCallback; 99 /** KeDeregisterProcessorChangeCallback - Introducted in Windows 7. */ 100 PFNKEDEREGISTERPROCESSORCHANGECALLBACK g_pfnrtKeDeregisterProcessorChangeCallback; 73 101 /** RtlGetVersion, introduced in ??. */ 74 PFNRTRTLGETVERSION g_pfnrtRtlGetVersion;102 PFNRTRTLGETVERSION g_pfnrtRtlGetVersion; 75 103 #ifndef RT_ARCH_AMD64 76 104 /** KeQueryInterruptTime - exported/new in Windows 2000. */ 77 PFNRTKEQUERYINTERRUPTTIME g_pfnrtKeQueryInterruptTime;105 PFNRTKEQUERYINTERRUPTTIME g_pfnrtKeQueryInterruptTime; 78 106 /** KeQuerySystemTime - exported/new in Windows 2000. */ 79 PFNRTKEQUERYSYSTEMTIME g_pfnrtKeQuerySystemTime;107 PFNRTKEQUERYSYSTEMTIME g_pfnrtKeQuerySystemTime; 80 108 #endif 81 109 /** KeQueryInterruptTimePrecise - new in Windows 8. */ 82 PFNRTKEQUERYINTERRUPTTIMEPRECISE g_pfnrtKeQueryInterruptTimePrecise;110 PFNRTKEQUERYINTERRUPTTIMEPRECISE g_pfnrtKeQueryInterruptTimePrecise; 83 111 /** KeQuerySystemTimePrecise - new in Windows 8. */ 84 PFNRTKEQUERYSYSTEMTIMEPRECISE g_pfnrtKeQuerySystemTimePrecise;112 PFNRTKEQUERYSYSTEMTIMEPRECISE g_pfnrtKeQuerySystemTimePrecise; 85 113 86 114 /** Offset of the _KPRCB::QuantumEnd field. 0 if not found. */ 87 uint32_t g_offrtNtPbQuantumEnd;115 uint32_t g_offrtNtPbQuantumEnd; 88 116 /** Size of the _KPRCB::QuantumEnd field. 0 if not found. */ 89 uint32_t g_cbrtNtPbQuantumEnd;117 uint32_t g_cbrtNtPbQuantumEnd; 90 118 /** Offset of the _KPRCB::DpcQueueDepth field. 0 if not found. */ 91 uint32_t g_offrtNtPbDpcQueueDepth;119 uint32_t g_offrtNtPbDpcQueueDepth; 92 120 93 121 … … 125 153 126 154 /* Note! We cannot quite say if something is MP or UNI. So, fSmp is 127 redefined to indicate that it must be MP. */ 128 pOsVerInfo->fSmp = RTMpGetCount() > 1 129 || ulMajorVersion >= 6; /* Vista and later has no UNI kernel AFAIK. */ 155 redefined to indicate that it must be MP. 156 Note! RTMpGetCount is not available here. */ 157 pOsVerInfo->fSmp = ulMajorVersion >= 6; /* Vista and later has no UNI kernel AFAIK. */ 158 if (!pOsVerInfo->fSmp) 159 { 160 if ( g_pfnrtKeQueryMaximumProcessorCountEx 161 && g_pfnrtKeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS) > 1) 162 pOsVerInfo->fSmp = true; 163 else if ( g_pfnrtKeQueryMaximumProcessorCount 164 && g_pfnrtKeQueryMaximumProcessorCount() > 1) 165 pOsVerInfo->fSmp = true; 166 else if ( g_pfnrtKeQueryActiveProcessors 167 && g_pfnrtKeQueryActiveProcessors() > 1) 168 pOsVerInfo->fSmp = true; 169 else if (KeNumberProcessors > 1) 170 pOsVerInfo->fSmp = true; 171 } 130 172 } 131 173 … … 203 245 204 246 247 /** 248 * Implements the NT PROCESSOR_CALLBACK_FUNCTION callback function. 249 * 250 * This maintains the g_rtMpNtCpuSet and works MP notification callbacks. When 251 * registered, it's called for each active CPU in the system, avoiding racing 252 * CPU hotplugging (as well as testing the callback). 253 * 254 * @param pvUser User context (not used). 255 * @param pChangeCtx Change context (in). 256 * @param prcOperationStatus Operation status (in/out). 257 */ 258 static VOID __stdcall rtR0NtMpProcessorChangeCallback(void *pvUser, PKE_PROCESSOR_CHANGE_NOTIFY_CONTEXT pChangeCtx, 259 PNTSTATUS prcOperationStatus) 260 { 261 RT_NOREF(pvUser, prcOperationStatus); 262 switch (pChangeCtx->State) 263 { 264 case KeProcessorAddCompleteNotify: 265 if (pChangeCtx->NtNumber < RTCPUSET_MAX_CPUS) 266 { 267 RTCpuSetAddByIndex(&g_rtMpNtCpuSet, pChangeCtx->NtNumber); 268 rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, pChangeCtx->NtNumber); 269 } 270 else 271 { 272 DbgPrint("rtR0NtMpProcessorChangeCallback: NtNumber=%u (%#x) is higher than RTCPUSET_MAX_CPUS (%d)\n", 273 pChangeCtx->NtNumber, pChangeCtx->NtNumber, RTCPUSET_MAX_CPUS); 274 AssertMsgFailed(("NtNumber=%u (%#x)\n", pChangeCtx->NtNumber, pChangeCtx->NtNumber)); 275 } 276 break; 277 278 case KeProcessorAddStartNotify: 279 case KeProcessorAddFailureNotify: 280 /* ignore */ 281 break; 282 283 default: 284 AssertMsgFailed(("State=%u\n", pChangeCtx->State)); 285 } 286 } 287 288 289 /** 290 * Wrapper around KeQueryLogicalProcessorRelationship. 291 * 292 * @returns IPRT status code. 293 * @param ppInfo Where to return the info. Pass to RTMemFree when done. 294 */ 295 static int rtR0NtInitQueryGroupRelations(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **ppInfo) 296 { 297 ULONG cbInfo = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) 298 + g_cRtMpNtMaxGroups * sizeof(GROUP_RELATIONSHIP); 299 NTSTATUS rcNt; 300 do 301 { 302 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)RTMemAlloc(cbInfo); 303 if (pInfo) 304 { 305 rcNt = g_pfnrtKeQueryLogicalProcessorRelationship(NULL /*pProcNumber*/, RelationGroup, pInfo, &cbInfo); 306 if (NT_SUCCESS(rcNt)) 307 { 308 *ppInfo = pInfo; 309 return VINF_SUCCESS; 310 } 311 312 RTMemFree(pInfo); 313 pInfo = NULL; 314 } 315 else 316 rcNt = STATUS_NO_MEMORY; 317 } while (rcNt == STATUS_INFO_LENGTH_MISMATCH); 318 DbgPrint("IPRT: Fatal: KeQueryLogicalProcessorRelationship failed: %#x\n", rcNt); 319 AssertMsgFailed(("KeQueryLogicalProcessorRelationship failed: %#x\n", rcNt)); 320 return RTErrConvertFromNtStatus(rcNt); 321 } 322 323 324 /** 325 * Initalizes multiprocessor globals. 326 * 327 * @returns IPRT status code. 328 */ 329 static int rtR0NtInitMp(RTNTSDBOSVER const *pOsVerInfo) 330 { 331 #define MY_CHECK_BREAK(a_Check, a_DbgPrintArgs) \ 332 AssertMsgBreakStmt(a_Check, a_DbgPrintArgs, DbgPrint a_DbgPrintArgs; rc = VERR_INTERNAL_ERROR_4 ) 333 #define MY_CHECK_RETURN(a_Check, a_DbgPrintArgs, a_rcRet) \ 334 AssertMsgReturnStmt(a_Check, a_DbgPrintArgs, DbgPrint a_DbgPrintArgs, a_rcRet) 335 #define MY_CHECK(a_Check, a_DbgPrintArgs) \ 336 AssertMsgStmt(a_Check, a_DbgPrintArgs, DbgPrint a_DbgPrintArgs; rc = VERR_INTERNAL_ERROR_4 ) 337 338 /* 339 * API combination checks. 340 */ 341 MY_CHECK_RETURN(!g_pfnrtKeSetTargetProcessorDpcEx || g_pfnrtKeGetProcessorNumberFromIndex, 342 ("IPRT: Fatal: Missing KeSetTargetProcessorDpcEx without KeGetProcessorNumberFromIndex!\n"), 343 VERR_SYMBOL_NOT_FOUND); 344 345 /* 346 * Get max number of processor groups. 347 */ 348 if (g_pfnrtKeQueryMaximumGroupCount) 349 { 350 g_cRtMpNtMaxGroups = g_pfnrtKeQueryMaximumGroupCount(); 351 MY_CHECK_RETURN(g_cRtMpNtMaxGroups <= RTCPUSET_MAX_CPUS && g_cRtMpNtMaxGroups > 0, 352 ("IPRT: Fatal: g_cRtMpNtMaxGroups=%u, max %u\n", g_cRtMpNtMaxGroups, RTCPUSET_MAX_CPUS), 353 VERR_MP_TOO_MANY_CPUS); 354 } 355 else 356 g_cRtMpNtMaxGroups = 1; 357 358 /* 359 * Get max number CPUs. 360 * This also defines the range of NT CPU indexes, RTCPUID and index into RTCPUSET. 361 */ 362 if (g_pfnrtKeQueryMaximumProcessorCountEx) 363 { 364 g_cRtMpNtMaxCpus = g_pfnrtKeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS); 365 MY_CHECK_RETURN(g_cRtMpNtMaxCpus <= RTCPUSET_MAX_CPUS && g_cRtMpNtMaxCpus > 0, 366 ("IPRT: Fatal: g_cRtMpNtMaxGroups=%u, max %u [KeQueryMaximumProcessorCountEx]\n", 367 g_cRtMpNtMaxGroups, RTCPUSET_MAX_CPUS), 368 VERR_MP_TOO_MANY_CPUS); 369 } 370 else if (g_pfnrtKeQueryMaximumProcessorCount) 371 { 372 g_cRtMpNtMaxCpus = g_pfnrtKeQueryMaximumProcessorCount(); 373 MY_CHECK_RETURN(g_cRtMpNtMaxCpus <= RTCPUSET_MAX_CPUS && g_cRtMpNtMaxCpus > 0, 374 ("IPRT: Fatal: g_cRtMpNtMaxGroups=%u, max %u [KeQueryMaximumProcessorCount]\n", 375 g_cRtMpNtMaxGroups, RTCPUSET_MAX_CPUS), 376 VERR_MP_TOO_MANY_CPUS); 377 } 378 else if (g_pfnrtKeQueryActiveProcessors) 379 { 380 KAFFINITY fActiveProcessors = g_pfnrtKeQueryActiveProcessors(); 381 MY_CHECK_RETURN(fActiveProcessors != 0, 382 ("IPRT: Fatal: KeQueryActiveProcessors returned 0!\n"), 383 VERR_INTERNAL_ERROR_2); 384 g_cRtMpNtMaxCpus = 0; 385 do 386 { 387 g_cRtMpNtMaxCpus++; 388 fActiveProcessors >>= 1; 389 } while (fActiveProcessors); 390 } 391 else 392 g_cRtMpNtMaxCpus = KeNumberProcessors; 393 394 /* 395 * Query the details for the groups to figure out which CPUs are online as 396 * well as the NT index limit. 397 */ 398 if (g_pfnrtKeQueryLogicalProcessorRelationship) 399 { 400 MY_CHECK_RETURN(g_pfnrtKeGetProcessorIndexFromNumber, 401 ("IPRT: Fatal: Found KeQueryLogicalProcessorRelationship but not KeGetProcessorIndexFromNumber!\n"), 402 VERR_SYMBOL_NOT_FOUND); 403 MY_CHECK_RETURN(g_pfnrtKeGetProcessorNumberFromIndex, 404 ("IPRT: Fatal: Found KeQueryLogicalProcessorRelationship but not KeGetProcessorIndexFromNumber!\n"), 405 VERR_SYMBOL_NOT_FOUND); 406 MY_CHECK_RETURN(g_pfnrtKeSetTargetProcessorDpcEx, 407 ("IPRT: Fatal: Found KeQueryLogicalProcessorRelationship but not KeSetTargetProcessorDpcEx!\n"), 408 VERR_SYMBOL_NOT_FOUND); 409 410 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pInfo = NULL; 411 int rc = rtR0NtInitQueryGroupRelations(&pInfo); 412 if (RT_FAILURE(rc)) 413 return rc; 414 415 AssertReturnStmt(pInfo->Group.MaximumGroupCount == g_cRtMpNtMaxGroups, RTMemFree(pInfo), VERR_INTERNAL_ERROR_3); 416 417 /* 418 * Calc online mask. 419 * 420 * Also check ASSUMPTIONS: 421 * - Processor indexes going to KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS) 422 * - Processor indexes being assigned to absent hotswappable CPUs, i.e. 423 * KeGetProcessorIndexFromNumber and KeGetProcessorNumberFromIndex works 424 * all possible indexes. [Not yet confirmed!] 425 * - Processor indexes are assigned in group order. 426 * - MaximumProcessorCount specifies the highest bit in the active mask. 427 * This is for confirming process IDs assigned by IPRT in ring-3. 428 */ 429 /** @todo Test the latter on a real/virtual system. */ 430 RTCpuSetEmpty(&g_rtMpNtCpuSet); 431 uint32_t idxCpuExpect = 0; 432 for (uint32_t idxGroup = 0; RT_SUCCESS(rc) && idxGroup < pInfo->Group.ActiveGroupCount; idxGroup++) 433 { 434 const PROCESSOR_GROUP_INFO *pGrpInfo = &pInfo->Group.GroupInfo[idxGroup]; 435 MY_CHECK_BREAK(pGrpInfo->MaximumProcessorCount <= MAXIMUM_PROC_PER_GROUP, 436 ("IPRT: Fatal: MaximumProcessorCount=%u\n", pGrpInfo->MaximumProcessorCount)); 437 MY_CHECK_BREAK(pGrpInfo->ActiveProcessorCount <= MAXIMUM_PROC_PER_GROUP, 438 ("IPRT: Fatal: ActiveProcessorCount=%u\n", pGrpInfo->ActiveProcessorCount)); 439 MY_CHECK_BREAK(pGrpInfo->ActiveProcessorCount <= pGrpInfo->MaximumProcessorCount, 440 ("IPRT: Fatal: ActiveProcessorCount=%u > MaximumProcessorCount=%u\n", 441 pGrpInfo->ActiveProcessorCount, pGrpInfo->MaximumProcessorCount)); 442 for (uint32_t idxMember = 0; idxMember < pGrpInfo->MaximumProcessorCount; idxMember++, idxCpuExpect++) 443 { 444 PROCESSOR_NUMBER ProcNum; 445 ProcNum.Group = (USHORT)idxGroup; 446 ProcNum.Number = (UCHAR)idxMember; 447 ProcNum.Reserved = 0; 448 ULONG idxCpu = g_pfnrtKeGetProcessorIndexFromNumber(&ProcNum); 449 MY_CHECK_BREAK(idxCpu != INVALID_PROCESSOR_INDEX, 450 ("IPRT: Fatal: KeGetProcessorIndexFromNumber(%u/%u) failed\n", idxGroup, idxMember)); 451 MY_CHECK_BREAK(idxCpu < g_cRtMpNtMaxCpus && idxCpu < RTCPUSET_MAX_CPUS, 452 ("IPRT: Fatal: idxCpu=%u >= g_cRtMpNtMaxCpu=%u (RTCPUSET_MAX_CPUS=%u)\n", 453 idxCpu, g_cRtMpNtMaxCpus, RTCPUSET_MAX_CPUS)); 454 MY_CHECK_BREAK(idxCpu == idxCpuExpect, ("IPRT: Fatal: idxCpu=%u != idxCpuExpect=%u\n", idxCpu, idxCpuExpect)); 455 456 ProcNum.Group = UINT16_MAX; 457 ProcNum.Number = UINT8_MAX; 458 ProcNum.Reserved = UINT8_MAX; 459 NTSTATUS rcNt = g_pfnrtKeGetProcessorNumberFromIndex(idxCpu, &ProcNum); 460 MY_CHECK_BREAK(NT_SUCCESS(rcNt), ("IPRT: Fatal: KeGetProcessorNumberFromIndex(%u,) -> %#x!\n", idxCpu, rcNt)); 461 MY_CHECK_BREAK(ProcNum.Group == idxGroup && ProcNum.Number == idxMember, 462 ("IPRT: Fatal: KeGetProcessorXxxxFromYyyy roundtrip error for %#x! Group: %u vs %u, Number: %u vs %u\n", 463 idxCpu, ProcNum.Group, idxGroup, ProcNum.Number, idxMember)); 464 465 if (pGrpInfo->ActiveProcessorMask & RT_BIT_64(idxMember)) 466 RTCpuSetAddByIndex(&g_rtMpNtCpuSet, idxCpu); 467 } 468 } 469 RTMemFree(pInfo); 470 if (RT_FAILURE(rc)) /* MY_CHECK_BREAK sets rc. */ 471 return rc; 472 } 473 else 474 { 475 /* Legacy: */ 476 MY_CHECK_RETURN(g_cRtMpNtMaxGroups == 1, ("IPRT: Fatal: Missing KeQueryLogicalProcessorRelationship!\n"), 477 VERR_SYMBOL_NOT_FOUND); 478 479 if (g_pfnrtKeQueryActiveProcessors) 480 RTCpuSetFromU64(&g_rtMpNtCpuSet, g_pfnrtKeQueryActiveProcessors()); 481 else if (g_cRtMpNtMaxCpus < 64) 482 RTCpuSetFromU64(&g_rtMpNtCpuSet, (UINT64_C(1) << g_cRtMpNtMaxCpus) - 1); 483 else 484 { 485 MY_CHECK_RETURN(g_cRtMpNtMaxCpus == 64, ("IPRT: Fatal: g_cRtMpNtMaxCpus=%u, expect 64 or less\n", g_cRtMpNtMaxCpus), 486 VERR_MP_TOO_MANY_CPUS); 487 RTCpuSetFromU64(&g_rtMpNtCpuSet, UINT64_MAX); 488 } 489 } 490 491 /* 492 * Register CPU hot plugging callback. 493 */ 494 Assert(g_pvMpCpuChangeCallback == NULL); 495 if (g_pfnrtKeRegisterProcessorChangeCallback) 496 { 497 MY_CHECK_RETURN(g_pfnrtKeDeregisterProcessorChangeCallback, 498 ("IPRT: Fatal: KeRegisterProcessorChangeCallback without KeDeregisterProcessorChangeCallback!\n"), 499 VERR_SYMBOL_NOT_FOUND); 500 501 RTCPUSET ActiveSetCopy = g_rtMpNtCpuSet; 502 RTCpuSetEmpty(&g_rtMpNtCpuSet); 503 g_pvMpCpuChangeCallback = g_pfnrtKeRegisterProcessorChangeCallback(rtR0NtMpProcessorChangeCallback, NULL /*pvUser*/, 504 KE_PROCESSOR_CHANGE_ADD_EXISTING); 505 if (!g_pvMpCpuChangeCallback) 506 { 507 AssertFailed(); 508 g_rtMpNtCpuSet = ActiveSetCopy; 509 } 510 } 511 512 /* 513 * Special IPI fun for RTMpPokeCpu. 514 * 515 * On Vista and later the DPC method doesn't seem to reliably send IPIs, 516 * so we have to use alternative methods. 517 * 518 * On AMD64 We used to use the HalSendSoftwareInterrupt API (also x86 on 519 * W10+), it looks faster and more convenient to use, however we're either 520 * using it wrong or it doesn't reliably do what we want (see @bugref{8343}). 521 * 522 * The HalRequestIpip API is thus far the only alternative to KeInsertQueueDpc 523 * for doing targetted IPIs. Trouble with this API is that it changed 524 * fundamentally in Window 7 when they added support for lots of processors. 525 * 526 * If we really think we cannot use KeInsertQueueDpc, we use the broadcast IPI 527 * API KeIpiGenericCall. 528 */ 529 if ( pOsVerInfo->uMajorVer > 6 530 || (pOsVerInfo->uMajorVer == 6 && pOsVerInfo->uMinorVer > 0)) 531 g_pfnrtHalRequestIpiPreW7 = NULL; 532 else 533 g_pfnrtHalRequestIpiW7Plus = NULL; 534 535 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingDpc; 536 #ifndef IPRT_TARGET_NT4 537 if ( g_pfnrtHalRequestIpiW7Plus 538 && g_pfnrtKeInitializeAffinityEx 539 && g_pfnrtKeAddProcessorAffinityEx 540 && g_pfnrtKeGetProcessorIndexFromNumber) 541 { 542 DbgPrint("IPRT: RTMpPoke => rtMpPokeCpuUsingHalReqestIpiW7Plus\n"); 543 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingHalReqestIpiW7Plus; 544 } 545 else if (pOsVerInfo->uMajorVer >= 6 && g_pfnrtKeIpiGenericCall) 546 { 547 DbgPrint("IPRT: RTMpPoke => rtMpPokeCpuUsingBroadcastIpi\n"); 548 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingBroadcastIpi; 549 } 550 else 551 DbgPrint("IPRT: RTMpPoke => rtMpPokeCpuUsingDpc\n"); 552 /* else: Windows XP should send always send an IPI -> VERIFY */ 553 #endif 554 555 return VINF_SUCCESS; 556 } 557 558 205 559 DECLHIDDEN(int) rtR0InitNative(void) 206 560 { 207 561 /* 208 * Init the Nt cpu set.562 * Initialize the function pointers. 209 563 */ 210 564 #ifdef IPRT_TARGET_NT4 211 KAFFINITY ActiveProcessors = (UINT64_C(1) << KeNumberProcessors) - UINT64_C(1); 565 # define GET_SYSTEM_ROUTINE_EX(a_Prf, a_Name, a_pfnType) do { RT_CONCAT3(g_pfnrt, a_Prf, a_Name) = NULL; } while (0) 212 566 #else 213 KAFFINITY ActiveProcessors = KeQueryActiveProcessors(); 567 UNICODE_STRING RoutineName; 568 # define GET_SYSTEM_ROUTINE_EX(a_Prf, a_Name, a_pfnType) \ 569 do { \ 570 RtlInitUnicodeString(&RoutineName, L#a_Name); \ 571 RT_CONCAT3(g_pfnrt, a_Prf, a_Name) = (a_pfnType)MmGetSystemRoutineAddress(&RoutineName); \ 572 } while (0) 214 573 #endif 215 RTCpuSetEmpty(&g_rtMpNtCpuSet); 216 RTCpuSetFromU64(&g_rtMpNtCpuSet, ActiveProcessors); 217 /** @todo Port to W2K8 with > 64 cpus/threads. */ 218 219 /* 220 * Initialize the function pointers. 221 */ 574 #define GET_SYSTEM_ROUTINE(a_Name) GET_SYSTEM_ROUTINE_EX(RT_NOTHING, a_Name, decltype(a_Name) *) 575 #define GET_SYSTEM_ROUTINE_PRF(a_Prf,a_Name) GET_SYSTEM_ROUTINE_EX(a_Prf, a_Name, decltype(a_Name) *) 576 #define GET_SYSTEM_ROUTINE_TYPE(a_Name, a_pfnType) GET_SYSTEM_ROUTINE_EX(RT_NOTHING, a_Name, a_pfnType) 577 578 GET_SYSTEM_ROUTINE_PRF(Nt,ExSetTimerResolution); 579 GET_SYSTEM_ROUTINE_PRF(Nt,KeFlushQueuedDpcs); 580 GET_SYSTEM_ROUTINE(KeIpiGenericCall); 581 GET_SYSTEM_ROUTINE(KeSetTargetProcessorDpcEx); 582 GET_SYSTEM_ROUTINE(KeInitializeAffinityEx); 583 GET_SYSTEM_ROUTINE(KeAddProcessorAffinityEx); 584 GET_SYSTEM_ROUTINE_TYPE(KeGetProcessorIndexFromNumber, PFNKEGETPROCESSORINDEXFROMNUMBER); 585 GET_SYSTEM_ROUTINE(KeGetProcessorNumberFromIndex); 586 GET_SYSTEM_ROUTINE_TYPE(KeGetCurrentProcessorNumberEx, PFNKEGETCURRENTPROCESSORNUMBEREX); 587 GET_SYSTEM_ROUTINE(KeQueryActiveProcessors); 588 GET_SYSTEM_ROUTINE(KeQueryMaximumProcessorCount); 589 GET_SYSTEM_ROUTINE(KeQueryMaximumProcessorCountEx); 590 GET_SYSTEM_ROUTINE(KeQueryMaximumGroupCount); 591 GET_SYSTEM_ROUTINE(KeQueryLogicalProcessorRelationship); 592 GET_SYSTEM_ROUTINE(KeRegisterProcessorChangeCallback); 593 GET_SYSTEM_ROUTINE(KeDeregisterProcessorChangeCallback); 594 595 GET_SYSTEM_ROUTINE_TYPE(RtlGetVersion, PFNRTRTLGETVERSION); 596 #ifndef RT_ARCH_AMD64 597 GET_SYSTEM_ROUTINE(KeQueryInterruptTime); 598 GET_SYSTEM_ROUTINE(KeQuerySystemTime); 599 #endif 600 GET_SYSTEM_ROUTINE_TYPE(KeQueryInterruptTimePrecise, PFNRTKEQUERYINTERRUPTTIMEPRECISE); 601 GET_SYSTEM_ROUTINE_TYPE(KeQuerySystemTimePrecise, PFNRTKEQUERYSYSTEMTIMEPRECISE); 602 222 603 #ifdef IPRT_TARGET_NT4 223 g_pfnrtNtExSetTimerResolution = NULL;224 g_pfnrtNtKeFlushQueuedDpcs = NULL;225 604 g_pfnrtHalRequestIpiW7Plus = NULL; 226 605 g_pfnrtHalRequestIpiPreW7 = NULL; 227 g_pfnrtKeIpiGenericCall = NULL;228 g_pfnrtKeInitializeAffinityEx = NULL;229 g_pfnrtKeAddProcessorAffinityEx = NULL;230 g_pfnrtKeGetProcessorIndexFromNumber = NULL;231 g_pfnrtRtlGetVersion = NULL;232 g_pfnrtKeQueryInterruptTime = NULL;233 g_pfnrtKeQueryInterruptTimePrecise = NULL;234 g_pfnrtKeQuerySystemTime = NULL;235 g_pfnrtKeQuerySystemTimePrecise = NULL;236 606 #else 237 UNICODE_STRING RoutineName;238 RtlInitUnicodeString(&RoutineName, L"ExSetTimerResolution");239 g_pfnrtNtExSetTimerResolution = (PFNMYEXSETTIMERRESOLUTION)MmGetSystemRoutineAddress(&RoutineName);240 241 RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");242 g_pfnrtNtKeFlushQueuedDpcs = (PFNMYKEFLUSHQUEUEDDPCS)MmGetSystemRoutineAddress(&RoutineName);243 244 607 RtlInitUnicodeString(&RoutineName, L"HalRequestIpi"); 245 608 g_pfnrtHalRequestIpiW7Plus = (PFNHALREQUESTIPI_W7PLUS)MmGetSystemRoutineAddress(&RoutineName); 246 609 g_pfnrtHalRequestIpiPreW7 = (PFNHALREQUESTIPI_PRE_W7)g_pfnrtHalRequestIpiW7Plus; 247 248 RtlInitUnicodeString(&RoutineName, L"KeIpiGenericCall");249 g_pfnrtKeIpiGenericCall = (PFNRTKEIPIGENERICCALL)MmGetSystemRoutineAddress(&RoutineName);250 251 RtlInitUnicodeString(&RoutineName, L"KeInitializeAffinityEx");252 g_pfnrtKeInitializeAffinityEx = (PFNKEINITIALIZEAFFINITYEX)MmGetSystemRoutineAddress(&RoutineName);253 254 RtlInitUnicodeString(&RoutineName, L"KeAddProcessorAffinityEx");255 g_pfnrtKeAddProcessorAffinityEx = (PFNKEADDPROCESSORAFFINITYEX)MmGetSystemRoutineAddress(&RoutineName);256 257 RtlInitUnicodeString(&RoutineName, L"KeGetProcessorIndexFromNumber");258 g_pfnrtKeGetProcessorIndexFromNumber = (PFNKEGETPROCESSORINDEXFROMNUMBER)MmGetSystemRoutineAddress(&RoutineName);259 260 RtlInitUnicodeString(&RoutineName, L"RtlGetVersion");261 g_pfnrtRtlGetVersion = (PFNRTRTLGETVERSION)MmGetSystemRoutineAddress(&RoutineName);262 # ifndef RT_ARCH_AMD64263 RtlInitUnicodeString(&RoutineName, L"KeQueryInterruptTime");264 g_pfnrtKeQueryInterruptTime = (PFNRTKEQUERYINTERRUPTTIME)MmGetSystemRoutineAddress(&RoutineName);265 266 RtlInitUnicodeString(&RoutineName, L"KeQuerySystemTime");267 g_pfnrtKeQuerySystemTime = (PFNRTKEQUERYSYSTEMTIME)MmGetSystemRoutineAddress(&RoutineName);268 # endif269 RtlInitUnicodeString(&RoutineName, L"KeQueryInterruptTimePrecise");270 g_pfnrtKeQueryInterruptTimePrecise = (PFNRTKEQUERYINTERRUPTTIMEPRECISE)MmGetSystemRoutineAddress(&RoutineName);271 272 RtlInitUnicodeString(&RoutineName, L"KeQuerySystemTimePrecise");273 g_pfnrtKeQuerySystemTimePrecise = (PFNRTKEQUERYSYSTEMTIMEPRECISE)MmGetSystemRoutineAddress(&RoutineName);274 610 #endif 275 611 … … 403 739 404 740 /* 405 * Special IPI fun for RTMpPokeCpu. 406 * 407 * On Vista and later the DPC method doesn't seem to reliably send IPIs, 408 * so we have to use alternative methods. 409 * 410 * On AMD64 We used to use the HalSendSoftwareInterrupt API (also x86 on 411 * W10+), it looks faster and more convenient to use, however we're either 412 * using it wrong or it doesn't reliably do what we want (see @bugref{8343}). 413 * 414 * The HalRequestIpip API is thus far the only alternative to KeInsertQueueDpc 415 * for doing targetted IPIs. Trouble with this API is that it changed 416 * fundamentally in Window 7 when they added support for lots of processors. 417 * 418 * If we really think we cannot use KeInsertQueueDpc, we use the broadcast IPI 419 * API KeIpiGenericCall. 420 */ 421 if ( OsVerInfo.uMajorVer > 6 422 || (OsVerInfo.uMajorVer == 6 && OsVerInfo.uMinorVer > 0)) 423 g_pfnrtHalRequestIpiPreW7 = NULL; 424 else 425 g_pfnrtHalRequestIpiW7Plus = NULL; 426 427 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingDpc; 428 #ifndef IPRT_TARGET_NT4 429 if ( g_pfnrtHalRequestIpiW7Plus 430 && g_pfnrtKeInitializeAffinityEx 431 && g_pfnrtKeAddProcessorAffinityEx 432 && g_pfnrtKeGetProcessorIndexFromNumber) 433 { 434 DbgPrint("IPRT: RTMpPoke => rtMpPokeCpuUsingHalReqestIpiW7Plus\n"); 435 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingHalReqestIpiW7Plus; 436 } 437 else if (OsVerInfo.uMajorVer >= 6 && g_pfnrtKeIpiGenericCall) 438 { 439 DbgPrint("IPRT: RTMpPoke => rtMpPokeCpuUsingBroadcastIpi\n"); 440 g_pfnrtMpPokeCpuWorker = rtMpPokeCpuUsingBroadcastIpi; 441 } 442 else 443 DbgPrint("IPRT: RTMpPoke => rtMpPokeCpuUsingDpc\n"); 444 /* else: Windows XP should send always send an IPI -> VERIFY */ 445 #endif 741 * Initialize multi processor stuff. This registers a callback, so 742 * we call rtR0TermNative to do the deregistration on failure. 743 */ 744 int rc = rtR0NtInitMp(&OsVerInfo); 745 if (RT_FAILURE(rc)) 746 { 747 rtR0TermNative(); 748 DbgPrint("IPRT: Fatal: rtR0NtInitMp failed: %d\n", rc); 749 return rc; 750 } 446 751 447 752 return VINF_SUCCESS; … … 451 756 DECLHIDDEN(void) rtR0TermNative(void) 452 757 { 758 /* 759 * Deregister the processor change callback. 760 */ 761 PVOID pvMpCpuChangeCallback = g_pvMpCpuChangeCallback; 762 g_pvMpCpuChangeCallback = NULL; 763 if (pvMpCpuChangeCallback) 764 { 765 AssertReturnVoid(g_pfnrtKeDeregisterProcessorChangeCallback); 766 g_pfnrtKeDeregisterProcessorChangeCallback(pvMpCpuChangeCallback); 767 } 453 768 } 454 769 -
trunk/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
r62477 r64234 53 53 * Global Variables * 54 54 *******************************************************************************/ 55 extern RTCPUSET g_rtMpNtCpuSet; 56 extern PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution; 57 extern PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs; 58 extern PFNHALREQUESTIPI_W7PLUS g_pfnrtHalRequestIpiW7Plus; 59 extern PFNHALREQUESTIPI_PRE_W7 g_pfnrtHalRequestIpiPreW7; 60 extern PFNHALSENDSOFTWAREINTERRUPT g_pfnrtNtHalSendSoftwareInterrupt; 61 extern PFNRTSENDIPI g_pfnrtMpPokeCpuWorker; 62 extern PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 63 extern PFNKEINITIALIZEAFFINITYEX g_pfnrtKeInitializeAffinityEx; 64 extern PFNKEADDPROCESSORAFFINITYEX g_pfnrtKeAddProcessorAffinityEx; 65 extern PFNKEGETPROCESSORINDEXFROMNUMBER g_pfnrtKeGetProcessorIndexFromNumber; 55 extern RTCPUSET g_rtMpNtCpuSet; 56 extern uint32_t g_cRtMpNtMaxGroups; 57 extern uint32_t g_cRtMpNtMaxCpus; 66 58 67 extern PFNRTRTLGETVERSION g_pfnrtRtlGetVersion; 59 extern PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution; 60 extern PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs; 61 extern PFNHALREQUESTIPI_W7PLUS g_pfnrtHalRequestIpiW7Plus; 62 extern PFNHALREQUESTIPI_PRE_W7 g_pfnrtHalRequestIpiPreW7; 63 extern PFNHALSENDSOFTWAREINTERRUPT g_pfnrtNtHalSendSoftwareInterrupt; 64 extern PFNRTSENDIPI g_pfnrtMpPokeCpuWorker; 65 extern PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall; 66 extern PFNKESETTARGETPROCESSORDPCEX g_pfnrtKeSetTargetProcessorDpcEx; 67 extern PFNKEINITIALIZEAFFINITYEX g_pfnrtKeInitializeAffinityEx; 68 extern PFNKEADDPROCESSORAFFINITYEX g_pfnrtKeAddProcessorAffinityEx; 69 extern PFNKEGETPROCESSORINDEXFROMNUMBER g_pfnrtKeGetProcessorIndexFromNumber; 70 extern PFNKEGETPROCESSORNUMBERFROMINDEX g_pfnrtKeGetProcessorNumberFromIndex; 71 extern PFNKEGETCURRENTPROCESSORNUMBEREX g_pfnrtKeGetCurrentProcessorNumberEx; 72 extern PFNKEQUERYACTIVEPROCESSORS g_pfnrtKeQueryActiveProcessors; 73 extern PFNKEQUERYMAXIMUMPROCESSORCOUNT g_pfnrtKeQueryMaximumProcessorCount; 74 extern PFNKEQUERYMAXIMUMPROCESSORCOUNTEX g_pfnrtKeQueryMaximumProcessorCountEx; 75 extern PFNKEQUERYMAXIMUMGROUPCOUNT g_pfnrtKeQueryMaximumGroupCount; 76 extern PFNKEQUERYLOGICALPROCESSORRELATIONSHIP g_pfnrtKeQueryLogicalProcessorRelationship; 77 extern PFNKEREGISTERPROCESSORCHANGECALLBACK g_pfnrtKeRegisterProcessorChangeCallback; 78 extern PFNKEDEREGISTERPROCESSORCHANGECALLBACK g_pfnrtKeDeregisterProcessorChangeCallback; 79 extern PFNRTRTLGETVERSION g_pfnrtRtlGetVersion; 68 80 #ifndef RT_ARCH_AMD64 69 extern PFNRTKEQUERYINTERRUPTTIME g_pfnrtKeQueryInterruptTime;70 extern PFNRTKEQUERYSYSTEMTIME g_pfnrtKeQuerySystemTime;81 extern PFNRTKEQUERYINTERRUPTTIME g_pfnrtKeQueryInterruptTime; 82 extern PFNRTKEQUERYSYSTEMTIME g_pfnrtKeQuerySystemTime; 71 83 #endif 72 extern PFNRTKEQUERYINTERRUPTTIMEPRECISE g_pfnrtKeQueryInterruptTimePrecise; 73 extern PFNRTKEQUERYSYSTEMTIMEPRECISE g_pfnrtKeQuerySystemTimePrecise; 74 extern uint32_t g_offrtNtPbQuantumEnd; 75 extern uint32_t g_cbrtNtPbQuantumEnd; 76 extern uint32_t g_offrtNtPbDpcQueueDepth; 84 extern PFNRTKEQUERYINTERRUPTTIMEPRECISE g_pfnrtKeQueryInterruptTimePrecise; 85 extern PFNRTKEQUERYSYSTEMTIMEPRECISE g_pfnrtKeQuerySystemTimePrecise; 86 87 extern uint32_t g_offrtNtPbQuantumEnd; 88 extern uint32_t g_cbrtNtPbQuantumEnd; 89 extern uint32_t g_offrtNtPbDpcQueueDepth; 77 90 78 91 … … 82 95 int __stdcall rtMpPokeCpuUsingHalReqestIpiPreW7(RTCPUID idCpu); 83 96 97 DECLHIDDEN(int) rtMpNtSetTargetProcessorDpc(KDPC *pDpc, RTCPUID idCpu); 98 84 99 RT_C_DECLS_END 85 100 -
trunk/src/VBox/Runtime/r0drv/nt/mp-r0drv-nt.cpp
r63063 r64234 76 76 77 77 78 /* test a couple of assumption. */79 AssertCompile(MAXIMUM_PROCESSORS <= RTCPUSET_MAX_CPUS);80 AssertCompile(NIL_RTCPUID >= MAXIMUM_PROCESSORS);81 82 /** @todo83 * We cannot do other than assume a 1:1 relationship between the84 * affinity mask and the process despite the vagueness/warnings in85 * the docs. If someone knows a better way to get this done, please86 * let bird know.87 */88 89 90 78 RTDECL(RTCPUID) RTMpCpuId(void) 91 79 { 80 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 81 82 if (g_pfnrtKeGetCurrentProcessorNumberEx) 83 { 84 KEPROCESSORINDEX idxCpu = g_pfnrtKeGetCurrentProcessorNumberEx(NULL); 85 Assert(idxCpu < RTCPUSET_MAX_CPUS); 86 return idxCpu; 87 } 88 92 89 /* WDK upgrade warning: PCR->Number changed from BYTE to WORD. */ 93 90 return KeGetCurrentProcessorNumber(); … … 97 94 RTDECL(int) RTMpCurSetIndex(void) 98 95 { 99 /* WDK upgrade warning: PCR->Number changed from BYTE to WORD. */ 100 return KeGetCurrentProcessorNumber(); 96 return (int)RTMpCpuId(); 101 97 } 102 98 … … 104 100 RTDECL(int) RTMpCurSetIndexAndId(PRTCPUID pidCpu) 105 101 { 106 return *pidCpu = KeGetCurrentProcessorNumber();102 return *pidCpu = RTMpCpuId(); 107 103 } 108 104 … … 110 106 RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu) 111 107 { 112 return idCpu < MAXIMUM_PROCESSORS ? (int)idCpu : -1; 108 /* 1:1 mapping, just do range checks. */ 109 return idCpu < RTCPUSET_MAX_CPUS ? (int)idCpu : -1; 113 110 } 114 111 … … 116 113 RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu) 117 114 { 118 return (unsigned)iCpu < MAXIMUM_PROCESSORS ? iCpu : NIL_RTCPUID; 115 /* 1:1 mapping, just do range checks. */ 116 return (unsigned)iCpu < RTCPUSET_MAX_CPUS ? iCpu : NIL_RTCPUID; 119 117 } 120 118 … … 122 120 RTDECL(RTCPUID) RTMpGetMaxCpuId(void) 123 121 { 124 /** @todo use KeQueryMaximumProcessorCount on vista+ */ 125 return MAXIMUM_PROCESSORS - 1; 122 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 123 124 /* According to MSDN the processor indexes goes from 0 to the maximum 125 number of CPUs in the system. We've check this in initterm-r0drv-nt.cpp. */ 126 return g_cRtMpNtMaxCpus - 1; 126 127 } 127 128 … … 129 130 RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu) 130 131 { 131 if (idCpu >= MAXIMUM_PROCESSORS) 132 return false; 133 134 #if 0 /* this isn't safe at all IRQLs (great work guys) */ 135 KAFFINITY Mask = KeQueryActiveProcessors(); 136 return !!(Mask & RT_BIT_64(idCpu)); 137 #else 138 return RTCpuSetIsMember(&g_rtMpNtCpuSet, idCpu); 139 #endif 132 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 133 return idCpu < RTCPUSET_MAX_CPUS 134 && RTCpuSetIsMember(&g_rtMpNtCpuSet, idCpu); 140 135 } 141 136 … … 143 138 RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu) 144 139 { 145 /* Cannot easily distinguish between online and offline cpus. */ 146 /** @todo online/present cpu stuff must be corrected for proper W2K8 support 147 * (KeQueryMaximumProcessorCount). */ 148 return RTMpIsCpuOnline(idCpu); 140 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 141 142 /* A possible CPU ID is one with a value lower than g_cRtMpNtMaxCpus (see 143 comment in RTMpGetMaxCpuId). */ 144 return idCpu < g_cRtMpNtMaxCpus; 149 145 } 150 146 … … 153 149 RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet) 154 150 { 155 /** @todo online/present cpu stuff must be corrected for proper W2K8 support 156 * (KeQueryMaximumProcessorCount). */ 157 return RTMpGetOnlineSet(pSet); 151 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 152 153 /* The set of possible CPU IDs(/indexes) are from 0 up to 154 g_cRtMpNtMaxCpus (see comment in RTMpGetMaxCpuId). */ 155 RTCpuSetEmpty(pSet); 156 int idxCpu = g_cRtMpNtMaxCpus; 157 while (idxCpu-- > 0) 158 RTCpuSetAddByIndex(pSet, idxCpu); 159 return pSet; 158 160 } 159 161 … … 161 163 RTDECL(RTCPUID) RTMpGetCount(void) 162 164 { 163 /** @todo online/present cpu stuff must be corrected for proper W2K8 support 164 * (KeQueryMaximumProcessorCount). */ 165 return RTMpGetOnlineCount(); 165 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 166 return g_cRtMpNtMaxCpus; 166 167 } 167 168 … … 169 170 RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet) 170 171 { 171 #if 0 /* this isn't safe at all IRQLs (great work guys) */ 172 KAFFINITY Mask = KeQueryActiveProcessors(); 173 return RTCpuSetFromU64(pSet, Mask); 174 #else 172 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 173 175 174 *pSet = g_rtMpNtCpuSet; 176 175 return pSet; 177 #endif178 176 } 179 177 … … 236 234 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 237 235 /*ASMAtomicIncU32(&pArgs->cHits); - not needed */ 238 pArgs->pfnWorker( KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2);236 pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2); 239 237 return 0; 240 238 } … … 250 248 { 251 249 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 252 RTCPUID idCpu = KeGetCurrentProcessorNumber();250 RTCPUID idCpu = RTMpCpuId(); 253 251 if (pArgs->idCpu != idCpu) 254 252 { … … 269 267 { 270 268 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 271 RTCPUID idCpu = KeGetCurrentProcessorNumber();269 RTCPUID idCpu = RTMpCpuId(); 272 270 if ( pArgs->idCpu == idCpu 273 271 || pArgs->idCpu2 == idCpu) … … 289 287 { 290 288 PRTMPARGS pArgs = (PRTMPARGS)uUserCtx; 291 RTCPUID idCpu = KeGetCurrentProcessorNumber();289 RTCPUID idCpu = RTMpCpuId(); 292 290 if (pArgs->idCpu == idCpu) 293 291 { … … 348 346 349 347 ASMAtomicIncU32(&pArgs->cHits); 350 pArgs->pfnWorker( KeGetCurrentProcessorNumber(), pArgs->pvUser1, pArgs->pvUser2);348 pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2); 351 349 352 350 /* Dereference the argument structure. */ … … 355 353 if (cRefs == 0) 356 354 ExFreePool(pArgs); 355 } 356 357 358 /** 359 * Wrapper around KeSetTargetProcessorDpcEx / KeSetTargetProcessorDpc. 360 * 361 * This is shared with the timer code. 362 * 363 * @returns IPRT status code (errors are asserted). 364 * @param pDpc The DPC. 365 * @param idCpu The ID of the new target CPU. 366 */ 367 DECLHIDDEN(int) rtMpNtSetTargetProcessorDpc(KDPC *pDpc, RTCPUID idCpu) 368 { 369 if (g_pfnrtKeSetTargetProcessorDpcEx) 370 { 371 /* Convert to stupid process number (bet KeSetTargetProcessorDpcEx does 372 the reverse conversion internally). */ 373 PROCESSOR_NUMBER ProcNum; 374 NTSTATUS rcNt = g_pfnrtKeGetProcessorNumberFromIndex(idCpu, &ProcNum); 375 AssertMsgReturn(NT_SUCCESS(rcNt), 376 ("KeGetProcessorNumberFromIndex(%u) -> %#x\n", idCpu, rcNt), 377 RTErrConvertFromNtStatus(rcNt)); 378 379 rcNt = g_pfnrtKeSetTargetProcessorDpcEx(pDpc, &ProcNum); 380 AssertMsgReturn(NT_SUCCESS(rcNt), 381 ("KeSetTargetProcessorDpcEx(,%u(%u/%u)) -> %#x\n", idCpu, ProcNum.Group, ProcNum.Number, rcNt), 382 RTErrConvertFromNtStatus(rcNt)); 383 } 384 else 385 KeSetTargetProcessorDpc(pDpc, (int)idCpu); 386 return VINF_SUCCESS; 357 387 } 358 388 … … 396 426 return VERR_NOT_SUPPORTED; 397 427 398 pArgs = (PRTMPARGS)ExAllocatePoolWithTag(NonPagedPool, MAXIMUM_PROCESSORS*sizeof(KDPC) + sizeof(RTMPARGS), (ULONG)'RTMp');428 pArgs = (PRTMPARGS)ExAllocatePoolWithTag(NonPagedPool, g_cRtMpNtMaxCpus * sizeof(KDPC) + sizeof(RTMPARGS), (ULONG)'RTMp'); 399 429 if (!pArgs) 400 430 return VERR_NO_MEMORY; … … 410 440 paExecCpuDpcs = (KDPC *)(pArgs + 1); 411 441 442 int rc; 412 443 if (enmCpuid == RT_NT_CPUID_SPECIFIC) 413 444 { 414 445 KeInitializeDpc(&paExecCpuDpcs[0], rtmpNtDPCWrapper, pArgs); 415 446 KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance); 416 KeSetTargetProcessorDpc(&paExecCpuDpcs[0], (int)idCpu);447 rc = rtMpNtSetTargetProcessorDpc(&paExecCpuDpcs[0], idCpu); 417 448 pArgs->idCpu = idCpu; 418 449 } … … 421 452 KeInitializeDpc(&paExecCpuDpcs[0], rtmpNtDPCWrapper, pArgs); 422 453 KeSetImportanceDpc(&paExecCpuDpcs[0], HighImportance); 423 KeSetTargetProcessorDpc(&paExecCpuDpcs[0], (int)idCpu);454 rc = rtMpNtSetTargetProcessorDpc(&paExecCpuDpcs[0], idCpu); 424 455 pArgs->idCpu = idCpu; 425 456 426 457 KeInitializeDpc(&paExecCpuDpcs[1], rtmpNtDPCWrapper, pArgs); 427 458 KeSetImportanceDpc(&paExecCpuDpcs[1], HighImportance); 428 KeSetTargetProcessorDpc(&paExecCpuDpcs[1], (int)idCpu2); 459 if (RT_SUCCESS(rc)) 460 rc = rtMpNtSetTargetProcessorDpc(&paExecCpuDpcs[1], (int)idCpu2); 429 461 pArgs->idCpu2 = idCpu2; 430 462 } 431 463 else 432 464 { 433 for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++) 465 rc = VINF_SUCCESS; 466 for (unsigned i = 0; i < g_cRtMpNtMaxCpus && RT_SUCCESS(rc); i++) 434 467 { 435 468 KeInitializeDpc(&paExecCpuDpcs[i], rtmpNtDPCWrapper, pArgs); 436 469 KeSetImportanceDpc(&paExecCpuDpcs[i], HighImportance); 437 KeSetTargetProcessorDpc(&paExecCpuDpcs[i], i);470 rc = rtMpNtSetTargetProcessorDpc(&paExecCpuDpcs[i], i); 438 471 } 472 } 473 if (RT_FAILURE(rc)) 474 { 475 ExFreePool(pArgs); 476 return rc; 439 477 } 440 478 … … 469 507 else 470 508 { 471 unsigned iSelf = KeGetCurrentProcessorNumber();472 473 for (unsigned i = 0; i < MAXIMUM_PROCESSORS; i++)509 unsigned iSelf = RTMpCpuId(); 510 511 for (unsigned i = 0; i < g_cRtMpNtMaxCpus; i++) 474 512 { 475 513 if ( (i != iSelf) … … 505 543 506 544 return VINF_SUCCESS; 507 #endif /* */545 #endif /* !IPRT_TARGET_NT4 */ 508 546 } 509 547 … … 611 649 ASMAtomicWriteBool(&pArgs->fExecuting, true); 612 650 613 pArgs->CallbackArgs.pfnWorker( KeGetCurrentProcessorNumber(), pArgs->CallbackArgs.pvUser1, pArgs->CallbackArgs.pvUser2);651 pArgs->CallbackArgs.pfnWorker(RTMpCpuId(), pArgs->CallbackArgs.pvUser1, pArgs->CallbackArgs.pvUser2); 614 652 615 653 ASMAtomicWriteBool(&pArgs->fDone, true); … … 683 721 KeInitializeDpc(&pArgs->Dpc, rtMpNtOnSpecificDpcWrapper, pArgs); 684 722 KeSetImportanceDpc(&pArgs->Dpc, HighImportance); 685 KeSetTargetProcessorDpc(&pArgs->Dpc, (int)idCpu); 723 rc = rtMpNtSetTargetProcessorDpc(&pArgs->Dpc, idCpu); 724 if (RT_FAILURE(rc)) 725 { 726 ExFreePool(pArgs); 727 return rc; 728 } 686 729 687 730 /* … … 832 875 int rtMpPokeCpuUsingHalReqestIpiW7Plus(RTCPUID idCpu) 833 876 { 834 /* 835 * I think we'll let idCpu be an NT processor number and not a HAL processor 836 * index. KeAddProcessorAffinityEx is for HAL and uses HAL processor 837 * indexes as input from what I can tell. 838 */ 839 PROCESSOR_NUMBER ProcNumber = { /*Group=*/ idCpu / 64, /*Number=*/ idCpu % 64, /* Reserved=*/ 0}; 840 KAFFINITY_EX Target; 877 /* idCpu is an HAL processor index, so we can use it directly. */ 878 KAFFINITY_EX Target; 841 879 g_pfnrtKeInitializeAffinityEx(&Target); 842 g_pfnrtKeAddProcessorAffinityEx(&Target, g_pfnrtKeGetProcessorIndexFromNumber(&ProcNumber));880 g_pfnrtKeAddProcessorAffinityEx(&Target, idCpu); 843 881 844 882 g_pfnrtHalRequestIpiW7Plus(0, &Target); … … 868 906 int rtMpPokeCpuUsingDpc(RTCPUID idCpu) 869 907 { 908 Assert(g_cRtMpNtMaxCpus > 0 && g_cRtMpNtMaxGroups > 0); /* init order */ 909 870 910 /* 871 911 * APC fallback. 872 912 */ 873 static KDPC s_aPokeDpcs[ MAXIMUM_PROCESSORS] = {0};913 static KDPC s_aPokeDpcs[RTCPUSET_MAX_CPUS] = {0}; 874 914 static bool s_fPokeDPCsInitialized = false; 875 915 876 916 if (!s_fPokeDPCsInitialized) 877 917 { 878 for (unsigned i = 0; i < RT_ELEMENTS(s_aPokeDpcs); i++)918 for (unsigned i = 0; i < g_cRtMpNtMaxCpus; i++) 879 919 { 880 920 KeInitializeDpc(&s_aPokeDpcs[i], rtMpNtPokeCpuDummy, NULL); 881 921 KeSetImportanceDpc(&s_aPokeDpcs[i], HighImportance); 882 KeSetTargetProcessorDpc(&s_aPokeDpcs[i], (int)i); 922 int rc = rtMpNtSetTargetProcessorDpc(&s_aPokeDpcs[i], idCpu); 923 if (RT_FAILURE(rc)) 924 return rc; 883 925 } 926 884 927 s_fPokeDPCsInitialized = true; 885 928 } … … 910 953 ? VERR_CPU_NOT_FOUND 911 954 : VERR_CPU_OFFLINE; 912 /* Calls rtMp SendIpiFallback, rtMpSendIpiWin7AndLater or rtMpSendIpiVista. */955 /* Calls rtMpPokeCpuUsingDpc, rtMpPokeCpuUsingHalReqestIpiW7Plus or rtMpPokeCpuUsingBroadcastIpi. */ 913 956 return g_pfnrtMpPokeCpuWorker(idCpu); 914 957 } -
trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp
r63063 r64234 511 511 pTimer->u64NanoInterval = u64NanoInterval; 512 512 KeInitializeTimerEx(&pTimer->NtTimer, SynchronizationTimer); 513 int rc = VINF_SUCCESS; 513 514 if (pTimer->fOmniTimer) 514 515 { … … 519 520 */ 520 521 pTimer->idCpu = NIL_RTCPUID; 521 for (unsigned iCpu = 0; iCpu < cSubTimers ; iCpu++)522 for (unsigned iCpu = 0; iCpu < cSubTimers && RT_SUCCESS(rc); iCpu++) 522 523 { 523 524 pTimer->aSubTimers[iCpu].iTick = 0; … … 533 534 KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniSlaveCallback, &pTimer->aSubTimers[iCpu]); 534 535 KeSetImportanceDpc(&pTimer->aSubTimers[iCpu].NtDpc, HighImportance); 535 KeSetTargetProcessorDpc(&pTimer->aSubTimers[iCpu].NtDpc, (int)RTMpCpuIdFromSetIndex(iCpu));536 rc = rtMpNtSetTargetProcessorDpc(&pTimer->aSubTimers[iCpu].NtDpc, iCpu); 536 537 } 537 538 Assert(pTimer->idCpu != NIL_RTCPUID); … … 549 550 KeSetImportanceDpc(&pTimer->aSubTimers[0].NtDpc, HighImportance); 550 551 if (pTimer->fSpecificCpu) 551 KeSetTargetProcessorDpc(&pTimer->aSubTimers[0].NtDpc, (int)pTimer->idCpu); 552 } 553 554 *ppTimer = pTimer; 555 return VINF_SUCCESS; 552 rc = rtMpNtSetTargetProcessorDpc(&pTimer->aSubTimers[0].NtDpc, (int)pTimer->idCpu); 553 } 554 if (RT_SUCCESS(rc)) 555 { 556 *ppTimer = pTimer; 557 return VINF_SUCCESS; 558 } 559 560 RTMemFree(pTimer); 561 return rc; 556 562 } 557 563 -
trunk/src/VBox/Runtime/r3/win/mp-win.cpp
r64220 r64234 109 109 * 110 110 * We ASSUME the the GroupInfo index is the same as the group number. 111 * 111 112 * We ASSUME there are no inactive groups, because otherwise it will 112 113 * be difficult to tell how many possible CPUs we can have and do a 113 * reasonable CPU ID/index partitioning. 114 * reasonable CPU ID/index partitioning. [probably bad assumption] 115 * 116 * We ASSUME that the kernel processor indexes are assigned in group order, 117 * which we match here with our own ID+index assignments. This claim is 118 * verified by initterm-r0drv-nt.cpp. 114 119 * 115 120 * Note! We will die if there are too many processors!
Note:
See TracChangeset
for help on using the changeset viewer.