• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2009-12-22
13  * Description: 中断模块
14  */
15 #include "prt_irq_internal.h"
16 
17 /* 业务没有注册中断服务程序,却触发了中断时,记录的中断号 */
18 OS_SEC_L4_BSS U32 g_defHandlerHwiNum;
19 
20 #if defined(OS_OPTION_HWI_MAX_NUM_CONFIG)
21 OS_SEC_BSS struct TagHwiHandleForm *g_hwiForm;
22 #if defined(OS_OPTION_HWI_ATTRIBUTE)
23 OS_SEC_BSS struct TagHwiModeForm *g_hwiModeForm;
24 #endif
25 
26 #else
27 /* 8字节对齐为了使用L64I指令 */
28 OS_SEC_BSS struct TagHwiHandleForm g_hwiForm[OS_HWI_FORMARRAY_NUM] __attribute__((aligned(8)));
29 #if defined(OS_OPTION_HWI_ATTRIBUTE)
30 OS_SEC_BSS struct TagHwiModeForm g_hwiModeForm[OS_HWI_MAX_NUM];
31 #endif
32 
33 #endif
34 
35 #if defined(OS_OPTION_HWI_COMBINE)
36 OS_SEC_BSS struct TagHwiCombineNode g_hwiCombineNode[OS_HWI_MAX_COMBINE_NODE];
37 OS_SEC_BSS struct TagHwiCombineNode *g_freeHwiComHead;
38 #endif
39 
40 OS_SEC_DATA U32 g_intCount = 0;
41 
42 /*
43  * 描述:硬中断默认注册钩子,会触发致命错误
44  */
OsHwiDefaultHandler(HwiArg arg)45 OS_SEC_L4_TEXT void OsHwiDefaultHandler(HwiArg arg)
46 {
47     g_defHandlerHwiNum = OS_IRQ2HWI(arg);
48     OS_REPORT_ERROR(OS_ERRNO_HWI_UNCREATED);
49 }
50 
OsHwiDescFieldInit(U32 irqNum)51 OS_SEC_ALW_INLINE INLINE void OsHwiDescFieldInit(U32 irqNum)
52 {
53     OsHwiFuncSet(irqNum, OsHwiDefaultHandler);
54     OsHwiParaSet(irqNum, irqNum);
55 }
56 
57 /*
58  * 描述:所有的中断描述符初始化
59  */
OsHwiDescInitAll(void)60 OS_SEC_ALW_INLINE INLINE void OsHwiDescInitAll(void)
61 {
62     U32 irqNum;
63     for (irqNum = 0; irqNum < OS_HWI_MAX_NUM; irqNum++) {
64         OsHwiDescFieldInit(irqNum);
65     }
66 }
67 
68 #if defined(OS_OPTION_HWI_COMBINE)
OsHwiCombineNodeInit(void)69 static OS_SEC_L4_TEXT void OsHwiCombineNodeInit(void)
70 {
71     U32 idx;
72     for (idx = 0; idx < OS_HWI_MAX_COMBINE_NODE - 1; idx++) {
73         g_hwiCombineNode[idx].next = &g_hwiCombineNode[idx + 1];
74         g_hwiCombineNode[idx].cmbHook = OsHwiDefaultHandler;
75     }
76     g_hwiCombineNode[idx].cmbHook = OsHwiDefaultHandler;
77     g_hwiCombineNode[idx].next = NULL;
78 
79     /* 将所有未使用的组合型中断结点挂结到g_freeHwiComHead */
80     g_freeHwiComHead = g_hwiCombineNode;
81 }
82 #endif
83 
84 #if defined(OS_OPTION_HWI_MAX_NUM_CONFIG)
OsHwiResourceAlloc(void)85 static OS_SEC_L4_TEXT U32 OsHwiResourceAlloc(void)
86 {
87     U32 size;
88     uintptr_t addr;
89 #if defined(OS_OPTION_HWI_ATTRIBUTE)
90     size = g_hwiMaxNumConfig * (sizeof(struct TagHwiHandleForm) + sizeof(struct TagHwiModeForm));
91 #else
92     size = g_hwiMaxNumConfig * sizeof(struct TagHwiHandleForm);
93 #endif
94     /* 8字节对齐为了使用L64I指令 */
95     addr = (uintptr_t)(uintptr_t *)OsMemAllocAlign(OS_MID_HWI, OS_MEM_DEFAULT_FSC_PT,
96                                                    size, MEM_ADDR_ALIGN_008);
97     if (addr == 0) {
98         return OS_ERRNO_HWI_RESOURCE_ALLOC_FAILED;
99     }
100     if (memset_s((void *)addr, size, 0, size) != EOK) {
101         OS_GOTO_SYS_ERROR1();
102     }
103 #if defined(OS_OPTION_HWI_ATTRIBUTE)
104     g_hwiForm = (struct TagHwiHandleForm *)addr;
105     g_hwiModeForm = (struct TagHwiModeForm *)(addr + g_hwiMaxNumConfig * sizeof(struct TagHwiHandleForm));
106 #else
107     g_hwiForm = (struct TagHwiHandleForm *)addr;
108 #endif
109     return OS_OK;
110 }
111 #endif
112 /*
113  * 描述:硬中断模块初始化
114  */
OsHwiConfigInit(void)115 OS_SEC_L4_TEXT U32 OsHwiConfigInit(void)
116 {
117 #if defined(OS_OPTION_HWI_MAX_NUM_CONFIG)
118     U32 ret = OsHwiResourceAlloc();
119     if (ret != OS_OK) {
120         return ret;
121     }
122 #endif
123     OS_HWI_SPINLOCK_INIT();
124 
125     OsHwiDescInitAll();
126 
127 #if defined(OS_OPTION_HWI_COMBINE)
128     /* 组合型中断结点初始化 */
129     OsHwiCombineNodeInit();
130 #endif
131 
132     /* 硬件中断控制器初始化 */
133     OsHwiGICInit();
134 
135     return OS_OK;
136 }
137 
OsHwiHookDispatcher(HwiHandle archHwi)138 OS_SEC_TEXT void OsHwiHookDispatcher(HwiHandle archHwi)
139 {
140     /*
141      * 将arch传入的参数转换成硬件中断号
142      */
143     HwiHandle hwiNum = OS_HWI_GET_HWINUM(archHwi);
144     U32 irqNum = OS_HWI2IRQ(hwiNum);
145 
146     OS_MHOOK_ACTIVATE_PARA1(OS_HOOK_HWI_ENTRY, hwiNum);
147 
148     OsHwiHandleActive(irqNum);
149 
150     OS_MHOOK_ACTIVATE_PARA1(OS_HOOK_HWI_EXIT, hwiNum);
151 }
152 
OsHwiSetAttrParaCheck(HwiHandle hwiNum,HwiPrior hwiPrio,HwiMode mode)153 static OS_SEC_L4_TEXT U32 OsHwiSetAttrParaCheck(HwiHandle hwiNum, HwiPrior hwiPrio, HwiMode mode)
154 {
155     if (OS_HWI_NUM_CHECK(hwiNum)) {
156         return OS_ERRNO_HWI_NUM_INVALID;
157     }
158 
159     if (OsHwiPrioCheck(hwiPrio)) {
160         return OS_ERRNO_HWI_PRI_ERROR;
161     }
162 
163     if (OsHwiModeCheck(mode)) {
164         return OS_ERRNO_HWI_MODE_ERROR;
165     }
166     return OS_OK;
167 }
168 
OsHwiSetAttrConflictErrCheck(U32 irqNum,U32 hwiPrio,HwiMode mode)169 static OS_SEC_L4_TEXT U32 OsHwiSetAttrConflictErrCheck(U32 irqNum, U32 hwiPrio, HwiMode mode)
170 {
171     /* 如果该硬中断属性已经被设置, 则不允许变更设置,  除非先删除 */
172     /* 支持私有服务程序的中断,各个核可独立配置,不做检查,其他的要做检查 */
173     if (OS_HWI_MODE_INV(irqNum) || (OsHwiNeedPrivateIsr(irqNum) == TRUE)) {
174         return OS_OK;
175     }
176 
177     if (mode != OS_HWI_MODE_GET(irqNum)) {
178         return OS_ERRNO_HWI_ATTR_CONFLICTED;
179     }
180 
181     if (OsHwiPrioConflictCheck(irqNum, (U16)hwiPrio)) {
182         return OS_ERRNO_HWI_ATTR_CONFLICTED;
183     }
184     return OS_OK;
185 }
186 
187 /*
188  * 描述:硬中断属性设置
189  */
PRT_HwiSetAttr(HwiHandle hwiNum,HwiPrior hwiPrio,HwiMode mode)190 OS_SEC_L4_TEXT U32 PRT_HwiSetAttr(HwiHandle hwiNum, HwiPrior hwiPrio, HwiMode mode)
191 {
192     uintptr_t intSave;
193     U32 irqNum;
194     U32 ret;
195 
196     ret = OsHwiSetAttrParaCheck(hwiNum, hwiPrio, mode);
197     if (ret != OS_OK) {
198         return ret;
199     }
200 
201     irqNum = OS_HWI2IRQ(hwiNum);
202 
203     OS_HWI_IRQ_LOCK(intSave);
204 
205 #if defined(OS_OPTION_HWI_ATTRIBUTE)
206     ret = OsHwiSetAttrConflictErrCheck(irqNum, hwiPrio, mode);
207     if (ret != OS_OK) {
208         OS_HWI_IRQ_UNLOCK(intSave);
209         return ret;
210     }
211 #endif
212 
213 #if defined(OS_OPTION_HWI_PRIORITY)
214     OsHwiPrioritySet(hwiNum, hwiPrio);
215 #endif
216 
217     OsHwiAttrSet(irqNum, hwiPrio, mode);
218 
219     OS_HWI_IRQ_UNLOCK(intSave);
220     return OS_OK;
221 }
222 
223 #if defined(OS_OPTION_HWI_COMBINE)
224 /*
225  * 描述:遍历组合型硬中断模块信息
226  */
OsHwiCombineDispatchHandler(HwiArg arg)227 OS_SEC_TEXT void OsHwiCombineDispatchHandler(HwiArg arg)
228 {
229     struct TagHwiCombineNode *hook = NULL;
230 
231     hook = (struct TagHwiCombineNode *)arg;
232 
233     while (hook != NULL) {
234         hook->cmbHook(hook->cmbParam);
235         hook = hook->next;
236     }
237 }
238 
OsHwiCombineAlloc(U32 irqNum,HwiProcFunc handler,HwiArg arg)239 static OS_SEC_L4_TEXT U32 OsHwiCombineAlloc(U32 irqNum, HwiProcFunc handler, HwiArg arg)
240 {
241     U8 freeNum;
242     struct TagHwiCombineNode *newHook = NULL;
243     struct TagHwiCombineNode *hwiCombineArray = NULL;
244     struct TagHwiCombineNode *prev = NULL;
245 
246     /* 若组合型中断结点为空, 则再申请8个一组的组合型中断结点 */
247     if (g_freeHwiComHead == NULL) {
248         hwiCombineArray = OsMemAlloc(OS_MID_HWI, OS_MEM_DEFAULT_FSC_PT,
249                                      (OS_HWI_MAX_COMBINE_NODE * sizeof(struct TagHwiCombineNode)));
250         if (hwiCombineArray == NULL) {
251             return OS_ERRNO_HWI_MEMORY_ALLOC_FAILED;
252         }
253 
254         g_freeHwiComHead = hwiCombineArray;
255 
256         /* 组合型中断结点初始化 */
257         for (freeNum = 0; freeNum < OS_HWI_MAX_COMBINE_NODE - 1; freeNum++) {
258             hwiCombineArray[freeNum].next = &hwiCombineArray[freeNum + 1];
259             hwiCombineArray[freeNum].cmbHook = OsHwiDefaultHandler;
260         }
261 
262         hwiCombineArray[freeNum].cmbHook = OsHwiDefaultHandler;
263         hwiCombineArray[freeNum].next = NULL;
264     }
265 
266     /* 若组合型中断结点不为空, 则从前往后依次将未使用的组合型结点摘走 */
267     newHook = g_freeHwiComHead;
268     g_freeHwiComHead = newHook->next;
269 
270     /* 首次注册组合型中断服务函数 */
271     if (OsHwiFuncGet(irqNum) == OsHwiDefaultHandler) {
272         OsHwiFuncSet(irqNum, OsHwiCombineDispatchHandler);
273         /* 组合型中断服务函数以当前摘取的结点作为入参, 通过该结点索引到下一个结点的中断服务函数 */
274         OsHwiParaSet(irqNum, (uintptr_t)newHook);
275     } else if (OsHwiFuncGet(irqNum) == OsHwiCombineDispatchHandler) {
276         /* 取同一中断号的组合型结点表头, 遍历该组合型结点链表 */
277         prev = (struct TagHwiCombineNode *)(HwiArg)OsHwiParaGet(irqNum);
278         while (prev != NULL) {
279             /* 若有出现相同中断号的用户中断钩子重复注册, 则报错返回 */
280             if (handler == prev->cmbHook) {
281                 g_freeHwiComHead = newHook;
282                 return OS_ERRNO_HWI_COMBINEHOOK_ALREADY_CREATED;
283             }
284 
285             if (prev->next == NULL) {
286                 prev->next = newHook;
287                 break;
288             }
289             prev = prev->next;
290         }
291     }
292 
293     newHook->next = NULL;
294     newHook->cmbHook = handler;
295     newHook->cmbParam = arg;
296 
297     return OS_OK;
298 }
299 
OsHwiCombineDelete(U32 irqNum)300 OS_SEC_ALW_INLINE INLINE void OsHwiCombineDelete(U32 irqNum)
301 {
302     struct TagHwiCombineNode *hook = NULL;
303     struct TagHwiCombineNode *newHook = NULL;
304 
305     hook = g_freeHwiComHead;
306     newHook = (struct TagHwiCombineNode *)(HwiArg)OsHwiParaGet(irqNum);
307 
308     if (hook == NULL) {
309         g_freeHwiComHead = newHook;
310     } else {
311         /* 索引至空闲链表表尾 */
312         while (hook->next != NULL) {
313             hook = hook->next;
314         }
315 
316         /* 释放的结点插入到空闲链表表尾 */
317         hook->next = newHook;
318     }
319     OsHwiFuncSet(irqNum, OsHwiDefaultHandler);
320     OsHwiParaSet(irqNum, (uintptr_t)NULL);
321 }
322 
323 #endif
324 
OsHwiConnectHandle(U32 irqNum,HwiProcFunc handler,HwiArg arg)325 static OS_SEC_L4_TEXT U32 OsHwiConnectHandle(U32 irqNum, HwiProcFunc handler, HwiArg arg)
326 {
327 #if defined(OS_OPTION_HWI_COMBINE)
328     if (OS_HWI_MODE_GET(irqNum) == OS_HWI_MODE_COMBINE) {
329         return OsHwiCombineAlloc(irqNum, handler, arg);
330     }
331 #endif
332     /* 判断是否允许注册 */
333     if (OsHwiIsCanCreated(irqNum) == FALSE) {
334         return OS_ERRNO_HWI_ALREADY_CREATED;
335     }
336 
337     OsHwiFuncSet(irqNum, handler);
338     OsHwiParaSet(irqNum, arg);
339 
340     OS_HWI_SET_HOOK_ATTR(OS_IRQ2HWI(irqNum), (U32)(OS_HWI_MODE_ATTR(irqNum)->prior), (uintptr_t)handler);
341 
342     return OS_OK;
343 }
344 
345 /*
346  * 描述:硬中断注册中断服务函数
347  */
PRT_HwiCreate(HwiHandle hwiNum,HwiProcFunc handler,HwiArg arg)348 OS_SEC_L4_TEXT U32 PRT_HwiCreate(HwiHandle hwiNum, HwiProcFunc handler, HwiArg arg)
349 {
350     uintptr_t intSave;
351     U32 irqNum;
352     U32 ret;
353 
354     if (OS_HWI_NUM_CHECK(hwiNum)) {
355         return OS_ERRNO_HWI_NUM_INVALID;
356     }
357 
358     if (handler == NULL) {
359         return OS_ERRNO_HWI_PROC_FUNC_NULL;
360     }
361 
362     irqNum = OS_HWI2IRQ(hwiNum);
363 
364     OS_HWI_IRQ_LOCK(intSave);
365 
366 #if defined(OS_OPTION_HWI_ATTRIBUTE)
367     if (OS_HWI_MODE_INV(irqNum)) {
368         OS_HWI_IRQ_UNLOCK(intSave);
369         return OS_ERRNO_HWI_MODE_UNSET;
370     }
371 #endif
372 
373     ret = OsHwiConnectHandle(irqNum, handler, arg);
374     if (ret != OS_OK) {
375         OS_HWI_IRQ_UNLOCK(intSave);
376         return ret;
377     }
378 
379     OS_HWI_IRQ_UNLOCK(intSave);
380     return OS_OK;
381 }
382 
OsHwiDeleteFormResume(U32 irqNum)383 static OS_SEC_L4_TEXT U32 OsHwiDeleteFormResume(U32 irqNum)
384 {
385 #if defined(OS_OPTION_HWI_ATTRIBUTE)
386     U32 ret = OsHwiAttrClear(irqNum);
387     if (ret != OS_OK) {
388         return ret;
389     }
390 #endif
391 
392 #if defined(OS_OPTION_HWI_COMBINE)
393     if (OsHwiFuncGet(irqNum) == OsHwiCombineDispatchHandler) {
394         OsHwiCombineDelete(irqNum);
395         return OS_OK;
396     }
397 #endif
398 
399     OsHwiFuncSet(irqNum, OsHwiDefaultHandler);
400     /* 逻辑上保持默认服务程序的入参是逻辑中断号 */
401     OsHwiParaSet(irqNum, irqNum);
402 
403     return OS_OK;
404 }
405 
406 /*
407  * 描述:硬中断删除函数
408  */
PRT_HwiDelete(HwiHandle hwiNum)409 OS_SEC_L4_TEXT U32 PRT_HwiDelete(HwiHandle hwiNum)
410 {
411     U32 ret;
412     uintptr_t intSave;
413     U32 irqNum;
414 
415     if (OS_HWI_NUM_CHECK(hwiNum)) {
416         return OS_ERRNO_HWI_NUM_INVALID;
417     }
418 
419     irqNum = OS_HWI2IRQ(hwiNum);
420 
421     /* 先disable中断 */
422     (void)PRT_HwiDisable(hwiNum);
423 
424     OS_HWI_IRQ_LOCK(intSave);
425 
426     ret = OsHwiDeleteFormResume(irqNum);
427     if (ret != OS_OK) {
428         OS_HWI_IRQ_UNLOCK(intSave);
429         return ret;
430     }
431 
432     OS_HWI_IRQ_UNLOCK(intSave);
433     return OS_OK;
434 }