revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-mingw32 / kernel / kernel_intr.c
blobbe0d077ceb251083b947820da341ca3fdb054fc0
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*
7 * Architecture-specific interrupt processing. We reimplement
8 * core_ExitInterrupt() because of non-typical idle loop implementation,
9 * hence the file name.
12 #include <exec/execbase.h>
13 #include <hardware/intbits.h>
14 #include <proto/exec.h>
16 #include <inttypes.h>
18 #include "kernel_base.h"
19 #include "kernel_intern.h"
20 #include "kernel_debug.h"
21 #include "kernel_interrupts.h"
22 #include "kernel_intr.h"
23 #include "kernel_scheduler.h"
24 #include "kernel_syscall.h"
25 #include "kernel_traps.h"
27 #define D(x) /* This may lock up. See notes in host_intr.c */
28 #define DSC(x)
29 #define DTRAP(x)
31 #define IRET return (SysBase->IDNestCnt < 0) ? INT_ENABLE : INT_DISABLE
34 * Leave the interrupt. This function receives the register frame used to leave the supervisor
35 * mode. It reschedules the task if it was asked for.
36 * This implementation differs from generic one because Windows-hosted AROS has very specific
37 * idle loop implementation.
39 void core_ExitInterrupt(CONTEXT *regs)
41 D(bug("[Scheduler] core_ExitInterrupt\n"));
43 /* Soft interrupt requested? It's high time to do it */
44 if (SysBase->SysFlags & SFF_SoftInt)
46 D(bug("[Scheduler] Causing SoftInt\n"));
47 core_Cause(INTB_SOFTINT, 1L << INTB_SOFTINT);
50 /* No tasks active (AROS is in idle state)? If yes, just pick up
51 a new ready task (if there is any) */
52 if (*KernelIFace.SleepState != SLEEP_MODE_OFF)
54 cpu_Dispatch(regs);
55 return;
58 /* If task switching is disabled, leave immediatelly */
59 D(bug("[Scheduler] TDNestCnt is %d\n", SysBase->TDNestCnt));
60 if (SysBase->TDNestCnt < 0)
62 /*
63 * Do not disturb task if it's not necessary.
64 * Reschedule only if switch pending flag is set. Exit otherwise.
66 if (SysBase->AttnResched & ARF_AttnSwitch)
68 D(bug("[Scheduler] Rescheduling\n"));
69 if (core_Schedule())
71 cpu_Switch(regs);
72 cpu_Dispatch(regs);
78 /* This entry point is called by host-side DLL when an IRQ arrives */
79 int core_IRQHandler(unsigned char *irqs, CONTEXT *regs)
81 struct IntrNode *in, *in2;
83 /* Run handlers for all active IRQs */
84 ForeachNodeSafe(KernelBase->kb_Interrupts, in, in2)
86 irqhandler_t h = in->in_Handler;
88 if (h && (irqs[in->in_nr]))
89 h(in->in_HandlerData, in->in_HandlerData2);
92 /* IRQ 0 is exec VBlank timer */
93 if (irqs[0])
94 core_Cause(INTB_VERTB, 1L << INTB_VERTB);
96 /* Reschedule tasks and exit */
97 core_ExitInterrupt(regs);
98 IRET;
101 /* Trap handler entry point */
102 int core_TrapHandler(unsigned int num, IPTR *args, CONTEXT *regs)
104 void (*trapHandler)(unsigned long, struct ExceptionContext *) = NULL;
105 struct ExceptionTranslation *ex;
106 struct AROSCPUContext *ctx;
108 switch (num)
110 case AROS_EXCEPTION_SYSCALL:
111 /* It's a SysCall exception issued by core_raise() */
112 DSC(bug("[KRN] SysCall 0x%04X\n", args[0]));
113 switch(args[0])
115 case SC_SCHEDULE:
116 if (!core_Schedule())
117 break;
119 case SC_SWITCH:
120 cpu_Switch(regs);
122 case SC_DISPATCH:
123 cpu_Dispatch(regs);
124 break;
126 case SC_CAUSE:
127 core_ExitInterrupt(regs);
128 break;
130 break;
132 case AROS_EXCEPTION_RESUME:
133 /* Restore saved context and continue */
134 ctx = (struct AROSCPUContext *)args[0];
135 RESTOREREGS(regs, ctx);
136 **KernelIFace.LastError = ctx->LastError;
137 break;
139 default:
140 /* It's something else, likely a CPU trap */
141 bug("[KRN] Exception 0x%08lX, SysBase 0x%p, KernelBase 0x%p\n", num, SysBase, KernelBase);
143 /* Find out trap handler for caught task */
144 if (SysBase)
146 struct Task *t = SysBase->ThisTask;
148 if (t)
150 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--");
151 trapHandler = t->tc_TrapCode;
152 D(bug("[KRN] Task trap handler 0x%p\n", trapHandler));
154 else
155 bug("[KRN] No task\n");
157 DTRAP(bug("[KRN] Exec trap handler 0x%p\n", SysBase->TaskTrapCode));
158 if (!trapHandler)
159 trapHandler = SysBase->TaskTrapCode;
162 PRINT_CPUCONTEXT(regs);
164 /* Translate Windows exception code to CPU and exec trap numbers */
165 for (ex = Traps; ex->ExceptionCode; ex++)
167 if (num == ex->ExceptionCode)
168 break;
170 DTRAP(bug("[KRN] CPU exception %d, AROS exception %d\n", ex->CPUTrap, ex->AROSTrap));
172 /* Convert CPU context to AROS structure */
173 struct ExceptionContext tmpContext;
174 TRAP_SAVEREGS(regs, tmpContext);
178 if (ex->CPUTrap != -1)
180 if (krnRunExceptionHandlers(KernelBase, ex->CPUTrap, &tmpContext))
181 break;
184 if (trapHandler && (ex->AmigaTrap != -1))
186 /* Call our trap handler. Note that we may return, this means that the handler has
187 fixed the problem somehow and we may safely continue */
188 DTRAP(bug("[KRN] Amiga trap %d\n", ex->AmigaTrap));
189 trapHandler(ex->AmigaTrap, &tmpContext);
191 break;
194 /* If we reach here, the trap is unhandled and we request the virtual machine to stop */
195 return INT_HALT;
196 } while(0);
198 TRAP_RESTOREREGS(regs, tmpContext);
201 IRET;