private static int DetermineShutdown(int exit) { switch (exit) { case -10000: Tracing.Log(Tracing.Audit, "Failed to start shell process."); return(Platform.EXIT_AND_RESTART); case Platform.EXIT_AND_WARMBOOT: case Platform.EXIT_AND_RESTART: case Platform.EXIT_AND_SHUTDOWN: return(exit); default: DebugStub.WriteLine("Shell process terminated improperly (0x{0:x4})", __arglist(exit)); Tracing.Log(Tracing.Audit, "Shell process terminated improperly"); DebugStub.Break(); return(Platform.EXIT_AND_SHUTDOWN); } }
private static int GetCpuCount(out int cpusLength) { int cpuReal = Platform.ThePlatform.CpuRealCount; int cpuLimit = Platform.ThePlatform.CpuMaxCount; DebugStub.Assert(cpuReal <= cpuLimit); // See if the command line argument limits our processor count int cpuCount = GetIntegerArgument("mp", cpuReal); cpusLength = cpuReal; #if !SINGULARITY_MP if (cpuCount > 1) { Console.WriteLine("Limiting processors to 1 due to SP build"); cpuCount = 1; } #endif return(cpuCount); }
public static void WaypointDump() { bool iflag = Processor.DisableInterrupts(); DebugStub.WriteLine("Interrupts: {0}", __arglist(Processor.CurrentProcessor.NumInterrupts - WaypointInterrupt)); DebugStub.WriteLine("WPT Waypoint Sequence THD Diff"); for (int i = 1; i < WaypointNumber; i++) { DebugStub.WriteLine("{0,3:d} {1,10:d} {2,10:d} {3,3:d} {4,10:d}", __arglist( i, Waypoints[i], WaypointSeq[i], WaypointThd[i].GetHashCode(), Waypoints[i] - Kernel.Waypoints[i - 1])); } Processor.RestoreInterrupts(iflag); }
// Create a log entry for the allocation that just occurred on this thread. protected override void Allocation(UIntPtr objAddr, Type type, UIntPtr size) { bool iflag; // We cannot recurse inside an Allocation notification, or we will simply // blow the stack on the first entry. Also, we don't want to log allocations // that occur as a consequence of logging the state of the GC heap -- though // we could support that if we chose to. if (enabled && recurseThread != Thread.CurrentThread && // recurse? Buffer.OwningThread != Thread.CurrentThread) // GC logging? { iflag = Processor.DisableLocalPreemption(); allocationLock.Acquire(); try { DebugStub.Assert(recurseThread == null); recurseThread = Thread.CurrentThread; Buffer.LogTick(); uint stackSize = Isa.GetStackReturnAddresses(stackEips); uint stkNo = 0; if (stackSize > 0) { stkNo = GetStackId(type, size, stackEips, stackSize); } ProfilerBuffer.LogAllocation(Thread.CurrentThread.GetThreadId(), objAddr, stkNo); } finally { recurseThread = null; allocationLock.Release(); Processor.RestoreLocalPreemption(iflag); } } }
// A GC has finished. The world is in a sane place, except that we might not // have started up all the mutator threads if this is a StopTheWorld collection. protected override void PostGC() { try { // emit the fact a GC has happened, including the state of the heap. // TODO: have another function to log the tick count here to estimate the // time spent in GC too. Buffer.LogTick(); // We should have an empty buffer, meaning we completed logging from the // previous operation while entering this code. DebugStub.Assert(tempGCBufferEntries == 0); ScanRoots(); unsafe { fixed(UIntPtr *ptr = &tempGCBuffer[0]) { ProfilerBuffer.LogRoots(tempGCBufferEntries, ptr); tempGCBufferEntries = 0; } } // Write all the reachability graph of the heap ScanObjects(); // Once we have finished writing everything, we can allow mutator threads to // share access to the fileBuffer with their own consistent entries. DebugStub.Assert(Buffer.OwningThread == Thread.CurrentThread); Buffer.OwningThread = null; } catch (Exception) { enabled = false; throw; } }
FreezeProcessor(ref SpillContext threadContext) { ProcessorContext *context = Processor.GetCurrentProcessorContext(); if (context->ipiFreeze == Uninitialized) { // Processor was still being initialized when IPI issued while (FreezeRequested == true) { ; // just spin until thaw occurs } return; } context->ipiFreeze = TargetFrozen; while (context->ipiFreeze != TargetThaw && FreezeRequested) { if ((context->ipiFreeze & FreezeActive) == FreezeActive) { // // This processor has been made the active processor // activeCpuContext = context; // Pass state over to debugger stub if (DebugStub.TrapForProcessorSwitch(ref threadContext)) { // We're returning to Freeze owner, make it active context->ipiFreeze &= ~FreezeActive; ownerCpuContext->ipiFreeze |= FreezeActive; } } } context->ipiFreeze = Running; }
static internal unsafe void AddProcessorContext(ProcessorContext *context) { // Add processor to list of processors in MP system. Careful // to avoid adding processor mid-freeze or without lock. start: freezeLock.Acquire(); try { if (FreezeRequested) { goto start; } ProcessorContext *head = Processor.processorTable[0].context; context->nextProcessorContext = head->nextProcessorContext; head->nextProcessorContext = context; context->ipiFreeze = Running; // From this point on the processor is visible // in the debugger DebugStub.AddProcessor(context->cpuRecord.id); } finally { freezeLock.Release(); } }
public static void StopApProcessors() { // // Note: This should go into a HAL interface and this // code confined to Platform.cs // // At this point the BSP and APs are running. Tracing.Log(Tracing.Debug, "Processor.StopApProcessors()"); if (Processor.GetRunningProcessorCount() > 1) { // // This stops them in MpExecution in a halt state with // interrupts off. // Platform.BroadcastFixedIPI((byte)Isal.IX.EVectors.HaltApProcessors, true); } while (GetRunningProcessorCount() != 1) { // Thread.Sleep(100); Thread.Sleep needs NoHeapAllocation annotation Thread.Yield(); } // // We must reset the AP Processors since a debug entry // will generated a NMI which will wake them up from HALT, // and they may start executing code again while the kernel // is still shutting down. // Platform.ResetApProcessors(); DebugStub.RevertToUniprocessor(); // At this point only the BSP is running. }
public void Uninitialize(int processorId) { Tracing.Log(Tracing.Debug, "UnInitializing Processor {0}", (UIntPtr)processorId); Interlocked.Decrement(ref runningCpus); // #if DEBUG // Interrupts should be off now if (!InterruptsDisabled()) { DebugStub.WriteLine("Processor::Uninitialize AP Processor does not have interrupts disabled\n"); DebugStub.Break(); } // #endif // DBG // Processor is out of commission HaltUntilInterrupt(); // #if DEBUG DebugStub.WriteLine("Processor::Uninitialize: AP processor woke up on shutdown!\n"); DebugStub.Break(); // #endif // DBG }
// The public API for a typical client app. static public void StartProfiling() { // Query the diagnosis service whether the GC profiling is enabled // This allows setting from the kernel debugger the buffer sizes // for both kernel and SIP profiling. // Note, these are controlled independently, the implementation // of GCProfileSettings is different between kernel and SIP if (CurrentProfiler != null) { // // The profiler has been set already. No second attempt is allowed // return; } unsafe { int result; ulong defaultMemorySize = 0; ulong Options = 0; result = DiagnosisService.GCProfileSettingsImpl( out defaultMemorySize, out Options ); if ((result == 0) && (defaultMemorySize > 0)) { CurrentProfiler = new GCProfilerLogger(); CurrentProfiler.Initialize(defaultMemorySize, Options); GC.SetProfiler(CurrentProfiler); DebugStub.WriteLine("GC Profiling started"); } } }
// // Someone must arrange to call this from *within* the // Protection Domain for us to have an opportunity to finish // initializing. // internal unsafe void InitHook() { // If paging is disabled then just return immediately if (!MemoryManager.UseAddressTranslation) { return; } DebugStub.Assert(AddressSpace.CurrentAddressSpace == this.AddressSpace); if (this.initialized) { // Someone else has already set up the space return; } bool iflag = initSpin.Lock(); try { if (this.initialized) { // Someone else snuck in and initialized return; } // // We're first into this space, so set it up. // #if VERBOSE DebugStub.WriteLine("Setting up protection domain \"{0}\"", __arglist(this.name)); #endif userRange = new VirtualMemoryRange(VMManager.UserHeapBase, VMManager.UserHeapLimit, this); #if PAGING if (kernelMode) { // This will be a ring-0, trusted domain, so just // point the userSharedHeap at the kernel's comm heap. userSharedHeap = SharedHeap.KernelSharedHeap; this.initialized = true; } else { // Create a new shared heap that lives in // user-land. userSharedHeap = new SharedHeap(this, userRange); #if VERBOSE DebugStub.WriteLine(" ...Created a shared heap"); #endif // // N.B.: this is kind of tricky. Loading an // executable image involves allocating memory, // which goes through this object. So, before // attempting the load, mark ourselves as initialized. // // ---- DON'T PUT GENUINE INITIALIZATION // CODE BELOW HERE! --------- this.initialized = true; // Load our own, protection-domain-private copy of the // ABI stubs. These will get shared by all apps in // this domain. IoMemory syscallsMemory = Binder.LoadRawImage("/init", "syscalls.dll"); IoMemory loadedMemory; // Load the stubs library into the user range, but make // the kernel process the logical owner. This seems like // the only sensible approach since the stubs do not // belong to any particular process but must be in the // user range of memory. // N.B.: RE-ENTERS this object! ring3AbiImage = PEImage.Load(Process.kernelProcess, syscallsMemory, out loadedMemory, false, // isForMp false // inKernelSpace ); ring3AbiExports = ring3AbiImage.GetExportTable(loadedMemory); #if VERBOSE DebugStub.WriteLine(" ...Loaded ring-3 ABI stubs"); #endif } #else // PAGING this.initialized = true; #endif // PAGING } finally { DebugStub.Assert(this.initialized); initSpin.Unlock(iflag); } }
internal static void Panic(string why) { DebugStub.WriteLine("KERNEL PANIC: {0}", __arglist(why)); Shutdown(Platform.EXIT_AND_HALT); }
private static void InitServices() { InitGCSupport(); args = GetCommandLine(); VTable.ParseArgs(args); ARM_PROGRESS("Kernel!011"); InitSchedulerTypes(); ARM_PROGRESS("Kernel!018"); Controller.InitializeSystem(); Tracing.InitializeSystem(); ARM_PROGRESS("Kernel!019"); // Read the profiler settings. The values are assumed in kbytes // convert them to bytes for direct consumption ProfilerBufferSize = (uint)GetIntegerArgument("profiler", 0); ProfilerBufferSize *= 1024; ARM_PROGRESS("Kernel!020"); SpinLock.StaticInitialize(); int cpusLength; int cpuCount = GetCpuCount(out cpusLength); Processor.InitializeProcessorTable(cpusLength); ARM_PROGRESS("Kernel!021"); Tracing.Log(Tracing.Audit, "processor"); Processor processor = Processor.EnableProcessor(0); PEImage.Initialize(); ARM_PROGRESS("Kernel!034"); // Initialize the sample profiling for the processor // after the initial breakpoint in kd in the call // PEImage.Initialize(). This will allow enabling profiling // from kd, by overwriting the ProfilerBufferSize value processor.EnableProfiling(); ARM_PROGRESS("Kernel!035"); FlatPages.InitializeMemoryMonitoring(); // initialize endpoints InitType(typeof(Microsoft.Singularity.Channels.EndpointCore)); // TODO Bug 59: Currently broken, need to review paging build. //#if PAGING // Microsoft.Singularity.Channels.EndpointTrusted.StaticInitialize(); //#endif ARM_PROGRESS("Kernel!036"); // get the system manifest IoMemory systemManifest = GetSystemManifest(); ARM_PROGRESS("Kernel!037"); XmlReader xmlReader = new XmlReader(systemManifest); XmlNode xmlData = xmlReader.Parse(); XmlNode manifestRoot = xmlData.GetChild("system"); XmlNode initConfig = manifestRoot.GetChild("initConfig"); ARM_PROGRESS("Kernel!038"); PerfCounters.Initialize(); // need to have processed the manifest before we can call Process initialize ARM_PROGRESS("Kernel!039"); PrincipalImpl.Initialize(initConfig); ARM_PROGRESS("Kernel!040"); Process.Initialize(manifestRoot.GetChild("processConfig")); InitIO(processor, initConfig, manifestRoot.GetChild("drivers")); InitBootTime(); ARM_PROGRESS("Kernel!045"); // From here on, we want lazy type initialization to worry about // competing threads. VTable.InitializeForMultipleThread(); ARM_PROGRESS("Kernel!046"); Console.WriteLine("Running C# Kernel of {0}", GetLinkDate()); Console.WriteLine(); // TODO: remove this Console.WriteLine("Current time: {0}", SystemClock.GetUtcTime().ToString("r")); ARM_PROGRESS("Kernel!047"); InitScheduling(); DirectoryService.StartNotificationThread(); Console.WriteLine("Initializing Shared Heap Walker"); ProtectionDomain.InitializeSharedHeapWalker(); ARM_PROGRESS("Kernel!050"); Console.WriteLine("Initializing Service Thread"); ServiceThread.Initialize(); ARM_PROGRESS("Kernel!051"); GC.EnableHeap(); GCProfilerLogger.StartProfiling(); ARM_PROGRESS("Kernel!052"); Tracing.Log(Tracing.Audit, "Waypoints init"); Waypoints = new long[2048]; WaypointSeq = new int[2048]; WaypointThd = new int[2048]; Tracing.Log(Tracing.Audit, "Interrupts ON."); Processor.RestoreInterrupts(true); ARM_PROGRESS("Kernel!053"); #if ISA_ARM && TEST_GC for (int i = 0; i < 1000; i++) { DebugStub.WriteLine("Iteration {0}", __arglist(i)); ArrayList a = new ArrayList(); for (int j = 0; j < 128; j++) { int size = 1024 * 1024; a.Add(new byte [size]); } } #endif // ISA_ARM ARM_PROGRESS("Kernel!054"); Tracing.Log(Tracing.Audit, "Binder"); Binder.Initialize(manifestRoot.GetChild("namingConventions")); #if ISA_ARM DebugStub.WriteLine("Exporting local namespace to BSP\n"); DirectoryService.ExportArmNamespace(); DebugStub.WriteLine("Export complete...redirecting binder\n"); Binder.RedirectRootRef(); DebugStub.WriteLine("Binder redirect complete\n"); #endif #if false Tracing.Log(Tracing.Audit, "Starting Security Service channels"); PrincipalImpl.Export(); ARM_PROGRESS("Kernel!055"); #endif Tracing.Log(Tracing.Audit, "Creating Root Directory."); //This can be moved below IoSystem.InitializeDirectoryService(); ARM_PROGRESS("Kernel!055"); #if false // Start User space namespace manager Console.WriteLine("Starting Directory Service SIP"); DirectoryService.StartUserSpaceDirectoryService(); #endif ARM_PROGRESS("Kernel!055.5"); #if !ISA_ARM Tracing.Log(Tracing.Audit, "Starting Security Service channels"); PrincipalImpl.Export(); #endif ARM_PROGRESS("Kernel!056"); Console.WriteLine("Initializing system channels"); // starting channels services DebugStub.Print("Initializing Channel Services\n"); ChannelDeliveryImplService.Initialize(); ARM_PROGRESS("Kernel!057"); ConsoleOutput.Initialize(); ARM_PROGRESS("Kernel!058"); // Initialize MP after Binder and ConsoleOutput // are initialized so there are no // initialization races if the additional // threads try to use them. Tracing.Log(Tracing.Audit, "Starting additional processors"); // For ABI to ARM support MpExecution.Initialize(); ARM_PROGRESS("Kernel!059"); mpEndEvent = new ManualResetEvent(false); Tracing.Log(Tracing.Audit, "Initializing Volume Manager."); #if !ISA_ARM IoSystem.InitializeVolumeManager(); #endif // ISA_ARM ARM_PROGRESS("Kernel!060"); InitDrivers(); if (cpuCount > 1) { unsafe { Console.WriteLine("Enabling {0} cpus out of {1} real cpus\n", cpuCount, Platform.ThePlatform.CpuRealCount); } Processor.EnableMoreProcessors(cpuCount); ARM_PROGRESS("Kernel!064"); } Tracing.Log(Tracing.Audit, "Initializing Service Manager."); IoSystem.InitializeServiceManager(manifestRoot.GetChild("serviceConfig")); ARM_PROGRESS("Kernel!065"); InitDiagnostics(); #if !ISA_ARM // At this point consider kernel finshed booting hasBooted = true; #endif // ISA_ARM Processor.StartSampling(); ARM_PROGRESS("Kernel!069"); Microsoft.Singularity.KernelDebugger.KdFilesNamespace.StartNamespaceThread(); ARM_PROGRESS("Kernel!070"); }
// [System.Diagnostics.Conditional("ISA_ARM")] private static void ARM_PROGRESS(string msg) { DebugStub.WriteLine(msg); }
internal static void InvalidateTLBEntry(UIntPtr pageAddr) { DebugStub.Assert(MemoryManager.IsPageAligned(pageAddr)); Isa.InvalidateTLBEntry(pageAddr); }