2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Default trap handler
9 #include <exec/alerts.h>
10 #include <exec/interrupts.h>
11 #include <exec/tasks.h>
12 #include <proto/exec.h>
15 #include "exec_intern.h"
16 #include "exec_util.h"
18 /* User-mode code where the task jumps to.
19 * NOTE: This is only called on ETasks!
21 static void Exec_CrashHandler(void)
23 struct Task
*ThisTask
= GET_THIS_TASK
;
24 struct IntETask
*iet
= GetIntETask(ThisTask
);
26 /* Makes Alert() attempting to bring up Intuition requester */
27 iet
->iet_AlertFlags
&= ~AF_Alert
;
29 Alert(iet
->iet_AlertCode
);
32 /* In original AmigaOS the trap handler is entered in supervisor mode with the
33 * following on the supervisor stack:
35 * 4(sp) Processor dependent exception frame
36 * In our current implementation we use two pointers on stack. The idea is taken
39 * For m68k, we need a thunk, since we will call this routine via
40 * the AOS 1.x-3.x method described above.
42 * See arch/m68k-all/kernel/m68k_exception.c for implementation details.
48 " .global Exec_TrapHandler\n"
50 " movem.l %d0-%d7/%a0-%a6,%sp@-\n" /* Save regs */
51 " move.l %sp@(15*4),%d0\n" /* Get trap code */
52 " move.l %usp,%a0\n" /* Get USP */
53 " move.l %a0,%sp@(15*4)\n" /* Fix up A7 to be USP */
54 " move.l %sp,%sp@-\n" /* Push on pointer to exception ctx */
55 " move.l %d0,%sp@-\n" /* Push on trap number */
56 " jsr Exec__TrapHandler\n" /* Call C routine */
57 " addq.l #8,%sp\n" /* Pop off C routine args */
58 " movem.l %sp@+,%d0-%d7/%a0-%a5\n" /* Restore registers */
59 " move.l %sp@(4), %a6\n"
60 " move.l %a6,%usp\n" /* Restore USP */
61 " move.l %sp@+,%a6\n" /* Restore A6 */
62 " addq.l #4,%sp\n" /* Skip past A7 */
63 " rte\n" /* Return from trap */
65 void Exec__TrapHandler(ULONG trapNum
, struct ExceptionContext
*ctx
)
67 void Exec_TrapHandler(ULONG trapNum
, struct ExceptionContext
*ctx
)
70 struct Task
*ThisTask
= GET_THIS_TASK
;
72 /* Our situation is deadend */
73 trapNum
|= AT_DeadEnd
;
76 * We must have a valid ETask in order to be able
77 * to display a requester in user mode.
79 if (ThisTask
&& (ThisTask
->tc_Flags
& TF_ETASK
) && (ThisTask
->tc_State
!= TS_REMOVED
))
81 /* Get internal task structure */
82 struct IntETask
*iet
= GetIntETask(ThisTask
);
84 if (iet
->iet_AlertFlags
& AF_Alert
)
87 * Protection against double-crash. If the task is already in alert state, we have
88 * a second crash during processing the first one. Then we just pick up initial alert code
89 * and call Alert() with it in supervisor mode.
91 trapNum
= iet
->iet_AlertCode
;
96 * Otherwise we can try to send the crash to user level.
98 * First mark crash condition, and also specify alert code for user-level handler.
99 * If we double-crash while jumping to user mode, we will know this (ETF_Alert will
102 iet
->iet_AlertType
= AT_CPU
;
103 iet
->iet_AlertFlags
= AF_Alert
|AF_Location
;
104 iet
->iet_AlertCode
= trapNum
;
105 iet
->iet_AlertLocation
= (APTR
)ctx
->PC
; /* Location is our PC, where we crashed */
106 iet
->iet_AlertStack
= (APTR
)ctx
->FP
; /* Remember also stack frame for backtrace */
109 * This is a CPU alert. We've got a full CPU context, so we remember it
110 * in our ETask structure for displaying to the user later.
111 * Note that we store only GPR part of the context. We don't copy
112 * attached FPU data (if any). This can be considered TODO.
114 CopyMem(ctx
, &iet
->iet_AlertData
, sizeof(struct ExceptionContext
));
117 * Make the task to jump to crash handler. We don't care about return address etc because
118 * the alert is deadend anyway.
120 ctx
->PC
= (IPTR
)Exec_CrashHandler
;
121 /* Let the task go */
126 Exec_ExtAlert(trapNum
, (APTR
)ctx
->PC
, (APTR
)ctx
->FP
, AT_CPU
, ctx
, SysBase
);