1 /*
2  * Copyright (c) 2021-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #include "hpm_common.h"
8 #include "hpm_soc.h"
9 #include <rtthread.h>
10 #include "rt_hw_stack_frame.h"
11 
12 #define MCAUSE_INSTR_ADDR_MISALIGNED (0U)       //!< Instruction Address misaligned
13 #define MCAUSE_INSTR_ACCESS_FAULT (1U)          //!< Instruction access fault
14 #define MCAUSE_ILLEGAL_INSTR (2U)               //!< Illegal instruction
15 #define MCAUSE_BREAKPOINT (3U)                  //!< Breakpoint
16 #define MCAUSE_LOAD_ADDR_MISALIGNED (4U)        //!< Load address misaligned
17 #define MCAUSE_LOAD_ACCESS_FAULT (5U)           //!< Load access fault
18 #define MCAUSE_STORE_AMO_ADDR_MISALIGNED (6U)   //!< Store/AMO address misaligned
19 #define MCAUSE_STORE_AMO_ACCESS_FAULT (7U)      //!< Store/AMO access fault
20 #define MCAUSE_ECALL_FROM_USER_MODE (8U)        //!< Environment call from User mode
21 #define MCAUSE_ECALL_FROM_SUPERVISOR_MODE (9U)  //!< Environment call from Supervisor mode
22 #define MCAUSE_ECALL_FROM_MACHINE_MODE (11U)    //!< Environment call from machine mode
23 #define MCAUSE_INSTR_PAGE_FAULT (12U)           //!< Instruction page fault
24 #define MCAUSE_LOAD_PAGE_FAULT (13)             //!< Load page fault
25 #define MCAUSE_STORE_AMO_PAGE_FAULT (15U)       //!< Store/AMO page fault
26 
27 #define IRQ_S_SOFT              1
28 #define IRQ_H_SOFT              2
29 #define IRQ_M_SOFT              3
30 #define IRQ_S_TIMER             5
31 #define IRQ_H_TIMER             6
32 #define IRQ_M_TIMER             7
33 #define IRQ_S_EXT               9
34 #define IRQ_H_EXT               10
35 #define IRQ_M_EXT               11
36 #define IRQ_COP                 12
37 #define IRQ_HOST                13
38 
39 #ifdef DEBUG
40 #define RT_EXCEPTION_TRACE rt_kprintf
41 #else
42 #define RT_EXCEPTION_TRACE(...)
43 #endif
44 
45 typedef void (*isr_func_t)(void);
46 
47 static volatile rt_hw_stack_frame_t *s_stack_frame;
48 
mchtmr_isr(void)49 __attribute((weak)) void mchtmr_isr(void)
50 {
51 }
52 
mswi_isr(void)53 __attribute__((weak)) void mswi_isr(void)
54 {
55 }
56 
syscall_handler(uint32_t n,uint32_t a0,uint32_t a1,uint32_t a2,uint32_t a3)57 __attribute__((weak)) void syscall_handler(uint32_t n, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3)
58 {
59 }
60 
rt_show_stack_frame(void)61 void rt_show_stack_frame(void)
62 {
63     RT_EXCEPTION_TRACE("Stack frame:\r\n----------------------------------------\r\n");
64     RT_EXCEPTION_TRACE("ra      : 0x%08x\r\n", s_stack_frame->ra);
65     RT_EXCEPTION_TRACE("mstatus : 0x%08x\r\n", read_csr(0x300));//mstatus
66     RT_EXCEPTION_TRACE("t0      : 0x%08x\r\n", s_stack_frame->t0);
67     RT_EXCEPTION_TRACE("t1      : 0x%08x\r\n", s_stack_frame->t1);
68     RT_EXCEPTION_TRACE("t2      : 0x%08x\r\n", s_stack_frame->t2);
69     RT_EXCEPTION_TRACE("a0      : 0x%08x\r\n", s_stack_frame->a0);
70     RT_EXCEPTION_TRACE("a1      : 0x%08x\r\n", s_stack_frame->a1);
71     RT_EXCEPTION_TRACE("a2      : 0x%08x\r\n", s_stack_frame->a2);
72     RT_EXCEPTION_TRACE("a3      : 0x%08x\r\n", s_stack_frame->a3);
73     RT_EXCEPTION_TRACE("a4      : 0x%08x\r\n", s_stack_frame->a4);
74     RT_EXCEPTION_TRACE("a5      : 0x%08x\r\n", s_stack_frame->a5);
75 #ifndef __riscv_32e
76     RT_EXCEPTION_TRACE("a6      : 0x%08x\r\n", s_stack_frame->a6);
77     RT_EXCEPTION_TRACE("a7      : 0x%08x\r\n", s_stack_frame->a7);
78     RT_EXCEPTION_TRACE("t3      : 0x%08x\r\n", s_stack_frame->t3);
79     RT_EXCEPTION_TRACE("t4      : 0x%08x\r\n", s_stack_frame->t4);
80     RT_EXCEPTION_TRACE("t5      : 0x%08x\r\n", s_stack_frame->t5);
81     RT_EXCEPTION_TRACE("t6      : 0x%08x\r\n", s_stack_frame->t6);
82 #endif
83 }
84 
exception_handler(uint32_t cause,uint32_t epc)85 uint32_t exception_handler(uint32_t cause, uint32_t epc)
86 {
87     /* Unhandled Trap */
88     uint32_t mdcause = read_csr(CSR_MDCAUSE);
89     uint32_t mtval = read_csr(CSR_MTVAL);
90     rt_uint32_t mscratch = read_csr(0x340);
91 
92     s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
93     rt_show_stack_frame();
94 
95     switch (cause)
96     {
97     case MCAUSE_INSTR_ADDR_MISALIGNED:
98         RT_EXCEPTION_TRACE("exception: instruction address was mis-aligned, mtval=0x%08x\n", mtval);
99         break;
100     case MCAUSE_INSTR_ACCESS_FAULT:
101         RT_EXCEPTION_TRACE("exception: instruction access fault happened, mtval=0x%08x, epc=0x%08x\n", mtval, epc);
102         switch (mdcause & 0x07)
103         {
104         case 1:
105             RT_EXCEPTION_TRACE("mdcause: ECC/Parity error\r\n");
106             break;
107         case 2:
108             RT_EXCEPTION_TRACE("mdcause: PMP instruction access violation \r\n");
109             break;
110         case 3:
111             RT_EXCEPTION_TRACE("mdcause: BUS error\r\n");
112             break;
113         case 4:
114             RT_EXCEPTION_TRACE("mdcause: PMP empty hole access \r\n");
115             break;
116         default:
117             RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
118             break;
119         }
120         break;
121     case MCAUSE_ILLEGAL_INSTR:
122         RT_EXCEPTION_TRACE("exception: illegal instruction was met, mtval=0x%08x\n", mtval);
123         switch (mdcause & 0x07)
124         {
125         case 0:
126             RT_EXCEPTION_TRACE("mdcause: the actual faulting instruction is stored in the mtval CSR\r\n");
127             break;
128         case 1:
129             RT_EXCEPTION_TRACE("mdcause: FP disabled exception \r\n");
130             break;
131         case 2:
132             RT_EXCEPTION_TRACE("mdcause: ACE disabled exception \r\n");
133             break;
134         default:
135             RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
136             break;
137         }
138         break;
139     case MCAUSE_BREAKPOINT:
140         RT_EXCEPTION_TRACE("exception: breakpoint was hit, mtval=0x%08x\n", mtval);
141         break;
142     case MCAUSE_LOAD_ADDR_MISALIGNED:
143         RT_EXCEPTION_TRACE("exception: load address was mis-aligned, mtval=0x%08x\n", mtval);
144         break;
145     case MCAUSE_LOAD_ACCESS_FAULT:
146         RT_EXCEPTION_TRACE("exception: load access fault happened, epc=%08x, mdcause=0x%x\n", epc, mdcause);
147         switch (mdcause & 0x07)
148         {
149         case 1:
150             RT_EXCEPTION_TRACE("mdcause: ECC/Parity error\r\n");
151             break;
152         case 2:
153             RT_EXCEPTION_TRACE("mdcause: PMP instruction access violation \r\n");
154             break;
155         case 3:
156             RT_EXCEPTION_TRACE("mdcause: BUS error\r\n");
157             break;
158         case 4:
159             RT_EXCEPTION_TRACE("mdcause: Misaligned access \r\n");
160             break;
161         case 5:
162             RT_EXCEPTION_TRACE("mdcause: PMP empty hole access \r\n");
163             break;
164         case 6:
165             RT_EXCEPTION_TRACE("mdcause: PMA attribute inconsistency\r\n");
166             break;
167         default:
168             RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
169             break;
170         }
171         break;
172     case MCAUSE_STORE_AMO_ADDR_MISALIGNED:
173         RT_EXCEPTION_TRACE("exception: store amo address was misaligned, epc=%08x\n", epc);
174         break;
175     case MCAUSE_STORE_AMO_ACCESS_FAULT:
176         RT_EXCEPTION_TRACE("exception: store amo access fault happened, epc=%08x\n", epc);
177         switch (mdcause & 0x07)
178         {
179         case 1:
180             RT_EXCEPTION_TRACE("mdcause: ECC/Parity error\r\n");
181             break;
182         case 2:
183             RT_EXCEPTION_TRACE("mdcause: PMP instruction access violation \r\n");
184             break;
185         case 3:
186             RT_EXCEPTION_TRACE("mdcause: BUS error\r\n");
187             break;
188         case 4:
189             RT_EXCEPTION_TRACE("mdcause: Misaligned access \r\n");
190             break;
191         case 5:
192             RT_EXCEPTION_TRACE("mdcause: PMP empty hole access \r\n");
193             break;
194         case 6:
195             RT_EXCEPTION_TRACE("mdcause: PMA attribute inconsistency\r\n");
196             break;
197         case 7:
198             RT_EXCEPTION_TRACE("mdcause: PMA NAMO exception \r\n");
199         default:
200             RT_EXCEPTION_TRACE("mdcause: reserved \r\n");
201             break;
202         }
203         break;
204     default:
205         RT_EXCEPTION_TRACE("Unknown exception happened, cause=%d\n", cause);
206         break;
207     }
208 
209     rt_kprintf("cause=0x%08x, epc=0x%08x, ra=0x%08x\n", cause, epc, s_stack_frame->ra);
210     while(1) {
211     }
212 }
213 
214 void trap_entry(void);
215 
trap_entry(void)216 void trap_entry(void)
217 {
218     uint32_t mcause = read_csr(CSR_MCAUSE);
219     uint32_t mepc = read_csr(CSR_MEPC);
220     uint32_t mstatus = read_csr(CSR_MSTATUS);
221 
222 #if SUPPORT_PFT_ARCH
223     uint32_t mxstatus = read_csr(CSR_MXSTATUS);
224 #endif
225 #ifdef __riscv_dsp
226     int ucode = read_csr(CSR_UCODE);
227 #endif
228 #ifdef __riscv_flen
229     int fcsr = read_fcsr();
230 #endif
231 
232     /* clobbers list for ecall */
233 #ifdef __riscv_32e
234     __asm volatile("" : : :"t0", "a0", "a1", "a2", "a3");
235 #else
236     __asm volatile("" : : :"a7", "a0", "a1", "a2", "a3");
237 #endif
238 
239     /* Do your trap handling */
240     uint32_t cause_type = mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK;
241     uint32_t irq_index;
242     if (mcause & CSR_MCAUSE_INTERRUPT_MASK)
243     {
244         switch (cause_type)
245         {
246         /* Machine timer interrupt */
247         case IRQ_M_TIMER:
248             mchtmr_isr();
249             break;
250             /* Machine EXT interrupt */
251         case IRQ_M_EXT:
252             /* Claim interrupt */
253             irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE);
254             /* Execute EXT interrupt handler */
255             if (irq_index > 0)
256             {
257                 ((isr_func_t) __vector_table[irq_index])();
258                 /* Complete interrupt */
259                 __plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE, irq_index);
260             }
261             break;
262             /* Machine SWI interrupt */
263         case IRQ_M_SOFT:
264             mswi_isr();
265             intc_m_complete_swi();
266             break;
267         }
268     }
269     else if (cause_type == MCAUSE_ECALL_FROM_MACHINE_MODE)
270     {
271         /* Machine Syscal call */
272         __asm volatile(
273                 "mv a4, a3\n"
274                 "mv a3, a2\n"
275                 "mv a2, a1\n"
276                 "mv a1, a0\n"
277 #ifdef __riscv_32e
278                 "mv a0, t0\n"
279 #else
280                 "mv a0, a7\n"
281 #endif
282                 "call syscall_handler\n"
283                 : : : "a4"
284         );
285         mepc += 4;
286     }
287     else
288     {
289         mepc = exception_handler(mcause, mepc);
290     }
291 
292     /* Restore CSR */
293     write_csr(CSR_MSTATUS, mstatus);
294     write_csr(CSR_MEPC, mepc);
295 #if SUPPORT_PFT_ARCH
296     write_csr(CSR_MXSTATUS, mxstatus);
297 #endif
298 #ifdef __riscv_dsp
299     write_csr(CSR_UCODE, ucode);
300 #endif
301 #ifdef __riscv_flen
302     write_fcsr(fcsr);
303 #endif
304 }
305 
306 /**
307  * Trap Handler
308  */
handle_trap(rt_uint32_t mcause,rt_uint32_t mepc,rt_uint32_t sp)309 rt_weak void handle_trap(rt_uint32_t mcause, rt_uint32_t mepc, rt_uint32_t sp)
310 {
311 }
312