patch to make enabling 64B L2 cache optional (tueidj)
[libogc.git] / libogc / exception.c
blob72155b1655d150957ae90de316c4dc8ec04784d9
1 /*-------------------------------------------------------------
3 exception.c -- PPC exception handling support
5 Copyright (C) 2004
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
26 distribution.
28 -------------------------------------------------------------*/
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include "asm.h"
36 #include "processor.h"
37 #include "cache.h"
38 #include "irq.h"
39 #include "context.h"
41 #include "system.h"
43 #include "gx.h"
44 #include "pad.h"
45 #include "consol.h"
46 #include "console.h"
47 #include "lwp_threads.h"
48 #include "ios.h"
50 #include "ogc/video_types.h"
52 //#define _EXC_DEBUG
54 #define CPU_STACK_TRACE_DEPTH 10
56 typedef struct _framerec {
57 struct _framerec *up;
58 void *lr;
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);
95 if(patch)
96 *(u32*)((u32)pAddr+(patch-data)) |= nExc;
98 DCFlushRangeNoSync(pAddr,len);
99 ICInvalidateRange(pAddr,len);
100 _sync();
103 void __systemcall_init()
105 __exception_load(EX_SYS_CALL,systemcallhandler_start,(systemcallhandler_end-systemcallhandler_start),NULL);
108 void __exception_init()
110 s32 i;
111 #ifdef _EXC_DEBUG
112 kprintf("__exception_init()\n\n");
113 #endif
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 u32 level;
131 void *pAdd = (void*)(0x80000000|exception_location[except]);
133 _CPU_ISR_Disable(level);
134 __exception_sethandler(except,NULL);
136 *(u32*)pAdd = 0x4C000064;
137 DCFlushRangeNoSync(pAdd,0x100);
138 ICInvalidateRange(pAdd,0x100);
139 _sync();
140 _CPU_ISR_Restore(level);
143 void __exception_closeall()
145 s32 i;
147 mtmsr(mfmsr()&~MSR_EE);
148 mtmsr(mfmsr()|(MSR_FP|MSR_RI));
150 for(i=0;i<NUM_EXCEPTIONS;i++) {
151 __exception_close(i);
155 void __exception_sethandler(u32 nExcept, void (*pHndl)(frame_context*))
157 _exceptionhandlertable[nExcept] = pHndl;
160 static void _cpu_print_stack(void *pc,void *lr,void *r1)
162 register u32 i = 0;
163 register frame_rec_t l,p = (frame_rec_t)lr;
165 l = p;
166 p = r1;
167 if(!p) __asm__ __volatile__("mr %0,%%r1" : "=r"(p));
169 kprintf("\n\tSTACK DUMP:");
171 for(i=0;i<CPU_STACK_TRACE_DEPTH-1 && p->up;p=p->up,i++) {
172 if(i%4) kprintf(" --> ");
173 else {
174 if(i>0) kprintf(" -->\n\t");
175 else kprintf("\n\t");
178 switch(i) {
179 case 0:
180 if(pc) kprintf("%p",pc);
181 break;
182 case 1:
183 if(!l) l = (frame_rec_t)mfspr(8);
184 kprintf("%p",(void*)l);
185 break;
186 default:
187 kprintf("%p",(void*)(p->up->lr));
188 break;
193 void __exception_setreload(int t)
195 reload_timer = t*50;
198 static void waitForReload()
200 u32 level;
202 PAD_Init();
204 if(reload_timer > 0)
205 kprintf("\n\tReloading in %d seconds\n", reload_timer/50);
207 while ( 1 )
209 PAD_ScanPads();
211 int buttonsDown = PAD_ButtonsDown(0);
213 if( (buttonsDown & PAD_TRIGGER_Z) || SYS_ResetButtonDown() ||
214 reload_timer == 0 )
216 kprintf("\n\tReload\n\n\n");
217 _CPU_ISR_Disable(level);
218 __reload ();
221 if ( buttonsDown & PAD_BUTTON_A )
223 kprintf("\n\tReset\n\n\n");
224 #if defined(HW_DOL)
225 SYS_ResetSystem(SYS_HOTRESET,0,FALSE);
226 #else
227 __reload ();
228 #endif
231 udelay(20000);
232 if(reload_timer > 0)
233 reload_timer--;
237 //just implement core for unrecoverable exceptions.
238 void c_default_exceptionhandler(frame_context *pCtx)
240 GX_AbortFrame();
241 VIDEO_SetFramebuffer(exception_xfb);
242 __console_init(exception_xfb,20,20,640,574,1280);
243 CON_EnableGecko(1, true);
245 kprintf("\n\n\n\tException (%s) occurred!\n", exception_name[pCtx->EXCPT_Number]);
247 kprintf("\tGPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n",pCtx->GPR[0], pCtx->GPR[8], pCtx->GPR[16], pCtx->GPR[24]);
248 kprintf("\tGPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n",pCtx->GPR[1], pCtx->GPR[9], pCtx->GPR[17], pCtx->GPR[25]);
249 kprintf("\tGPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n",pCtx->GPR[2], pCtx->GPR[10], pCtx->GPR[18], pCtx->GPR[26]);
250 kprintf("\tGPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n",pCtx->GPR[3], pCtx->GPR[11], pCtx->GPR[19], pCtx->GPR[27]);
251 kprintf("\tGPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n",pCtx->GPR[4], pCtx->GPR[12], pCtx->GPR[20], pCtx->GPR[28]);
252 kprintf("\tGPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n",pCtx->GPR[5], pCtx->GPR[13], pCtx->GPR[21], pCtx->GPR[29]);
253 kprintf("\tGPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n",pCtx->GPR[6], pCtx->GPR[14], pCtx->GPR[22], pCtx->GPR[30]);
254 kprintf("\tGPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n",pCtx->GPR[7], pCtx->GPR[15], pCtx->GPR[23], pCtx->GPR[31]);
255 kprintf("\tLR %08X SRR0 %08x SRR1 %08x MSR %08x\n", pCtx->LR, pCtx->SRR0, pCtx->SRR1,pCtx->MSR);
256 kprintf("\tDAR %08X DSISR %08X\n", mfspr(19), mfspr(18));
258 _cpu_print_stack((void*)pCtx->SRR0,(void*)pCtx->LR,(void*)pCtx->GPR[1]);
260 if((pCtx->EXCPT_Number==EX_DSI) || (pCtx->EXCPT_Number==EX_FP)) {
261 u32 i;
262 u32 *pAdd = (u32*)pCtx->SRR0;
263 kprintf("\n\n\tCODE DUMP:\n");
264 for (i=0; i<12; i+=4)
265 kprintf("\t%p: %08X %08X %08X %08X\n",
266 &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]);
269 waitForReload();