• 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     OsHwiAttrSet(irqNum, hwiPrio, mode);
214 
215     OS_HWI_IRQ_UNLOCK(intSave);
216     return OS_OK;
217 }
218 
219 #if defined(OS_OPTION_HWI_COMBINE)
220 /*
221  * 描述:遍历组合型硬中断模块信息
222  */
OsHwiCombineDispatchHandler(HwiArg arg)223 OS_SEC_TEXT void OsHwiCombineDispatchHandler(HwiArg arg)
224 {
225     struct TagHwiCombineNode *hook = NULL;
226 
227     hook = (struct TagHwiCombineNode *)arg;
228 
229     while (hook != NULL) {
230         hook->cmbHook(hook->cmbParam);
231         hook = hook->next;
232     }
233 }
234 
OsHwiCombineAlloc(U32 irqNum,HwiProcFunc handler,HwiArg arg)235 static OS_SEC_L4_TEXT U32 OsHwiCombineAlloc(U32 irqNum, HwiProcFunc handler, HwiArg arg)
236 {
237     U8 freeNum;
238     struct TagHwiCombineNode *newHook = NULL;
239     struct TagHwiCombineNode *hwiCombineArray = NULL;
240     struct TagHwiCombineNode *prev = NULL;
241 
242     /* 若组合型中断结点为空, 则再申请8个一组的组合型中断结点 */
243     if (g_freeHwiComHead == NULL) {
244         hwiCombineArray = OsMemAlloc(OS_MID_HWI, OS_MEM_DEFAULT_FSC_PT,
245                                      (OS_HWI_MAX_COMBINE_NODE * sizeof(struct TagHwiCombineNode)));
246         if (hwiCombineArray == NULL) {
247             return OS_ERRNO_HWI_MEMORY_ALLOC_FAILED;
248         }
249 
250         g_freeHwiComHead = hwiCombineArray;
251 
252         /* 组合型中断结点初始化 */
253         for (freeNum = 0; freeNum < OS_HWI_MAX_COMBINE_NODE - 1; freeNum++) {
254             hwiCombineArray[freeNum].next = &hwiCombineArray[freeNum + 1];
255             hwiCombineArray[freeNum].cmbHook = OsHwiDefaultHandler;
256         }
257 
258         hwiCombineArray[freeNum].cmbHook = OsHwiDefaultHandler;
259         hwiCombineArray[freeNum].next = NULL;
260     }
261 
262     /* 若组合型中断结点不为空, 则从前往后依次将未使用的组合型结点摘走 */
263     newHook = g_freeHwiComHead;
264     g_freeHwiComHead = newHook->next;
265 
266     /* 首次注册组合型中断服务函数 */
267     if (OsHwiFuncGet(irqNum) == OsHwiDefaultHandler) {
268         OsHwiFuncSet(irqNum, OsHwiCombineDispatchHandler);
269         /* 组合型中断服务函数以当前摘取的结点作为入参, 通过该结点索引到下一个结点的中断服务函数 */
270         OsHwiParaSet(irqNum, (uintptr_t)newHook);
271     } else if (OsHwiFuncGet(irqNum) == OsHwiCombineDispatchHandler) {
272         /* 取同一中断号的组合型结点表头, 遍历该组合型结点链表 */
273         prev = (struct TagHwiCombineNode *)(HwiArg)OsHwiParaGet(irqNum);
274         while (prev != NULL) {
275             /* 若有出现相同中断号的用户中断钩子重复注册, 则报错返回 */
276             if (handler == prev->cmbHook) {
277                 g_freeHwiComHead = newHook;
278                 return OS_ERRNO_HWI_COMBINEHOOK_ALREADY_CREATED;
279             }
280 
281             if (prev->next == NULL) {
282                 prev->next = newHook;
283                 break;
284             }
285             prev = prev->next;
286         }
287     }
288 
289     newHook->next = NULL;
290     newHook->cmbHook = handler;
291     newHook->cmbParam = arg;
292 
293     return OS_OK;
294 }
295 
OsHwiCombineDelete(U32 irqNum)296 OS_SEC_ALW_INLINE INLINE void OsHwiCombineDelete(U32 irqNum)
297 {
298     struct TagHwiCombineNode *hook = NULL;
299     struct TagHwiCombineNode *newHook = NULL;
300 
301     hook = g_freeHwiComHead;
302     newHook = (struct TagHwiCombineNode *)(HwiArg)OsHwiParaGet(irqNum);
303 
304     if (hook == NULL) {
305         g_freeHwiComHead = newHook;
306     } else {
307         /* 索引至空闲链表表尾 */
308         while (hook->next != NULL) {
309             hook = hook->next;
310         }
311 
312         /* 释放的结点插入到空闲链表表尾 */
313         hook->next = newHook;
314     }
315     OsHwiFuncSet(irqNum, OsHwiDefaultHandler);
316     OsHwiParaSet(irqNum, (uintptr_t)NULL);
317 }
318 
319 #endif
320 
OsHwiConnectHandle(U32 irqNum,HwiProcFunc handler,HwiArg arg)321 static OS_SEC_L4_TEXT U32 OsHwiConnectHandle(U32 irqNum, HwiProcFunc handler, HwiArg arg)
322 {
323 #if defined(OS_OPTION_HWI_COMBINE)
324     if (OS_HWI_MODE_GET(irqNum) == OS_HWI_MODE_COMBINE) {
325         return OsHwiCombineAlloc(irqNum, handler, arg);
326     }
327 #endif
328     /* 判断是否允许注册 */
329     if (OsHwiIsCanCreated(irqNum) == FALSE) {
330         return OS_ERRNO_HWI_ALREADY_CREATED;
331     }
332 
333     OsHwiFuncSet(irqNum, handler);
334     OsHwiParaSet(irqNum, arg);
335 
336     OS_HWI_SET_HOOK_ATTR(OS_IRQ2HWI(irqNum), (U32)(OS_HWI_MODE_ATTR(irqNum)->prior), (uintptr_t)handler);
337 
338     return OS_OK;
339 }
340 
341 /*
342  * 描述:硬中断注册中断服务函数
343  */
PRT_HwiCreate(HwiHandle hwiNum,HwiProcFunc handler,HwiArg arg)344 OS_SEC_L4_TEXT U32 PRT_HwiCreate(HwiHandle hwiNum, HwiProcFunc handler, HwiArg arg)
345 {
346     uintptr_t intSave;
347     U32 irqNum;
348     U32 ret;
349 
350     if (OS_HWI_NUM_CHECK(hwiNum)) {
351         return OS_ERRNO_HWI_NUM_INVALID;
352     }
353 
354     if (handler == NULL) {
355         return OS_ERRNO_HWI_PROC_FUNC_NULL;
356     }
357 
358     irqNum = OS_HWI2IRQ(hwiNum);
359 
360     OS_HWI_IRQ_LOCK(intSave);
361 
362 #if defined(OS_OPTION_HWI_ATTRIBUTE)
363     if (OS_HWI_MODE_INV(irqNum)) {
364         OS_HWI_IRQ_UNLOCK(intSave);
365         return OS_ERRNO_HWI_MODE_UNSET;
366     }
367 #endif
368 
369     ret = OsHwiConnectHandle(irqNum, handler, arg);
370     if (ret != OS_OK) {
371         OS_HWI_IRQ_UNLOCK(intSave);
372         return ret;
373     }
374 
375     OS_HWI_IRQ_UNLOCK(intSave);
376     return OS_OK;
377 }
378 
OsHwiDeleteFormResume(U32 irqNum)379 static OS_SEC_L4_TEXT U32 OsHwiDeleteFormResume(U32 irqNum)
380 {
381 #if defined(OS_OPTION_HWI_ATTRIBUTE)
382     U32 ret = OsHwiAttrClear(irqNum);
383     if (ret != OS_OK) {
384         return ret;
385     }
386 #endif
387 
388 #if defined(OS_OPTION_HWI_COMBINE)
389     if (OsHwiFuncGet(irqNum) == OsHwiCombineDispatchHandler) {
390         OsHwiCombineDelete(irqNum);
391         return OS_OK;
392     }
393 #endif
394 
395     OsHwiFuncSet(irqNum, OsHwiDefaultHandler);
396     /* 逻辑上保持默认服务程序的入参是逻辑中断号 */
397     OsHwiParaSet(irqNum, irqNum);
398 
399     return OS_OK;
400 }
401 
402 /*
403  * 描述:硬中断删除函数
404  */
PRT_HwiDelete(HwiHandle hwiNum)405 OS_SEC_L4_TEXT U32 PRT_HwiDelete(HwiHandle hwiNum)
406 {
407     U32 ret;
408     uintptr_t intSave;
409     U32 irqNum;
410 
411     if (OS_HWI_NUM_CHECK(hwiNum)) {
412         return OS_ERRNO_HWI_NUM_INVALID;
413     }
414 
415     irqNum = OS_HWI2IRQ(hwiNum);
416 
417     /* 先disable中断 */
418     (void)PRT_HwiDisable(hwiNum);
419 
420     OS_HWI_IRQ_LOCK(intSave);
421 
422     ret = OsHwiDeleteFormResume(irqNum);
423     if (ret != OS_OK) {
424         OS_HWI_IRQ_UNLOCK(intSave);
425         return ret;
426     }
427 
428     OS_HWI_IRQ_UNLOCK(intSave);
429     return OS_OK;
430 }