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 }