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
)
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);
140 _CPU_ISR_Restore(level
);
143 void __exception_closeall()
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
)
163 register frame_rec_t l
,p
= (frame_rec_t
)lr
;
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(" --> ");
174 if(i
>0) kprintf(" -->\n\t");
175 else kprintf("\n\t");
180 if(pc
) kprintf("%p",pc
);
183 if(!l
) l
= (frame_rec_t
)mfspr(8);
184 kprintf("%p",(void*)l
);
187 kprintf("%p",(void*)(p
->up
->lr
));
193 void __exception_setreload(int t
)
198 static void waitForReload()
205 kprintf("\n\tReloading in %d seconds\n", reload_timer
/50);
211 int buttonsDown
= PAD_ButtonsDown(0);
213 if( (buttonsDown
& PAD_TRIGGER_Z
) || SYS_ResetButtonDown() ||
216 kprintf("\n\tReload\n\n\n");
217 _CPU_ISR_Disable(level
);
221 if ( buttonsDown
& PAD_BUTTON_A
)
223 kprintf("\n\tReset\n\n\n");
225 SYS_ResetSystem(SYS_HOTRESET
,0,FALSE
);
237 //just implement core for unrecoverable exceptions.
238 void c_default_exceptionhandler(frame_context
*pCtx
)
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
)) {
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]);