1 /*
2 * Copyright (c) 2013-2020, Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <stdio.h>
33 #include <stdarg.h>
34 #include "los_arch.h"
35 #include "los_arch_interrupt.h"
36 #include "los_arch_context.h"
37 #include "los_task.h"
38 #include "los_sched.h"
39 #include "los_debug.h"
40 #include "los_hook.h"
41 #include "riscv_hal.h"
42
43
44 LosExcInfo g_excInfo;
45 #define RISCV_EXC_TYPE_NUM 16
46 #define RISCV_EXC_LOAD_MISALIGNED 4
47 #define RISCV_EXC_STORE_MISALIGNED 6
48 const CHAR g_excInformation[RISCV_EXC_TYPE_NUM][50] = {
49 { "Instruction address misaligned!" },
50 { "Instruction access fault!" },
51 { "Illegal instruction" },
52 { "Breakpoint!" },
53 { "Load address misaligned!" },
54 { "Load access fault!" },
55 { "Store/AMO address misaligned!" },
56 { "Store/AMO access fault!" },
57 { "Environment call form U-mode!" },
58 { "Environment call form S-mode!" },
59 { "Reserved!" },
60 { "Environment call form M-mode!" },
61 { "Instruction page fault!" },
62 { "Load page fault!" },
63 { "Reserved!" },
64 { "Store/AMO page fault!" },
65 };
66
67 LITE_OS_SEC_BSS UINT32 g_intCount = 0;
68 LITE_OS_SEC_BSS UINT32 g_hwiFormCnt[OS_HWI_MAX_NUM];
69 LITE_OS_SEC_DATA_INIT HWI_HANDLE_FORM_S g_hwiForm[OS_HWI_MAX_NUM] = {
70 { .pfnHook = NULL, .uwParam = 0 }, // 0 User software interrupt handler
71 { .pfnHook = NULL, .uwParam = 0 }, // 1 Supervisor software interrupt handler
72 { .pfnHook = NULL, .uwParam = 0 }, // 2 Reserved
73 { .pfnHook = HalHwiDefaultHandler, .uwParam = 0 }, // 3 Machine software interrupt handler
74 { .pfnHook = NULL, .uwParam = 0 }, // 4 User timer interrupt handler
75 { .pfnHook = NULL, .uwParam = 0 }, // 5 Supervisor timer interrupt handler
76 { .pfnHook = NULL, .uwParam = 0 }, // 6 Reserved
77 { .pfnHook = HalHwiDefaultHandler, .uwParam = 0 }, // 7 Machine timer interrupt handler
78 { .pfnHook = NULL, .uwParam = 0 }, // 8 User external interrupt handler
79 { .pfnHook = NULL, .uwParam = 0 }, // 9 Supervisor external interrupt handler
80 { .pfnHook = NULL, .uwParam = 0 }, // 10 Reserved
81 { .pfnHook = HalHwiDefaultHandler, .uwParam = 0 }, // 11 Machine external interrupt handler
82 { .pfnHook = HalHwiDefaultHandler, .uwParam = 0 }, // 12 NMI handler
83 { .pfnHook = NULL, .uwParam = 0 }, // 13 Reserved
84 { .pfnHook = NULL, .uwParam = 0 }, // 14 Reserved
85 { .pfnHook = NULL, .uwParam = 0 }, // 15 Reserved
86 { .pfnHook = NULL, .uwParam = 0 }, // 16 Reserved
87 { .pfnHook = NULL, .uwParam = 0 }, // 17 Reserved
88 { .pfnHook = NULL, .uwParam = 0 }, // 18 Reserved
89 { .pfnHook = NULL, .uwParam = 0 }, // 19 Reserved
90 { .pfnHook = NULL, .uwParam = 0 }, // 20 Reserved
91 { .pfnHook = NULL, .uwParam = 0 }, // 21 Reserved
92 { .pfnHook = NULL, .uwParam = 0 }, // 22 Reserved
93 { .pfnHook = NULL, .uwParam = 0 }, // 23 Reserved
94 { .pfnHook = NULL, .uwParam = 0 }, // 24 Reserved
95 { .pfnHook = NULL, .uwParam = 0 }, // 25 Reserved
96 };
97
HalHwiDefaultHandler(VOID * arg)98 LITE_OS_SEC_TEXT_INIT VOID HalHwiDefaultHandler(VOID *arg)
99 {
100 (VOID)arg;
101 PRINT_ERR("default handler\n");
102 while (1) {
103 }
104 }
105
HalHwiInit(VOID)106 LITE_OS_SEC_TEXT_INIT VOID HalHwiInit(VOID)
107 {
108 UINT32 index;
109 for (index = OS_RISCV_SYS_VECTOR_CNT; index < OS_HWI_MAX_NUM; index++) {
110 g_hwiForm[index].pfnHook = HalHwiDefaultHandler;
111 g_hwiForm[index].uwParam = 0;
112 }
113 }
114
115 typedef VOID (*HwiProcFunc)(VOID *arg);
HalHwiInterruptDone(HWI_HANDLE_T hwiNum)116 __attribute__((section(".interrupt.text"))) VOID HalHwiInterruptDone(HWI_HANDLE_T hwiNum)
117 {
118 g_intCount++;
119
120 OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, hwiNum);
121
122 HWI_HANDLE_FORM_S *hwiForm = &g_hwiForm[hwiNum];
123 HwiProcFunc func = (HwiProcFunc)(hwiForm->pfnHook);
124 func(hwiForm->uwParam);
125
126 ++g_hwiFormCnt[hwiNum];
127
128 OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, hwiNum);
129
130 g_intCount--;
131 }
132
HalGetHwiFormCnt(HWI_HANDLE_T hwiNum)133 LITE_OS_SEC_TEXT UINT32 HalGetHwiFormCnt(HWI_HANDLE_T hwiNum)
134 {
135 if (hwiNum < OS_HWI_MAX_NUM) {
136 return g_hwiFormCnt[hwiNum];
137 }
138
139 return LOS_NOK;
140 }
141
HalGetHwiForm(VOID)142 LITE_OS_SEC_TEXT HWI_HANDLE_FORM_S *HalGetHwiForm(VOID)
143 {
144 return g_hwiForm;
145 }
146
147
ArchIsIntActive(VOID)148 inline UINT32 ArchIsIntActive(VOID)
149 {
150 return (g_intCount > 0);
151 }
152
153 /*****************************************************************************
154 Function : ArchHwiCreate
155 Description : create hardware interrupt
156 Input : hwiNum --- hwi num to create
157 hwiPrio --- priority of the hwi
158 hwiMode --- hwi interrupt mode
159 hwiHandler --- hwi handler
160 irqParam --- param of the hwi handler
161 Output : None
162 Return : LOS_OK on success or error code on failure
163 *****************************************************************************/
ArchHwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio,HWI_MODE_T hwiMode,HWI_PROC_FUNC hwiHandler,HwiIrqParam * irqParam)164 LITE_OS_SEC_TEXT UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum,
165 HWI_PRIOR_T hwiPrio,
166 HWI_MODE_T hwiMode,
167 HWI_PROC_FUNC hwiHandler,
168 HwiIrqParam *irqParam)
169 {
170 UINT32 intSave;
171
172 if (hwiHandler == NULL) {
173 return OS_ERRNO_HWI_PROC_FUNC_NULL;
174 }
175 if (hwiNum >= OS_HWI_MAX_NUM) {
176 return OS_ERRNO_HWI_NUM_INVALID;
177 }
178 if (g_hwiForm[hwiNum].pfnHook == NULL) {
179 return OS_ERRNO_HWI_NUM_INVALID;
180 } else if (g_hwiForm[hwiNum].pfnHook != HalHwiDefaultHandler) {
181 return OS_ERRNO_HWI_NUM_INVALID;
182 }
183 if ((hwiPrio < OS_HWI_PRIO_LOWEST) || (hwiPrio > OS_HWI_PRIO_HIGHEST)) {
184 return OS_ERRNO_HWI_PRIO_INVALID;
185 }
186
187 intSave = LOS_IntLock();
188 g_hwiForm[hwiNum].pfnHook = hwiHandler;
189 if (irqParam != NULL) {
190 g_hwiForm[hwiNum].uwParam = (VOID *)irqParam->pDevId;
191 } else {
192 g_hwiForm[hwiNum].uwParam = NULL;
193 }
194 if (hwiNum >= OS_RISCV_SYS_VECTOR_CNT) {
195 HalSetLocalInterPri(hwiNum, hwiPrio);
196 }
197
198 LOS_IntRestore(intSave);
199
200 return LOS_OK;
201 }
202
203 /*****************************************************************************
204 Function : ArchHwiDelete
205 Description : Delete hardware interrupt
206 Input : hwiNum --- hwi num to delete
207 irqParam --- param of the hwi handler
208 Return : LOS_OK on success or error code on failure
209 *****************************************************************************/
ArchHwiDelete(HWI_HANDLE_T hwiNum,HwiIrqParam * irqParam)210 LITE_OS_SEC_TEXT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
211 {
212 (VOID)irqParam;
213 UINT32 intSave;
214
215 if (hwiNum >= OS_HWI_MAX_NUM) {
216 return OS_ERRNO_HWI_NUM_INVALID;
217 }
218
219 intSave = LOS_IntLock();
220 g_hwiForm[hwiNum].pfnHook = HalHwiDefaultHandler;
221 g_hwiForm[hwiNum].uwParam = 0;
222 LOS_IntRestore(intSave);
223 return LOS_OK;
224 }
225
ExcBackTrace(UINTPTR fp)226 STATIC VOID ExcBackTrace(UINTPTR fp)
227 {
228 UINTPTR LR[LOSCFG_BACKTRACE_DEPTH] = { 0 };
229 UINT32 index;
230
231 OsBackTraceHookCall(LR, LOSCFG_BACKTRACE_DEPTH, 0, fp);
232
233 PRINTK("----- traceback start -----\n");
234 for (index = 0; index < LOSCFG_BACKTRACE_DEPTH; index++) {
235 if (LR[index] == 0) {
236 break;
237 }
238 PRINTK("traceback %d -- lr = 0x%x\n", index, LR[index]);
239 }
240 PRINTK("----- traceback end -----\n");
241 }
242
ExcInfoDisplayContext(const LosExcInfo * exc)243 STATIC VOID ExcInfoDisplayContext(const LosExcInfo *exc)
244 {
245 const TaskContext *taskContext = &(exc->context->taskContext);
246
247 PRINTK("mepc = 0x%x\n", taskContext->mepc);
248 PRINTK("mstatus = 0x%x\n", taskContext->mstatus);
249 PRINTK("mtval = 0x%x\n", exc->context->mtval);
250 PRINTK("mcause = 0x%x\n", exc->context->mcause);
251 PRINTK("ra = 0x%x\n", taskContext->ra);
252 PRINTK("sp = 0x%x\n", taskContext->sp);
253 PRINTK("gp = 0x%x\n", exc->context->gp);
254 PRINTK("tp = 0x%x\n", taskContext->tp);
255 PRINTK("t0 = 0x%x\n", taskContext->t0);
256 PRINTK("t1 = 0x%x\n", taskContext->t1);
257 PRINTK("t2 = 0x%x\n", taskContext->t2);
258 PRINTK("s0 = 0x%x\n", taskContext->s0);
259 PRINTK("s1 = 0x%x\n", taskContext->s1);
260 PRINTK("a0 = 0x%x\n", taskContext->a0);
261 PRINTK("a1 = 0x%x\n", taskContext->a1);
262 PRINTK("a2 = 0x%x\n", taskContext->a2);
263 PRINTK("a3 = 0x%x\n", taskContext->a3);
264 PRINTK("a4 = 0x%x\n", taskContext->a4);
265 PRINTK("a5 = 0x%x\n", taskContext->a5);
266 PRINTK("a6 = 0x%x\n", taskContext->a6);
267 PRINTK("a7 = 0x%x\n", taskContext->a7);
268 PRINTK("s2 = 0x%x\n", taskContext->s2);
269 PRINTK("s3 = 0x%x\n", taskContext->s3);
270 PRINTK("s4 = 0x%x\n", taskContext->s4);
271 PRINTK("s5 = 0x%x\n", taskContext->s5);
272 PRINTK("s6 = 0x%x\n", taskContext->s6);
273 PRINTK("s7 = 0x%x\n", taskContext->s7);
274 PRINTK("s8 = 0x%x\n", taskContext->s8);
275 PRINTK("s9 = 0x%x\n", taskContext->s9);
276 PRINTK("s10 = 0x%x\n", taskContext->s10);
277 PRINTK("s11 = 0x%x\n", taskContext->s11);
278 PRINTK("t3 = 0x%x\n", taskContext->t3);
279 PRINTK("t4 = 0x%x\n", taskContext->t4);
280 PRINTK("t5 = 0x%x\n", taskContext->t5);
281 PRINTK("t6 = 0x%x\n", taskContext->t6);
282
283 ExcBackTrace(taskContext->s0);
284 }
285
ExcInfoDisplay(const LosExcContext * excBufAddr)286 STATIC VOID ExcInfoDisplay(const LosExcContext *excBufAddr)
287 {
288 PRINTK("\nException Information \n");
289
290 if (g_excInfo.type < RISCV_EXC_TYPE_NUM) {
291 PRINTK("Exc type : Oops - %s\n", g_excInformation[g_excInfo.type]);
292 } else {
293 PRINTK("Exc type : Oops - Invalid\n");
294 }
295
296 if (LOS_TaskIsRunning()) {
297 PRINTK("taskName = %s\n", g_losTask.runTask->taskName);
298 PRINTK("taskID = %u\n", g_losTask.runTask->taskID);
299 } else {
300 PRINTK("The exception occurs during system startup!\n");
301 }
302 PRINTK("system mem addr:0x%x\n", (UINTPTR)LOSCFG_SYS_HEAP_ADDR);
303 ExcInfoDisplayContext(&g_excInfo);
304 }
305
HalUnalignedAccessFix(UINTPTR mcause,UINTPTR mepc,UINTPTR mtval,VOID * sp)306 WEAK UINT32 HalUnalignedAccessFix(UINTPTR mcause, UINTPTR mepc, UINTPTR mtval, VOID *sp)
307 {
308 /* Unaligned access fixes are not supported by default */
309 PRINTK("Unaligned access fixes are not supported by default!\n");
310 return LOS_NOK;
311 }
312
HalExcEntry(const LosExcContext * excBufAddr)313 VOID HalExcEntry(const LosExcContext *excBufAddr)
314 {
315 UINT32 ret;
316 g_excInfo.type = excBufAddr->mcause & 0x1FF;
317 g_excInfo.context = (LosExcContext *)excBufAddr;
318 if (g_excInfo.nestCnt > 2) { /* 2: Number of layers of exception nesting */
319 PRINTK("hard fault!\n");
320 goto SYSTEM_DEATH;
321 }
322
323 if ((g_excInfo.type == RISCV_EXC_LOAD_MISALIGNED) ||
324 (g_excInfo.type == RISCV_EXC_STORE_MISALIGNED)) {
325 ret = HalUnalignedAccessFix(excBufAddr->mcause, excBufAddr->taskContext.mepc, excBufAddr->mtval,
326 (VOID *)excBufAddr);
327 if (!ret) {
328 return;
329 }
330 }
331
332 ExcInfoDisplay(excBufAddr);
333
334 if (LOS_TaskIsRunning()) {
335 PRINTK("----------------All Task information ------------\n");
336 OsGetAllTskInfo();
337 }
338
339 SYSTEM_DEATH:
340 OsDoExcHook(EXC_INTERRUPT);
341 while (1) {
342 }
343 }
344
345