2 Copyright © 1995-2011, 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 static void Exec_CrashHandler(void)
21 struct Task
*task
= FindTask(NULL
);
22 struct IntETask
*iet
= GetIntETask(task
);
24 iet
->iet_AlertFlags
&= ~AF_Alert
; /* Makes Alert() attempting to bring up Intuition requester */
26 Alert(iet
->iet_AlertCode
);
29 /* In original AmigaOS the trap handler is entered in supervisor mode with the
30 * following on the supervisor stack:
32 * 4(sp) Processor dependent exception frame
33 * In our current implementation we use two pointers on stack. The idea is taken
36 * For m68k, we need a thunk, since we will call this routine via
37 * the AOS 1.x-3.x method described above.
39 * See arch/m68k-all/kernel/m68k_exception.c for implementation details.
45 " .global Exec_TrapHandler\n"
47 " move.l #0,%sp@-\n" /* Push on a NULL trapcode */
48 " movem.l %d0-%d7/%a0-%a7,%sp@-\n" /* Save regs */
49 " move.l %usp,%a0\n" /* Get USP */
50 " move.l %a0,%sp@(15*4)\n" /* Fix up A7 to be USP */
51 " move.l %sp@(17*4),%d0\n" /* Get the trap number */
52 " move.l %sp,%sp@-\n" /* Push on pointer to exception ctx */
53 " move.l %d0,%sp@-\n" /* Push on trap number */
54 " jsr Exec__TrapHandler\n" /* Call C routine */
55 " addq.l #8,%sp\n" /* Pop off C routine args */
56 " movem.l %sp@+,%d0-%d7/%a0-%a5\n" /* Restore registers */
57 " move.l %sp@(4), %a6\n"
58 " move.l %a6,%usp\n" /* Restore USP */
59 " move.l %sp@+,%a6\n" /* Restore A6 */
60 " addq.l #4,%sp\n" /* Skip past A7 */
61 " addq.l #8,%sp\n" /* Skip past trapcode and traparg */
62 " rte\n" /* Return from trap */
64 void Exec__TrapHandler(ULONG trapNum
, struct ExceptionContext
*ctx
)
66 void Exec_TrapHandler(ULONG trapNum
, struct ExceptionContext
*ctx
)
69 struct Task
*task
= SysBase
->ThisTask
;
71 /* Our situation is deadend */
72 trapNum
|= AT_DeadEnd
;
75 * We must have a valid ETask in order to be able
76 * to display a requester in user mode.
78 if (task
&& (task
->tc_Flags
& TF_ETASK
) && (task
->tc_State
!= TS_REMOVED
))
80 /* Get internal task structure */
81 struct IntETask
*iet
= GetIntETask(task
);
84 * Protection against double-crash. If the task is already in alert state, we have
85 * a second crash during processing the first one. Then we just pick up initial alert code
86 * and call Alert() with it in supervisor mode.
88 if (iet
->iet_AlertFlags
& AF_Alert
)
89 trapNum
= iet
->iet_AlertCode
;
92 * Workaround for i386-native. There trap handler already runs in user mode (BAD!),
93 * and it gets NULL as context pointer (this port saves CPU context in own format,
94 * which is TWICE BAD!!!)
95 * All this needs to be fixed.
100 * Otherwise we can try to send the crash to user level.
102 * First mark crash condition, and also specify alert code for user-level handler.
103 * If we double-crash while jumping to user mode, we will know this (ETF_Alert will
106 iet
->iet_AlertType
= AT_CPU
;
107 iet
->iet_AlertFlags
= AF_Alert
|AF_Location
;
108 iet
->iet_AlertCode
= trapNum
;
109 iet
->iet_AlertLocation
= (APTR
)ctx
->PC
; /* Location is our PC, where we crashed */
110 iet
->iet_AlertStack
= (APTR
)ctx
->FP
; /* Remember also stack frame for backtrace */
113 * This is a CPU alert. We've got a full CPU context, so we remember it
114 * in our ETask structure for displaying to the user later.
115 * Note that we store only GPR part of the context. We don't copy
116 * attached FPU data (if any). This can be considered TODO.
118 CopyMem(ctx
, &iet
->iet_AlertData
, sizeof(struct ExceptionContext
));
121 * Make the task to jump to crash handler. We don't care about return address etc because
122 * the alert is deadend anyway.
124 ctx
->PC
= (IPTR
)Exec_CrashHandler
;
125 /* Let the task go */
130 Exec_ExtAlert(trapNum
, ctx
? (APTR
)ctx
->PC
: NULL
, ctx
? (APTR
)ctx
->FP
: NULL
, AT_CPU
, ctx
, SysBase
);