Esempio n. 1
0
        /// <summary>
        /// Switch to a specific thread.
        /// This method will not return!
        /// </summary>
        public static unsafe void SwitchToThread(int threadID)
        {
            var thread = Threads[threadID];
            var proc   = thread.Process;

            if (KConfig.Log.TaskSwitch)
            {
                KernelMessage.WriteLine("Switching to Thread {0}. StackState: {1:X8}", threadID, (uint)thread.StackState);
            }

            //Assert.True(thread != null, "invalid thread id");

            thread.Ticks++;

            SetThreadID(threadID);

            PIC.SendEndOfInterrupt((int)KnownInterrupt.ClockTimer);

            thread.Status = ThreadStatus.Running;

            if (thread.StackState == null)
            {
                DumpStats();
                KernelMessage.WriteLine("threadID: {0}", threadID);
                Debug.Break();
            }

            thread.StackState->Stack.EFLAGS |= X86_EFlags.InterruptEnableFlag;

            if (proc.PageTable != PageTable.KernelTable)
            {
                Debug.Nop();
            }

            uint pageDirAddr = proc.PageTable.GetPageTablePhysAddr();
            //KernelMessage.WriteLine("PageDirAddr: {0:X8}", pageDirAddr);
            uint stackStateAddr = (uint)thread.StackState;
            uint dataSelector   = thread.DataSelector;

            if (!thread.User)
            {
                thread.StackState = null; // just to be sure
            }
            GDT.Tss->ESP0 = thread.KernelStackBottom;

            if (thread.Debug)
            {
                Native.Nop();
            }

            GDT.SetThreadStorageSegmentBase(thread.ThreadLocalStorageBaseAddr);

            InterruptReturn(stackStateAddr, pageDirAddr, dataSelector, KnownSegments.UserThreadStorage);
        }
Esempio n. 2
0
File: IDT.cs Progetto: djlw78/abanu
        /// <summary>
        /// Entry point into the ISR (Interrupt Service Routine)
        /// </summary>
        /// <param name="stack">Pointer to the ISR stack</param>
        private static unsafe void ProcessInterrupt(ref IDTStack stack)
        {
            // Switch to Kernel segments
            ushort dataSelector = KnownSegments.KernelData;

            Native.SetSegments(dataSelector, dataSelector, KnownSegments.KernelThreadStorage, dataSelector, dataSelector);

            // Switch to Kernel Adresse space
            var block = (InterruptControlBlock *)Address.InterruptControlBlock;

            Native.SetCR3(block->KernelPageTableAddr);

            // Get the IRQ
            var irq = stack.Interrupt;

            // Get the pagetable address of the interrupted process
            uint pageTableAddr = 0;
            var  thread        = Scheduler.GetCurrentThread();

            if (thread != null)
            {
                dataSelector  = (ushort)thread.DataSelector;
                pageTableAddr = thread.Process.PageTable.GetPageTablePhysAddr();
            }

            // If the IDTManager is not initialized yet or hard disabled, we return now
            if (!IDTManager.Enabled)
            {
                PIC.SendEndOfInterrupt(irq);
                return;
            }

            // Get interrupt info for the IRQ
            var interruptInfo = IDTManager.Handlers[irq];

            if (KConfig.Log.Interrupts && interruptInfo.Trace && thread != null)
            {
                KernelMessage.WriteLine("Interrupt {0}, Thread {1}, EIP={2:X8} ESP={3:X8}", irq, (uint)thread.ThreadID, stack.EIP, stack.ESP);
            }

            // Some statistics

            IDTManager.RaisedCount++;

            if (interruptInfo.CountStatistcs)
            {
                IDTManager.RaisedCountCustom++;
            }

            if (KConfig.Log.Interrupts)
            {
                if (interruptInfo.Trace)
                {
                    KernelMessage.WriteLine("Interrupt: {0}", irq);
                }

                var col = Screen.Column;
                var row = Screen.Row;
                Screen.Column = 0;
                Screen.Goto(2, 35);
                Screen.Write("Interrupts: ");
                Screen.Write(IDTManager.RaisedCount);
                Screen.Goto(3, 35);
                Screen.Write("IntNoClock: ");
                Screen.Write(IDTManager.RaisedCountCustom);
                Screen.Row    = row;
                Screen.Column = col;
            }

            // This should never happen
            if (irq < 0 || irq > 255)
            {
                Panic.Error("Invalid Interrupt");
            }

            // Invoke handlers

            if (interruptInfo.PreHandler != null)
            {
                interruptInfo.PreHandler(ref stack);
            }

            if (interruptInfo.Handler == null)
            {
                Panic.Error("Handler is null");
            }
            else
            {
            }

            interruptInfo.Handler(ref stack);

            // Important! Otherwise we will get any more interrupts of this kind
            PIC.SendEndOfInterrupt(irq);

            // Switch to original address space
            if (pageTableAddr > 0)
            {
                Native.SetCR3(pageTableAddr);
            }

            // Switch to original segments
            Native.SetSegments(dataSelector, dataSelector, KnownSegments.UserThreadStorage, dataSelector, KnownSegments.KernelData);

            // ISR is completed. The upper ISR stub will re-enable interrupts and resume the original process
        }
Esempio n. 3
0
        /// <summary>
        /// Interrupts the handler.
        /// </summary>
        /// <param name="stackStatePointer">The stack state pointer.</param>
        private static unsafe void ProcessInterrupt(uint stackStatePointer)
        {
            ushort dataSelector = 0x10;

            Native.SetSegments(dataSelector, dataSelector, dataSelector, dataSelector, dataSelector);
            var block = (InterruptControlBlock *)Address.InterruptControlBlock;

            Native.SetCR3(block->KernelPageTableAddr);

            //KernelMessage.WriteLine("Interrupt occurred");

            var stack = (IDTStack *)stackStatePointer;
            var irq   = stack->Interrupt;

            uint pageTableAddr = 0;
            var  thread        = Scheduler.GetCurrentThread();

            if (thread != null)
            {
                dataSelector  = (ushort)thread.DataSelector;
                pageTableAddr = thread.Process.PageTable.GetPageTablePhysAddr();
            }

            if (!IDTManager.Enabled)
            {
                PIC.SendEndOfInterrupt(irq);
                return;
            }

            var interruptInfo = IDTManager.Handlers[irq];

            if (KConfig.Log.Interrupts && interruptInfo.Trace && thread != null)
            {
                KernelMessage.WriteLine("Interrupt {0}, Thread {1}, EIP={2:X8} ESP={3:X8}", irq, thread.ThreadID, stack->EIP, stack->ESP);
            }

            IDTManager.RaisedCount++;

            if (interruptInfo.CountStatistcs)
            {
                IDTManager.RaisedCountCustom++;
            }

            if (KConfig.Log.Interrupts)
            {
                if (interruptInfo.Trace)
                {
                    KernelMessage.WriteLine("Interrupt: {0}", irq);
                }

                var col = Screen.Column;
                var row = Screen.Row;
                Screen.Column = 0;
                Screen.Goto(2, 35);
                Screen.Write("Interrupts: ");
                Screen.Write(IDTManager.RaisedCount);
                Screen.Goto(3, 35);
                Screen.Write("IntNoClock: ");
                Screen.Write(IDTManager.RaisedCountCustom);
                Screen.Row    = row;
                Screen.Column = col;
            }

            if (irq < 0 || irq > 255)
            {
                Panic.Error("Invalid Interrupt");
            }

            if (interruptInfo.PreHandler != null)
            {
                interruptInfo.PreHandler(stack);
            }

            if (interruptInfo.Handler == null)
            {
                Panic.Error("Handler is null");
            }
            else
            {
            }

            interruptInfo.Handler(stack);

            PIC.SendEndOfInterrupt(irq);

            if (pageTableAddr > 0)
            {
                Native.SetCR3(pageTableAddr);
            }

            Native.SetSegments(dataSelector, dataSelector, dataSelector, dataSelector, 0x10);
        }