2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
7 * Architecture-specific interrupt processing. We reimplement
8 * core_ExitInterrupt() because of non-typical idle loop implementation,
12 #include <exec/execbase.h>
13 #include <hardware/intbits.h>
14 #include <proto/exec.h>
18 #include "kernel_base.h"
19 #include "kernel_debug.h"
20 #include "kernel_interrupts.h"
21 #include "kernel_intr.h"
22 #include "kernel_mingw32.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 */
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
)
58 /* If task switching is disabled, leave immediatelly */
59 D(bug("[Scheduler] TDNestCnt is %d\n", SysBase
->TDNestCnt
));
60 if (SysBase
->TDNestCnt
< 0)
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"));
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 */
94 core_Cause(INTB_VERTB
, 1L << INTB_VERTB
);
96 /* Reschedule tasks and exit */
97 core_ExitInterrupt(regs
);
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
;
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]));
116 if (!core_Schedule())
127 core_ExitInterrupt(regs
);
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
;
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 */
146 struct Task
*t
= SysBase
->ThisTask
;
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
));
155 bug("[KRN] No task\n");
157 DTRAP(bug("[KRN] Exec trap handler 0x%p\n", SysBase
->TaskTrapCode
));
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
)
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
))
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
);
194 /* If we reach here, the trap is unhandled and we request the virtual machine to stop */
198 TRAP_RESTOREREGS(regs
, tmpContext
);