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_traps.h"
22 #define D(x) /* This may lock up. See notes in host_intr.c */
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
)
53 /* If task switching is disabled, leave immediatelly */
54 D(bug("[Scheduler] TDNestCnt is %d\n", SysBase
->TDNestCnt
));
55 if (SysBase
->TDNestCnt
< 0)
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"));
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 */
89 core_Cause(INTB_VERTB
, 1L << INTB_VERTB
);
91 /* Reschedule tasks and exit */
92 core_ExitInterrupt(regs
);
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
;
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]));
111 if (!core_Schedule())
122 core_ExitInterrupt(regs
);
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
;
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 */
141 struct Task
*t
= SysBase
->ThisTask
;
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
));
150 bug("[KRN] No task\n");
152 DTRAP(bug("[KRN] Exec trap handler 0x%p\n", SysBase
->TaskTrapCode
));
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
)
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
))
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
);
189 /* If we reach here, the trap is unhandled and we request the virtual machine to stop */
193 TRAP_RESTOREREGS(regs
, tmpContext
);