PageRenderTime 69ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/base/Kernel/Singularity/Kernel.cs

https://bitbucket.org/MpDzik/singularity-rdk
C# | 1033 lines | 747 code | 163 blank | 123 comment | 61 complexity | 7eb53b0599859f5a32416e9ac61d981d MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // Note:
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Diagnostics;
  12. using System.Reflection;
  13. using System.Runtime.CompilerServices;
  14. using System.Runtime.InteropServices;
  15. using System.Threading;
  16. using Microsoft.Bartok.Runtime;
  17. using Microsoft.SingSharp;
  18. using Microsoft.Singularity.Channels;
  19. using Microsoft.Singularity.Directory;
  20. using Microsoft.Singularity.Drivers;
  21. using Microsoft.Singularity.Eventing;
  22. using Microsoft.Singularity.Hal;
  23. using Microsoft.Singularity.Io;
  24. using Microsoft.Singularity.Loader;
  25. using Microsoft.Singularity.Memory;
  26. using Microsoft.Singularity.Scheduling;
  27. using Microsoft.Singularity.Security;
  28. using Microsoft.Singularity.V1.Services;
  29. using Microsoft.Singularity.Xml;
  30. [assembly: AssemblyTitle("Microsoft.Singularity")]
  31. [assembly: AssemblyProduct("Microsoft Research Singularity Operating System")]
  32. [assembly: AssemblyCompany("Microsoft Corporation")]
  33. [assembly: AssemblyVersion("1.0.0.0")]
  34. [assembly: AssemblyKeyFile("public.snk")]
  35. [assembly: AssemblyDelaySign(true)]
  36. namespace Microsoft.Singularity
  37. {
  38. [NoCCtor]
  39. [CLSCompliant(false)]
  40. [AccessedByRuntime("referenced from hal.cpp/hal.cpp")]
  41. public class Kernel
  42. {
  43. private static string[] args;
  44. private static ManualResetEvent mpEndEvent;
  45. private static int bootReturnCode;
  46. // sample profiler kernel data
  47. public static uint ProfilerBufferSize;
  48. #region Waypoints
  49. public static long[] Waypoints;
  50. public static int[] WaypointSeq;
  51. public static int[] WaypointThd;
  52. public static int WaypointNumber;// = 0;
  53. public static long WaypointSamples;// = 0;
  54. public static bool WaypointSuspicious;
  55. public static uint WaypointInterrupt;
  56. public const int NWP = 2048; // XXX PBAR if this is readonly then it seems to read as 0!
  57. // This is temporary, until we get a HAL-based plug-and-play system going.
  58. public const byte HalIpiInterrupt = 249;
  59. /// <summary> Flag indicating if kernel has succesfully booted </summary>
  60. private static bool hasBooted;
  61. private static Scheduler scheduler;
  62. ///
  63. /// <summary>
  64. /// Property to find out if kernel finished booting
  65. /// </summary>
  66. ///
  67. public static bool HasBooted
  68. {
  69. [NoHeapAllocation]
  70. get
  71. {
  72. return hasBooted;
  73. }
  74. }
  75. /// <summary>
  76. /// Get a default kernel scheduler
  77. /// </summary>
  78. internal static Scheduler TheScheduler
  79. {
  80. [Inline]
  81. [NoHeapAllocation]
  82. get
  83. {
  84. return scheduler;
  85. }
  86. }
  87. [Conditional("WAYPOINTS")]
  88. [NoHeapAllocation]
  89. public static void Waypoint0()
  90. {
  91. WaypointSamples++;
  92. Waypoints[0] = (long)Processor.CycleCount;
  93. WaypointNumber = 1;
  94. WaypointSuspicious = false;
  95. WaypointInterrupt = Processor.CurrentProcessor.NumInterrupts;
  96. }
  97. [Conditional("WAYPOINTS")]
  98. [NoHeapAllocation]
  99. public static void Waypoint(int num)
  100. {
  101. if (Waypoints == null || Waypoints[0] == 0 || WaypointNumber > NWP - 1) {
  102. return;
  103. }
  104. long delta = (long)Processor.CycleCount - Waypoints[0];
  105. if (delta > 7000000) {
  106. WaypointSuspicious = true;
  107. }
  108. WaypointSeq[WaypointNumber] = num;
  109. WaypointThd[WaypointNumber] = Thread.GetCurrentThreadIndex();
  110. Waypoints[WaypointNumber++] = delta;
  111. }
  112. [Conditional("WAYPOINTS")]
  113. [NoHeapAllocation]
  114. public static void WaypointDone()
  115. {
  116. Waypoints[0] = 0;
  117. }
  118. #if false
  119. [Conditional("WAYPOINTS")]
  120. [NoHeapAllocation]
  121. public static void WaypointDump()
  122. {
  123. WaypointDump(NWP);
  124. }
  125. #endif
  126. [Conditional("WAYPOINTS")]
  127. public static void WaypointDump()
  128. {
  129. bool iflag = Processor.DisableInterrupts();
  130. DebugStub.WriteLine("Interrupts: {0}",
  131. __arglist(Processor.CurrentProcessor.NumInterrupts
  132. - WaypointInterrupt));
  133. DebugStub.WriteLine("WPT Waypoint Sequence THD Diff");
  134. for (int i = 1; i < WaypointNumber; i++) {
  135. DebugStub.WriteLine("{0,3:d} {1,10:d} {2,10:d} {3,3:d} {4,10:d}",
  136. __arglist(
  137. i,
  138. Waypoints[i],
  139. WaypointSeq[i],
  140. WaypointThd[i].GetHashCode(),
  141. Waypoints[i] - Kernel.Waypoints[i-1]));
  142. }
  143. Processor.RestoreInterrupts(iflag);
  144. }
  145. [Conditional("WAYPOINTS")]
  146. [NoHeapAllocation]
  147. public static void WaypointReset()
  148. {
  149. for (int i = 0; i < NWP; i++) {
  150. Waypoints[i] = 0;
  151. }
  152. WaypointSamples = 0;
  153. }
  154. #endregion // Waypoints
  155. internal static DateTime BootTime;
  156. // [System.Diagnostics.Conditional("ISA_ARM")]
  157. private static void ARM_PROGRESS(string msg)
  158. {
  159. DebugStub.WriteLine(msg);
  160. }
  161. [System.Diagnostics.Conditional("ISA_ARM")]
  162. private static void ARM_SPIN_FOREVER(string msg)
  163. {
  164. DebugStub.Assert(!Processor.InterruptsDisabled());
  165. Processor p = Processor.CurrentProcessor;
  166. DebugStub.WriteLine(msg);
  167. DateTime last = DateTime.Now;
  168. uint n = 0;
  169. while (true) {
  170. Thread.Sleep(1000);
  171. }
  172. }
  173. // Note: This function is called by Hal.cpp.
  174. [AccessedByRuntime("referenced from hal.cpp")]
  175. internal static int Main()
  176. {
  177. bootReturnCode = Platform.EXIT_AND_RESTART;
  178. InitPreMonitoring();
  179. try {
  180. InitServices();
  181. // Consider boot successful at this stage.
  182. bootReturnCode = Platform.EXIT_AND_SHUTDOWN;
  183. ARM_SPIN_FOREVER("kernel.arm Spinning forever");
  184. bootReturnCode = SpawnAndWaitForShell();
  185. // The shell has exited when we get here
  186. FinalizeServices();
  187. }
  188. catch (Exception e) {
  189. System.Console.WriteLine("EXCEPTION:: " + e.Message);
  190. Tracing.Log(Tracing.Fatal, "Caught exception {0}", e.Message);
  191. DebugStub.WriteLine("Caught {0}", __arglist(e.Message));
  192. bootReturnCode = -1;
  193. DebugStub.Break();
  194. }
  195. DebugStub.WriteLine("Kernel exiting with 0x{0:x4}", __arglist(bootReturnCode));
  196. FinalizePreMonitoring();
  197. if (bootReturnCode != Platform.EXIT_AND_WARMBOOT) {
  198. Kill(bootReturnCode);
  199. }
  200. return bootReturnCode;
  201. }
  202. private static void InitPreMonitoring()
  203. {
  204. Tracing.Log(0);
  205. Tracing.Log(1);
  206. Tracing.Log(2);
  207. Tracing.Log(3);
  208. DebugStub.WriteLine("-------------------------------------------------------------------------------");
  209. ARM_PROGRESS("Kernel!001");
  210. // Indicate that we are not booted yet
  211. hasBooted = false;
  212. // Rather than mark all bootstrap code with [NoBarriers], perform a mini-
  213. // initialization that gives us a working WriteBarrier.
  214. System.GCs.Barrier.PreInitialize();
  215. ARM_PROGRESS("Kernel!002");
  216. // Initialize the memory subsystem. If enabled this turns on paging
  217. MemoryManager.Initialize();
  218. // Note for Monitoring early boot process:
  219. // if you ever want to monitor stuff before this point, you should
  220. // allocate a static memory area in BootInit.cs, init the
  221. // monitoring system earlier, hold the system at this point here,
  222. // copy over all the collected data up to now to the new
  223. // dynamically created buffer and continue
  224. Monitoring.Initialize(); // uses page memory
  225. ARM_PROGRESS("Kernel!003");
  226. HandleTable.Initialize();
  227. }
  228. private static void InitGCSupport()
  229. {
  230. ARM_PROGRESS("Kernel!004");
  231. // Initialize the rest of the primitive runtime.
  232. VTable.Initialize((RuntimeType)typeof(Kernel));
  233. ARM_PROGRESS("Kernel!005");
  234. // Must occur before MemoryManager.PostGCInitialize()
  235. ProtectionDomain.Initialize();
  236. ARM_PROGRESS("Kernel!006");
  237. // Must occur before SharedHeap.Initialize()
  238. MemoryManager.PostGCInitialize();
  239. ARM_PROGRESS("Kernel!007");
  240. // Allocates callback objects for stack growth
  241. Stacks.Initialize();
  242. ARM_PROGRESS("Kernel!008");
  243. // Initialize the HAL parts which require GC allocation
  244. Platform.ThePlatform.InitializeServices();
  245. ARM_PROGRESS("Kernel!009");
  246. SharedHeap.Initialize();
  247. ARM_PROGRESS("Kernel!010");
  248. // Must occur after SharedHeap.Initialize();
  249. ProtectionDomain.DefaultDomain.InitHook();
  250. }
  251. private static void InitServices()
  252. {
  253. InitGCSupport();
  254. args = GetCommandLine();
  255. VTable.ParseArgs(args);
  256. ARM_PROGRESS("Kernel!011");
  257. InitSchedulerTypes();
  258. ARM_PROGRESS("Kernel!018");
  259. Controller.InitializeSystem();
  260. Tracing.InitializeSystem();
  261. ARM_PROGRESS("Kernel!019");
  262. // Read the profiler settings. The values are assumed in kbytes
  263. // convert them to bytes for direct consumption
  264. ProfilerBufferSize = (uint)GetIntegerArgument("profiler", 0);
  265. ProfilerBufferSize *= 1024;
  266. ARM_PROGRESS("Kernel!020");
  267. SpinLock.StaticInitialize();
  268. int cpusLength;
  269. int cpuCount = GetCpuCount(out cpusLength);
  270. Processor.InitializeProcessorTable(cpusLength);
  271. ARM_PROGRESS("Kernel!021");
  272. Tracing.Log(Tracing.Audit, "processor");
  273. Processor processor = Processor.EnableProcessor(0);
  274. PEImage.Initialize();
  275. ARM_PROGRESS("Kernel!034");
  276. // Initialize the sample profiling for the processor
  277. // after the initial breakpoint in kd in the call
  278. // PEImage.Initialize(). This will allow enabling profiling
  279. // from kd, by overwriting the ProfilerBufferSize value
  280. processor.EnableProfiling();
  281. ARM_PROGRESS("Kernel!035");
  282. FlatPages.InitializeMemoryMonitoring();
  283. // initialize endpoints
  284. InitType(typeof(Microsoft.Singularity.Channels.EndpointCore));
  285. // TODO Bug 59: Currently broken, need to review paging build.
  286. //#if PAGING
  287. // Microsoft.Singularity.Channels.EndpointTrusted.StaticInitialize();
  288. //#endif
  289. ARM_PROGRESS("Kernel!036");
  290. // get the system manifest
  291. IoMemory systemManifest = GetSystemManifest();
  292. ARM_PROGRESS("Kernel!037");
  293. XmlReader xmlReader = new XmlReader(systemManifest);
  294. XmlNode xmlData = xmlReader.Parse();
  295. XmlNode manifestRoot = xmlData.GetChild("system");
  296. XmlNode initConfig = manifestRoot.GetChild("initConfig");
  297. ARM_PROGRESS("Kernel!038");
  298. PerfCounters.Initialize();
  299. // need to have processed the manifest before we can call Process initialize
  300. ARM_PROGRESS("Kernel!039");
  301. PrincipalImpl.Initialize(initConfig);
  302. ARM_PROGRESS("Kernel!040");
  303. Process.Initialize(manifestRoot.GetChild("processConfig"));
  304. InitIO(processor, initConfig, manifestRoot.GetChild("drivers"));
  305. InitBootTime();
  306. ARM_PROGRESS("Kernel!045");
  307. // From here on, we want lazy type initialization to worry about
  308. // competing threads.
  309. VTable.InitializeForMultipleThread();
  310. ARM_PROGRESS("Kernel!046");
  311. Console.WriteLine("Running C# Kernel of {0}", GetLinkDate());
  312. Console.WriteLine();
  313. // TODO: remove this
  314. Console.WriteLine("Current time: {0}", SystemClock.GetUtcTime().ToString("r"));
  315. ARM_PROGRESS("Kernel!047");
  316. InitScheduling();
  317. DirectoryService.StartNotificationThread();
  318. Console.WriteLine("Initializing Shared Heap Walker");
  319. ProtectionDomain.InitializeSharedHeapWalker();
  320. ARM_PROGRESS("Kernel!050");
  321. Console.WriteLine("Initializing Service Thread");
  322. ServiceThread.Initialize();
  323. ARM_PROGRESS("Kernel!051");
  324. GC.EnableHeap();
  325. GCProfilerLogger.StartProfiling();
  326. ARM_PROGRESS("Kernel!052");
  327. Tracing.Log(Tracing.Audit, "Waypoints init");
  328. Waypoints = new long[2048];
  329. WaypointSeq = new int[2048];
  330. WaypointThd = new int[2048];
  331. Tracing.Log(Tracing.Audit, "Interrupts ON.");
  332. Processor.RestoreInterrupts(true);
  333. ARM_PROGRESS("Kernel!053");
  334. #if ISA_ARM && TEST_GC
  335. for (int i = 0; i < 1000; i++) {
  336. DebugStub.WriteLine("Iteration {0}", __arglist(i));
  337. ArrayList a = new ArrayList();
  338. for (int j = 0; j < 128; j++) {
  339. int size = 1024 * 1024;
  340. a.Add(new byte [size]);
  341. }
  342. }
  343. #endif // ISA_ARM
  344. ARM_PROGRESS("Kernel!054");
  345. Tracing.Log(Tracing.Audit, "Binder");
  346. Binder.Initialize(manifestRoot.GetChild("namingConventions"));
  347. #if ISA_ARM
  348. DebugStub.WriteLine("Exporting local namespace to BSP\n");
  349. DirectoryService.ExportArmNamespace();
  350. DebugStub.WriteLine("Export complete...redirecting binder\n");
  351. Binder.RedirectRootRef();
  352. DebugStub.WriteLine("Binder redirect complete\n");
  353. #endif
  354. #if false
  355. Tracing.Log(Tracing.Audit, "Starting Security Service channels");
  356. PrincipalImpl.Export();
  357. ARM_PROGRESS("Kernel!055");
  358. #endif
  359. Tracing.Log(Tracing.Audit, "Creating Root Directory.");
  360. //This can be moved below
  361. IoSystem.InitializeDirectoryService();
  362. ARM_PROGRESS("Kernel!055");
  363. #if false
  364. // Start User space namespace manager
  365. Console.WriteLine("Starting Directory Service SIP");
  366. DirectoryService.StartUserSpaceDirectoryService();
  367. #endif
  368. ARM_PROGRESS("Kernel!055.5");
  369. #if !ISA_ARM
  370. Tracing.Log(Tracing.Audit, "Starting Security Service channels");
  371. PrincipalImpl.Export();
  372. #endif
  373. ARM_PROGRESS("Kernel!056");
  374. Console.WriteLine("Initializing system channels");
  375. // starting channels services
  376. DebugStub.Print("Initializing Channel Services\n");
  377. ChannelDeliveryImplService.Initialize();
  378. ARM_PROGRESS("Kernel!057");
  379. ConsoleOutput.Initialize();
  380. ARM_PROGRESS("Kernel!058");
  381. // Initialize MP after Binder and ConsoleOutput
  382. // are initialized so there are no
  383. // initialization races if the additional
  384. // threads try to use them.
  385. Tracing.Log(Tracing.Audit, "Starting additional processors");
  386. // For ABI to ARM support
  387. MpExecution.Initialize();
  388. ARM_PROGRESS("Kernel!059");
  389. mpEndEvent = new ManualResetEvent(false);
  390. Tracing.Log(Tracing.Audit, "Initializing Volume Manager.");
  391. #if !ISA_ARM
  392. IoSystem.InitializeVolumeManager();
  393. #endif // ISA_ARM
  394. ARM_PROGRESS("Kernel!060");
  395. InitDrivers();
  396. if (cpuCount > 1) {
  397. unsafe {
  398. Console.WriteLine("Enabling {0} cpus out of {1} real cpus\n", cpuCount, Platform.ThePlatform.CpuRealCount);
  399. }
  400. Processor.EnableMoreProcessors(cpuCount);
  401. ARM_PROGRESS("Kernel!064");
  402. }
  403. Tracing.Log(Tracing.Audit, "Initializing Service Manager.");
  404. IoSystem.InitializeServiceManager(manifestRoot.GetChild("serviceConfig"));
  405. ARM_PROGRESS("Kernel!065");
  406. InitDiagnostics();
  407. #if !ISA_ARM
  408. // At this point consider kernel finshed booting
  409. hasBooted = true;
  410. #endif // ISA_ARM
  411. Processor.StartSampling();
  412. ARM_PROGRESS("Kernel!069");
  413. Microsoft.Singularity.KernelDebugger.KdFilesNamespace.StartNamespaceThread();
  414. ARM_PROGRESS("Kernel!070");
  415. }
  416. private static void InitSchedulerTypes()
  417. {
  418. InitType(typeof(Processor));
  419. InitType(typeof(Scheduler));
  420. InitType(typeof(ProcessorDispatcher));
  421. // InitType(typeof(AffinityScheduler));
  422. InitType(typeof(MinScheduler));
  423. ARM_PROGRESS("Kernel!013");
  424. // Create scheduler before initializing processes
  425. scheduler = new MinScheduler();
  426. ARM_PROGRESS("Kernel!017");
  427. // Initialize processor dispatcher
  428. ProcessorDispatcher.StaticInitialize(scheduler);
  429. }
  430. private static void InitScheduling()
  431. {
  432. Console.WriteLine("Initializing Scheduler");
  433. ARM_PROGRESS("Kernel!047");
  434. // Finish scheduler initialization:
  435. scheduler.Initialize();
  436. ARM_PROGRESS("Kernel!048");
  437. // Initialize initial dispatcher
  438. Processor.InitializeDispatcher(0);
  439. Processor.ActivateTimer(0);
  440. ARM_PROGRESS("Kernel!049");
  441. }
  442. private static void InitIO(Processor p, XmlNode initConfig, XmlNode driverConfig)
  443. {
  444. // obtain the configuration for the namespace service
  445. // and initialize the namespace service
  446. ARM_PROGRESS("Kernel!041");
  447. DirectoryService.Initialize(initConfig);
  448. Tracing.Log(Tracing.Audit, "IoSystem");
  449. ARM_PROGRESS("Kernel!042");
  450. IoSystem.Initialize(driverConfig);
  451. Tracing.Log(Tracing.Audit, "Registering HAL Drivers.");
  452. ARM_PROGRESS("Kernel!043");
  453. Devices.RegisterPnpResources(); // add the root devices
  454. ARM_PROGRESS("Kernel!044");
  455. Platform.InitializeHal(p);
  456. }
  457. private static int SpawnAndWaitForShell()
  458. {
  459. #if ISA_ARM
  460. // spin here for now
  461. while (true) {
  462. Thread.Yield();
  463. }
  464. #else
  465. Tracing.Log(Tracing.Audit, "Creating Shell Process");
  466. ARM_PROGRESS("Kernel!071");
  467. int exit = -10000;
  468. Manifest manifest;
  469. #if KERNEL_USE_LOGIN
  470. IoMemory memory;
  471. if (args[0] == "bvt") {
  472. memory = Binder.LoadImage(Thread.CurrentProcess, "tty", out manifest);
  473. }
  474. else{
  475. // TODO: The login app needs to be fixed to setup stdin and stdout pipes for
  476. // the shell and pump the data back and forth.
  477. memory = Binder.LoadImage(Thread.CurrentProcess, "login", out manifest);
  478. }
  479. #else
  480. IoMemory memory = Binder.LoadImage(Thread.CurrentProcess, "tty", out manifest);
  481. #endif
  482. ARM_PROGRESS("Kernel!073");
  483. if (memory == null || memory.Length > 0) {
  484. String[] shellArgs = new String[args.Length + 2];
  485. shellArgs[0] = "tty";
  486. shellArgs[1] = "shell";
  487. for (int i = 0; i < args.Length; i++) {
  488. shellArgs[i + 2] = args[i];
  489. }
  490. Process process = new Process(Thread.CurrentProcess, memory, null, shellArgs, manifest);
  491. if (process != null) {
  492. PrintBootTime();
  493. process.Start();
  494. process.Join();
  495. exit = process.ExitCode;
  496. }
  497. ARM_PROGRESS("Kernel!074");
  498. }
  499. return DetermineShutdown(exit);
  500. #endif
  501. }
  502. private static int DetermineShutdown(int exit)
  503. {
  504. switch (exit) {
  505. case -10000:
  506. Tracing.Log(Tracing.Audit, "Failed to start shell process.");
  507. return Platform.EXIT_AND_RESTART;
  508. case Platform.EXIT_AND_WARMBOOT:
  509. case Platform.EXIT_AND_RESTART:
  510. case Platform.EXIT_AND_SHUTDOWN:
  511. return exit;
  512. default:
  513. DebugStub.WriteLine("Shell process terminated improperly (0x{0:x4})",
  514. __arglist(exit));
  515. Tracing.Log(Tracing.Audit, "Shell process terminated improperly");
  516. DebugStub.Break();
  517. return Platform.EXIT_AND_SHUTDOWN;
  518. }
  519. }
  520. private static void InitBootTime()
  521. {
  522. if (Platform.ThePlatform.BootYear != 0) {
  523. BootTime = new DateTime((int)Platform.ThePlatform.BootYear,
  524. (int)Platform.ThePlatform.BootMonth,
  525. (int)Platform.ThePlatform.BootDay,
  526. (int)Platform.ThePlatform.BootHour,
  527. (int)Platform.ThePlatform.BootMinute,
  528. (int)Platform.ThePlatform.BootSecond,
  529. 0);
  530. // There is no time zone support in Singularity, the clock assumes GMT
  531. // but the CMOS reports it in local time. Hardcode the correction here for now
  532. BootTime = BootTime.AddHours(8);
  533. }
  534. else {
  535. // Other HALs do not capture the load time. Make the best effort to
  536. // capture now, after the devices are initialized.
  537. BootTime = DateTime.Now;
  538. }
  539. }
  540. private static void InitDrivers()
  541. {
  542. // Register drivers who depend on scheduling and resource management.
  543. DebugStub.WriteLine("--- Registering Drivers ---------------------------");
  544. Console.WriteLine("Registering Non-HAL Drivers.");
  545. // register the metadata-based drivers
  546. IoSystem.RegisterDrivers();
  547. ARM_PROGRESS("Kernel!061");
  548. // register the internal kernel drivers
  549. Devices.RegisterInternalDrivers();
  550. ARM_PROGRESS("Kernel!062");
  551. #if DEBUG
  552. // and output the results
  553. IoSystem.Dump(false);
  554. #endif
  555. DebugStub.WriteLine("--- Activating Devices ----------------------------");
  556. // now do device initialization
  557. IoSystem.ActivateDrivers();
  558. ARM_PROGRESS("Kernel!063");
  559. #if DEBUG
  560. // and output the results
  561. // IoSystem.Dump(true);
  562. #endif
  563. }
  564. private static void InitDiagnostics()
  565. {
  566. // Start up the kernel's diagnostics module
  567. Console.WriteLine("Starting diagnostics module...");
  568. Diagnostics.DiagnosticsModule.Initialize();
  569. ARM_PROGRESS("Kernel!066");
  570. // Start up the kernel's stress test module
  571. Console.WriteLine("Initializing stress module...");
  572. Stress.StressService.Initialize();
  573. ARM_PROGRESS("Kernel!067");
  574. }
  575. private static IoMemory GetSystemManifest()
  576. {
  577. IoMemory res = Binder.GetSystemManifest();
  578. if (res == null) {
  579. DebugStub.WriteLine("Failed to load system manifest.");
  580. DebugStub.Break();
  581. throw new Exception("The system manifest could not be loaded.");
  582. }
  583. return res;
  584. }
  585. private static void FinalizeServices()
  586. {
  587. ARM_PROGRESS("Kernel!075");
  588. Tracing.Log(Tracing.Audit, "Shutting down AP processors");
  589. Processor.StopApProcessors();
  590. Tracing.Log(Tracing.Audit, "Shutting down I/O system");
  591. Console.WriteLine("Shutting down I/O system");
  592. IoSystem.Finalize();
  593. Tracing.Log(Tracing.Audit, "Interrupts OFF.");
  594. Processor.DisableInterrupts();
  595. Tracing.Log(Tracing.Audit, "Shutting down scheduler");
  596. Console.WriteLine("Shutting down scheduler");
  597. for (int i = 0; i < Processor.processorTable.Length; i++) {
  598. Processor p = Processor.processorTable[i];
  599. if (p != null) {
  600. Console.WriteLine(" cpu {0}: {1} context switches, {2} interrupts", i, p.NumContextSwitches, p.NumInterrupts);
  601. }
  602. }
  603. // Finalize the scheduler
  604. scheduler.Finalize();
  605. // We should turn off interrupts here!
  606. Platform.ReleaseResources();
  607. PEImage.Finalize();
  608. DebugStub.WriteLine("Kernel Exiting [{0}]",
  609. __arglist(bootReturnCode));
  610. }
  611. private static void FinalizePreMonitoring()
  612. {
  613. Stacks.Finalize();
  614. HandleTable.Finalize();
  615. SharedHeap.Finalize();
  616. MemoryManager.Finalize();
  617. }
  618. private static int GetCpuCount(out int cpusLength)
  619. {
  620. int cpuReal = Platform.ThePlatform.CpuRealCount;
  621. int cpuLimit = Platform.ThePlatform.CpuMaxCount;
  622. DebugStub.Assert(cpuReal <= cpuLimit);
  623. // See if the command line argument limits our processor count
  624. int cpuCount = GetIntegerArgument("mp", cpuReal);
  625. cpusLength = cpuReal;
  626. #if !SINGULARITY_MP
  627. if (cpuCount > 1) {
  628. Console.WriteLine("Limiting processors to 1 due to SP build");
  629. cpuCount = 1;
  630. }
  631. #endif
  632. return cpuCount;
  633. }
  634. // Note: This function is entry point to the managed
  635. // kernel for CPU's other than the bootstrap processor.
  636. // It is called from the Hal or Hal.
  637. [AccessedByRuntime("referenced from hal.cpp")]
  638. internal static int MpMain(int cpu)
  639. {
  640. Tracing.Log(Tracing.Audit, "processor");
  641. Processor processor = Processor.EnableProcessor(cpu);
  642. // Initialize dispatcher
  643. Processor.InitializeDispatcher(cpu);
  644. // Initialize the HAL processor services
  645. // Note that this must occur after EnableProcessor, as the kernel
  646. // thread does not get bound until then. (It gets bound much
  647. // earlier in the boot processor case -- need to decide if this difference is
  648. // really appropriate.)
  649. Platform.Cpu(cpu).InitializeServices();
  650. Platform.InitializeHal(processor);
  651. Thread.CurrentThread.Affinity = cpu;
  652. Processor.ActivateTimer(cpu);
  653. #if DEBUG_SYSTEM_LOCKUP
  654. // Spin one CPU on debugger. For instance with a quad-proc
  655. // box, spin CPU 3.
  656. while (cpu == 3) {
  657. if (DebugStub.PollForBreak() == true) {
  658. DebugStub.Break();
  659. }
  660. }
  661. #endif // DEBUG_SYSTEM_LOCKUP
  662. Processor.RestoreInterrupts(true);
  663. Tracing.Log(Tracing.Audit,
  664. "Looping in processor's kernel thread.");
  665. //while (cpu > 0) {
  666. // Thread.Yield();
  667. //}
  668. // This probably won't be the
  669. // ultimate way of dissociating kernel entry threads
  670. // from the kernel.
  671. DebugStub.Print("AP Processor started, about to wait\n");
  672. mpEndEvent.WaitOne();
  673. return 0;
  674. }
  675. // This function is called by the GC to locate all non-static object
  676. // references allocated somewhere other than the stack.
  677. internal static
  678. void VisitSpecialData(System.GCs.DirectReferenceVisitor visitor)
  679. {
  680. Platform.ThePlatform.VisitSpecialData(visitor);
  681. Process.VisitSpecialData(visitor);
  682. visitor.VisitReferenceFields(Processor.processorTable);
  683. }
  684. // This function is called by GCs that move object to update all
  685. // object references contained in non-objects (i.e. unsafe structs).
  686. internal static void UpdateAfterGC(Thread currentThread)
  687. {
  688. Processor.UpdateAfterGC(currentThread);
  689. }
  690. [AccessedByRuntime("defined in HAL.cpp")]
  691. [MethodImpl(MethodImplOptions.InternalCall)]
  692. [StackBound(256)]
  693. [NoHeapAllocation]
  694. private static unsafe extern char * HalGetLinkDate();
  695. internal static unsafe string GetLinkDate()
  696. {
  697. return new String(HalGetLinkDate());
  698. }
  699. internal static unsafe string[] GetCommandLine()
  700. {
  701. String[] args =
  702. (new String((char *)(Platform.ThePlatform.CommandLine),
  703. 0, Platform.ThePlatform.CommandLineCount)).Split(null);
  704. int dst = 0;
  705. for (int src = 0; src < args.Length; src++) {
  706. if (args[src] != null && args[src].Length > 0) {
  707. args[dst++] = args[src];
  708. }
  709. }
  710. if (dst < args.Length) {
  711. String[] list = new String[dst];
  712. for (int i = 0; i < dst; i++) {
  713. list[i] = args[i];
  714. }
  715. return list;
  716. }
  717. return args;
  718. }
  719. // kind the argument "key" and extract the string value following a colon.
  720. internal static string
  721. GetStringArgument(string key, string defaultValue)
  722. {
  723. key = key + ":";
  724. for (int i = 0; i < args.Length; i++) {
  725. string arg = args[i];
  726. if ((arg.StartsWith("-") || arg.StartsWith("/")) &&
  727. 0 == String.Compare(arg, 1, key, 0, key.Length, true)) {
  728. string result = arg.Substring(key.Length+1);
  729. string[] newargs = new string[args.Length - 1];
  730. Array.Copy(args, 0, newargs, 0, i);
  731. Array.Copy(args, i + 1, newargs, i, args.Length - i - 1);
  732. args = newargs;
  733. return result;
  734. }
  735. }
  736. return defaultValue;
  737. }
  738. internal static int GetIntegerArgument(string key, int defaultValue)
  739. {
  740. key = key + ":";
  741. for (int i = 0; i < args.Length; i++) {
  742. string arg = args[i];
  743. if ((arg.StartsWith("-") || arg.StartsWith("/")) &&
  744. 0 == String.Compare(arg, 1, key, 0, key.Length, true)) {
  745. string result = arg.Substring(key.Length+1);
  746. string[] newargs = new string[args.Length - 1];
  747. Array.Copy(args, 0, newargs, 0, i);
  748. Array.Copy(args, i + 1, newargs, i, args.Length - i - 1);
  749. args = newargs;
  750. // TODO this should be try-parse
  751. return Int32.Parse(result);
  752. }
  753. }
  754. return defaultValue;
  755. }
  756. [NoHeapAllocation]
  757. public static void RequestWarmBoot()
  758. {
  759. bootReturnCode = Platform.EXIT_AND_WARMBOOT;
  760. }
  761. [NoHeapAllocation]
  762. public static void RequestRestart()
  763. {
  764. bootReturnCode = Platform.EXIT_AND_RESTART;
  765. }
  766. [NoHeapAllocation]
  767. public static void RequestShutdown()
  768. {
  769. bootReturnCode = Platform.EXIT_AND_SHUTDOWN;
  770. }
  771. private static void Kill(int exitCode)
  772. {
  773. Platform.ThePlatform.Kill(exitCode);
  774. }
  775. internal static void Shutdown(int exitCode)
  776. {
  777. unchecked {
  778. Tracing.Log(Tracing.Audit, "Kernel.Shutdown({0})", (UIntPtr)(uint)exitCode);
  779. }
  780. DebugStub.WriteLine("Kernel.Shutdown(0x{0:x4})",
  781. __arglist(exitCode));
  782. DebugStub.Break();
  783. VTable.Shutdown(exitCode);
  784. }
  785. // Rationale for cutting the fact that no stack probes are permitted in this
  786. // tree of calls:
  787. //
  788. // * We are already hosed.
  789. // * Without this cut, places that cannot (transitively) tolerate stack link extensions
  790. // * cannot call Panic.
  791. [NoStackLinkCheckTransCut][IgnoreLockRank]
  792. internal static void Panic(string why)
  793. {
  794. DebugStub.WriteLine("KERNEL PANIC: {0}", __arglist(why));
  795. Shutdown(Platform.EXIT_AND_HALT);
  796. }
  797. //////////////////////////////////////////////////////////////////////
  798. //
  799. [NoHeapAllocation]
  800. public static UIntPtr AddressOf(Object o)
  801. {
  802. return Magic.addressOf(o);
  803. }
  804. [NoHeapAllocation]
  805. public static UIntPtr SizeOf(Object o)
  806. {
  807. return System.GCs.ObjectLayout.Sizeof(o);
  808. }
  809. [NoHeapAllocation]
  810. public static UIntPtr AddressOf(ITracked tracked)
  811. {
  812. return Magic.addressOf(tracked);
  813. }
  814. [NoHeapAllocation]
  815. unsafe public static UIntPtr AddressOf(void * ptr)
  816. {
  817. return (UIntPtr)ptr;
  818. }
  819. public static void InitType(Type ty)
  820. {
  821. VTable.initType((RuntimeType) ty);
  822. }
  823. [NoHeapAllocation]
  824. public static string TypeName(Object o)
  825. {
  826. if (o == null) {
  827. return "null";
  828. }
  829. else {
  830. Type t = o.GetType();
  831. RuntimeType r = (RuntimeType)t;
  832. return r.Name;
  833. }
  834. }
  835. [NoHeapAllocation]
  836. public static string TypeNameSpace(Object o)
  837. {
  838. if (o == null) {
  839. return "null";
  840. }
  841. else {
  842. Type t = o.GetType();
  843. RuntimeType r = (RuntimeType)t;
  844. return r.Namespace;
  845. }
  846. }
  847. public static string FullTypeName(Object o)
  848. {
  849. if (o == null) {
  850. return "null";
  851. }
  852. else {
  853. Type t = o.GetType();
  854. RuntimeType r = (RuntimeType)t;
  855. return r.Namespace + "." + r.Name;
  856. }
  857. }
  858. public static void DumpPageTable()
  859. {
  860. System.GCs.PageTable.Dump("PageTable");
  861. }
  862. internal static void PrintBootTime()
  863. {
  864. // Console.WriteLine("Current time: {0}", SystemClock.GetUtcTime().ToString("r"));
  865. // Console.WriteLine("Boot time: {0}", BootTime.ToString("r"));
  866. TimeSpan delta = SystemClock.GetUtcTime() - BootTime;
  867. DebugStub.WriteLine("Elapsed boot time = {0} msec.", __arglist(delta.TotalMilliseconds));
  868. }
  869. }
  870. }