1
0

init.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. init.c
  9. Abstract:
  10. This module implements the kernel system startup.
  11. Author:
  12. Evan Green 2-Jul-2012
  13. Environment:
  14. Kernel Initialization
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/kernel.h>
  20. #include <minoca/lib/bconf.h>
  21. #include <minoca/kernel/bootload.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // The first row has at max 11 * 4 = 44 characters of value.
  27. // The second row has at max 13 + (4 * 4) + 11 + 11 = 51 characters of value.
  28. //
  29. #define KE_BANNER_FULL_WIDTH 116
  30. #define KE_BANNER_FULL_MEMORY_FORMAT \
  31. "Memory Used/Total: %s Paged Pool: %s Non-Paged Pool: %s Cache: %s"
  32. #define KE_BANNER_FULL_TIME_FORMAT \
  33. "Uptime: %s CPU User: %s Kernel: %s Interrupt: %s Idle: %s IO: %s%s"
  34. #define KE_BANNER_FULL_PAGING_FORMAT " Pg: %s"
  35. #define KE_BANNER_SHORT_WIDTH 80
  36. #define KE_BANNER_SHORT_MEMORY_FORMAT \
  37. "Memory: %s Paged: %s Non-paged: %s Cache: %s"
  38. #define KE_BANNER_SHORT_TIME_FORMAT \
  39. "%s U: %s K: %s In: %s Id: %s IO: %s%s"
  40. #define KE_BANNER_SHORT_PAGING_FORMAT " Pg: %s"
  41. #define KE_BANNER_TINY_WIDTH 40
  42. #define KE_BANNER_TINY_MEMORY_FORMAT "Memory: %s Cache: %s"
  43. #define KE_BANNER_TINY_TIME_FORMAT \
  44. "%s U%s K%s IO:%s"
  45. #define KE_BANNER_TINY_PAGING_FORMAT ""
  46. //
  47. // ------------------------------------------------------ Data Type Definitions
  48. //
  49. typedef enum _KERNEL_SUBSYSTEM {
  50. KernelSubsystemInvalid,
  51. KernelSubsystemKernelDebugger,
  52. KernelSubsystemKernelExecutive,
  53. KernelSubsystemMemoryManager,
  54. KernelSubsystemObjectManager,
  55. KernelSubsystemAcpi,
  56. KernelSubsystemHardwareLayer,
  57. KernelSubsystemProcess,
  58. KernelSubsystemInputOutput,
  59. KernelSubsystemProfiler
  60. } KERNEL_SUBSYSTEM, *PKERNEL_SUBSYSTEM;
  61. typedef struct _SYSTEM_USAGE_CONTEXT {
  62. ULONGLONG TimeCounter;
  63. ULONGLONG TimeCounterFrequency;
  64. ULONGLONG CycleCounterFrequency;
  65. ULONGLONG UserCycles;
  66. ULONGLONG KernelCycles;
  67. ULONGLONG InterruptCycles;
  68. ULONGLONG IdleCycles;
  69. ULONGLONG TotalCycles;
  70. ULONG UserPercent;
  71. ULONG KernelPercent;
  72. ULONG InterruptPercent;
  73. ULONG IdlePercent;
  74. } SYSTEM_USAGE_CONTEXT, *PSYSTEM_USAGE_CONTEXT;
  75. //
  76. // ----------------------------------------------- Internal Function Prototypes
  77. //
  78. VOID
  79. KepApplicationProcessorStartup (
  80. PPROCESSOR_START_BLOCK StartBlock
  81. );
  82. VOID
  83. KepCompleteSystemInitialization (
  84. PVOID Parameter
  85. );
  86. VOID
  87. KepAcquireProcessorStartLock (
  88. VOID
  89. );
  90. VOID
  91. KepReleaseProcessorStartLock (
  92. VOID
  93. );
  94. VOID
  95. KepBannerThread (
  96. PVOID Context
  97. );
  98. VOID
  99. KepUpdateSystemUsage (
  100. PSYSTEM_USAGE_CONTEXT Context
  101. );
  102. VOID
  103. KepPrintFormattedMemoryUsage (
  104. PCHAR String,
  105. ULONG StringSize,
  106. ULONGLONG UsedValue,
  107. ULONGLONG TotalValue
  108. );
  109. ULONG
  110. KepPrintFormattedSize (
  111. PCHAR String,
  112. ULONG StringSize,
  113. ULONGLONG Value
  114. );
  115. ULONG
  116. KepPrintFormattedPercent (
  117. PCHAR String,
  118. ULONG StringSize,
  119. ULONG PercentTimesTen
  120. );
  121. //
  122. // -------------------------------------------------------------------- Globals
  123. //
  124. //
  125. // Define a lock used to serializes parts of the AP startup execution.
  126. //
  127. volatile ULONG KeProcessorStartLock = 0;
  128. volatile ULONG KeProcessorsReady = 0;
  129. volatile BOOL KeAllProcessorsInitialize = FALSE;
  130. volatile BOOL KeAllProcessorsGo = FALSE;
  131. //
  132. // Odd values are off, even values are on.
  133. //
  134. volatile ULONG KeBannerThreadEnabled = 1;
  135. //
  136. // ------------------------------------------------------------------ Functions
  137. //
  138. __USED
  139. VOID
  140. KepStartSystem (
  141. PKERNEL_INITIALIZATION_BLOCK Parameters
  142. )
  143. /*++
  144. Routine Description:
  145. This routine implements the first function called in the kernel from the
  146. boot loader.
  147. Arguments:
  148. Parameters - Supplies information about the system and memory layout as
  149. set up by the loader.
  150. Return Value:
  151. This function does not return.
  152. --*/
  153. {
  154. PBOOT_ENTRY BootEntry;
  155. PDEBUG_DEVICE_DESCRIPTION DebugDevice;
  156. KERNEL_SUBSYSTEM FailingSubsystem;
  157. ULONG ProcessorCount;
  158. KSTATUS Status;
  159. DebugDevice = NULL;
  160. FailingSubsystem = KernelSubsystemInvalid;
  161. //
  162. // Perform very basic processor initialization, preparing it to take
  163. // exceptions and use the serial port.
  164. //
  165. ArInitializeProcessor(FALSE, NULL);
  166. AcpiInitializePreDebugger(Parameters);
  167. Status = MmInitialize(Parameters, NULL, 0);
  168. if (!KSUCCESS(Status)) {
  169. FailingSubsystem = KernelSubsystemMemoryManager;
  170. goto StartSystemEnd;
  171. }
  172. HlInitializePreDebugger(Parameters, 0, &DebugDevice);
  173. //
  174. // Initialize the debugging subsystem.
  175. //
  176. BootEntry = Parameters->BootEntry;
  177. if ((BootEntry != NULL) &&
  178. ((BootEntry->Flags & BOOT_ENTRY_FLAG_DEBUG) != 0)) {
  179. Status = KdInitialize(DebugDevice, Parameters->KernelModule);
  180. if (!KSUCCESS(Status)) {
  181. FailingSubsystem = KernelSubsystemKernelDebugger;
  182. goto StartSystemEnd;
  183. }
  184. }
  185. //
  186. // Initialize the kernel executive.
  187. //
  188. Status = KeInitialize(0, Parameters);
  189. if (!KSUCCESS(Status)) {
  190. FailingSubsystem = KernelSubsystemKernelExecutive;
  191. goto StartSystemEnd;
  192. }
  193. //
  194. // Perform phase 1 MM Initialization.
  195. //
  196. Status = MmInitialize(Parameters, NULL, 1);
  197. if (!KSUCCESS(Status)) {
  198. FailingSubsystem = KernelSubsystemMemoryManager;
  199. goto StartSystemEnd;
  200. }
  201. //
  202. // Initialize the Object Manager.
  203. //
  204. Status = ObInitialize();
  205. if (!KSUCCESS(Status)) {
  206. FailingSubsystem = KernelSubsystemObjectManager;
  207. goto StartSystemEnd;
  208. }
  209. //
  210. // Perform phase 1 executive initialization, which sets up primitives like
  211. // queued locks and events.
  212. //
  213. Status = KeInitialize(1, Parameters);
  214. if (!KSUCCESS(Status)) {
  215. FailingSubsystem = KernelSubsystemKernelExecutive;
  216. goto StartSystemEnd;
  217. }
  218. //
  219. // Initialize ACPI.
  220. //
  221. Status = AcpiInitialize(Parameters);
  222. if (!KSUCCESS(Status)) {
  223. FailingSubsystem = KernelSubsystemAcpi;
  224. goto StartSystemEnd;
  225. }
  226. //
  227. // Initialize the hardware layer.
  228. //
  229. Status = HlInitialize(Parameters, 0);
  230. if (!KSUCCESS(Status)) {
  231. FailingSubsystem = KernelSubsystemHardwareLayer;
  232. goto StartSystemEnd;
  233. }
  234. //
  235. // Initialize the process and thread subsystem.
  236. //
  237. Status = PsInitialize(0,
  238. Parameters,
  239. Parameters->KernelStack.Buffer,
  240. Parameters->KernelStack.Size);
  241. if (!KSUCCESS(Status)) {
  242. FailingSubsystem = KernelSubsystemProcess;
  243. goto StartSystemEnd;
  244. }
  245. //
  246. // Perform phase 1 hardware layer initialization. The scheduler becomes
  247. // active at this point.
  248. //
  249. Status = HlInitialize(Parameters, 1);
  250. if (!KSUCCESS(Status)) {
  251. FailingSubsystem = KernelSubsystemHardwareLayer;
  252. goto StartSystemEnd;
  253. }
  254. //
  255. // Now that the system is multithreaded, lock down MM.
  256. //
  257. Status = MmInitialize(Parameters, NULL, 2);
  258. if (!KSUCCESS(Status)) {
  259. FailingSubsystem = KernelSubsystemMemoryManager;
  260. goto StartSystemEnd;
  261. }
  262. //
  263. // Perform additional process initialization now that MM is fully up.
  264. //
  265. Status = PsInitialize(1, Parameters, NULL, 0);
  266. if (!KSUCCESS(Status)) {
  267. FailingSubsystem = KernelSubsystemProcess;
  268. goto StartSystemEnd;
  269. }
  270. //
  271. // Start all processors. Wait for all processors to initialize before
  272. // allowing the debugger to start broadcasting NMIs.
  273. //
  274. Status = HlStartAllProcessors(KepApplicationProcessorStartup,
  275. &ProcessorCount);
  276. if (!KSUCCESS(Status)) {
  277. FailingSubsystem = KernelSubsystemHardwareLayer;
  278. goto StartSystemEnd;
  279. }
  280. KeAllProcessorsInitialize = TRUE;
  281. RtlAtomicAdd32(&KeProcessorsReady, 1);
  282. while (KeProcessorsReady != ProcessorCount) {
  283. ArProcessorYield();
  284. }
  285. KdEnableNmiBroadcast(TRUE);
  286. //
  287. // Perform phase 2 executive initialization, which creates things like the
  288. // worker threads.
  289. //
  290. Status = KeInitialize(2, Parameters);
  291. if (!KSUCCESS(Status)) {
  292. FailingSubsystem = KernelSubsystemKernelExecutive;
  293. goto StartSystemEnd;
  294. }
  295. //
  296. // Initialize the system profiler subsystem, which will start profiling
  297. // only if early profiling is enabled.
  298. //
  299. Status = SpInitializeProfiler();
  300. if (!KSUCCESS(Status)) {
  301. FailingSubsystem = KernelSubsystemProfiler;
  302. goto StartSystemEnd;
  303. }
  304. //
  305. // Create a thread to continue system initialization that may involve
  306. // blocking, letting this thread become the idle thread. After this point,
  307. // the idle thread really is the idle thread.
  308. //
  309. Status = PsCreateKernelThread(KepCompleteSystemInitialization,
  310. Parameters,
  311. "Init");
  312. if (!KSUCCESS(Status)) {
  313. goto StartSystemEnd;
  314. }
  315. //
  316. // Boot mappings will be freed by the thread just kicked off, so the
  317. // parameters are now untouchable.
  318. //
  319. Parameters = NULL;
  320. StartSystemEnd:
  321. if (!KSUCCESS(Status)) {
  322. KeVideoPrintString(0, 14, "Kernel Failure: 0x");
  323. KeVideoPrintHexInteger(18, 14, Status);
  324. KeVideoPrintString(0, 15, "Subsystem: ");
  325. KeVideoPrintInteger(11, 15, FailingSubsystem);
  326. KeCrashSystem(CRASH_SYSTEM_INITIALIZATION_FAILURE,
  327. FailingSubsystem,
  328. Status,
  329. 0,
  330. 0);
  331. }
  332. //
  333. // Drop into the idle loop.
  334. //
  335. KeIdleLoop();
  336. return;
  337. }
  338. VOID
  339. KepApplicationProcessorStartup (
  340. PPROCESSOR_START_BLOCK StartBlock
  341. )
  342. /*++
  343. Routine Description:
  344. This routine implements the main initialization routine for processors
  345. other than P0.
  346. Arguments:
  347. StartBlock - Supplies a pointer to the processor start block that contains
  348. this processor's initialization information.
  349. Return Value:
  350. This function does not return, this thread eventually becomes the idle
  351. thread.
  352. --*/
  353. {
  354. KSTATUS Status;
  355. //
  356. // Mark the core as started.
  357. //
  358. StartBlock->Started = TRUE;
  359. RtlMemoryBarrier();
  360. //
  361. // Wait here until P0 says it's okay to initialize. This barrier allows
  362. // all processors to get out of the stub code as quickly as possible and
  363. // not have to worry about contending for non-paged pool locks while
  364. // allocating an idle stack.
  365. //
  366. while (KeAllProcessorsInitialize == FALSE) {
  367. ArProcessorYield();
  368. }
  369. KepAcquireProcessorStartLock();
  370. ArInitializeProcessor(FALSE, StartBlock->ProcessorStructures);
  371. //
  372. // Initialize the kernel executive.
  373. //
  374. Status = KeInitialize(0, NULL);
  375. if (!KSUCCESS(Status)) {
  376. goto ApplicationProcessorStartupEnd;
  377. }
  378. //
  379. // Perform phase 1 MM Initialization.
  380. //
  381. Status = MmInitialize(NULL, StartBlock, 1);
  382. if (!KSUCCESS(Status)) {
  383. goto ApplicationProcessorStartupEnd;
  384. }
  385. //
  386. // Perform phase 1 executive initialization.
  387. //
  388. Status = KeInitialize(1, NULL);
  389. if (!KSUCCESS(Status)) {
  390. goto ApplicationProcessorStartupEnd;
  391. }
  392. //
  393. // Initialize the hardware layer. The clock interrupt becomes active at
  394. // this point. As a result, this routine raises the run level from low to
  395. // dispatch to prevent the scheduler from becoming active before the
  396. // process and thread subsystem is initialized.
  397. //
  398. Status = HlInitialize(NULL, 0);
  399. if (!KSUCCESS(Status)) {
  400. goto ApplicationProcessorStartupEnd;
  401. }
  402. //
  403. // Initialize the process and thread subsystem.
  404. //
  405. Status = PsInitialize(0,
  406. NULL,
  407. StartBlock->StackBase,
  408. StartBlock->StackSize);
  409. if (!KSUCCESS(Status)) {
  410. goto ApplicationProcessorStartupEnd;
  411. }
  412. //
  413. // Perform phase 1 hardware layer initialization.
  414. //
  415. Status = HlInitialize(NULL, 1);
  416. if (!KSUCCESS(Status)) {
  417. goto ApplicationProcessorStartupEnd;
  418. }
  419. ApplicationProcessorStartupEnd:
  420. KeFreeProcessorStartBlock(StartBlock, FALSE);
  421. KepReleaseProcessorStartLock();
  422. StartBlock = NULL;
  423. //
  424. // On failure, take the system down.
  425. //
  426. if (!KSUCCESS(Status)) {
  427. KeCrashSystem(CRASH_SYSTEM_INITIALIZATION_FAILURE,
  428. KeGetCurrentProcessorNumber(),
  429. Status,
  430. 0,
  431. 0);
  432. }
  433. //
  434. // Wait until all processors are ready, and drop down to low level.
  435. //
  436. RtlAtomicAdd32(&KeProcessorsReady, 1);
  437. while (KeAllProcessorsGo == FALSE) {
  438. ArProcessorYield();
  439. }
  440. KeLowerRunLevel(RunLevelLow);
  441. KeIdleLoop();
  442. return;
  443. }
  444. KSTATUS
  445. KepSetBannerThread (
  446. PVOID Data,
  447. PUINTN DataSize,
  448. BOOL Set
  449. )
  450. /*++
  451. Routine Description:
  452. This routine enables or disables the banner thread.
  453. Arguments:
  454. Data - Supplies a pointer to the data buffer where the data is either
  455. returned for a get operation or given for a set operation.
  456. DataSize - Supplies a pointer that on input contains the size of the
  457. data buffer. On output, contains the required size of the data buffer.
  458. Set - Supplies a boolean indicating if this is a get operation (FALSE) or
  459. a set operation (TRUE).
  460. Return Value:
  461. Status code.
  462. --*/
  463. {
  464. ULONG PreviousValue;
  465. KSTATUS Status;
  466. PULONG Value;
  467. if (*DataSize < sizeof(ULONG)) {
  468. *DataSize = sizeof(ULONG);
  469. return STATUS_BUFFER_TOO_SMALL;
  470. }
  471. Value = Data;
  472. *DataSize = sizeof(ULONG);
  473. if (Set == FALSE) {
  474. *Value = (KeBannerThreadEnabled & 0x1) != FALSE;
  475. return STATUS_SUCCESS;
  476. }
  477. //
  478. // This is privileged because there's no reason random users should be
  479. // doing it. Also since the threads linger hammering on this could lead to
  480. // resource exhaustion.
  481. //
  482. Status = PsCheckPermission(PERMISSION_SYSTEM_ADMINISTRATOR);
  483. if (!KSUCCESS(Status)) {
  484. return Status;
  485. }
  486. //
  487. // Loop increasing the generation number until the correct edge is
  488. // performed.
  489. //
  490. while (TRUE) {
  491. PreviousValue = KeBannerThreadEnabled;
  492. //
  493. // If the current value agrees with what the user wants, then break out.
  494. //
  495. if ((PreviousValue & 0x1) == (*Value != FALSE)) {
  496. break;
  497. }
  498. //
  499. // Bump the generation, which will hopefully make the desired
  500. // transition, but might end up doing the opposite if multiple threads
  501. // are in here.
  502. //
  503. PreviousValue = RtlAtomicAdd32(&KeBannerThreadEnabled, 1);
  504. //
  505. // Handle the thread previously being on (ie this turned it off). If the
  506. // user wanted it off, then great. Otherwise, loop again to try and
  507. // turn it back on.
  508. //
  509. if ((PreviousValue & 0x1) != 0) {
  510. if (*Value == FALSE) {
  511. break;
  512. }
  513. //
  514. // This action just turned it on. If the user wanted it on, then great,
  515. // create the thread. Otherwise, loop again to try and turn it off.
  516. //
  517. } else {
  518. if (*Value != FALSE) {
  519. Status = PsCreateKernelThread(KepBannerThread,
  520. (PVOID)(UINTN)(PreviousValue + 1),
  521. "KepBannerThread");
  522. break;
  523. }
  524. }
  525. }
  526. *Value = (PreviousValue & 0x1) != FALSE;
  527. return Status;
  528. }
  529. //
  530. // --------------------------------------------------------- Internal Functions
  531. //
  532. VOID
  533. KepCompleteSystemInitialization (
  534. PVOID Parameter
  535. )
  536. /*++
  537. Routine Description:
  538. This routine completes initial kernel startup. It is performed on a
  539. separate thread to allow the startup thread to mature into the idle thread
  540. before blocking work starts. There is no guarantee that this routine will
  541. be executed exclusively on any one processor, the scheduler and all
  542. processors are active at this point.
  543. Arguments:
  544. Parameter - Supplies information about the system and memory layout as
  545. set up by the loader, the kernel initialization block.
  546. Return Value:
  547. None.
  548. --*/
  549. {
  550. KERNEL_SUBSYSTEM FailingSubsystem;
  551. PKERNEL_INITIALIZATION_BLOCK Parameters;
  552. KSTATUS Status;
  553. FailingSubsystem = KernelSubsystemInvalid;
  554. Parameters = (PKERNEL_INITIALIZATION_BLOCK)Parameter;
  555. //
  556. // Let all processors idle.
  557. //
  558. KeAllProcessorsGo = TRUE;
  559. //
  560. // Perform phase 0 initialization of the I/O subsystem, which will
  561. // initialize boot start drivers.
  562. //
  563. Status = IoInitialize(0, Parameters);
  564. if (!KSUCCESS(Status)) {
  565. FailingSubsystem = KernelSubsystemInputOutput;
  566. goto CompleteSystemInitializationEnd;
  567. }
  568. //
  569. // Perform phase 3 executive initialization, which signs up for entropy
  570. // interface notifications.
  571. //
  572. Status = KeInitialize(3, NULL);
  573. if (!KSUCCESS(Status)) {
  574. FailingSubsystem = KernelSubsystemKernelExecutive;
  575. goto CompleteSystemInitializationEnd;
  576. }
  577. //
  578. // Perform phase 3 initialization of the memory manager, which completes
  579. // initialization by freeing all boot allocations. From here on out, the
  580. // parameters pointer is inaccessible.
  581. //
  582. Status = MmInitialize(Parameters, NULL, 3);
  583. if (!KSUCCESS(Status)) {
  584. FailingSubsystem = KernelSubsystemMemoryManager;
  585. goto CompleteSystemInitializationEnd;
  586. }
  587. //
  588. // Fire up the banner thread.
  589. //
  590. if ((KeBannerThreadEnabled & 0x1) != 0) {
  591. PsCreateKernelThread(KepBannerThread,
  592. (PVOID)(UINTN)KeBannerThreadEnabled,
  593. "KepBannerThread");
  594. }
  595. CompleteSystemInitializationEnd:
  596. if (!KSUCCESS(Status)) {
  597. KeVideoPrintString(0, 24, "Failure: 0x");
  598. KeVideoPrintHexInteger(11, 24, Status);
  599. KeCrashSystem(CRASH_SYSTEM_INITIALIZATION_FAILURE,
  600. FailingSubsystem,
  601. Status,
  602. 0,
  603. 0);
  604. }
  605. return;
  606. }
  607. VOID
  608. KepAcquireProcessorStartLock (
  609. VOID
  610. )
  611. /*++
  612. Routine Description:
  613. This routine acquires the processor start lock.
  614. Arguments:
  615. None.
  616. Return Value:
  617. None.
  618. --*/
  619. {
  620. ULONG LockValue;
  621. while (TRUE) {
  622. LockValue = RtlAtomicCompareExchange32(&KeProcessorStartLock, 1, 0);
  623. if (LockValue == 0) {
  624. break;
  625. }
  626. ArProcessorYield();
  627. }
  628. return;
  629. }
  630. VOID
  631. KepReleaseProcessorStartLock (
  632. VOID
  633. )
  634. /*++
  635. Routine Description:
  636. This routine releases the processor start lock.
  637. Arguments:
  638. None.
  639. Return Value:
  640. None.
  641. --*/
  642. {
  643. ULONG LockValue;
  644. LockValue = RtlAtomicExchange32(&KeProcessorStartLock, 0);
  645. //
  646. // Assert if the lock was not held.
  647. //
  648. ASSERT(LockValue != 0);
  649. return;
  650. }
  651. VOID
  652. KepBannerThread (
  653. PVOID Context
  654. )
  655. /*++
  656. Routine Description:
  657. This routine prints an updated banner at the top of the screen.
  658. Arguments:
  659. Context - Supplies a context pointer, which in this case is a generation
  660. number. If the generation number changes from this, the thread exits.
  661. Return Value:
  662. None.
  663. --*/
  664. {
  665. CHAR BannerString[120];
  666. IO_CACHE_STATISTICS Cache;
  667. CHAR CacheString[16];
  668. ULONG CellHeight;
  669. ULONG Columns;
  670. CHAR CpuIdleString[16];
  671. CHAR CpuInterruptString[16];
  672. CHAR CpuKernelString[16];
  673. CHAR CpuUserString[16];
  674. ULONGLONG Days;
  675. ULONGLONG Frequency;
  676. ULONGLONG Hours;
  677. IO_GLOBAL_STATISTICS IoStatistics;
  678. CHAR IoString[16];
  679. MM_STATISTICS Memory;
  680. PSTR MemoryFormat;
  681. ULONGLONG Minutes;
  682. CHAR NonPagedPoolString[16];
  683. CHAR PagedPoolString[16];
  684. ULONG PageShift;
  685. PSTR PagingFormat;
  686. CHAR PagingString[24];
  687. CHAR PagingValueString[16];
  688. IO_GLOBAL_STATISTICS PreviousIoStatistics;
  689. ULONGLONG ReadDifference;
  690. ULONG Rows;
  691. ULONGLONG Seconds;
  692. ULONG Size;
  693. KSTATUS Status;
  694. ULONGLONG TimeCounter;
  695. PSTR TimeFormat;
  696. PKTIMER Timer;
  697. TIMER_QUEUE_TYPE TimerQueueType;
  698. CHAR TotalMemoryString[16];
  699. CHAR UptimeString[16];
  700. SYSTEM_USAGE_CONTEXT UsageContext;
  701. UINTN UsedSize;
  702. ULONG Width;
  703. ULONGLONG WriteDifference;
  704. Frequency = HlQueryTimeCounterFrequency();
  705. PageShift = MmPageShift();
  706. RtlZeroMemory(&Memory, sizeof(MM_STATISTICS));
  707. RtlZeroMemory(&Cache, sizeof(IO_CACHE_STATISTICS));
  708. RtlZeroMemory(&UsageContext, sizeof(SYSTEM_USAGE_CONTEXT));
  709. RtlZeroMemory(&PreviousIoStatistics, sizeof(IO_GLOBAL_STATISTICS));
  710. IoStatistics.Version = IO_GLOBAL_STATISTICS_VERSION;
  711. Memory.Version = MM_STATISTICS_VERSION;
  712. Cache.Version = IO_CACHE_STATISTICS_VERSION;
  713. Status = KeVideoGetDimensions(&Width,
  714. NULL,
  715. NULL,
  716. &CellHeight,
  717. &Columns,
  718. &Rows);
  719. if ((!KSUCCESS(Status)) || (Rows < 3)) {
  720. return;
  721. }
  722. if (Columns > sizeof(BannerString) - 1) {
  723. Columns = sizeof(BannerString) - 1;
  724. }
  725. //
  726. // Determine the right format given the width of the console.
  727. //
  728. if (Columns >= KE_BANNER_FULL_WIDTH) {
  729. MemoryFormat = KE_BANNER_FULL_MEMORY_FORMAT;
  730. TimeFormat = KE_BANNER_FULL_TIME_FORMAT;
  731. PagingFormat = KE_BANNER_FULL_PAGING_FORMAT;
  732. } else if (Columns >= KE_BANNER_SHORT_WIDTH) {
  733. MemoryFormat = KE_BANNER_SHORT_MEMORY_FORMAT;
  734. TimeFormat = KE_BANNER_SHORT_TIME_FORMAT;
  735. PagingFormat = KE_BANNER_SHORT_PAGING_FORMAT;
  736. } else if (Columns >= KE_BANNER_TINY_WIDTH) {
  737. MemoryFormat = KE_BANNER_TINY_MEMORY_FORMAT;
  738. TimeFormat = KE_BANNER_TINY_TIME_FORMAT;
  739. PagingFormat = KE_BANNER_TINY_PAGING_FORMAT;
  740. } else {
  741. return;
  742. }
  743. Timer = KeCreateTimer(KE_ALLOCATION_TAG);
  744. if (Timer == NULL) {
  745. return;
  746. }
  747. KeVideoClearScreen(0, 0, Width, CellHeight * 3);
  748. while (TRUE) {
  749. if (KeBannerThreadEnabled != (ULONG)(UINTN)Context) {
  750. break;
  751. }
  752. Status = MmGetMemoryStatistics(&Memory);
  753. if (!KSUCCESS(Status)) {
  754. RtlDebugPrint("Failed to get MM statistics.\n");
  755. break;
  756. }
  757. Status = IoGetCacheStatistics(&Cache);
  758. if (!KSUCCESS(Status)) {
  759. RtlDebugPrint("Failed to get IO cache statistics.\n");
  760. }
  761. IoGetGlobalStatistics(&IoStatistics);
  762. TimeCounter = KeGetRecentTimeCounter();
  763. Seconds = TimeCounter / Frequency;
  764. Minutes = Seconds / SECONDS_PER_MINUTE;
  765. Seconds %= SECONDS_PER_MINUTE;
  766. Hours = Minutes / MINUTES_PER_HOUR;
  767. Minutes %= MINUTES_PER_HOUR;
  768. Days = Hours / HOURS_PER_DAY;
  769. Hours %= HOURS_PER_DAY;
  770. KepPrintFormattedMemoryUsage(TotalMemoryString,
  771. sizeof(TotalMemoryString),
  772. Memory.AllocatedPhysicalPages << PageShift,
  773. Memory.PhysicalPages << PageShift);
  774. UsedSize = Memory.PagedPool.TotalHeapSize -
  775. Memory.PagedPool.FreeListSize;
  776. KepPrintFormattedMemoryUsage(PagedPoolString,
  777. sizeof(PagedPoolString),
  778. UsedSize,
  779. Memory.PagedPool.TotalHeapSize);
  780. UsedSize = Memory.NonPagedPool.TotalHeapSize -
  781. Memory.NonPagedPool.FreeListSize;
  782. KepPrintFormattedMemoryUsage(NonPagedPoolString,
  783. sizeof(NonPagedPoolString),
  784. UsedSize,
  785. Memory.NonPagedPool.TotalHeapSize);
  786. KepPrintFormattedMemoryUsage(CacheString,
  787. sizeof(CacheString),
  788. Cache.DirtyPageCount << PageShift,
  789. Cache.PhysicalPageCount << PageShift);
  790. if (Columns >= KE_BANNER_SHORT_WIDTH) {
  791. Size = RtlPrintToString(BannerString,
  792. Columns + 1,
  793. CharacterEncodingDefault,
  794. MemoryFormat,
  795. TotalMemoryString,
  796. PagedPoolString,
  797. NonPagedPoolString,
  798. CacheString);
  799. } else {
  800. Size = RtlPrintToString(BannerString,
  801. Columns + 1,
  802. CharacterEncodingDefault,
  803. MemoryFormat,
  804. TotalMemoryString,
  805. CacheString);
  806. }
  807. Size -= 1;
  808. while (Size < Columns) {
  809. BannerString[Size] = ' ';
  810. Size += 1;
  811. }
  812. BannerString[Size] = '\0';
  813. KeVideoPrintString(0, 0, BannerString);
  814. //
  815. // Also update the second line, which contains the system usage.
  816. //
  817. KepUpdateSystemUsage(&UsageContext);
  818. if (Days == 0) {
  819. RtlPrintToString(UptimeString,
  820. sizeof(UptimeString),
  821. CharacterEncodingAscii,
  822. "%02lld:%02lld:%02lld",
  823. Hours,
  824. Minutes,
  825. Seconds);
  826. } else {
  827. RtlPrintToString(UptimeString,
  828. sizeof(UptimeString),
  829. CharacterEncodingAscii,
  830. "%02lld:%02lld:%02lld:%02lld",
  831. Days,
  832. Hours,
  833. Minutes,
  834. Seconds);
  835. }
  836. KepPrintFormattedPercent(CpuUserString,
  837. sizeof(CpuUserString),
  838. UsageContext.UserPercent);
  839. KepPrintFormattedPercent(CpuKernelString,
  840. sizeof(CpuKernelString),
  841. UsageContext.KernelPercent);
  842. KepPrintFormattedPercent(CpuInterruptString,
  843. sizeof(CpuInterruptString),
  844. UsageContext.InterruptPercent);
  845. KepPrintFormattedPercent(CpuIdleString,
  846. sizeof(CpuIdleString),
  847. UsageContext.IdlePercent);
  848. ReadDifference = IoStatistics.BytesRead -
  849. PreviousIoStatistics.BytesRead;
  850. WriteDifference = IoStatistics.BytesWritten -
  851. PreviousIoStatistics.BytesWritten;
  852. KepPrintFormattedMemoryUsage(IoString,
  853. sizeof(IoString),
  854. ReadDifference,
  855. WriteDifference);
  856. ReadDifference = IoStatistics.PagingBytesRead -
  857. PreviousIoStatistics.PagingBytesRead;
  858. WriteDifference = IoStatistics.PagingBytesWritten -
  859. PreviousIoStatistics.PagingBytesWritten;
  860. PagingString[0] = '\0';
  861. if ((ReadDifference != 0) || (WriteDifference != 0)) {
  862. KepPrintFormattedMemoryUsage(PagingValueString,
  863. sizeof(PagingValueString),
  864. ReadDifference,
  865. WriteDifference);
  866. RtlPrintToString(PagingString,
  867. sizeof(PagingString),
  868. CharacterEncodingAscii,
  869. PagingFormat,
  870. PagingValueString);
  871. }
  872. RtlCopyMemory(&PreviousIoStatistics,
  873. &IoStatistics,
  874. sizeof(IO_GLOBAL_STATISTICS));
  875. if (Columns >= KE_BANNER_SHORT_WIDTH) {
  876. Size = RtlPrintToString(BannerString,
  877. Columns + 1,
  878. CharacterEncodingDefault,
  879. TimeFormat,
  880. UptimeString,
  881. CpuUserString,
  882. CpuKernelString,
  883. CpuInterruptString,
  884. CpuIdleString,
  885. IoString,
  886. PagingString);
  887. } else {
  888. Size = RtlPrintToString(BannerString,
  889. Columns + 1,
  890. CharacterEncodingDefault,
  891. TimeFormat,
  892. UptimeString,
  893. CpuUserString,
  894. CpuKernelString,
  895. IoString);
  896. }
  897. Size -= 1;
  898. while (Size < Columns) {
  899. BannerString[Size] = ' ';
  900. Size += 1;
  901. }
  902. BannerString[Size] = '\0';
  903. KeVideoPrintString(0, 1, BannerString);
  904. TimerQueueType = TimerQueueSoftWake;
  905. if ((Seconds % 5) == 0) {
  906. TimerQueueType = TimerQueueSoft;
  907. }
  908. KeQueueTimer(Timer,
  909. TimerQueueType,
  910. TimeCounter + Frequency,
  911. 0,
  912. 0,
  913. NULL);
  914. ObWaitOnObject(Timer, 0, WAIT_TIME_INDEFINITE);
  915. }
  916. KeDestroyTimer(Timer);
  917. return;
  918. }
  919. VOID
  920. KepUpdateSystemUsage (
  921. PSYSTEM_USAGE_CONTEXT Context
  922. )
  923. /*++
  924. Routine Description:
  925. This routine updates the system usage information.
  926. Arguments:
  927. Context - Supplies a pointer to the context information.
  928. Return Value:
  929. None.
  930. --*/
  931. {
  932. PROCESSOR_CYCLE_ACCOUNTING Cycles;
  933. ULONGLONG DeltaTotal;
  934. ULONGLONG ExpectedTotalDelta;
  935. ULONGLONG IdleDelta;
  936. ULONGLONG InterruptDelta;
  937. ULONGLONG KernelDelta;
  938. ULONGLONG StoppedCycles;
  939. ULONGLONG TimeCounter;
  940. ULONGLONG TimeCounterDelta;
  941. ULONGLONG TotalCycles;
  942. ULONGLONG TotalDelta;
  943. ULONGLONG UserDelta;
  944. if (Context->TimeCounterFrequency == 0) {
  945. Context->TimeCounterFrequency = HlQueryTimeCounterFrequency();
  946. }
  947. if (Context->CycleCounterFrequency == 0) {
  948. Context->CycleCounterFrequency = HlQueryProcessorCounterFrequency();
  949. }
  950. //
  951. // Snap the time counter and cycle counters.
  952. //
  953. TimeCounter = HlQueryTimeCounter();
  954. KeGetTotalProcessorCycleAccounting(&Cycles);
  955. //
  956. // The cycle counter may not count while the processor is idle. Use the
  957. // time counter to figure out how many cycles there should have been, and
  958. // compare to how many there actually are. Any difference gets added to the
  959. // idle cycles.
  960. //
  961. TimeCounterDelta = TimeCounter - Context->TimeCounter;
  962. if (TimeCounterDelta == 0) {
  963. return;
  964. }
  965. //
  966. // TcTicks * CcTicks/ * s/ = CcTicks.
  967. // s TcTicks
  968. //
  969. ExpectedTotalDelta = TimeCounterDelta * Context->CycleCounterFrequency *
  970. KeGetActiveProcessorCount() /
  971. Context->TimeCounterFrequency;
  972. TotalCycles = Cycles.UserCycles + Cycles.KernelCycles +
  973. Cycles.InterruptCycles + Cycles.IdleCycles;
  974. TotalDelta = TotalCycles - Context->TotalCycles;
  975. StoppedCycles = 0;
  976. if (ExpectedTotalDelta > TotalDelta) {
  977. StoppedCycles = ExpectedTotalDelta - TotalDelta;
  978. }
  979. //
  980. // Compute the differences between this time and last time.
  981. //
  982. UserDelta = Cycles.UserCycles - Context->UserCycles;
  983. KernelDelta = Cycles.KernelCycles - Context->KernelCycles;
  984. InterruptDelta = Cycles.InterruptCycles - Context->InterruptCycles;
  985. IdleDelta = Cycles.IdleCycles - Context->IdleCycles + StoppedCycles;
  986. DeltaTotal = UserDelta + KernelDelta + InterruptDelta + IdleDelta;
  987. //
  988. // Save this snapshot into the context as the new previous snapshot.
  989. //
  990. Context->TimeCounter = TimeCounter;
  991. Context->UserCycles = Cycles.UserCycles;
  992. Context->KernelCycles = Cycles.KernelCycles;
  993. Context->InterruptCycles = Cycles.InterruptCycles;
  994. Context->IdleCycles = Cycles.IdleCycles;
  995. Context->TotalCycles = TotalCycles;
  996. //
  997. // Finally, update the percent (times ten) values.
  998. //
  999. Context->UserPercent = UserDelta * 1000 / DeltaTotal;
  1000. Context->KernelPercent = KernelDelta * 1000 / DeltaTotal;
  1001. Context->InterruptPercent = InterruptDelta * 1000 / DeltaTotal;
  1002. Context->IdlePercent = IdleDelta * 1000 / DeltaTotal;
  1003. return;
  1004. }
  1005. VOID
  1006. KepPrintFormattedMemoryUsage (
  1007. PCHAR String,
  1008. ULONG StringSize,
  1009. ULONGLONG UsedValue,
  1010. ULONGLONG TotalValue
  1011. )
  1012. /*++
  1013. Routine Description:
  1014. This routine prints two formatted sizes a la 5.8M/64M.
  1015. Arguments:
  1016. String - Supplies a pointer to the string buffer to print to.
  1017. StringSize - Supplies the total size of the string buffer in bytes.
  1018. UsedValue - Supplies the first value to print.
  1019. TotalValue - Supplies the second value to print.
  1020. Return Value:
  1021. None.
  1022. --*/
  1023. {
  1024. ULONG Size;
  1025. Size = KepPrintFormattedSize(String, StringSize, UsedValue);
  1026. if (Size != 0) {
  1027. Size -= 1;
  1028. }
  1029. String += Size;
  1030. StringSize -= Size;
  1031. if (StringSize > 1) {
  1032. *String = '/';
  1033. String += 1;
  1034. StringSize -= 1;
  1035. }
  1036. if (StringSize > 1) {
  1037. KepPrintFormattedSize(String, StringSize, TotalValue);
  1038. }
  1039. return;
  1040. }
  1041. ULONG
  1042. KepPrintFormattedSize (
  1043. PCHAR String,
  1044. ULONG StringSize,
  1045. ULONGLONG Value
  1046. )
  1047. /*++
  1048. Routine Description:
  1049. This routine prints a formatted size a la 5.8M (M for megabytes).
  1050. Arguments:
  1051. String - Supplies a pointer to the string buffer to print to.
  1052. StringSize - Supplies the total size of the string buffer in bytes.
  1053. Value - Supplies the value in bytes to print.
  1054. Return Value:
  1055. Returns the length of the final string after all formatting has been
  1056. completed.
  1057. --*/
  1058. {
  1059. ULONG Size;
  1060. CHAR Suffix;
  1061. Suffix = 'B';
  1062. if (Value > 1024) {
  1063. Suffix = 'K';
  1064. Value = (Value * 10) / 1024;
  1065. if (Value / 10 >= 1024) {
  1066. Suffix = 'M';
  1067. Value /= 1024;
  1068. if (Value / 10 >= 1024) {
  1069. Suffix = 'G';
  1070. Value /= 1024;
  1071. }
  1072. }
  1073. }
  1074. ASSERT(Value < 1024 * 10);
  1075. if (Suffix == 'B') {
  1076. Size = RtlPrintToString(String,
  1077. StringSize,
  1078. CharacterEncodingAscii,
  1079. "%d",
  1080. (ULONG)Value);
  1081. } else {
  1082. if (Value < 100) {
  1083. Size = RtlPrintToString(String,
  1084. StringSize,
  1085. CharacterEncodingAscii,
  1086. "%d.%d%c",
  1087. (ULONG)Value / 10,
  1088. (ULONG)Value % 10,
  1089. Suffix);
  1090. } else {
  1091. Size = RtlPrintToString(String,
  1092. StringSize,
  1093. CharacterEncodingAscii,
  1094. "%d%c",
  1095. (ULONG)Value / 10,
  1096. Suffix);
  1097. }
  1098. }
  1099. return Size;
  1100. }
  1101. ULONG
  1102. KepPrintFormattedPercent (
  1103. PCHAR String,
  1104. ULONG StringSize,
  1105. ULONG PercentTimesTen
  1106. )
  1107. /*++
  1108. Routine Description:
  1109. This routine prints a formatted percentage a la 5.8% or 99%. The field
  1110. width is always 4.
  1111. Arguments:
  1112. String - Supplies a pointer to the string buffer to print to.
  1113. StringSize - Supplies the total size of the string buffer in bytes.
  1114. PercentTimesTen - Supplies ten times the percentage value. So 54.8% would
  1115. have a value of 548. This value will be rounded to the precision that
  1116. is printed.
  1117. Offset - Supplies a pointer that on input supplies the offset within the
  1118. string to print. This value will be updated to the new end of the
  1119. string.
  1120. Return Value:
  1121. Returns the length of the final string after all formatting has been
  1122. completed.
  1123. --*/
  1124. {
  1125. ULONG Size;
  1126. //
  1127. // For values less than 10%, print the single digit and first decimal
  1128. // point.
  1129. //
  1130. if (PercentTimesTen < 100) {
  1131. Size = RtlPrintToString(String,
  1132. StringSize,
  1133. CharacterEncodingAscii,
  1134. "%d.%d%%",
  1135. PercentTimesTen / 10,
  1136. PercentTimesTen % 10);
  1137. } else {
  1138. PercentTimesTen += 5;
  1139. Size = RtlPrintToString(String,
  1140. StringSize,
  1141. CharacterEncodingAscii,
  1142. "%3d%%",
  1143. PercentTimesTen / 10);
  1144. }
  1145. return Size;
  1146. }