Example #1
0
        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();
                }
            }
        }
Example #2
0
 /// <summary>
 /// Enable the IDTManager
 /// </summary>
 public static void Start()
 {
     KernelMessage.Write("Enabling interrupts...");
     Enabled = true;
     Flush();
     KernelMessage.WriteLine("done");
 }
Example #3
0
        private static uint Cmd_WriteDebugChar(SysCallContext *context, SystemMessage *args)
        {
            var c = (char)args->Arg1;

            KernelMessage.Write(c);
            return(0);
        }
Example #4
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');
                }
            }
        }
Example #5
0
        internal static uint WriteDebugChar(ref SysCallContext context, ref SystemMessage args)
        {
            var c = (char)args.Arg1;

            KernelMessage.Write(c);
            return(0);
        }
Example #6
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");
        }
Example #7
0
        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);
            }
        }
Example #8
0
 public static void DumpToConsoleLine(uint addr, uint length)
 {
     DumpToConsole(addr, length);
     KernelMessage.Write('\n');
 }
Example #9
0
        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();
        }
Example #10
0
 /// <summary>
 /// Stop the IDTManager
 /// </summary>
 public static void Stop()
 {
     KernelMessage.Write("Disable interrupts");
     Native.Cli();
     Enabled = false;
 }
Example #11
0
        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);
        }
Example #12
0
        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");
            }
        }
Example #13
0
        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");
            }
        }