2 * Architecture-specific interrupt processing. We reimplement
3 * core_ExitInterrupt() because of non-typical idle loop implementation,
7 #include <exec/execbase.h>
8 #include <hardware/intbits.h>
9 #include <proto/exec.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_timer.h"
21 #include "kernel_traps.h"
23 #define D(x) /* This may lock up. See notes in host_intr.c */
27 #define IRET return (SysBase->IDNestCnt < 0) ? INT_ENABLE : INT_DISABLE
30 * Leave the interrupt. This function receives the register frame used to leave the supervisor
31 * mode. It reschedules the task if it was asked for.
32 * This implementation differs from generic one because Windows-hosted AROS has very specific
33 * idle loop implementation.
35 void core_ExitInterrupt(CONTEXT
*regs
)
37 D(bug("[Scheduler] core_ExitInterrupt\n"));
39 /* Soft interrupt requested? It's high time to do it */
40 if (SysBase
->SysFlags
& SFF_SoftInt
)
42 D(bug("[Scheduler] Causing SoftInt\n"));
43 core_Cause(INTB_SOFTINT
, 1L << INTB_SOFTINT
);
46 /* No tasks active (AROS is in idle state)? If yes, just pick up
47 a new ready task (if there is any) */
48 if (Sleep_Mode
!= SLEEP_MODE_OFF
)
54 /* If task switching is disabled, leave immediatelly */
55 D(bug("[Scheduler] TDNestCnt is %d\n", SysBase
->TDNestCnt
));
56 if (SysBase
->TDNestCnt
< 0)
59 * Do not disturb task if it's not necessary.
60 * Reschedule only if switch pending flag is set. Exit otherwise.
62 if (SysBase
->AttnResched
& ARF_AttnSwitch
)
64 D(bug("[Scheduler] Rescheduling\n"));
74 /* This entry point is called by host-side DLL when an IRQ arrives */
75 int core_IRQHandler(unsigned char *irqs
, CONTEXT
*regs
)
77 struct IntrNode
*in
, *in2
;
79 /* Run handlers for all active IRQs */
80 ForeachNodeSafe(KernelBase
->kb_Interrupts
, in
, in2
)
82 irqhandler_t h
= in
->in_Handler
;
84 if (h
&& (irqs
[in
->in_nr
]))
85 h(in
->in_HandlerData
, in
->in_HandlerData2
);
88 /* Timer IRQ is also used to emulate exec VBlank */
92 /* Reschedule tasks and exit */
93 core_ExitInterrupt(regs
);
97 /* Trap handler entry point */
98 int core_TrapHandler(unsigned int num
, IPTR
*args
, CONTEXT
*regs
)
100 void (*trapHandler
)(unsigned long, struct ExceptionContext
*) = NULL
;
101 struct ExceptionTranslation
*ex
;
102 struct AROSCPUContext
*ctx
;
106 case AROS_EXCEPTION_SYSCALL
:
107 /* It's a SysCall exception issued by core_raise() */
108 DSC(bug("[KRN] SysCall 0x%04X\n", args
[0]));
112 if (!core_Schedule())
123 core_ExitInterrupt(regs
);
128 case AROS_EXCEPTION_RESUME
:
129 /* Restore saved context and continue */
130 ctx
= (struct AROSCPUContext
*)args
[0];
131 RESTOREREGS(regs
, ctx
);
132 *LastErrorPtr
= ctx
->LastError
;
136 /* It's something else, likely a CPU trap */
137 bug("[KRN] Exception 0x%08lX, SysBase 0x%p, KernelBase 0x%p\n", num
, SysBase
, KernelBase
);
139 /* Find out trap handler for caught task */
142 struct Task
*t
= SysBase
->ThisTask
;
146 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--");
147 trapHandler
= t
->tc_TrapCode
;
148 D(bug("[KRN] Task trap handler 0x%p\n", trapHandler
));
151 bug("[KRN] No task\n");
153 DTRAP(bug("[KRN] Exec trap handler 0x%p\n", SysBase
->TaskTrapCode
));
155 trapHandler
= SysBase
->TaskTrapCode
;
158 PRINT_CPUCONTEXT(regs
);
160 /* Translate Windows exception code to CPU and exec trap numbers */
161 for (ex
= Traps
; ex
->ExceptionCode
; ex
++)
163 if (num
== ex
->ExceptionCode
)
166 DTRAP(bug("[KRN] CPU exception %d, AROS exception %d\n", ex
->CPUTrap
, ex
->AROSTrap
));
168 /* Convert CPU context to AROS structure */
169 struct ExceptionContext tmpContext
;
170 TRAP_SAVEREGS(regs
, tmpContext
);
174 if (ex
->CPUTrap
!= -1)
176 if (krnRunExceptionHandlers(ex
->CPUTrap
, &tmpContext
))
180 if (trapHandler
&& (ex
->AmigaTrap
!= -1))
182 /* Call our trap handler. Note that we may return, this means that the handler has
183 fixed the problem somehow and we may safely continue */
184 DTRAP(bug("[KRN] Amiga trap %d\n", ex
->AmigaTrap
));
185 trapHandler(ex
->AmigaTrap
, &tmpContext
);
190 /* If we reach here, the trap is unhandled and we request the virtual machine to stop */
194 TRAP_RESTOREREGS(regs
, tmpContext
);