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-18
13 * Description: 硬件GIC相关的处理。
14 */
15 #include "prt_hwi.h"
16 #include "prt_gic_external.h"
17 #include "prt_gic_internal.h"
18 #include "prt_attr_external.h"
19 #include "prt_task.h"
20
21 #if (OS_GIC_VER == 2)
22 union IccSgirEl1 {
23 struct {
24 U32 intId : 4;
25 U32 rsvd0 : 11;
26 U32 nsatt : 1;
27 U32 targetlist : 8;
28 U32 filter : 2;
29 U32 rsvd1 : 6;
30 } bits;
31 U32 value;
32 };
33 #elif (OS_GIC_VER == 3)
34 /* ICC_SGIR_EL1 */
35 union IccSgirEl1 {
36 struct {
37 U64 targetlist : 16; // bit[0..15] 每bit对应1个核,bit置1代表中断会触发到对应的核
38 U64 aff1 : 8; // bit[16..23]
39 U64 intId : 4; // bit[24..27] SGI 中断号.
40 U64 rsvd0 : 4; // bit[28..31]
41 U64 aff2 : 8; // bit[32..39]
42 /* bit[40] 0:中断触发给Aff3.Aff2.Aff1.<target list>;1:中断触发给本核以外的所有核 */
43 U64 irm : 1; // bit[40]
44 U64 rsvd1 : 3; // bit[41..43]
45 /* bit[44..47] range selector,RS域共4个bit,可以表示16个范围,16×16=256,刚好表示256个cpu */
46 /* 所以spec里面,说TargetList[n]表示的aff0的值为RS*16 + n。 */
47 U64 rs : 4; // bit[44..47]
48 U64 aff3 : 8; // bit[48..55]
49 U64 rsvd2 : 8; // bit[63..56]
50 } bits;
51 U64 value;
52 };
53 #endif
54
55 /* GIC基地址 */
56 OS_SEC_BSS uintptr_t g_gicdBase;
57 /* GICR相对于GIC基地址偏移向量 */
58 OS_SEC_BSS uintptr_t g_gicrOffset;
59 /* GICR核间偏移向量配置 */
60 OS_SEC_BSS uintptr_t g_gicrStride;
61 /* 存放Core Map值 */
62 OS_SEC_DATA union GicCoreMap g_gicCoreMap = {0};
63
64 /*
65 * 描述: 去使能指定中断
66 */
OsGicDisableInt(U32 intId)67 OS_SEC_L4_TEXT void OsGicDisableInt(U32 intId)
68 {
69 if (intId <= MAX_NNSPI_ID) {
70 OsGicrDisableInt(PRT_GetCoreID(), intId);
71 } else if (intId <= MAX_SPI_ID) {
72 OsGicdDisableInt(intId);
73 }
74 }
75
76 /*
77 * 描述: 使能指定中断
78 */
OsGicEnableInt(U32 intId)79 OS_SEC_L4_TEXT void OsGicEnableInt(U32 intId)
80 {
81 if (intId <= MAX_NNSPI_ID) {
82 OsGicrEnableInt(PRT_GetCoreID(), intId);
83 } else if (intId <= MAX_SPI_ID) {
84 OsGicdEnableInt(intId);
85 }
86 }
87
88 #if (OS_GIC_VER == 2)
89 /*
90 * 描述: 触发中断到目标核,仅支持SGI
91 */
OsGicTrigIntToCores(U32 intId,U32 targetList)92 OS_SEC_TEXT void OsGicTrigIntToCores(U32 intId, U32 targetList)
93 {
94 union IccSgirEl1 iccSgirEl1;
95 U32 core;
96
97 PRT_DSB();
98 for (core = 0; (core < OS_MAX_CORE_NUM) && (targetList != 0); ++core) {
99 if ((targetList & (1U << core)) != 0) {
100 iccSgirEl1.value = 0; // 每个位域默认为0
101 iccSgirEl1.bits.intId = intId;
102 iccSgirEl1.bits.targetlist = 1 << core;
103 GIC_REG_WRITE(GICD_SGIR, iccSgirEl1.value);
104 }
105 }
106 /* 内存屏障,强制生效执行上述对ICC_SGI1R_EL1的写操作 */
107 PRT_ISB();
108 }
109 #elif (OS_GIC_VER == 3)
110 /*
111 * 描述: 触发中断到目标核,仅支持SGI
112 */
OsGicTrigIntToCores(U32 intId,U32 targetList)113 OS_SEC_TEXT void OsGicTrigIntToCores(U32 intId, U32 targetList)
114 {
115 union IccSgirEl1 iccSgirEl1;
116 U32 core;
117 U16 targetMask = 0x1;
118
119 PRT_DSB();
120 for (core = 0; (core < OS_MAX_CORE_NUM) && (targetList != 0); ++core) {
121 if ((targetList & (1U << core)) != 0) {
122 iccSgirEl1.value = 0; // 每个位域默认为0
123 iccSgirEl1.bits.intId = intId;
124 iccSgirEl1.bits.targetlist = targetMask;
125 iccSgirEl1.bits.aff1 = core;
126 iccSgirEl1.bits.aff2 = g_gicCoreMap.bits.aff2;
127 iccSgirEl1.bits.aff3 = g_gicCoreMap.bits.aff3;
128 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_SGI1R_EL1) ", %0 \n" : : "r"(iccSgirEl1.value) : "memory");
129 }
130 }
131 /* 内存屏障,强制生效执行上述对ICC_SGI1R_EL1的写操作 */
132 PRT_ISB();
133 }
134 #endif
135
136
137 /*
138 * 描述: 设置中断的优先级
139 */
OsGicSetPriority(U32 intId,U32 priority)140 OS_SEC_L4_TEXT U32 OsGicSetPriority(U32 intId, U32 priority)
141 {
142 U32 coreId;
143 enum GicIntState state;
144
145 if (intId > MAX_SPI_ID || priority > MAX_INT_PRIORITY) {
146 return OS_FAIL;
147 }
148
149 /* 修改配置前,务必保证中断处于禁能状态 */
150 if (intId <= MAX_NNSPI_ID) {
151 for (coreId = 0; coreId < OS_MAX_CORE_NUM; coreId++) {
152 state = OsGicrGetIntState(coreId, intId);
153 OsGicrDisableInt(coreId, intId);
154 OsGicrSetPriority(coreId, intId, priority);
155 if (state == GIC_ENABLE) {
156 OsGicrEnableInt(coreId, intId);
157 }
158 }
159 } else {
160 state = OsGicdGetIntState(intId);
161 OsGicdDisableInt(intId);
162 OsGicdSetPriority(intId, priority);
163 if (state == GIC_ENABLE) {
164 OsGicdEnableInt(intId);
165 }
166 }
167 return OS_OK;
168 }
169
170 /*
171 * 描述: 获取中断的优先级
172 */
OsGicGetPriority(U32 intId)173 OS_SEC_L4_TEXT U32 OsGicGetPriority(U32 intId)
174 {
175 if (intId <= MAX_NNSPI_ID) {
176 return OsGicrGetPriority(PRT_GetCoreID(), intId);
177 }
178
179 return OsGicdGetPriority(intId);
180 }
181
182 /*
183 * 描述: 设置中断路由目标核,参数有效性由调用者保证
184 * 备注: 仅对非N-N SPI有效,仅支持1个目标核。
185 */
OsGicSetTargetId(U32 intId,U32 targetId)186 OS_SEC_L4_TEXT void OsGicSetTargetId(U32 intId, U32 targetId)
187 {
188 enum GicIntState state;
189
190 /* 修改配置前,务必保证中断处于禁能状态 */
191 state = OsGicdGetIntState(intId);
192 OsGicdDisableInt(intId);
193 OsGicdCfgTargetId(intId, targetId);
194 if (state == GIC_ENABLE) {
195 OsGicdEnableInt(intId);
196 }
197 }
198
199 /*
200 * 描述: 配置GIC基地址
201 * 备注: 此处仅对入参做基础校验,需要用户参考硬件手册,保证入参的正确。
202 */
OsGicConfigRegister(uintptr_t gicdBase,uintptr_t gicrOffset,uintptr_t gicrStride)203 OS_SEC_L4_TEXT U32 OsGicConfigRegister(uintptr_t gicdBase, uintptr_t gicrOffset, uintptr_t gicrStride)
204 {
205 if ((gicdBase == 0) || (gicrOffset == 0) || (gicrStride == 0)) {
206 return OS_ERROR_HWI_BASE_ADDR_INVALID;
207 }
208
209 g_gicdBase = gicdBase;
210 g_gicrOffset = gicrOffset;
211 g_gicrStride = gicrStride;
212
213 return OS_OK;
214 }
215
216 /*
217 * 描述: SPI中断范围Check
218 */
OsGicIsSpi(U32 intId)219 OS_SEC_L4_TEXT bool OsGicIsSpi(U32 intId)
220 {
221 return (((intId) >= MIN_SPI_ID) && ((intId) <= MAX_SPI_ID));
222 }
223