1*10465441SEvalZero #include <rtthread.h>
2*10465441SEvalZero #include <asm/processor.h>
3*10465441SEvalZero #include <asm/ppc4xx-uic.h>
4*10465441SEvalZero
5*10465441SEvalZero /* Returns 0 if exception not found and fixup otherwise. */
6*10465441SEvalZero extern unsigned long search_exception_table(unsigned long);
7*10465441SEvalZero
8*10465441SEvalZero /* THIS NEEDS CHANGING to use the board info structure.
9*10465441SEvalZero */
10*10465441SEvalZero #define END_OF_MEM 0x800000
11*10465441SEvalZero #define UICB0_ALL 0
12*10465441SEvalZero
13*10465441SEvalZero #define ESR_MCI 0x80000000
14*10465441SEvalZero #define ESR_PIL 0x08000000
15*10465441SEvalZero #define ESR_PPR 0x04000000
16*10465441SEvalZero #define ESR_PTR 0x02000000
17*10465441SEvalZero #define ESR_DST 0x00800000
18*10465441SEvalZero #define ESR_DIZ 0x00400000
19*10465441SEvalZero #define ESR_U0F 0x00008000
20*10465441SEvalZero
set_tsr(unsigned long val)21*10465441SEvalZero rt_inline void set_tsr(unsigned long val)
22*10465441SEvalZero {
23*10465441SEvalZero mtspr(SPRN_TSR, val);
24*10465441SEvalZero }
25*10465441SEvalZero
get_esr(void)26*10465441SEvalZero rt_inline rt_uint32_t get_esr(void)
27*10465441SEvalZero {
28*10465441SEvalZero rt_uint32_t val;
29*10465441SEvalZero
30*10465441SEvalZero val = mfspr(SPRN_ESR);
31*10465441SEvalZero return val;
32*10465441SEvalZero }
33*10465441SEvalZero
34*10465441SEvalZero /*
35*10465441SEvalZero * Trap & Exception support
36*10465441SEvalZero */
37*10465441SEvalZero
print_backtrace(unsigned long * sp)38*10465441SEvalZero void print_backtrace(unsigned long *sp)
39*10465441SEvalZero {
40*10465441SEvalZero int cnt = 0;
41*10465441SEvalZero unsigned long i;
42*10465441SEvalZero
43*10465441SEvalZero rt_kprintf("Call backtrace: ");
44*10465441SEvalZero while (sp) {
45*10465441SEvalZero if ((rt_uint32_t)sp > END_OF_MEM)
46*10465441SEvalZero break;
47*10465441SEvalZero
48*10465441SEvalZero i = sp[1];
49*10465441SEvalZero if (cnt++ % 7 == 0)
50*10465441SEvalZero rt_kprintf("\n");
51*10465441SEvalZero rt_kprintf("%08lX ", i);
52*10465441SEvalZero if (cnt > 32) break;
53*10465441SEvalZero sp = (unsigned long *)*sp;
54*10465441SEvalZero }
55*10465441SEvalZero rt_kprintf("\n");
56*10465441SEvalZero }
57*10465441SEvalZero
show_regs(struct pt_regs * regs)58*10465441SEvalZero void show_regs(struct pt_regs * regs)
59*10465441SEvalZero {
60*10465441SEvalZero int i;
61*10465441SEvalZero
62*10465441SEvalZero rt_kprintf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n",
63*10465441SEvalZero regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
64*10465441SEvalZero rt_kprintf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
65*10465441SEvalZero regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
66*10465441SEvalZero regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
67*10465441SEvalZero regs->msr&MSR_IR ? 1 : 0,
68*10465441SEvalZero regs->msr&MSR_DR ? 1 : 0);
69*10465441SEvalZero
70*10465441SEvalZero rt_kprintf("\n");
71*10465441SEvalZero for (i = 0; i < 32; i++) {
72*10465441SEvalZero if ((i % 8) == 0) {
73*10465441SEvalZero rt_kprintf("GPR%02d: ", i);
74*10465441SEvalZero }
75*10465441SEvalZero
76*10465441SEvalZero rt_kprintf("%08lX ", regs->gpr[i]);
77*10465441SEvalZero if ((i % 8) == 7) {
78*10465441SEvalZero rt_kprintf("\n");
79*10465441SEvalZero }
80*10465441SEvalZero }
81*10465441SEvalZero }
82*10465441SEvalZero
panic(const char * fmt,...)83*10465441SEvalZero void panic(const char *fmt, ...)
84*10465441SEvalZero {
85*10465441SEvalZero while(1);
86*10465441SEvalZero }
87*10465441SEvalZero
88*10465441SEvalZero void
_exception(int signr,struct pt_regs * regs)89*10465441SEvalZero _exception(int signr, struct pt_regs *regs)
90*10465441SEvalZero {
91*10465441SEvalZero show_regs(regs);
92*10465441SEvalZero print_backtrace((unsigned long *)regs->gpr[1]);
93*10465441SEvalZero panic("Exception");
94*10465441SEvalZero }
95*10465441SEvalZero
96*10465441SEvalZero unsigned long
search_exception_table(unsigned long addr)97*10465441SEvalZero search_exception_table(unsigned long addr)
98*10465441SEvalZero {
99*10465441SEvalZero unsigned long ret = 0;
100*10465441SEvalZero
101*10465441SEvalZero /* There is only the kernel to search. */
102*10465441SEvalZero // ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
103*10465441SEvalZero /* if the serial port does not hang in exception, rt_kprintf can be used */
104*10465441SEvalZero if (ret) return ret;
105*10465441SEvalZero
106*10465441SEvalZero return 0;
107*10465441SEvalZero }
108*10465441SEvalZero
109*10465441SEvalZero /*
110*10465441SEvalZero * Handle external interrupts
111*10465441SEvalZero */
external_interrupt(struct pt_regs * regs)112*10465441SEvalZero void external_interrupt(struct pt_regs *regs)
113*10465441SEvalZero {
114*10465441SEvalZero u32 uic_msr;
115*10465441SEvalZero
116*10465441SEvalZero /*
117*10465441SEvalZero * Read masked interrupt status register to determine interrupt source
118*10465441SEvalZero */
119*10465441SEvalZero uic_msr = mfdcr(uic0msr);
120*10465441SEvalZero
121*10465441SEvalZero mtdcr(uic0sr, (uic_msr & UICB0_ALL));
122*10465441SEvalZero
123*10465441SEvalZero if (uic_msr & ~(UICB0_ALL))
124*10465441SEvalZero {
125*10465441SEvalZero uic_interrupt(UIC0_DCR_BASE, 0);
126*10465441SEvalZero }
127*10465441SEvalZero
128*10465441SEvalZero return;
129*10465441SEvalZero }
130*10465441SEvalZero
MachineCheckException(struct pt_regs * regs)131*10465441SEvalZero void MachineCheckException(struct pt_regs *regs)
132*10465441SEvalZero {
133*10465441SEvalZero unsigned long fixup, val;
134*10465441SEvalZero
135*10465441SEvalZero if ((fixup = search_exception_table(regs->nip)) != 0) {
136*10465441SEvalZero regs->nip = fixup;
137*10465441SEvalZero val = mfspr(MCSR);
138*10465441SEvalZero /* Clear MCSR */
139*10465441SEvalZero mtspr(SPRN_MCSR, val);
140*10465441SEvalZero return;
141*10465441SEvalZero }
142*10465441SEvalZero
143*10465441SEvalZero rt_kprintf("Machine Check Exception.\n");
144*10465441SEvalZero rt_kprintf("Caused by (from msr): ");
145*10465441SEvalZero rt_kprintf("regs %p ", regs);
146*10465441SEvalZero
147*10465441SEvalZero val = get_esr();
148*10465441SEvalZero
149*10465441SEvalZero if (val& ESR_IMCP) {
150*10465441SEvalZero rt_kprintf("Instruction");
151*10465441SEvalZero mtspr(ESR, val & ~ESR_IMCP);
152*10465441SEvalZero } else {
153*10465441SEvalZero rt_kprintf("Data");
154*10465441SEvalZero }
155*10465441SEvalZero rt_kprintf(" machine check.\n");
156*10465441SEvalZero
157*10465441SEvalZero show_regs(regs);
158*10465441SEvalZero print_backtrace((unsigned long *)regs->gpr[1]);
159*10465441SEvalZero panic("machine check");
160*10465441SEvalZero }
161*10465441SEvalZero
AlignmentException(struct pt_regs * regs)162*10465441SEvalZero void AlignmentException(struct pt_regs *regs)
163*10465441SEvalZero {
164*10465441SEvalZero show_regs(regs);
165*10465441SEvalZero print_backtrace((unsigned long *)regs->gpr[1]);
166*10465441SEvalZero panic("Alignment Exception");
167*10465441SEvalZero }
168*10465441SEvalZero
ProgramCheckException(struct pt_regs * regs)169*10465441SEvalZero void ProgramCheckException(struct pt_regs *regs)
170*10465441SEvalZero {
171*10465441SEvalZero long esr_val;
172*10465441SEvalZero
173*10465441SEvalZero show_regs(regs);
174*10465441SEvalZero
175*10465441SEvalZero esr_val = get_esr();
176*10465441SEvalZero if( esr_val & ESR_PIL )
177*10465441SEvalZero rt_kprintf( "** Illegal Instruction **\n" );
178*10465441SEvalZero else if( esr_val & ESR_PPR )
179*10465441SEvalZero rt_kprintf( "** Privileged Instruction **\n" );
180*10465441SEvalZero else if( esr_val & ESR_PTR )
181*10465441SEvalZero rt_kprintf( "** Trap Instruction **\n" );
182*10465441SEvalZero
183*10465441SEvalZero print_backtrace((unsigned long *)regs->gpr[1]);
184*10465441SEvalZero panic("Program Check Exception");
185*10465441SEvalZero }
186*10465441SEvalZero
DecrementerPITException(struct pt_regs * regs)187*10465441SEvalZero void DecrementerPITException(struct pt_regs *regs)
188*10465441SEvalZero {
189*10465441SEvalZero /* reset PIT interrupt */
190*10465441SEvalZero set_tsr(0x08000000);
191*10465441SEvalZero
192*10465441SEvalZero /* increase a OS Tick */
193*10465441SEvalZero rt_tick_increase();
194*10465441SEvalZero }
195*10465441SEvalZero
UnknownException(struct pt_regs * regs)196*10465441SEvalZero void UnknownException(struct pt_regs *regs)
197*10465441SEvalZero {
198*10465441SEvalZero
199*10465441SEvalZero rt_kprintf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
200*10465441SEvalZero regs->nip, regs->msr, regs->trap);
201*10465441SEvalZero _exception(0, regs);
202*10465441SEvalZero }
203*10465441SEvalZero
DebugException(struct pt_regs * regs)204*10465441SEvalZero void DebugException(struct pt_regs *regs)
205*10465441SEvalZero {
206*10465441SEvalZero rt_kprintf("Debugger trap at @ %lx @regs %lx\n", regs->nip, (rt_uint32_t)regs );
207*10465441SEvalZero show_regs(regs);
208*10465441SEvalZero }
209