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 }