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