Added support for compiling C++ files. It isn't included for all
[AROS.git] / arch / all-mingw32 / kernel / kernel_intr.c
blob42bbef8b473fc3b866a98c88cc540aa5a851993e
1 /*
2 * Architecture-specific interrupt processing. We reimplement
3 * core_ExitInterrupt() because of non-typical idle loop implementation,
4 * hence the file name.
5 */
7 #include <exec/execbase.h>
8 #include <hardware/intbits.h>
9 #include <proto/exec.h>
11 #include <inttypes.h>
13 #include "kernel_base.h"
14 #include "kernel_debug.h"
15 #include "kernel_interrupts.h"
16 #include "kernel_intr.h"
17 #include "kernel_mingw32.h"
18 #include "kernel_scheduler.h"
19 #include "kernel_syscall.h"
20 #include "kernel_traps.h"
22 #define D(x) /* This may lock up. See notes in host_intr.c */
23 #define DSC(x)
24 #define DTRAP(x)
26 #define IRET return (SysBase->IDNestCnt < 0) ? INT_ENABLE : INT_DISABLE
29 * Leave the interrupt. This function receives the register frame used to leave the supervisor
30 * mode. It reschedules the task if it was asked for.
31 * This implementation differs from generic one because Windows-hosted AROS has very specific
32 * idle loop implementation.
34 void core_ExitInterrupt(CONTEXT *regs)
36 D(bug("[Scheduler] core_ExitInterrupt\n"));
38 /* Soft interrupt requested? It's high time to do it */
39 if (SysBase->SysFlags & SFF_SoftInt)
41 D(bug("[Scheduler] Causing SoftInt\n"));
42 core_Cause(INTB_SOFTINT, 1L << INTB_SOFTINT);
45 /* No tasks active (AROS is in idle state)? If yes, just pick up
46 a new ready task (if there is any) */
47 if (Sleep_Mode != SLEEP_MODE_OFF)
49 cpu_Dispatch(regs);
50 return;
53 /* If task switching is disabled, leave immediatelly */
54 D(bug("[Scheduler] TDNestCnt is %d\n", SysBase->TDNestCnt));
55 if (SysBase->TDNestCnt < 0)
57 /*
58 * Do not disturb task if it's not necessary.
59 * Reschedule only if switch pending flag is set. Exit otherwise.
61 if (SysBase->AttnResched & ARF_AttnSwitch)
63 D(bug("[Scheduler] Rescheduling\n"));
64 if (core_Schedule())
66 cpu_Switch(regs);
67 cpu_Dispatch(regs);
73 /* This entry point is called by host-side DLL when an IRQ arrives */
74 int core_IRQHandler(unsigned char *irqs, CONTEXT *regs)
76 struct IntrNode *in, *in2;
78 /* Run handlers for all active IRQs */
79 ForeachNodeSafe(KernelBase->kb_Interrupts, in, in2)
81 irqhandler_t h = in->in_Handler;
83 if (h && (irqs[in->in_nr]))
84 h(in->in_HandlerData, in->in_HandlerData2);
87 /* IRQ 0 is exec VBlank timer */
88 if (irqs[0])
89 core_Cause(INTB_VERTB, 1L << INTB_VERTB);
91 /* Reschedule tasks and exit */
92 core_ExitInterrupt(regs);
93 IRET;
96 /* Trap handler entry point */
97 int core_TrapHandler(unsigned int num, IPTR *args, CONTEXT *regs)
99 void (*trapHandler)(unsigned long, struct ExceptionContext *) = NULL;
100 struct ExceptionTranslation *ex;
101 struct AROSCPUContext *ctx;
103 switch (num)
105 case AROS_EXCEPTION_SYSCALL:
106 /* It's a SysCall exception issued by core_raise() */
107 DSC(bug("[KRN] SysCall 0x%04X\n", args[0]));
108 switch(args[0])
110 case SC_SCHEDULE:
111 if (!core_Schedule())
112 break;
114 case SC_SWITCH:
115 cpu_Switch(regs);
117 case SC_DISPATCH:
118 cpu_Dispatch(regs);
119 break;
121 case SC_CAUSE:
122 core_ExitInterrupt(regs);
123 break;
125 break;
127 case AROS_EXCEPTION_RESUME:
128 /* Restore saved context and continue */
129 ctx = (struct AROSCPUContext *)args[0];
130 RESTOREREGS(regs, ctx);
131 *LastErrorPtr = ctx->LastError;
132 break;
134 default:
135 /* It's something else, likely a CPU trap */
136 bug("[KRN] Exception 0x%08lX, SysBase 0x%p, KernelBase 0x%p\n", num, SysBase, KernelBase);
138 /* Find out trap handler for caught task */
139 if (SysBase)
141 struct Task *t = SysBase->ThisTask;
143 if (t)
145 bug("[KRN] %s 0x%p (%s)\n", t->tc_Node.ln_Type == NT_TASK ? "Task":"Process", t, t->tc_Node.ln_Name ? t->tc_Node.ln_Name : "--unknown--");
146 trapHandler = t->tc_TrapCode;
147 D(bug("[KRN] Task trap handler 0x%p\n", trapHandler));
149 else
150 bug("[KRN] No task\n");
152 DTRAP(bug("[KRN] Exec trap handler 0x%p\n", SysBase->TaskTrapCode));
153 if (!trapHandler)
154 trapHandler = SysBase->TaskTrapCode;
157 PRINT_CPUCONTEXT(regs);
159 /* Translate Windows exception code to CPU and exec trap numbers */
160 for (ex = Traps; ex->ExceptionCode; ex++)
162 if (num == ex->ExceptionCode)
163 break;
165 DTRAP(bug("[KRN] CPU exception %d, AROS exception %d\n", ex->CPUTrap, ex->AROSTrap));
167 /* Convert CPU context to AROS structure */
168 struct ExceptionContext tmpContext;
169 TRAP_SAVEREGS(regs, tmpContext);
173 if (ex->CPUTrap != -1)
175 if (krnRunExceptionHandlers(KernelBase, ex->CPUTrap, &tmpContext))
176 break;
179 if (trapHandler && (ex->AmigaTrap != -1))
181 /* Call our trap handler. Note that we may return, this means that the handler has
182 fixed the problem somehow and we may safely continue */
183 DTRAP(bug("[KRN] Amiga trap %d\n", ex->AmigaTrap));
184 trapHandler(ex->AmigaTrap, &tmpContext);
186 break;
189 /* If we reach here, the trap is unhandled and we request the virtual machine to stop */
190 return INT_HALT;
191 } while(0);
193 TRAP_RESTOREREGS(regs, tmpContext);
196 IRET;