1 /*
2 * Copyright (c) 2022-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: 2022-11-22
13 * Description: 硬中断。
14 */
15 #include "prt_hwi_external.h"
16 #include "prt_task_external.h"
17 #include "prt_irq_external.h"
18 #include "prt_hwi_internal.h"
19
20 /*
21 * 描述: GIC模块初始化
22 */
OsHwiGICInit(void)23 INIT_SEC_L4_TEXT void OsHwiGICInit(void)
24 {
25 return;
26 }
27
28 /*
29 * 描述: 获取硬中断优先级
30 */
OsHwiPriorityGet(HwiHandle hwiNum)31 INIT_SEC_L4_TEXT U32 OsHwiPriorityGet(HwiHandle hwiNum)
32 {
33 return OsGicGetPriority(hwiNum);
34 }
35
36 /*
37 * 描述: 设置硬中断优先级
38 */
OsHwiPrioritySet(HwiHandle hwiNum,HwiPrior hwiPrio)39 INIT_SEC_L4_TEXT void OsHwiPrioritySet(HwiHandle hwiNum, HwiPrior hwiPrio)
40 {
41 OS_ERR_RECORD(OsGicSetPriority(hwiNum, hwiPrio));
42 }
43
44 /*
45 * 描述: 禁止指定中断
46 */
PRT_HwiDisable(HwiHandle hwiNum)47 OS_SEC_L2_TEXT U32 PRT_HwiDisable(HwiHandle hwiNum)
48 {
49 if (hwiNum > OS_HWI_MAX) {
50 return OS_ERRNO_HWI_NUM_INVALID;
51 }
52 OsGicDisableInt(hwiNum);
53
54 return OS_OK;
55 }
56
57 /*
58 * 描述: 使能指定中断
59 */
PRT_HwiEnable(HwiHandle hwiNum)60 OS_SEC_L2_TEXT U32 PRT_HwiEnable(HwiHandle hwiNum)
61 {
62 if (hwiNum > OS_HWI_MAX) {
63 return OS_ERRNO_HWI_NUM_INVALID;
64 }
65 OsGicEnableInt(hwiNum);
66
67 return OS_OK;
68 }
69
70 /*
71 * 描述: 触发核间SGI中断,放置OS_SEC_TEXT段
72 */
OsHwiMcTrigger(U32 coreMask,U32 hwiNum)73 OS_SEC_TEXT void OsHwiMcTrigger(U32 coreMask, U32 hwiNum)
74 {
75 OsGicTrigIntToCores(hwiNum, coreMask);
76 return;
77 }
78
79 /*
80 * 描述: 上报中断号错误
81 */
OsHwiReportHwiNumErr(void)82 OS_SEC_TEXT void OsHwiReportHwiNumErr(void)
83 {
84 OS_REPORT_ERROR(OS_ERRNO_HWI_HW_REPORT_HWINO_INVALID);
85 return;
86 }
87
88 /*
89 * 描述: 中断处理, 调用处外部已关中断
90 */
OsHwiDispatchHandle(U32 arg1)91 OS_SEC_L0_TEXT void OsHwiDispatchHandle(U32 arg1)
92 {
93 U32 hwiNum;
94 (void)arg1;
95
96 UNI_FLAG |= OS_FLG_HWI_ACTIVE;
97 OS_INT_COUNT++;
98 /* ARMv8硬件约束,fiq和和irq都会在在异常和入口被mask掉 */
99 /* 此处需要同时清F比特,确保FIQ能及时响应 */
100 OsFiqEnable();
101
102 hwiNum = OsHwiNumGet();
103
104 if (OS_HWI_CLEAR_CHECK(hwiNum) || OS_HWI_NUM_CHECK(hwiNum)) {
105 goto OS_HWI_CONTINUE;
106 }
107
108 OsHwiNestedIntEnable();
109 OsHwiHookDispatcher(hwiNum);
110 OsHwiNestedIntDisable();
111
112 OS_HWI_CONTINUE:
113 // 清除中断位
114 OsHwiClear(hwiNum);
115 OS_INT_COUNT--;
116 /* 不支持中断嵌套,但这里防止中断服务程序中错误打开了中断 */
117 if (OS_INT_COUNT > 0) {
118 return;
119 }
120
121 UNI_FLAG &= ~OS_FLG_HWI_ACTIVE;
122
123 OsHwiDispatchTail();
124 }
125
126 /*
127 * 描述: 中断处理入口, 调用处外部已关中断
128 */
OsHwiDispatch(uintptr_t sp,U32 arg1)129 OS_SEC_L0_TEXT void OsHwiDispatch(uintptr_t sp, U32 arg1)
130 {
131 // 该函数体内有切栈动作, 不允许有局部变量
132 if (!OS_INT_ACTIVE) {
133 // 被打断的是任务
134 RUNNING_TASK->stackPointer = (void *)sp;
135 OsSetSysStackSP(OsGetSysStackSP(), arg1);
136 }
137
138 // 有可能切栈, 中断入口函数不使用局部变量
139 OsHwiDispatchHandle(arg1);
140 }
141
142 /*
143 * 描述: 开启全局可屏蔽中断。
144 */
PRT_HwiUnLock(void)145 OS_SEC_L0_TEXT uintptr_t PRT_HwiUnLock(void)
146 {
147 uintptr_t state = 0;
148
149 OS_EMBED_ASM(
150 "mrs %0, DAIF \n"
151 "msr DAIFClr, %1 \n"
152 : "=r"(state)
153 : "i"(DAIF_IRQ_BIT)
154 : "memory", "cc");
155
156 return state & INT_MASK;
157 }
158
159 /*
160 * 描述: 关闭全局可屏蔽中断。
161 */
PRT_HwiLock(void)162 OS_SEC_L0_TEXT uintptr_t PRT_HwiLock(void)
163 {
164 uintptr_t state = 0;
165 OS_EMBED_ASM(
166 "mrs %0, DAIF \n"
167 "msr DAIFSet, %1 \n"
168 : "=r"(state)
169 : "i"(DAIF_IRQ_BIT)
170 : "memory", "cc");
171 return state & INT_MASK;
172 }
173
174 /*
175 * 描述: 恢复原中断状态寄存器。
176 */
PRT_HwiRestore(uintptr_t intSave)177 OS_SEC_L0_TEXT void PRT_HwiRestore(uintptr_t intSave)
178 {
179 if ((intSave & INT_MASK) == 0) {
180 OS_EMBED_ASM(
181 "msr DAIFClr, %0\n"
182 :
183 : "i"(DAIF_IRQ_BIT)
184 : "memory", "cc");
185 } else {
186 OS_EMBED_ASM(
187 "msr DAIFSet, %0\n"
188 :
189 : "i"(DAIF_IRQ_BIT)
190 : "memory", "cc");
191 }
192 return;
193 }