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.

573 lines
14 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. kiinit.c
  5. Abstract:
  6. This module implements architecture independent kernel initialization.
  7. Author:
  8. David N. Cutler 11-May-1993
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. //
  15. // External data.
  16. //
  17. extern KSPIN_LOCK AfdWorkQueueSpinLock;
  18. extern KSPIN_LOCK CcBcbSpinLock;
  19. extern KSPIN_LOCK CcMasterSpinLock;
  20. extern KSPIN_LOCK CcVacbSpinLock;
  21. extern KSPIN_LOCK CcWorkQueueSpinLock;
  22. extern KSPIN_LOCK IopCancelSpinLock;
  23. extern KSPIN_LOCK IopCompletionLock;
  24. extern KSPIN_LOCK IopDatabaseLock;
  25. extern KSPIN_LOCK IopVpbSpinLock;
  26. extern KSPIN_LOCK NtfsStructLock;
  27. extern KSPIN_LOCK MmPfnLock;
  28. extern KSPIN_LOCK NonPagedPoolLock;
  29. extern KSPIN_LOCK MmNonPagedPoolLock;
  30. extern KSPIN_LOCK MmSystemSpaceLock;
  31. #if DBG && defined(_IA64_)
  32. extern KSPIN_LOCK KipGlobalAlignmentDatabaseLock;
  33. #endif
  34. //
  35. // Put all code for kernel initialization in the INIT section. It will be
  36. // deallocated by memory management when phase 1 initialization is completed.
  37. //
  38. #pragma alloc_text(INIT, KeInitSystem)
  39. #pragma alloc_text(INIT, KiInitSpinLocks)
  40. #pragma alloc_text(INIT, KiInitSystem)
  41. #pragma alloc_text(INIT, KiComputeReciprocal)
  42. #pragma alloc_text(INIT, KeNumaInitialize)
  43. BOOLEAN
  44. KeInitSystem (
  45. VOID
  46. )
  47. /*++
  48. Routine Description:
  49. This function initializes executive structures implemented by the
  50. kernel.
  51. N.B. This function is only called during phase 1 initialization.
  52. Arguments:
  53. None.
  54. Return Value:
  55. A value of TRUE is returned if initialization is successful. Otherwise,
  56. a value of FALSE is returned.
  57. --*/
  58. {
  59. HANDLE Handle;
  60. ULONG Index;
  61. ULONG Limit;
  62. OBJECT_ATTRIBUTES ObjectAttributes;
  63. PKPRCB Prcb;
  64. NTSTATUS Status;
  65. //
  66. // If threaded DPCs are enabled for the host system, then create a DPC
  67. // thread for each processor.
  68. //
  69. if (KeThreadDpcEnable != FALSE) {
  70. Index = 0;
  71. Limit = (ULONG)KeNumberProcessors;
  72. InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL);
  73. do {
  74. Prcb = KiProcessorBlock[Index];
  75. KeInitializeEvent(&Prcb->DpcEvent, SynchronizationEvent, FALSE);
  76. InitializeListHead(&Prcb->DpcData[DPC_THREADED].DpcListHead);
  77. KeInitializeSpinLock(&Prcb->DpcData[DPC_THREADED].DpcLock);
  78. Prcb->DpcData[DPC_THREADED].DpcQueueDepth = 0;
  79. Status = PsCreateSystemThread(&Handle,
  80. THREAD_ALL_ACCESS,
  81. &ObjectAttributes,
  82. NULL,
  83. NULL,
  84. KiExecuteDpc,
  85. Prcb);
  86. if (!NT_SUCCESS(Status)) {
  87. return FALSE;
  88. }
  89. ZwClose(Handle);
  90. Index += 1;
  91. } while (Index < Limit);
  92. }
  93. //
  94. // Perform platform dependent initialization.
  95. //
  96. return KiInitMachineDependent();
  97. }
  98. VOID
  99. KiInitSpinLocks (
  100. PKPRCB Prcb,
  101. ULONG Number
  102. )
  103. /*++
  104. Routine Description:
  105. This function initializes the spinlock structures in the per processor
  106. PRCB. This function is called once for each processor.
  107. Arguments:
  108. Prcb - Supplies a pointer to a PRCB.
  109. Number - Supplies the number of respective processor.
  110. Return Value:
  111. None.
  112. --*/
  113. {
  114. ULONG Index;
  115. //
  116. // Initialize dispatcher ready queue list heads, the ready summary, and
  117. // the deferred ready list head.
  118. //
  119. Prcb->ReadySummary = 0;
  120. Prcb->DeferredReadyListHead.Next = NULL;
  121. for (Index = 0; Index < MAXIMUM_PRIORITY; Index += 1) {
  122. InitializeListHead(&Prcb->DispatcherReadyListHead[Index]);
  123. }
  124. //
  125. // Initialize the normal DPC data.
  126. //
  127. InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
  128. KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
  129. Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
  130. Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
  131. Prcb->DpcRoutineActive = 0;
  132. Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
  133. Prcb->MinimumDpcRate = KiMinimumDpcRate;
  134. Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
  135. //
  136. // Initialize the generic call DPC structure, set the target processor
  137. // number, and set the DPC importance.
  138. //
  139. KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
  140. KeSetTargetProcessorDpc(&Prcb->CallDpc, (CCHAR)Number);
  141. KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
  142. //
  143. // Initialize wait list.
  144. //
  145. InitializeListHead(&Prcb->WaitListHead);
  146. //
  147. // Initialize queued spinlock structures.
  148. //
  149. Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
  150. Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
  151. Prcb->LockQueue[LockQueueUnusedSpare1].Next = NULL;
  152. Prcb->LockQueue[LockQueueUnusedSpare1].Lock = NULL;
  153. Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
  154. Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
  155. Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
  156. Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
  157. Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
  158. Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
  159. Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
  160. Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
  161. Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
  162. Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
  163. Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
  164. Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
  165. Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
  166. Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
  167. Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
  168. Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
  169. Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
  170. Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
  171. Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
  172. Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
  173. Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
  174. Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
  175. Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
  176. Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
  177. Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
  178. Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
  179. Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
  180. Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
  181. //
  182. // Initialize processor control block lock.
  183. //
  184. KeInitializeSpinLock(&Prcb->PrcbLock);
  185. //
  186. // If this is processor zero, then also initialize the queued spin lock
  187. // home address.
  188. //
  189. if (Number == 0) {
  190. KeInitializeSpinLock(&KiDispatcherLock);
  191. KeInitializeSpinLock(&KiReverseStallIpiLock);
  192. KeInitializeSpinLock(&MmPfnLock);
  193. KeInitializeSpinLock(&MmSystemSpaceLock);
  194. KeInitializeSpinLock(&CcBcbSpinLock);
  195. KeInitializeSpinLock(&CcMasterSpinLock);
  196. KeInitializeSpinLock(&CcVacbSpinLock);
  197. KeInitializeSpinLock(&CcWorkQueueSpinLock);
  198. KeInitializeSpinLock(&IopCancelSpinLock);
  199. KeInitializeSpinLock(&IopCompletionLock);
  200. KeInitializeSpinLock(&IopDatabaseLock);
  201. KeInitializeSpinLock(&IopVpbSpinLock);
  202. KeInitializeSpinLock(&NonPagedPoolLock);
  203. KeInitializeSpinLock(&MmNonPagedPoolLock);
  204. KeInitializeSpinLock(&NtfsStructLock);
  205. KeInitializeSpinLock(&AfdWorkQueueSpinLock);
  206. }
  207. return;
  208. }
  209. VOID
  210. KiInitSystem (
  211. VOID
  212. )
  213. /*++
  214. Routine Description:
  215. This function initializes architecture independent kernel structures.
  216. N.B. This function is only called on processor 0.
  217. Arguments:
  218. None.
  219. Return Value:
  220. None.
  221. --*/
  222. {
  223. ULONG Index;
  224. //
  225. // Initialize bug check callback listhead and spinlock.
  226. //
  227. InitializeListHead(&KeBugCheckCallbackListHead);
  228. InitializeListHead(&KeBugCheckReasonCallbackListHead);
  229. KeInitializeSpinLock(&KeBugCheckCallbackLock);
  230. //
  231. // Initialize the timer expiration DPC object and set the destination
  232. // processor to processor zero.
  233. //
  234. KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
  235. KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0);
  236. //
  237. // Initialize the profile listhead and profile locks
  238. //
  239. KeInitializeSpinLock(&KiProfileLock);
  240. InitializeListHead(&KiProfileListHead);
  241. //
  242. // Initialize the global alignment fault database lock
  243. //
  244. #if DBG && defined(_IA64_)
  245. KeInitializeSpinLock(&KipGlobalAlignmentDatabaseLock);
  246. #endif
  247. //
  248. // Initialize the active profile source listhead.
  249. //
  250. InitializeListHead(&KiProfileSourceListHead);
  251. //
  252. // Initialize the timer table, the timer completion listhead, and the
  253. // timer completion DPC.
  254. //
  255. for (Index = 0; Index < TIMER_TABLE_SIZE; Index += 1) {
  256. InitializeListHead(&KiTimerTableListHead[Index]);
  257. }
  258. //
  259. // Initialize the swap event, the process inswap listhead, the
  260. // process outswap listhead, and the kernel stack inswap listhead.
  261. //
  262. KeInitializeEvent(&KiSwapEvent,
  263. SynchronizationEvent,
  264. FALSE);
  265. KiProcessInSwapListHead.Next = NULL;
  266. KiProcessOutSwapListHead.Next = NULL;
  267. KiStackInSwapListHead.Next = NULL;
  268. //
  269. // Initialize the generic DPC call fast mutex.
  270. //
  271. ExInitializeFastMutex(&KiGenericCallDpcMutex);
  272. //
  273. // Initialize the system service descriptor table.
  274. //
  275. KeServiceDescriptorTable[0].Base = &KiServiceTable[0];
  276. KeServiceDescriptorTable[0].Count = NULL;
  277. KeServiceDescriptorTable[0].Limit = KiServiceLimit;
  278. //
  279. // The global pointer associated with the table base is placed just
  280. // before the service table on the ia64.
  281. //
  282. #if defined(_IA64_)
  283. KeServiceDescriptorTable[0].TableBaseGpOffset =
  284. (LONG)(*(KiServiceTable-1) - (ULONG_PTR)KiServiceTable);
  285. #endif
  286. KeServiceDescriptorTable[0].Number = &KiArgumentTable[0];
  287. for (Index = 1; Index < NUMBER_SERVICE_TABLES; Index += 1) {
  288. KeServiceDescriptorTable[Index].Limit = 0;
  289. }
  290. //
  291. // Copy the system service descriptor table to the shadow table
  292. // which is used to record the Win32 system services.
  293. //
  294. RtlCopyMemory(KeServiceDescriptorTableShadow,
  295. KeServiceDescriptorTable,
  296. sizeof(KeServiceDescriptorTable));
  297. //
  298. // Initialize call performance data structures.
  299. //
  300. #if defined(_COLLECT_FLUSH_SINGLE_CALLDATA_)
  301. ExInitializeCallData(&KiFlushSingleCallData);
  302. #endif
  303. #if defined(_COLLECT_SET_EVENT_CALLDATA_)
  304. ExInitializeCallData(&KiSetEventCallData);
  305. #endif
  306. #if defined(_COLLECT_WAIT_SINGLE_CALLDATA_)
  307. ExInitializeCallData(&KiWaitSingleCallData);
  308. #endif
  309. return;
  310. }
  311. LARGE_INTEGER
  312. KiComputeReciprocal (
  313. IN LONG Divisor,
  314. OUT PCCHAR Shift
  315. )
  316. /*++
  317. Routine Description:
  318. This function computes the large integer reciprocal of the specified
  319. value.
  320. Arguments:
  321. Divisor - Supplies the value for which the large integer reciprocal is
  322. computed.
  323. Shift - Supplies a pointer to a variable that receives the computed
  324. shift count.
  325. Return Value:
  326. The large integer reciprocal is returned as the fucntion value.
  327. --*/
  328. {
  329. LARGE_INTEGER Fraction;
  330. LONG NumberBits;
  331. LONG Remainder;
  332. //
  333. // Compute the large integer reciprocal of the specified value.
  334. //
  335. NumberBits = 0;
  336. Remainder = 1;
  337. Fraction.LowPart = 0;
  338. Fraction.HighPart = 0;
  339. while (Fraction.HighPart >= 0) {
  340. NumberBits += 1;
  341. Fraction.HighPart = (Fraction.HighPart << 1) | (Fraction.LowPart >> 31);
  342. Fraction.LowPart <<= 1;
  343. Remainder <<= 1;
  344. if (Remainder >= Divisor) {
  345. Remainder -= Divisor;
  346. Fraction.LowPart |= 1;
  347. }
  348. }
  349. if (Remainder != 0) {
  350. if ((Fraction.LowPart == 0xffffffff) && (Fraction.HighPart == 0xffffffff)) {
  351. Fraction.LowPart = 0;
  352. Fraction.HighPart = 0x80000000;
  353. NumberBits -= 1;
  354. } else {
  355. if (Fraction.LowPart == 0xffffffff) {
  356. Fraction.LowPart = 0;
  357. Fraction.HighPart += 1;
  358. } else {
  359. Fraction.LowPart += 1;
  360. }
  361. }
  362. }
  363. //
  364. // Compute the shift count value and return the reciprocal fraction.
  365. //
  366. *Shift = (CCHAR)(NumberBits - 64);
  367. return Fraction;
  368. }
  369. VOID
  370. KeNumaInitialize (
  371. VOID
  372. )
  373. /*++
  374. Routine Description:
  375. Initialize ntos kernel structures needed to support NUMA.
  376. Arguments:
  377. None.
  378. Return Value:
  379. None.
  380. --*/
  381. {
  382. #if defined(KE_MULTINODE)
  383. NTSTATUS Status;
  384. HAL_NUMA_TOPOLOGY_INTERFACE HalNumaInfo;
  385. ULONG ReturnedLength;
  386. extern PHALNUMAQUERYPROCESSORNODE KiQueryProcessorNode;
  387. extern PHALNUMAPAGETONODE MmPageToNode;
  388. Status = HalQuerySystemInformation (HalNumaTopologyInterface,
  389. sizeof(HalNumaInfo),
  390. &HalNumaInfo,
  391. &ReturnedLength);
  392. if (NT_SUCCESS(Status)) {
  393. ASSERT (ReturnedLength == sizeof(HalNumaInfo));
  394. ASSERT (HalNumaInfo.NumberOfNodes <= MAXIMUM_CCNUMA_NODES);
  395. ASSERT (HalNumaInfo.QueryProcessorNode);
  396. ASSERT (HalNumaInfo.PageToNode);
  397. if (HalNumaInfo.NumberOfNodes > 1) {
  398. KeNumberNodes = (UCHAR)HalNumaInfo.NumberOfNodes;
  399. MmPageToNode = HalNumaInfo.PageToNode;
  400. KiQueryProcessorNode = HalNumaInfo.QueryProcessorNode;
  401. }
  402. }
  403. #endif
  404. }