public static bool Create(byte irqNum, out InterruptHandle handle) { bool ret = false; handle = new InterruptHandle(); // // Create an IoIrq, and a handle in the current process to hold it. // IoConfig config = Thread.CurrentProcess.IoConfig; for (int i = 0; i < config.DynamicRanges.Length; i++) { IoIrqRange iir = config.DynamicRanges[i] as IoIrqRange; if (iir != null && iir.Irq <= irqNum && irqNum < iir.Irq + iir.Size) { IoIrq irq = iir.IrqAtOffset((byte)(irqNum - iir.Irq)); handle = new InterruptHandle( Thread.CurrentProcess.AllocateHandle(irq)); irq.RegisterInterrupt(); ret = true; break; } } Tracing.Log(Tracing.Debug, "InterruptHandle.Create(irq={0:x2}, out id={0:x8})", irqNum, handle.id); return(ret); }
public static void Pulse(InterruptHandle handle) { if (handle.id == UIntPtr.Zero) { Tracing.Log(Tracing.Error, "InterruptHandle.Wait(id={0:x8}) on bad handle", handle.id); return; } IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq; irq.Pulse(); Tracing.Log(Tracing.Debug, "InterruptHandle.Pulse(id={0:x8})", handle.id); }
public static bool Dispose(InterruptHandle handle) { Tracing.Log(Tracing.Debug, "InterruptHandle.Dispose(id={0:x8})", handle.id); bool ret = false; if (handle.id != UIntPtr.Zero) { // // Releasing the handle will allow the IoIrq event to be // garbage-collected. // IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq; ret = irq.ReleaseInterrupt(); Thread.CurrentProcess.ReleaseHandle(handle.id); } return(ret); }
public static bool Ack(InterruptHandle handle) { if (handle.id == UIntPtr.Zero) { Tracing.Log(Tracing.Error, "InterruptHandle.Ack(id={0:x8}) on bad handle", handle.id); return(false); } // // Convert the handle to an auto-reset event; set the event. // IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq; bool ret = irq.AckInterrupt(); Tracing.Log(Tracing.Debug, "InterruptHandle.Ack(id={0:x8})", handle.id); return(ret); }
public static bool Wait(InterruptHandle handle) { if (handle.id == UIntPtr.Zero) { Tracing.Log(Tracing.Error, "InterruptHandle.Wait(id={0:x8}) on bad handle", handle.id); return(false); } // // Convert the handle to a IoIrq and wait on it. // IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq; bool ret = irq.WaitForInterrupt(); Tracing.Log(Tracing.Debug, "InterruptHandle.Wait(id={0:x8})", handle.id); return(ret); }
public unsafe void DispatchInterrupt(InterruptContext *context) { Processor p = Processor.CurrentProcessor; int interrupt = context->ExceptionId; // Indicate that we are in an interrupt context. Thread target = null; Thread current = Processor.GetCurrentThread(); Kernel.Waypoint(801); // Don't generate loads of output for debugger-related interrupts #if DEBUG_INTERRUPTS DebugStub.WriteLine("Int{0:x2}", __arglist(interrupt)); context->Display(); #endif if (Processor.IsSamplingEnabled) { if (p.nextSampleIdle == false) { p.Profiler.LogStackTrace(context->InstructionPointer, context->StackPointer); } p.nextSampleIdle = false; } if (halted) { p.clock.CpuResumeFromHaltEvent(); halted = false; } unchecked { if (interrupt != p.clockInterrupt && interrupt != p.timerInterrupt) { // We don't log the clockInterrupt because of all the spew. Tracing.Log(Tracing.Debug, "Interrupt 0x{0:x}, count={1:x}, eip={2:x} [CC={3:x8}]", (UIntPtr)(uint)interrupt, (UIntPtr)p.interruptCounts[interrupt], (UIntPtr)context->InstructionPointer, (UIntPtr)(uint)Processor.CycleCount); } } Monitoring.Log(Monitoring.Provider.Processor, (ushort)ProcessorEvent.Interrupt, 0, (uint)interrupt, 0, 0, 0, 0); if (interrupt == Kernel.HalIpiInterrupt) { #if DEBUG_IPI DebugStub.WriteLine("IPI received 0x{0:x2} on processor {1}", __arglist(interrupt, p.Id)); #endif // DEBUG_DISPATCH_TIMER Platform.ClearFixedIPI(interrupt); //p.dispatcher.HandlePreemptionReschedule(); } else if (interrupt == p.timerInterrupt) { // Polling on every timer interrupt is EXCEEDINGLY costly p.timer.ClearInterrupt(); p.dispatcher.HandlePreemptionReschedule(p.timer); } else if (interrupt == p.clockInterrupt) { p.clock.ClearInterrupt(); #if DEBUG // Check for a debug break. if (DebugStub.PollForBreak()) { DebugStub.WriteLine("Debugger ctrl-break after interrupt 0x{0:x2}", __arglist(interrupt)); DebugStub.Break(); } #endif // DEBUG } #if ISA_IX else if (interrupt == EVectors.GCSynchronization) { Platform.ClearFixedIPI(interrupt); MpExecution.GCSynchronizationInterrupt(); } else if (interrupt == EVectors.SpuriousInterrupt) { // FIXME: identify the source of these isolated interrupts after the // warmboot. Ignore them for now. DebugStub.WriteLine("Spurious interrupt"); } #endif // ISA_IX else { if (!Platform.InternalInterrupt((byte)interrupt)) { HalPic pic = p.GetPic(); DebugStub.Assert(pic != null); pic.ClearInterrupt((byte)interrupt); IoIrq.SignalInterrupt(pic.InterruptToIrq((byte)interrupt)); #if DEBUG_DISPATCH_IO DebugStub.WriteLine("++DispatchInterruptEvent Irq={0:x2}, Thread={1:x8}", __arglist(pic.InterruptToIrq((byte)interrupt), Kernel.AddressOf(target))); #endif // DEBUG_DISPATCH_IO p.dispatcher.HandleIOReschedule(); } else { // Potentially missed interrupt DebugStub.Break(); } } #if DEBUG_INTERRUPTS DebugStub.WriteLine("(2nd)Int{0:x2}", __arglist(interrupt)); context->Display(); if (!Processor.InterruptsDisabled()) { DebugStub.WriteLine(" interrupts enabled!!!!!!!"); DebugStub.Break(); } #if DEBUG_DEEPER DebugStub.WriteLine("Int{0:x2}", __arglist(interrupt)); Thread.DisplayAbbrev(ref context, " int end"); #endif #endif // Now swap in the resulting current thread. (Note that this call will not return.) Isa.GetCurrentThread()->spill.Resume(); }