public static unsafe void SaveThreadState(uint threadID, IntPtr stackState) { //Assert.True(threadID < MaxThreads, "SaveThreadState(): invalid thread id > max"); var thread = Threads[threadID]; if (thread.Status != ThreadStatus.Running) { return; // New threads doesn't have a stack in use. Take the initial one. } //Assert.True(thread != null, "SaveThreadState(): thread id = null"); if (thread.User) { Assert.IsSet(thread.StackState, "thread.StackState is null"); *thread.StackState = *(IDTTaskStack *)stackState; } else { thread.StackState = (IDTTaskStack *)stackState; } if (KConfig.Log.TaskSwitch) { KernelMessage.Write("Task {0}: Stored ThreadState from {1:X8} stored at {2:X8}, EIP={3:X8}", threadID, (uint)stackState, (uint)thread.StackState, thread.StackState->Stack.EIP); if (thread.User) { KernelMessage.WriteLine(" ESP={0:X8}", thread.StackState->TASK_ESP); } else { KernelMessage.WriteLine(); } } }
/// <summary> /// Enable the IDTManager /// </summary> public static void Start() { KernelMessage.Write("Enabling interrupts..."); Enabled = true; Flush(); KernelMessage.WriteLine("done"); }
private static uint Cmd_WriteDebugChar(SysCallContext *context, SystemMessage *args) { var c = (char)args->Arg1; KernelMessage.Write(c); return(0); }
public static void Dump(bool canScheduled) { for (var i = 0; i < ThreadCapacity; i++) { var th = Threads[i]; if (th.CanScheduled == canScheduled && th.Status != ThreadStatus.Empty) { KernelMessage.Write("ThreadID={0} Status={1}", th.ThreadID, (uint)th.Status); if (th.DebugName != null) { KernelMessage.Write(" DebugName=" + th.DebugName); } if (th.Process != null && th.Process.Path != null) { KernelMessage.Write(" proc=" + th.Process.Path); } if (th.Process != null) { KernelMessage.Write(" procID=" + th.Process.ProcessID); } if (th.DebugSystemMessage.Target > 0) { var msg = th.DebugSystemMessage; KernelMessage.Write(" Target={0} arg1={1} arg2={2} arg3={3}", (uint)msg.Target, msg.Arg1, msg.Arg2, msg.Arg3); } KernelMessage.Write('\n'); } } }
internal static uint WriteDebugChar(ref SysCallContext context, ref SystemMessage args) { var c = (char)args.Arg1; KernelMessage.Write(c); return(0); }
public void EnablePaging() { KernelMessage.Write("Enable Paging... "); // Set CR0 register on processor - turns on virtual memory Native.SetCR0(Native.GetCR0() | 0x80000000); KernelMessage.WriteLine("Done"); }
public static void DumpToConsole(uint addr, uint length) { var sb = new StringBuffer(); sb.Append("{0:X}+{1:D} ", addr, length); KernelMessage.Write(sb); sb.Clear(); for (uint a = addr; a < addr + length; a++) { sb.Clear(); if (a != addr) { sb.Append(" "); } var m = Native.Get8(a); sb.Append(m, 16, 2); KernelMessage.Write(sb); } }
public static void DumpToConsoleLine(uint addr, uint length) { DumpToConsole(addr, length); KernelMessage.Write('\n'); }
public static unsafe void Setup() { KernelMessage.WriteLine("Setup IDT"); Enabled = false; InitControlBlock(); // Allocate memory for the IDT IDTAddr = VirtualPageManager.AllocatePages(1); KernelMemoryMapManager.Header->Used.Add(new KernelMemoryMap(IDTAddr, 4096, BootInfoMemoryType.IDT, AddressSpaceKind.Virtual)); PageTable.KernelTable.SetWritable(IDTAddr, 4096); KernelMessage.WriteLine("Address of IDT: {0:X8}", IDTAddr); // Setup IDT table Mosa.Runtime.Internal.MemoryClear(new Pointer((uint)IDTAddr), 6); Intrinsic.Store16(new Pointer((uint)IDTAddr), (Offset.TotalSize * 256) - 1); Intrinsic.Store32(new Pointer((uint)IDTAddr), 2, IDTAddr + 6); KernelMessage.Write("Set IDT table entries..."); SetTableEntries(); KernelMessage.WriteLine("done"); Handlers = new InterruptInfo[256]; for (var i = 0; i <= 255; i++) { var info = new InterruptInfo { Interrupt = i, CountStatistcs = true, Trace = true, Handler = InterruptHandlers.Undefined, }; if (i == (int)KnownInterrupt.ClockTimer) { info.Trace = false; info.CountStatistcs = false; } Handlers[i] = info; } // Set basic Interrupt handlers SetInterruptHandler(KnownInterrupt.DivideError, InterruptHandlers.DivideError); SetInterruptHandler(KnownInterrupt.ArithmeticOverflowException, InterruptHandlers.ArithmeticOverflowException); SetInterruptHandler(KnownInterrupt.BoundCheckError, InterruptHandlers.BoundCheckError); SetInterruptHandler(KnownInterrupt.InvalidOpcode, InterruptHandlers.InvalidOpcode); SetInterruptHandler(KnownInterrupt.CoProcessorNotAvailable, InterruptHandlers.CoProcessorNotAvailable); SetInterruptHandler(KnownInterrupt.DoubleFault, InterruptHandlers.DoubleFault); SetInterruptHandler(KnownInterrupt.CoProcessorSegmentOverrun, InterruptHandlers.CoProcessorSegmentOverrun); SetInterruptHandler(KnownInterrupt.InvalidTSS, InterruptHandlers.InvalidTSS); SetInterruptHandler(KnownInterrupt.SegmentNotPresent, InterruptHandlers.SegmentNotPresent); SetInterruptHandler(KnownInterrupt.StackException, InterruptHandlers.StackException); SetInterruptHandler(KnownInterrupt.GeneralProtectionException, InterruptHandlers.GeneralProtectionException); SetInterruptHandler(KnownInterrupt.PageFault, InterruptHandlers.PageFault); SetInterruptHandler(KnownInterrupt.CoProcessorError, InterruptHandlers.CoProcessorError); SetInterruptHandler(KnownInterrupt.SIMDFloatinPointException, InterruptHandlers.SIMDFloatinPointException); SetInterruptHandler(KnownInterrupt.ClockTimer, InterruptHandlers.ClockTimer); SetInterruptHandler(KnownInterrupt.TerminateCurrentThread, InterruptHandlers.TermindateCurrentThread); SetInterruptPreHandler(KnownInterrupt.Keyboard, InterruptHandlers.Keyboard); // apply IDT Start(); }
/// <summary> /// Stop the IDTManager /// </summary> public static void Stop() { KernelMessage.Write("Disable interrupts"); Native.Cli(); Enabled = false; }
public static unsafe Thread CreateThread(Process proc, ThreadStartOptions options) { Thread thread; uint threadID; lock (SyncRoot) { threadID = FindEmptyThreadSlot(); if (threadID == 0) { ResetTerminatedThreads(); threadID = FindEmptyThreadSlot(); Assert.False(threadID == 0 && Enabled, "No more free Thread-Slots!"); } thread = Threads[threadID]; thread.Status = ThreadStatus.Creating; } // Debug: //options.User = false; thread.User = proc.User; thread.Debug = options.Debug; thread.DebugName = options.DebugName; thread.Priority = options.Priority; var stackSize = options.StackSize; var argBufSize = options.ArgumentBufferSize; thread.ArgumentBufferSize = options.ArgumentBufferSize; var stackPages = KMath.DivCeil(stackSize, PhysicalPageManager.PageSize); if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("Requesting {0} stack pages", stackPages); } var debugPadding = 8u; stackSize = stackPages * PhysicalPageManager.PageSize; var stack = new Pointer((void *)VirtualPageManager.AllocatePages(stackPages, new AllocatePageOptions { DebugName = "ThreadStack" })); PageTable.KernelTable.SetWritable((uint)stack, stackSize); if (thread.User && proc.PageTable != PageTable.KernelTable) { proc.PageTable.MapCopy(PageTable.KernelTable, (uint)stack, stackSize); } stackSize -= debugPadding; var stackBottom = stack + (int)stackSize; if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.Write("Create Thread {0}. EntryPoint: {1:X8} Stack: {2:X8}-{3:X8} Type: ", threadID, options.MethodAddr, (uint)stack, (uint)stackBottom - 1); } if (KConfig.Log.Threads >= KLogLevel.Trace) { if (thread.User) { KernelMessage.Write("User"); } else { KernelMessage.Write("Kernel"); } } if (KConfig.Log.Threads >= KLogLevel.Trace) { if (thread.DebugName != null) { KernelMessage.Write(" Thread DebugName: {0}", thread.DebugName); } if (thread.Process != null) { KernelMessage.WriteLine(" Process: {0}", thread.Process.Path); } } // -- kernel stack thread.KernelStackSize = 4 * 4096; //thhread.tssAddr = RawVirtualFrameAllocator.RequestRawVirtalMemoryPages(1); PageTable.KernelTable.SetWritable(KernelStart.TssAddr, 4096); thread.KernelStack = VirtualPageManager.AllocatePages( KMath.DivCeil(thread.KernelStackSize, 4096), new AllocatePageOptions { DebugName = "ThreadKernelStack" }); // TODO: Decrease Kernel Stack, because Stack have to be changed directly because of multi-threading. thread.KernelStackBottom = thread.KernelStack + thread.KernelStackSize; if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("tssEntry: {0:X8}, tssKernelStack: {1:X8}-{2:X8}", KernelStart.TssAddr, thread.KernelStack, thread.KernelStackBottom - 1); } PageTable.KernelTable.SetWritable(thread.KernelStack, 256 * 4096); // --- uint stackStateOffset = 8; stackStateOffset += argBufSize; uint cS = 0x08; if (thread.User) { cS = 0x1B; } var stateSize = thread.User ? IDTTaskStack.Size : IDTStack.Size; thread.StackTop = (uint)stack; thread.StackBottom = (uint)stackBottom; Intrinsic.Store32(stackBottom, 4, 0xFF00001); // Debug Marker Intrinsic.Store32(stackBottom, 0, 0xFF00002); // Debug Marker Intrinsic.Store32(stackBottom, -4, (uint)stackBottom); Intrinsic.Store32(stackBottom, -(8 + (int)argBufSize), SignalThreadTerminationMethodAddress.ToInt32()); // Address of method that will raise a interrupt signal to terminate thread uint argAddr = (uint)stackBottom - argBufSize; IDTTaskStack *stackState = null; if (thread.User) { stackState = (IDTTaskStack *)VirtualPageManager.AllocatePages(1, new AllocatePageOptions { DebugName = "ThreadStackState" }); if (proc.PageTable != PageTable.KernelTable) { proc.PageTable.MapCopy(PageTable.KernelTable, (uint)stackState, IDTTaskStack.Size); } } else { stackState = (IDTTaskStack *)(stackBottom - 8 - IDTStack.Size); // IDTStackSize is correct - we don't need the Task-Members. } thread.StackState = stackState; if (thread.User && KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("StackState at {0:X8}", (uint)stackState); } stackState->Stack.EFLAGS = X86_EFlags.Reserved1; if (thread.User) { // Never set this values for Non-User, otherwise you will override stack informations. stackState->TASK_SS = 0x23; stackState->TASK_ESP = (uint)stackBottom - (uint)stackStateOffset; proc.PageTable.MapCopy(PageTable.KernelTable, thread.KernelStack, thread.KernelStackSize); proc.PageTable.MapCopy(PageTable.KernelTable, KernelStart.TssAddr, 4096); } if (thread.User && options.AllowUserModeIOPort) { byte IOPL = 3; stackState->Stack.EFLAGS = (X86_EFlags)((uint)stackState->Stack.EFLAGS).SetBits(12, 2, IOPL); } stackState->Stack.CS = cS; stackState->Stack.EIP = options.MethodAddr; stackState->Stack.EBP = (uint)(stackBottom - (int)stackStateOffset).ToInt32(); thread.DataSelector = thread.User ? 0x23u : 0x10u; UninterruptableMonitor.Enter(proc.Threads); try { thread.Process = proc; proc.Threads.Add(thread); } finally { UninterruptableMonitor.Exit(proc.Threads); } ThreadsAllocated++; if (ThreadsAllocated > ThreadsMaxAllocated) { ThreadsMaxAllocated = ThreadsAllocated; if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("Threads Max Allocated: {0}. Allocated {0} Active: {1}", ThreadsMaxAllocated, ThreadsAllocated, GetActiveThreadCount()); } if (KConfig.Log.Threads >= KLogLevel.Trace) { DumpStats(); } } else if (KConfig.Log.Threads >= KLogLevel.Debug) { KernelMessage.WriteLine("Threads Allocated {0} Active: {1}", ThreadsAllocated, GetActiveThreadCount()); } return(thread); }
private static unsafe void SelfTest(IPageFrameAllocator allocator) { if (SelfTestDump) { allocator.DumpPages(); } KernelMessage.WriteLine("Begin SelfTest {0}", allocator.DebugName); var ptrPages = (allocator.TotalPages * 4) / 4096; var ptrListAddr = AllocatePages(ptrPages); // pointers for 4GB of pages var ptrList = (Addr *)ptrListAddr; var checkPageCount = allocator.FreePages; checkPageCount -= allocator.CriticalLowPages; uint checkPagesEach = 4; checkPageCount /= checkPagesEach; //checkPageCount = 32; var mapPhysAddr = PhysicalPageManager.AllocatePageAddr(checkPagesEach); for (var i = 0; i < checkPageCount; i++) { if (SelfTestDump) { KernelMessage.Write("."); } var testAddr = allocator.AllocatePagesAddr(checkPagesEach); ptrList[i] = testAddr; //KernelMessage.WriteLine("{0:X8}-->{1:X8}", testAddr, mapPhysAddr); PageTable.KernelTable.Map(testAddr, mapPhysAddr, 4096 * checkPagesEach, true, true); var mapPtr = (uint *)testAddr; for (var pos = 0; pos < 1024 * checkPagesEach; pos++) { *mapPtr = 0xEBFEEBFE; mapPtr += 1; } PageTable.KernelTable.UnMap(testAddr, 4096 * checkPagesEach, true); //Default.Free(testPage); } PhysicalPageManager.FreeAddr(mapPhysAddr); if (SelfTestDump) { allocator.DumpPages(); } KernelMessage.WriteLine("Free Pages now"); for (var i = 0; i < checkPageCount; i++) { if (SelfTestDump) { KernelMessage.Write(":"); } var testAddr = ptrList[i]; //KernelMessage.WriteLine("Free: {0:X8}", testAddr); allocator.FreeAddr(testAddr); } KernelMessage.WriteLine("Free ptrList"); FreeAddr(ptrListAddr); KernelMessage.WriteLine("SelfTest Done"); if (SelfTestDump) { allocator.DumpPages(); KernelMessage.WriteLine("Final Dump"); } }
public static void SelfTest() { if (SelfTestDump) { Default.DumpPages(); } KernelMessage.WriteLine("Begin SelfTest"); var ptrPages = ((BootInfo.Header->InstalledPhysicalMemory / 4096) * 4) / 4096; var ptrList = (Addr *)AllocatePageAddr(ptrPages); // pointers for 4GB of pages var ptrListMapped = (Addr *)0x3000; PageTable.KernelTable.Map(ptrListMapped, ptrList, ptrPages * 4096, true, true); var checkPageCount = Default.FreePages; checkPageCount -= Default.CriticalLowPages; //checkPageCount = 32; var mapAddr = 0x2000u; for (var i = 0; i < checkPageCount; i++) { if (SelfTestDump) { KernelMessage.Write("."); } var testPage = Default.AllocatePage(); var testAddr = Default.GetAddress(testPage); ptrListMapped[i] = testAddr; PageTable.KernelTable.Map(mapAddr, testAddr, 4096, true, true); var mapPtr = (uint *)mapAddr; for (var pos = 0; pos < 1024; pos++) { *mapPtr = 0xEBFEEBFE; mapPtr += 1; } PageTable.KernelTable.UnMap(mapAddr, 4096, true); //Default.Free(testPage); } if (SelfTestDump) { Default.DumpPages(); } KernelMessage.WriteLine("Free Pages now"); for (var i = 0; i < checkPageCount; i++) { if (SelfTestDump) { KernelMessage.Write(":"); } var testAddr = ptrListMapped[i]; Default.FreeAddr(testAddr); } Default.FreeAddr(ptrList); KernelMessage.WriteLine("SelfTest Done"); if (SelfTestDump) { Default.DumpPages(); KernelMessage.WriteLine("Final Dump"); } }