• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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