1 /*
2  * Copyright (c) 2021-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_common.h"
9 #include "hpm_soc.h"
10 
11 #ifdef __ICCRISCV__
12 #pragma language = extended
13 #endif
14 
15 /********************** MCAUSE exception types **************************************/
16 #define MCAUSE_INSTR_ADDR_MISALIGNED (0U)       /* !< Instruction Address misaligned */
17 #define MCAUSE_INSTR_ACCESS_FAULT (1U)          /* !< Instruction access fault */
18 #define MCAUSE_ILLEGAL_INSTR (2U)               /* !< Illegal instruction */
19 #define MCAUSE_BREAKPOINT (3U)                  /* !< Breakpoint */
20 #define MCAUSE_LOAD_ADDR_MISALIGNED (4U)        /* !< Load address misaligned */
21 #define MCAUSE_LOAD_ACCESS_FAULT (5U)           /* !< Load access fault */
22 #define MCAUSE_STORE_AMO_ADDR_MISALIGNED (6U)   /* !< Store/AMO address misaligned */
23 #define MCAUSE_STORE_AMO_ACCESS_FAULT (7U)      /* !< Store/AMO access fault */
24 #define MCAUSE_ECALL_FROM_USER_MODE (8U)        /* !< Environment call from User mode */
25 #define MCAUSE_ECALL_FROM_SUPERVISOR_MODE (9U)  /* !< Environment call from Supervisor mode */
26 #define MCAUSE_ECALL_FROM_MACHINE_MODE (11U)    /* !< Environment call from machine mode */
27 #define MCAUSE_INSTR_PAGE_FAULT (12U)           /* !< Instruction page fault */
28 #define MCAUSE_LOAD_PAGE_FAULT (13)             /* !< Load page fault */
29 #define MCAUSE_STORE_AMO_PAGE_FAULT (15U)       /* !< Store/AMO page fault */
30 
31 #define IRQ_S_SOFT            1
32 #define IRQ_H_SOFT            2
33 #define IRQ_M_SOFT            3
34 #define IRQ_S_TIMER            5
35 #define IRQ_H_TIMER            6
36 #define IRQ_M_TIMER            7
37 #define IRQ_S_EXT            9
38 #define IRQ_H_EXT            10
39 #define IRQ_M_EXT            11
40 #define IRQ_COP                12
41 #define IRQ_HOST                13
42 
mchtmr_isr(void)43 __attribute__((weak)) void mchtmr_isr(void)
44 {
45 }
46 
swi_isr(void)47 __attribute__((weak)) void swi_isr(void)
48 {
49 }
50 
syscall_handler(long n,long a0,long a1,long a2,long a3)51 __attribute__((weak)) void syscall_handler(long n, long a0, long a1, long a2, long a3)
52 {
53     (void) n;
54     (void) a0;
55     (void) a1;
56     (void) a2;
57     (void) a3;
58 }
59 
exception_handler(long cause,long epc)60 __attribute__((weak)) long exception_handler(long cause, long epc)
61 {
62     switch (cause) {
63     case MCAUSE_INSTR_ADDR_MISALIGNED:
64         break;
65     case MCAUSE_INSTR_ACCESS_FAULT:
66         break;
67     case MCAUSE_ILLEGAL_INSTR:
68         break;
69     case MCAUSE_BREAKPOINT:
70         break;
71     case MCAUSE_LOAD_ADDR_MISALIGNED:
72         break;
73     case MCAUSE_LOAD_ACCESS_FAULT:
74         break;
75     case MCAUSE_STORE_AMO_ADDR_MISALIGNED:
76         break;
77     case MCAUSE_STORE_AMO_ACCESS_FAULT:
78         break;
79     case MCAUSE_ECALL_FROM_USER_MODE:
80         break;
81     case MCAUSE_ECALL_FROM_SUPERVISOR_MODE:
82         break;
83     case MCAUSE_ECALL_FROM_MACHINE_MODE:
84         break;
85     case MCAUSE_INSTR_PAGE_FAULT:
86         break;
87     case MCAUSE_LOAD_PAGE_FAULT:
88         break;
89     case MCAUSE_STORE_AMO_PAGE_FAULT:
90         break;
91     default:
92         break;
93     }
94     /* Unhandled Trap */
95     return epc;
96 }
97 
98 #if !defined(CONFIG_FREERTOS) && !defined(CONFIG_UCOS_III) && !defined(CONFIG_THREADX) && !defined(CONFIG_RTTHREAD)
99 HPM_ATTR_MACHINE_INTERRUPT void irq_handler_trap(void);
100 #define IRQ_HANDLER_TRAP_AS_ISR 1
101 #else
102 void irq_handler_trap(void) __attribute__ ((section(".isr_vector")));
103 #endif
104 
105 #if defined(__ICCRISCV__) && (IRQ_HANDLER_TRAP_AS_ISR == 1)
106 extern int __vector_table[];
107 HPM_ATTR_MACHINE_INTERRUPT
108 #endif
irq_handler_trap(void)109 void irq_handler_trap(void)
110 {
111     long mcause = read_csr(CSR_MCAUSE);
112     long mepc = read_csr(CSR_MEPC);
113     long mstatus = read_csr(CSR_MSTATUS);
114 #if defined(SUPPORT_PFT_ARCH) && SUPPORT_PFT_ARCH
115     long mxstatus = read_csr(CSR_MXSTATUS);
116 #endif
117 #ifdef __riscv_dsp
118     int ucode = read_csr(CSR_UCODE);
119 #endif
120 #ifdef __riscv_flen
121     int fcsr = read_fcsr();
122 #endif
123 
124     /* clobbers list for ecall */
125 #ifdef __riscv_32e
126     __asm volatile("" : : : "t0", "a0", "a1", "a2", "a3");
127 #else
128     __asm volatile("" : : : "a7", "a0", "a1", "a2", "a3");
129 #endif
130 
131     /* Do your trap handling */
132     if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_TIMER)) {
133         /* Machine timer interrupt */
134         mchtmr_isr();
135     }
136 #ifdef USE_NONVECTOR_MODE
137     else if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_EXT)) {
138 
139         typedef void(*isr_func_t)(void);
140 
141         /* Machine-level interrupt from PLIC */
142         uint32_t irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE);
143         if (irq_index) {
144         /* Workaround: irq number returned by __plic_claim_irq might be 0, which is caused by plic. So skip invalid irq_index as a workaround */
145 #if !defined(DISABLE_IRQ_PREEMPTIVE) || (DISABLE_IRQ_PREEMPTIVE == 0)
146             enable_global_irq(CSR_MSTATUS_MIE_MASK);
147 #endif
148             ((isr_func_t)__vector_table[irq_index])();
149             __plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE, irq_index);
150         }
151     }
152 #endif
153 
154     else if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_SOFT)) {
155         /* Machine SWI interrupt */
156         intc_m_claim_swi();
157         swi_isr();
158         intc_m_complete_swi();
159     } else if (!(mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == MCAUSE_ECALL_FROM_MACHINE_MODE)) {
160         /* Machine Syscal call */
161         __asm volatile(
162         "mv a4, a3\n"
163         "mv a3, a2\n"
164         "mv a2, a1\n"
165         "mv a1, a0\n"
166         #ifdef __riscv_32e
167         "mv a0, t0\n"
168         #else
169         "mv a0, a7\n"
170         #endif
171         "jalr %0\n"
172         : : "r"(syscall_handler) : "a4"
173         );
174         mepc += 4;
175     } else {
176         mepc = exception_handler(mcause, mepc);
177     }
178 
179     /* Restore CSR */
180     write_csr(CSR_MSTATUS, mstatus);
181     write_csr(CSR_MEPC, mepc);
182 #if defined(SUPPORT_PFT_ARCH) && SUPPORT_PFT_ARCH
183     write_csr(CSR_MXSTATUS, mxstatus);
184 #endif
185 #ifdef __riscv_dsp
186     write_csr(CSR_UCODE, ucode);
187 #endif
188 #ifdef __riscv_flen
189     write_fcsr(fcsr);
190 #endif
191 }
192