1 /*
2  * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-11-16     Dystopia     the first version
9  */
10 
11 #include "trap.h"
12 #include "c66xx.h"
13 
14 #include <rthw.h>
15 #include <rtdef.h>
16 #include <rtthread.h>
17 
18 #define RT_SYS_STACK_SIZE    4096
19 
20 rt_uint8_t rt_system_stack[RT_SYS_STACK_SIZE];
21 rt_uint8_t *rt_system_stack_top;
22 
rt_trap_init(void)23 void rt_trap_init(void)
24 {
25     rt_system_stack_top = &rt_system_stack[RT_SYS_STACK_SIZE-1];
26     rt_system_stack_top  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)rt_system_stack_top, 8);
27 
28     ack_exception(EXCEPT_TYPE_NXF);
29     ack_exception(EXCEPT_TYPE_EXC);
30     ack_exception(EXCEPT_TYPE_IXF);
31     ack_exception(EXCEPT_TYPE_SXF);
32     rt_hw_enable_exception();
33 }
34 
show_regs(struct rt_hw_exp_stack_register * regs)35 void show_regs(struct rt_hw_exp_stack_register *regs)
36 {
37     rt_kprintf("\n");
38     rt_kprintf("PC: %08lx SP: %08lx\n",
39            regs->pc, regs->hw_register.sp);
40     rt_kprintf("Status: %08lx ORIG_A4: %08lx\n",
41            regs->csr, regs->orig_a4);
42     rt_kprintf("A0: %08lx  B0: %08lx\n",
43            regs->hw_register.a0, regs->hw_register.b0);
44     rt_kprintf("A1: %08lx  B1: %08lx\n",
45            regs->hw_register.a1, regs->hw_register.b1);
46     rt_kprintf("A2: %08lx  B2: %08lx\n",
47            regs->hw_register.a2, regs->hw_register.b2);
48     rt_kprintf("A3: %08lx  B3: %08lx\n",
49            regs->hw_register.a3, regs->hw_register.b3);
50     rt_kprintf("A4: %08lx  B4: %08lx\n",
51            regs->hw_register.a4, regs->hw_register.b4);
52     rt_kprintf("A5: %08lx  B5: %08lx\n",
53            regs->hw_register.a5, regs->hw_register.b5);
54     rt_kprintf("A6: %08lx  B6: %08lx\n",
55            regs->hw_register.a6, regs->hw_register.b6);
56     rt_kprintf("A7: %08lx  B7: %08lx\n",
57            regs->hw_register.a7, regs->hw_register.b7);
58     rt_kprintf("A8: %08lx  B8: %08lx\n",
59            regs->hw_register.a8, regs->hw_register.b8);
60     rt_kprintf("A9: %08lx  B9: %08lx\n",
61            regs->hw_register.a9, regs->hw_register.b9);
62     rt_kprintf("A10: %08lx  B10: %08lx\n",
63            regs->hw_register.a10, regs->hw_register.b10);
64     rt_kprintf("A11: %08lx  B11: %08lx\n",
65            regs->hw_register.a11, regs->hw_register.b11);
66     rt_kprintf("A12: %08lx  B12: %08lx\n",
67            regs->hw_register.a12, regs->hw_register.b12);
68     rt_kprintf("A13: %08lx  B13: %08lx\n",
69            regs->hw_register.a13, regs->hw_register.b13);
70     rt_kprintf("A14: %08lx  B14: %08lx\n",
71            regs->hw_register.a14, regs->hw_register.dp);
72     rt_kprintf("A15: %08lx  B15: %08lx\n",
73            regs->hw_register.a15, regs->hw_register.sp);
74     rt_kprintf("A16: %08lx  B16: %08lx\n",
75            regs->hw_register.a16, regs->hw_register.b16);
76     rt_kprintf("A17: %08lx  B17: %08lx\n",
77            regs->hw_register.a17, regs->hw_register.b17);
78     rt_kprintf("A18: %08lx  B18: %08lx\n",
79            regs->hw_register.a18, regs->hw_register.b18);
80     rt_kprintf("A19: %08lx  B19: %08lx\n",
81            regs->hw_register.a19, regs->hw_register.b19);
82     rt_kprintf("A20: %08lx  B20: %08lx\n",
83            regs->hw_register.a20, regs->hw_register.b20);
84     rt_kprintf("A21: %08lx  B21: %08lx\n",
85            regs->hw_register.a21, regs->hw_register.b21);
86     rt_kprintf("A22: %08lx  B22: %08lx\n",
87            regs->hw_register.a22, regs->hw_register.b22);
88     rt_kprintf("A23: %08lx  B23: %08lx\n",
89            regs->hw_register.a23, regs->hw_register.b23);
90     rt_kprintf("A24: %08lx  B24: %08lx\n",
91            regs->hw_register.a24, regs->hw_register.b24);
92     rt_kprintf("A25: %08lx  B25: %08lx\n",
93            regs->hw_register.a25, regs->hw_register.b25);
94     rt_kprintf("A26: %08lx  B26: %08lx\n",
95            regs->hw_register.a26, regs->hw_register.b26);
96     rt_kprintf("A27: %08lx  B27: %08lx\n",
97            regs->hw_register.a27, regs->hw_register.b27);
98     rt_kprintf("A28: %08lx  B28: %08lx\n",
99            regs->hw_register.a28, regs->hw_register.b28);
100     rt_kprintf("A29: %08lx  B29: %08lx\n",
101            regs->hw_register.a29, regs->hw_register.b29);
102     rt_kprintf("A30: %08lx  B30: %08lx\n",
103            regs->hw_register.a30, regs->hw_register.b30);
104     rt_kprintf("A31: %08lx  B31: %08lx\n",
105            regs->hw_register.a31, regs->hw_register.b31);
106 }
107 
do_trap(struct rt_exception_info * except_info,struct rt_hw_exp_stack_register * regs)108 void do_trap(struct rt_exception_info *except_info, struct rt_hw_exp_stack_register *regs)
109 {
110     rt_kprintf("Enter exception: %s\n", except_info->kernel_str);
111 
112     show_regs(regs);
113 
114     for(;;){}
115 }
116 
117 static struct rt_exception_info iexcept_table[10] = {
118     { " - instruction fetch",         ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
119     { " - fetch packet",              ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
120     { " - execute packet",            ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL },
121     { " - undefined instruction",     ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL },
122     { " - resource conflict",         ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL },
123     { " - resource access",           ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL },
124     { " - privilege",                 ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL },
125     { " - loops buffer",              ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL },
126     { " - software exception",        ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL },
127     { " - unknown exception",         ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }
128 };
129 
130 /*
131  * Process an internal exception (non maskable)
132  */
process_iexcept(struct rt_hw_exp_stack_register * regs)133 static int process_iexcept(struct rt_hw_exp_stack_register *regs)
134 {
135     unsigned int iexcept_report = get_iexcept();
136     unsigned int iexcept_num = 0;
137 
138     ack_exception(EXCEPT_TYPE_IXF);
139 
140     while(iexcept_report)
141     {
142         iexcept_num = ffs(iexcept_report);
143         iexcept_report &= ~(1 << iexcept_num);
144         set_iexcept(iexcept_report);
145 
146         if (*(unsigned int *)regs->pc == BKPT_OPCODE)
147         {
148             /* This is a breakpoint */
149             struct rt_exception_info bkpt_exception = \
150                                      { " - undefined instruction",\
151                                      ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL };
152             do_trap(&bkpt_exception, regs);
153             iexcept_report &= ~(0xFF);
154             set_iexcept(iexcept_report);
155             continue;
156         }
157         do_trap(&iexcept_table[iexcept_num], regs);
158     }
159     return 0;
160 }
161 
162 static struct rt_exception_info eexcept_table[128] = {
163     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
164     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
165     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
166     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
167     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
168     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
169     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
170     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
171     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
172     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
173     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
174     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
175     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
176     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
177     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
178     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
179     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
180     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
181     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
182     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
183     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
184     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
185     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
186     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
187     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
188     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
189     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
190     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
191     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
192     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
193     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
194     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
195 
196     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
197     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
198     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
199     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
200     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
201     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
202     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
203     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
204     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
205     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
206     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
207     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
208     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
209     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
210     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
211     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
212     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
213     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
214     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
215     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
216     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
217     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
218     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
219     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
220     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
221     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
222     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
223     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
224     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
225     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
226     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
227     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
228 
229     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
230     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
231     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
232     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
233     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
234     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
235     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
236     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
237     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
238     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
239     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
240     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
241     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
242     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
243     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
244     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
245     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
246     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
247     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
248     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
249     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
250     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
251     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
252     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
253     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
254     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
255     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
256     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
257     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
258     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
259     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
260     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
261 
262     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
263     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
264     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
265     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
266     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
267     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
268     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
269     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
270     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
271     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
272     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
273     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
274     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
275     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
276     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
277     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
278     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
279     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
280     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
281     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
282     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
283     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
284     { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR },
285 
286     { " - CPU memory protection fault",        ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
287     { " - CPU memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
288     { " - DMA memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
289     { " - CPU memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
290     { " - DMA memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
291     { " - CPU memory protection fault in L2",  ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
292     { " - DMA memory protection fault in L2",  ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
293     { " - EMC CPU memory protection fault",    ABORT_TYPE_MAP, ABORT_BUS_ACCERR },
294     { " - EMC bus error",                      ABORT_TYPE_MAP, ABORT_BUS_ADDRERR }
295 };
296 
297 /*
298  * Process an external exception (maskable)
299  */
process_eexcept(struct rt_hw_exp_stack_register * regs)300 static void process_eexcept(struct rt_hw_exp_stack_register *regs)
301 {
302     int except_num = 0;
303     int bank = 0;
304     int i = 0;
305 
306     for (i = 0; i <= 3; i++)
307     {
308         while (INTC_MEXPMASK[i])
309        {
310             __dint();
311             except_num = ffs(INTC_MEXPMASK[i]);
312             INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */
313             __rint();
314             do_trap(&eexcept_table[except_num + (bank << 5)], regs);
315         }
316         bank++;
317     }
318 
319     ack_exception(EXCEPT_TYPE_EXC);
320 }
321 
322 extern void hw_nmi_handler(struct rt_hw_exp_stack_register *regs);
323 /*
324  * Main exception processing
325  */
rt_hw_process_exception(struct rt_hw_exp_stack_register * regs)326 int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs)
327 {
328     int type = 0;
329     int type_num = 0;
330     int ie_num = 9; /* default is unknown exception */
331 
332     while ((type = get_except_type()) != 0) {
333         type_num = fls(type) - 1;
334 
335         switch(type_num) {
336         case EXCEPT_TYPE_NXF:                   /* NMI exception   */
337             ack_exception(EXCEPT_TYPE_NXF);     /* clear exception */
338             if (hw_nmi_handler != RT_NULL)
339             {
340                 hw_nmi_handler(regs);
341             }
342             break;
343 
344         case EXCEPT_TYPE_IXF:                   /* internal exception */
345             if (process_iexcept(regs))
346             {
347                 return 1;
348             }
349             break;
350 
351         case EXCEPT_TYPE_EXC:                   /* external exception  */
352             process_eexcept(regs);
353             break;
354 
355         case EXCEPT_TYPE_SXF:                   /* software exception */
356             ie_num = 8;
357             ack_exception(type_num);
358             break;
359         default:                                /* clear exception */
360             ack_exception(type_num);
361             do_trap(&iexcept_table[ie_num], regs);
362             break;
363         }
364     }
365     return 0;
366 }
367 
368