Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

563 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. allproc.c
  5. Abstract:
  6. This module allocates and intializes kernel resources required
  7. to start a new processor, and passes a complete processor state
  8. structure to the HAL to obtain a new processor.
  9. Author:
  10. Bernard Lint 31-Jul-96
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. Based on MIPS original (David N. Cutler 29-Apr-1993)
  15. --*/
  16. #include "ki.h"
  17. #include "pool.h"
  18. #if defined(KE_MULTINODE)
  19. NTSTATUS
  20. KiNotNumaQueryProcessorNode(
  21. IN ULONG ProcessorNumber,
  22. OUT PUSHORT Identifier,
  23. OUT PUCHAR Node
  24. );
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text(INIT, KiNotNumaQueryProcessorNode)
  27. #endif
  28. #endif
  29. #ifdef ALLOC_PRAGMA
  30. #pragma alloc_text(INIT, KeStartAllProcessors)
  31. #pragma alloc_text(INIT, KiAllProcessorsStarted)
  32. #endif
  33. //
  34. // Define macro to round up to 128-byte boundary to account for cache
  35. // line size increase and define block size.
  36. //
  37. #define ROUND_UP(x) ((sizeof(x) + 127) & (~127))
  38. #define BLOCK_SIZE (PAGE_SIZE + ROUND_UP(KPRCB) + ROUND_UP(KNODE) + ROUND_UP(ETHREAD))
  39. //
  40. // PER PROCESSOR MEMORY ALLOCATION NOTES:
  41. //
  42. //
  43. // Kernel/Panic stacks are allocated using MmCreateKernelStack. IA64
  44. // stacks grows down, RSE (backing store) grows up. Stack allocations
  45. // include associated backing store.
  46. //
  47. // Additional datastructures are layed out in a single memory
  48. // allocation as follows:
  49. //
  50. // * PCR page = Base
  51. // * KPRCB = Base + PAGE_SIZE
  52. // * KNODE = Base + PAGE_SIZE + ROUND_UP(KPRCB)
  53. // * ETHREAD = Base + PAGE_SIZE + ROUND_UP(KPRCB) + ROUND_UP(KNODE)
  54. //
  55. #if !defined(NT_UP)
  56. //
  57. // Define barrier wait static data.
  58. //
  59. ULONG KiBarrierWait = 0;
  60. #endif
  61. #if defined(KE_MULTINODE)
  62. PHALNUMAQUERYPROCESSORNODE KiQueryProcessorNode = KiNotNumaQueryProcessorNode;
  63. //
  64. // Statically preallocate enough KNODE structures to allow MM
  65. // to allocate pages by node during system initialization. As
  66. // processors are brought online, real KNODE structures are
  67. // allocated in the appropriate memory for the node.
  68. //
  69. // This statically allocated set will be deallocated once the
  70. // system is initialized.
  71. //
  72. #ifdef ALLOC_DATA_PRAGMA
  73. #pragma data_seg("INITDATA")
  74. #endif
  75. KNODE KiNodeInit[MAXIMUM_PROCESSORS];
  76. #endif
  77. extern ULONG_PTR KiUserSharedDataPage;
  78. extern ULONG_PTR KiKernelPcrPage;
  79. //
  80. // Define forward referenced prototypes.
  81. //
  82. VOID
  83. KiCalibratePerformanceCounter(
  84. VOID
  85. );
  86. VOID
  87. KiCalibratePerformanceCounterTarget (
  88. IN PULONG SignalDone,
  89. IN PVOID Count,
  90. IN PVOID Parameter2,
  91. IN PVOID Parameter3
  92. );
  93. VOID
  94. KiOSRendezvous (
  95. VOID
  96. );
  97. VOID
  98. KeStartAllProcessors(
  99. VOID
  100. )
  101. /*++
  102. Routine Description:
  103. This function is called during phase 1 initialize on the master boot
  104. processor to start all of the other registered processors.
  105. Arguments:
  106. None.
  107. Return Value:
  108. None.
  109. --*/
  110. {
  111. #if !defined(NT_UP)
  112. ULONG_PTR MemoryBlock;
  113. PUCHAR KernelStack;
  114. PUCHAR PanicStack;
  115. PVOID PoolTagTable;
  116. ULONG_PTR PcrAddress;
  117. ULONG Number;
  118. ULONG Count;
  119. PHYSICAL_ADDRESS PcrPage;
  120. BOOLEAN Started;
  121. KPROCESSOR_STATE ProcessorState;
  122. UCHAR NodeNumber = 0;
  123. USHORT ProcessorId;
  124. PKNODE Node;
  125. NTSTATUS Status;
  126. PKPCR NewPcr;
  127. #if defined(KE_MULTINODE)
  128. //
  129. // In the unlikely event that processor 0 is not on node
  130. // 0, fix it.
  131. //
  132. if (KeNumberNodes > 1) {
  133. Status = KiQueryProcessorNode(0,
  134. &ProcessorId,
  135. &NodeNumber);
  136. if (NT_SUCCESS(Status)) {
  137. //
  138. // Adjust the data structures to reflect that P0 is not on Node 0.
  139. //
  140. if (NodeNumber != 0) {
  141. ASSERT(KeNodeBlock[0] == &KiNode0);
  142. KeNodeBlock[0]->ProcessorMask &= ~1I64;
  143. KiNodeInit[0] = *KeNodeBlock[0];
  144. KeNodeBlock[0] = &KiNodeInit[0];
  145. KiNode0 = *KeNodeBlock[NodeNumber];
  146. KeNodeBlock[NodeNumber] = &KiNode0;
  147. KeNodeBlock[NodeNumber]->ProcessorMask |= 1;
  148. }
  149. KeGetCurrentPrcb()->ProcessorId = ProcessorId;
  150. }
  151. }
  152. #endif
  153. //
  154. // If the registered number of processors is greater than the maximum
  155. // number of processors supported, then only allow the maximum number
  156. // of supported processors.
  157. //
  158. if (KeRegisteredProcessors > MAXIMUM_PROCESSORS) {
  159. KeRegisteredProcessors = MAXIMUM_PROCESSORS;
  160. }
  161. //
  162. // Set barrier that will prevent any other processor from entering the
  163. // idle loop until all processors have been started.
  164. //
  165. KiBarrierWait = 1;
  166. //
  167. // Initialize the processor state that will be used to start each of
  168. // processors. Each processor starts in the system initialization code
  169. // with address of the loader parameter block as an argument.
  170. //
  171. Number = 0;
  172. Count = 1;
  173. RtlZeroMemory(&ProcessorState, sizeof(KPROCESSOR_STATE));
  174. ProcessorState.ContextFrame.StIIP = ((PPLABEL_DESCRIPTOR)(ULONG_PTR)KiOSRendezvous)->EntryPoint;
  175. while (Count < KeRegisteredProcessors) {
  176. Number++;
  177. if (Number >= MAXIMUM_PROCESSORS) {
  178. break;
  179. }
  180. #if defined(KE_MULTINODE)
  181. Status = KiQueryProcessorNode(Number,
  182. &ProcessorId,
  183. &NodeNumber);
  184. if (!NT_SUCCESS(Status)) {
  185. //
  186. // No such processor, advance to next.
  187. //
  188. continue;
  189. }
  190. Node = KeNodeBlock[NodeNumber];
  191. #endif
  192. //
  193. // Allocate idle thread kernel stack and panic stacks
  194. //
  195. KernelStack = MmCreateKernelStack(FALSE, NodeNumber);
  196. PanicStack = MmCreateKernelStack(FALSE, NodeNumber);
  197. //
  198. // Allocate block containing PCR page, processor block, KNODE and an
  199. // executive thread object. If any allocation fails, stop
  200. // starting processors.
  201. //
  202. MemoryBlock = (ULONG_PTR)MmAllocateIndependentPages(BLOCK_SIZE, NodeNumber);
  203. //
  204. // Allocate a pool tag table for the new processor.
  205. //
  206. PoolTagTable = ExCreatePoolTagTable (Number, NodeNumber);
  207. if ((KernelStack == NULL) ||
  208. (PanicStack == NULL) ||
  209. (MemoryBlock == 0) ||
  210. (PoolTagTable == NULL)) {
  211. if (PoolTagTable) {
  212. ExDeletePoolTagTable(Number);
  213. }
  214. if (MemoryBlock) {
  215. MmFreeIndependentPages((PUCHAR) MemoryBlock, BLOCK_SIZE);
  216. }
  217. if (PanicStack) {
  218. MmDeleteKernelStack(PanicStack, FALSE);
  219. }
  220. if (KernelStack) {
  221. MmDeleteKernelStack(KernelStack, FALSE);
  222. }
  223. break;
  224. }
  225. RtlZeroMemory((PVOID)MemoryBlock, BLOCK_SIZE);
  226. //
  227. // Set address of idle thread kernel stack in loader parameter block.
  228. //
  229. KeLoaderBlock->KernelStack = (ULONG_PTR) KernelStack;
  230. //
  231. // Set address of panic stack in loader parameter block.
  232. //
  233. KeLoaderBlock->u.Ia64.PanicStack = (ULONG_PTR) PanicStack;
  234. //
  235. // Set the address of the processor block and executive thread in the
  236. // loader parameter block.
  237. //
  238. KeLoaderBlock->Prcb = MemoryBlock + PAGE_SIZE;
  239. KeLoaderBlock->Thread = KeLoaderBlock->Prcb + ROUND_UP(KPRCB) +
  240. ROUND_UP(KNODE);
  241. ((PKPRCB)KeLoaderBlock->Prcb)->Number = (UCHAR)Number;
  242. #if defined(KE_MULTINODE)
  243. //
  244. // If this is the first processor on this node, use the
  245. // space allocated for KNODE as the KNODE.
  246. //
  247. if (KeNodeBlock[NodeNumber] == &KiNodeInit[NodeNumber]) {
  248. Node = (PKNODE)(KeLoaderBlock->Prcb + ROUND_UP(KPRCB));
  249. *Node = KiNodeInit[NodeNumber];
  250. KeNodeBlock[NodeNumber] = Node;
  251. }
  252. ((PKPRCB)KeLoaderBlock->Prcb)->ParentNode = Node;
  253. ((PKPRCB)KeLoaderBlock->Prcb)->ProcessorId = ProcessorId;
  254. #else
  255. ((PKPRCB)KeLoaderBlock->Prcb)->ParentNode = KeNodeBlock[0];
  256. #endif
  257. //
  258. // Set the page frame of the PCR page in the loader parameter block.
  259. //
  260. PcrAddress = MemoryBlock;
  261. PcrPage = MmGetPhysicalAddress((PVOID)PcrAddress);
  262. KeLoaderBlock->u.Ia64.PcrPage = PcrPage.QuadPart >> PAGE_SHIFT;
  263. KeLoaderBlock->u.Ia64.PcrPage2 = KiUserSharedDataPage;
  264. KiKernelPcrPage = KeLoaderBlock->u.Ia64.PcrPage;
  265. //
  266. // Initialize the NT page table base addresses in PCR
  267. //
  268. NewPcr = (PKPCR) PcrAddress;
  269. NewPcr->PteUbase = PCR->PteUbase;
  270. NewPcr->PteKbase = PCR->PteKbase;
  271. NewPcr->PteSbase = PCR->PteSbase;
  272. NewPcr->PdeUbase = PCR->PdeUbase;
  273. NewPcr->PdeKbase = PCR->PdeKbase;
  274. NewPcr->PdeSbase = PCR->PdeSbase;
  275. NewPcr->PdeUtbase = PCR->PdeUtbase;
  276. NewPcr->PdeKtbase = PCR->PdeKtbase;
  277. NewPcr->PdeStbase = PCR->PdeStbase;
  278. //
  279. // Attempt to start the next processor. If attempt is successful,
  280. // then wait for the processor to get initialized. Otherwise,
  281. // deallocate the processor resources and terminate the loop.
  282. //
  283. Started = HalStartNextProcessor(KeLoaderBlock, &ProcessorState);
  284. if (Started) {
  285. //
  286. // Wait for processor to initialize in kernel,
  287. // then loop for another
  288. //
  289. while (*((volatile ULONG_PTR *) &KeLoaderBlock->Prcb) != 0) {
  290. KeYieldProcessor();
  291. }
  292. #if defined(KE_MULTINODE)
  293. Node->ProcessorMask |= 1I64 << Number;
  294. #endif
  295. } else {
  296. ExDeletePoolTagTable(Number);
  297. MmFreeIndependentPages((PUCHAR) MemoryBlock, BLOCK_SIZE);
  298. MmDeleteKernelStack(PanicStack, FALSE);
  299. MmDeleteKernelStack(KernelStack, FALSE);
  300. break;
  301. }
  302. Count += 1;
  303. }
  304. //
  305. // All processors have been stated.
  306. //
  307. KiAllProcessorsStarted();
  308. //
  309. // Allow all processor that were started to enter the idle loop and
  310. // begin execution.
  311. //
  312. KiBarrierWait = 0;
  313. #endif
  314. //
  315. // Reset and synchronize the performance counters of all processors.
  316. //
  317. KeAdjustInterruptTime (0);
  318. return;
  319. }
  320. #if !defined(NT_UP)
  321. VOID
  322. KiAllProcessorsStarted(
  323. VOID
  324. )
  325. /*++
  326. Routine Description:
  327. This routine is called once all processors in the system
  328. have been started.
  329. Arguments:
  330. None.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. ULONG i;
  336. #if defined(KE_MULTINODE)
  337. //
  338. // Make sure there are no references to the temporary nodes
  339. // used during initialization.
  340. //
  341. for (i = 0; i < KeNumberNodes; i++) {
  342. if (KeNodeBlock[i] == &KiNodeInit[i]) {
  343. //
  344. // No processor started on this node so no new node
  345. // structure has been allocated. This is possible
  346. // if the node contains only memory or IO busses. At
  347. // this time we need to allocate a permanent node
  348. // structure for the node.
  349. //
  350. KeNodeBlock[i] = ExAllocatePoolWithTag(NonPagedPool,
  351. sizeof(KNODE),
  352. ' eK');
  353. if (KeNodeBlock[i]) {
  354. *KeNodeBlock[i] = KiNodeInit[i];
  355. }
  356. }
  357. //
  358. // Set the node number.
  359. //
  360. KeNodeBlock[i]->NodeNumber = (UCHAR)i;
  361. }
  362. for (i = KeNumberNodes; i < MAXIMUM_CCNUMA_NODES; i++) {
  363. KeNodeBlock[i] = NULL;
  364. }
  365. #endif
  366. if (KeNumberNodes == 1) {
  367. //
  368. // For Non NUMA machines, Node 0 gets all processors.
  369. //
  370. KeNodeBlock[0]->ProcessorMask = KeActiveProcessors;
  371. }
  372. }
  373. #endif
  374. #if defined(KE_MULTINODE)
  375. NTSTATUS
  376. KiNotNumaQueryProcessorNode(
  377. IN ULONG ProcessorNumber,
  378. OUT PUSHORT Identifier,
  379. OUT PUCHAR Node
  380. )
  381. /*++
  382. Routine Description:
  383. This routine is a stub used on non NUMA systems to provide a
  384. consistent method of determining the NUMA configuration rather
  385. than checking for the presense of multiple nodes inline.
  386. Arguments:
  387. ProcessorNumber supplies the system logical processor number.
  388. Identifier supplies the address of a variable to receive
  389. the unique identifier for this processor.
  390. NodeNumber supplies the address of a variable to receive
  391. the number of the node this processor resides on.
  392. Return Value:
  393. Returns success.
  394. --*/
  395. {
  396. *Identifier = (USHORT)ProcessorNumber;
  397. *Node = 0;
  398. return STATUS_SUCCESS;
  399. }
  400. #endif
  401. #ifdef ALLOC_DATA_PRAGMA
  402. #pragma data_seg()
  403. #endif