1 /*-------------------------------------------------------------
3 exception.c -- PPC exception handling support
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
36 #include "processor.h"
47 #include "lwp_threads.h"
50 #include "ogc/video_types.h"
54 #define CPU_STACK_TRACE_DEPTH 10
56 typedef struct _framerec
{
59 } frame_rec
, *frame_rec_t
;
61 static void *exception_xfb
= (void*)0xC1700000; //we use a static address above ArenaHi.
62 static int reload_timer
= -1;
64 void __exception_sethandler(u32 nExcept
, void (*pHndl
)(frame_context
*));
66 extern void udelay(int us
);
67 extern void fpu_exceptionhandler();
68 extern void irq_exceptionhandler();
69 extern void dec_exceptionhandler();
70 extern void default_exceptionhandler();
71 extern void VIDEO_SetFramebuffer(void *);
72 extern void __reload();
74 extern s8 exceptionhandler_start
[],exceptionhandler_end
[],exceptionhandler_patch
[];
75 extern s8 systemcallhandler_start
[],systemcallhandler_end
[];
77 void (*_exceptionhandlertable
[NUM_EXCEPTIONS
])(frame_context
*);
79 static u32 exception_location
[NUM_EXCEPTIONS
] = {
80 0x00000100, 0x00000200, 0x00000300, 0x00000400,
81 0x00000500, 0x00000600, 0x00000700, 0x00000800,
82 0x00000900, 0x00000C00, 0x00000D00, 0x00000F00,
83 0x00001300, 0x00001400, 0x00001700 };
85 static const char *exception_name
[NUM_EXCEPTIONS
] = {
86 "System Reset", "Machine Check", "DSI", "ISI",
87 "Interrupt", "Alignment", "Program", "Floating Point",
88 "Decrementer", "System Call", "Trace", "Performance",
89 "IABR", "Reserved", "Thermal"};
91 void __exception_load(u32 nExc
,void *data
,u32 len
,void *patch
)
93 void *pAddr
= (void*)(0x80000000|exception_location
[nExc
]);
94 memcpy(pAddr
,data
,len
);
96 *(u32
*)((u32
)pAddr
+(patch
-data
)) |= nExc
;
98 DCFlushRangeNoSync(pAddr
,len
);
99 ICInvalidateRange(pAddr
,len
);
103 void __systemcall_init()
105 __exception_load(EX_SYS_CALL
,systemcallhandler_start
,(systemcallhandler_end
-systemcallhandler_start
),NULL
);
108 void __exception_init()
112 kprintf("__exception_init()\n\n");
114 // init all exceptions with the default handler & vector code
115 for(i
=0;i
<NUM_EXCEPTIONS
;i
++) {
116 // load default exception vector handler code
117 __exception_load(i
,exceptionhandler_start
,(exceptionhandler_end
-exceptionhandler_start
),exceptionhandler_patch
);
118 //set default exception handler into table
119 __exception_sethandler(i
,default_exceptionhandler
);
121 __exception_sethandler(EX_FP
,fpu_exceptionhandler
);
122 __exception_sethandler(EX_INT
,irq_exceptionhandler
);
123 __exception_sethandler(EX_DEC
,dec_exceptionhandler
);
125 mtmsr(mfmsr()|MSR_RI
);
128 void __exception_close(u32 except
)
130 void *pAdd
= (void*)(0x80000000|exception_location
[except
]);
131 *(u32
*)pAdd
= 0x4C000064;
132 DCFlushRangeNoSync(pAdd
,0x100);
133 ICInvalidateRange(pAdd
,0x100);
137 void __exception_closeall()
140 for(i
=0;i
<NUM_EXCEPTIONS
;i
++) {
141 __exception_close(i
);
143 mtmsr(mfmsr()&~MSR_EE
);
144 mtmsr(mfmsr()|(MSR_FP
|MSR_RI
));
147 void __exception_sethandler(u32 nExcept
, void (*pHndl
)(frame_context
*))
149 _exceptionhandlertable
[nExcept
] = pHndl
;
152 static void _cpu_print_stack(void *pc
,void *lr
,void *r1
)
155 register frame_rec_t l
,p
= (frame_rec_t
)lr
;
159 if(!p
) __asm__
__volatile__("mr %0,%%r1" : "=r"(p
));
161 kprintf("\n\tSTACK DUMP:");
163 for(i
=0;i
<CPU_STACK_TRACE_DEPTH
-1 && p
->up
;p
=p
->up
,i
++) {
164 if(i
%4) kprintf(" --> ");
166 if(i
>0) kprintf(" -->\n\t");
167 else kprintf("\n\t");
172 if(pc
) kprintf("%p",pc
);
175 if(!l
) l
= (frame_rec_t
)mfspr(8);
176 kprintf("%p",(void*)l
);
179 kprintf("%p",(void*)(p
->up
->lr
));
185 void __exception_setreload(int t
)
190 static void waitForReload()
197 kprintf("\n\tReloading in %d seconds\n", reload_timer
/50);
203 int buttonsDown
= PAD_ButtonsDown(0);
205 if( (buttonsDown
& PAD_TRIGGER_Z
) || SYS_ResetButtonDown() ||
208 kprintf("\n\tReload\n\n\n");
209 _CPU_ISR_Disable(level
);
213 if ( buttonsDown
& PAD_BUTTON_A
)
215 kprintf("\n\tReset\n\n\n");
217 SYS_ResetSystem(SYS_HOTRESET
,0,FALSE
);
229 //just implement core for unrecoverable exceptions.
230 void c_default_exceptionhandler(frame_context
*pCtx
)
233 VIDEO_SetFramebuffer(exception_xfb
);
234 __console_init(exception_xfb
,20,20,640,574,1280);
235 CON_EnableGecko(1, true);
237 kprintf("\n\n\n\tException (%s) occurred!\n", exception_name
[pCtx
->EXCPT_Number
]);
239 kprintf("\tGPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n",pCtx
->GPR
[0], pCtx
->GPR
[8], pCtx
->GPR
[16], pCtx
->GPR
[24]);
240 kprintf("\tGPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n",pCtx
->GPR
[1], pCtx
->GPR
[9], pCtx
->GPR
[17], pCtx
->GPR
[25]);
241 kprintf("\tGPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n",pCtx
->GPR
[2], pCtx
->GPR
[10], pCtx
->GPR
[18], pCtx
->GPR
[26]);
242 kprintf("\tGPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n",pCtx
->GPR
[3], pCtx
->GPR
[11], pCtx
->GPR
[19], pCtx
->GPR
[27]);
243 kprintf("\tGPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n",pCtx
->GPR
[4], pCtx
->GPR
[12], pCtx
->GPR
[20], pCtx
->GPR
[28]);
244 kprintf("\tGPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n",pCtx
->GPR
[5], pCtx
->GPR
[13], pCtx
->GPR
[21], pCtx
->GPR
[29]);
245 kprintf("\tGPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n",pCtx
->GPR
[6], pCtx
->GPR
[14], pCtx
->GPR
[22], pCtx
->GPR
[30]);
246 kprintf("\tGPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n",pCtx
->GPR
[7], pCtx
->GPR
[15], pCtx
->GPR
[23], pCtx
->GPR
[31]);
247 kprintf("\tLR %08X SRR0 %08x SRR1 %08x MSR %08x\n", pCtx
->LR
, pCtx
->SRR0
, pCtx
->SRR1
,pCtx
->MSR
);
248 kprintf("\tDAR %08X DSISR %08X\n", mfspr(19), mfspr(18));
250 _cpu_print_stack((void*)pCtx
->SRR0
,(void*)pCtx
->LR
,(void*)pCtx
->GPR
[1]);
252 if((pCtx
->EXCPT_Number
==EX_DSI
) || (pCtx
->EXCPT_Number
==EX_FP
)) {
254 u32
*pAdd
= (u32
*)pCtx
->SRR0
;
255 kprintf("\n\n\tCODE DUMP:\n");
256 for (i
=0; i
<12; i
+=4)
257 kprintf("\t%p: %08X %08X %08X %08X\n",
258 &(pAdd
[i
]),pAdd
[i
], pAdd
[i
+1], pAdd
[i
+2], pAdd
[i
+3]);