更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
gic_v3.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "gic_common.h"
33#include "gic_v3.h"
34#include "los_typedef.h"
35#include "los_hwi.h"
36#include "los_hwi_pri.h"
37#include "los_mp.h"
38
39#ifdef LOSCFG_ARCH_GIC_V3
40
42
43STATIC INLINE UINT64 MpidrToAffinity(UINT64 mpidr)
44{
45 return ((MPIDR_AFF_LEVEL(mpidr, 3) << 32) |
46 (MPIDR_AFF_LEVEL(mpidr, 2) << 16) |
47 (MPIDR_AFF_LEVEL(mpidr, 1) << 8) |
48 (MPIDR_AFF_LEVEL(mpidr, 0)));
49}
50
51#ifdef LOSCFG_KERNEL_SMP
52
53STATIC UINT32 NextCpu(UINT32 cpu, UINT32 cpuMask)
54{
55 UINT32 next = cpu + 1;
56
57 while (next < LOSCFG_KERNEL_CORE_NUM) {
58 if (cpuMask & (1U << next)) {
59 goto OUT;
60 }
61
62 next++;
63 }
64
65OUT:
66 return next;
67}
68
69STATIC UINT16 GicTargetList(UINT32 *base, UINT32 cpuMask, UINT64 cluster)
70{
71 UINT32 nextCpu;
72 UINT16 tList = 0;
73 UINT32 cpu = *base;
74 UINT64 mpidr = CPU_MAP_GET(cpu);
75 while (cpu < LOSCFG_KERNEL_CORE_NUM) {
76 tList |= 1U << (mpidr & 0xf);
77
78 nextCpu = NextCpu(cpu, cpuMask);
79 if (nextCpu >= LOSCFG_KERNEL_CORE_NUM) {
80 goto out;
81 }
82
83 cpu = nextCpu;
84 mpidr = CPU_MAP_GET(cpu);
85 if (cluster != (mpidr & ~0xffUL)) {
86 cpu--;
87 goto out;
88 }
89 }
90
91out:
92 *base = cpu;
93 return tList;
94}
95
96STATIC VOID GicSgi(UINT32 irq, UINT32 cpuMask)
97{
98 UINT16 tList;
99 UINT32 cpu = 0;
100 UINT64 val, cluster;
101
102 while (cpuMask && (cpu < LOSCFG_KERNEL_CORE_NUM)) {
103 if (cpuMask & (1U << cpu)) {
104 cluster = CPU_MAP_GET(cpu) & ~0xffUL;
105
106 tList = GicTargetList(&cpu, cpuMask, cluster);
107
108 /* Generates a Group 1 interrupt for the current security state */
109 val = ((MPIDR_AFF_LEVEL(cluster, 3) << 48) |
110 (MPIDR_AFF_LEVEL(cluster, 2) << 32) |
111 (MPIDR_AFF_LEVEL(cluster, 1) << 16) |
112 (irq << 24) | tList);
113
114 GiccSetSgi1r(val);
115 }
116
117 cpu++;
118 }
119}
120
121VOID HalIrqSendIpi(UINT32 target, UINT32 ipi)
122{
123 GicSgi(ipi, target);
124}
125
127{
128 UINT64 affinity = MpidrToAffinity(NextCpu(0, cpuMask));
129
130 /* When ARE is on, use router */
131 GIC_REG_64(GICD_IROUTER(irq)) = affinity;
132}
133
134#endif
135
136STATIC VOID GicWaitForRwp(UINT64 reg)
137{
138 INT32 count = 1000000; /* 1s */
139
140 while (GIC_REG_32(reg) & GICD_CTLR_RWP) {
141 count -= 1;
142 if (!count) {
143 PRINTK("gic_v3: rwp timeout 0x%x\n", GIC_REG_32(reg));
144 return;
145 }
146 }
147}
148
149STATIC INLINE VOID GicdSetGroup(UINT32 irq)
150{
151 /* configure spi as group 0 on secure mode and group 1 on unsecure mode */
152#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE
153 GIC_REG_32(GICD_IGROUPR(irq / 32)) = 0;
154#else
155 GIC_REG_32(GICD_IGROUPR(irq / 32)) = 0xffffffff;
156#endif
157}
158
159STATIC INLINE VOID GicrSetWaker(UINT32 cpu)
160{
161 GIC_REG_32(GICR_WAKER(cpu)) &= ~GICR_WAKER_PROCESSORSLEEP;
162 DSB;
163 ISB;
164 while ((GIC_REG_32(GICR_WAKER(cpu)) & 0x4) == GICR_WAKER_CHILDRENASLEEP);
165}
166
167STATIC INLINE VOID GicrSetGroup(UINT32 cpu)
168{
169 /* configure sgi/ppi as group 0 on secure mode and group 1 on unsecure mode */
170#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE
171 GIC_REG_32(GICR_IGROUPR0(cpu)) = 0;
172 GIC_REG_32(GICR_IGRPMOD0(cpu)) = 0;
173#else
174 GIC_REG_32(GICR_IGROUPR0(cpu)) = 0xffffffff;
175#endif
176}
177
178STATIC VOID GicdSetPmr(UINT32 irq, UINT8 priority)
179{
180 UINT32 pos = irq >> 2; /* one irq have the 8-bit interrupt priority field */
181 UINT32 newPri = GIC_REG_32(GICD_IPRIORITYR(pos));
182
183 /* Shift and mask the correct bits for the priority */
184 newPri &= ~(GIC_PRIORITY_MASK << ((irq % 4) * GIC_PRIORITY_OFFSET));
185 newPri |= priority << ((irq % 4) * GIC_PRIORITY_OFFSET);
186
187 GIC_REG_32(GICD_IPRIORITYR(pos)) = newPri;
188}
189
190STATIC VOID GicrSetPmr(UINT32 irq, UINT8 priority)
191{
192 UINT32 cpu = ArchCurrCpuid();
193 UINT32 pos = irq >> 2; /* one irq have the 8-bit interrupt priority field */
194 UINT32 newPri = GIC_REG_32(GICR_IPRIORITYR0(cpu) + pos * 4);
195
196 /* Clear priority offset bits and set new priority */
197 newPri &= ~(GIC_PRIORITY_MASK << ((irq % 4) * GIC_PRIORITY_OFFSET));
198 newPri |= priority << ((irq % 4) * GIC_PRIORITY_OFFSET);
199
200 GIC_REG_32(GICR_IPRIORITYR0(cpu) + pos * 4) = newPri;
201}
202
203STATIC VOID GiccInitPercpu(VOID)
204{
205 /* enable system register interface */
206 UINT32 sre = GiccGetSre();
207 if (!(sre & 0x1)) {
208 GiccSetSre(sre | 0x1);
209
210 /*
211 * Need to check that the SRE bit has actually been set. If
212 * not, it means that SRE is disabled at up EL level. We're going to
213 * die painfully, and there is nothing we can do about it.
214 */
215 sre = GiccGetSre();
216 LOS_ASSERT(sre & 0x1);
217 }
218
219#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE
220 /* Enable group 0 and disable grp1ns grp1s interrupts */
223
224 /*
225 * For priority grouping.
226 * The value of this field control show the 8-bit interrupt priority field
227 * is split into a group priority field, that determines interrupt preemption,
228 * and a subpriority field.
229 */
230 GiccSetBpr0(MAX_BINARY_POINT_VALUE);
231#else
232 /* enable group 1 interrupts */
234#endif
235
236 /* set priority threshold to max */
237 GiccSetPmr(0xff);
238
239 /* EOI deactivates interrupt too (mode 0) */
240 GiccSetCtlr(0);
241}
242
244{
245 return g_curIrqNum;
246}
247
248VOID HalIrqMask(UINT32 vector)
249{
250 INT32 i;
251 const UINT32 mask = 1U << (vector % 32);
252
253 if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
254 return;
255 }
256
257 if (vector < 32) {
258 for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
259 GIC_REG_32(GICR_ICENABLER0(i)) = mask;
260 GicWaitForRwp(GICR_CTLR(i));
261 }
262 } else {
263 GIC_REG_32(GICD_ICENABLER(vector >> 5)) = mask;
264 GicWaitForRwp(GICD_CTLR);
265 }
266}
267
269{
270 INT32 i;
271 const UINT32 mask = 1U << (vector % 32);
272
273 if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
274 return;
275 }
276
277 if (vector < 32) {
278 for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) {
279 GIC_REG_32(GICR_ISENABLER0(i)) = mask;
280 GicWaitForRwp(GICR_CTLR(i));
281 }
282 } else {
283 GIC_REG_32(GICD_ISENABLER(vector >> 5)) = mask;
284 GicWaitForRwp(GICD_CTLR);
285 }
286}
287
289{
290 if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
291 return;
292 }
293
294 GIC_REG_32(GICD_ISPENDR(vector >> 5)) = 1U << (vector % 32);
295}
296
297VOID HalIrqClear(UINT32 vector)
298{
299 GiccSetEoir(vector);
300 ISB;
301}
302
304{
305 UINT8 prio = priority;
306
307 if (vector > OS_HWI_MAX_NUM) {
308 PRINT_ERR("Invalid irq value %u, max irq is %u\n", vector, OS_HWI_MAX_NUM);
309 return LOS_NOK;
310 }
311
312 prio = prio & (UINT8)GIC_INTR_PRIO_MASK;
313
314 if (vector >= GIC_MIN_SPI_NUM) {
315 GicdSetPmr(vector, prio);
316 } else {
317 GicrSetPmr(vector, prio);
318 }
319
320 return LOS_OK;
321}
322
324{
325 INT32 idx;
326 UINT32 cpu = ArchCurrCpuid();
327
328 /* GICR init */
329 GicrSetWaker(cpu);
330 GicrSetGroup(cpu);
331 GicWaitForRwp(GICR_CTLR(cpu));
332
333 /* GICR: clear and mask sgi/ppi */
334 GIC_REG_32(GICR_ICENABLER0(cpu)) = 0xffffffff;
335 GIC_REG_32(GICR_ICPENDR0(cpu)) = 0xffffffff;
336
337 GIC_REG_32(GICR_ISENABLER0(cpu)) = 0xffffffff;
338
339 for (idx = 0; idx < GIC_MIN_SPI_NUM; idx += 1) {
340 GicrSetPmr(idx, MIN_INTERRUPT_PRIORITY);
341 }
342
343 GicWaitForRwp(GICR_CTLR(cpu));
344
345 /* GICC init */
347
348#ifdef LOSCFG_KERNEL_SMP
349 /* unmask ipi interrupts */
352#endif
353}
354
355VOID HalIrqInit(VOID)
356{
357 UINT32 i;
358 UINT64 affinity;
359
360 /* disable distributor */
361 GIC_REG_32(GICD_CTLR) = 0;
362 GicWaitForRwp(GICD_CTLR);
363 ISB;
364
365 /* set externel interrupts to be level triggered, active low. */
366 for (i = 32; i < OS_HWI_MAX_NUM; i += 16) {
367 GIC_REG_32(GICD_ICFGR(i / 16)) = 0;
368 }
369
370 /* config distributer, mask and clear all spis, set group x */
371 for (i = 32; i < OS_HWI_MAX_NUM; i += 32) {
372 GIC_REG_32(GICD_ICENABLER(i / 32)) = 0xffffffff;
373 GIC_REG_32(GICD_ICPENDR(i / 32)) = 0xffffffff;
374 GIC_REG_32(GICD_IGRPMODR(i / 32)) = 0;
375
376 GicdSetGroup(i);
377 }
378
379 /* set spi priority as default */
380 for (i = 32; i < OS_HWI_MAX_NUM; i++) {
381 GicdSetPmr(i, MIN_INTERRUPT_PRIORITY);
382 }
383
384 GicWaitForRwp(GICD_CTLR);
385
386 /* disable all interrupts. */
387 for (i = 0; i < OS_HWI_MAX_NUM; i += 32) {
388 GIC_REG_32(GICD_ICENABLER(i / 32)) = 0xffffffff;
389 }
390
391 /* enable distributor with ARE, group 1 enabled */
392 GIC_REG_32(GICD_CTLR) = CTLR_ENALBE_G0 | CTLR_ENABLE_G1NS | CTLR_ARE_S;
393
394 /* set spi to boot cpu only. ARE must be enabled */
395 affinity = MpidrToAffinity(AARCH64_SYSREG_READ(mpidr_el1));
396 for (i = 32; i < OS_HWI_MAX_NUM; i++) {
397 GIC_REG_64(GICD_IROUTER(i)) = affinity;
398 }
399
401
402#ifdef LOSCFG_KERNEL_SMP
403 /* register inter-processor interrupt */
407#ifdef LOSCFG_KERNEL_SMP_CALL
409#endif
410#endif
411}
412
414{
415 UINT32 iar = GiccGetIar();
416 UINT32 vector = iar & 0x3FFU;
417
418 /*
419 * invalid irq number, mainly the spurious interrupts 0x3ff,
420 * valid irq ranges from 0~1019, we use OS_HWI_MAX_NUM to do
421 * the checking.
422 */
423 if (vector >= OS_HWI_MAX_NUM) {
424 return;
425 }
426 g_curIrqNum = vector;
427
428 OsInterrupt(vector);
429 GiccSetEoir(vector);
430}
431
433{
434 UINT32 pidr = GIC_REG_32(GICD_PIDR2V3);
435 CHAR *irqVerString = NULL;
436
437 switch (pidr >> GIC_REV_OFFSET) {
438 case GICV3:
439 irqVerString = "GICv3";
440 break;
441 case GICV4:
442 irqVerString = "GICv4";
443 break;
444 default:
445 irqVerString = "unknown";
446 }
447 return irqVerString;
448}
449
450#endif
GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器 http://weharmonyos.com/blog/44....
@ GICV3
Definition: gic_common.h:57
@ GICV4
Definition: gic_common.h:58
UINT32 HalCurIrqGet(VOID)
获取当前中断号
Definition: gic_v3.c:243
VOID HalIrqInit(VOID)
中断控制器本身初始化
Definition: gic_v3.c:355
VOID HalIrqHandler(VOID)
Definition: gic_v3.c:413
VOID HalIrqSendIpi(UINT32 target, UINT32 ipi)
Definition: gic_v3.c:121
STATIC INLINE VOID GicrSetWaker(UINT32 cpu)
Definition: gic_v3.c:159
STATIC VOID GicrSetPmr(UINT32 irq, UINT8 priority)
Definition: gic_v3.c:190
STATIC INLINE VOID GicdSetGroup(UINT32 irq)
Definition: gic_v3.c:149
STATIC INLINE VOID GicrSetGroup(UINT32 cpu)
Definition: gic_v3.c:167
VOID HalIrqUnmask(UINT32 vector)
撤销中断屏蔽
Definition: gic_v3.c:268
STATIC UINT32 NextCpu(UINT32 cpu, UINT32 cpuMask)
Definition: gic_v3.c:53
UINT32 HalIrqSetPrio(UINT32 vector, UINT8 priority)
Definition: gic_v3.c:303
STATIC VOID GiccInitPercpu(VOID)
Definition: gic_v3.c:203
VOID HalIrqPending(UINT32 vector)
Definition: gic_v3.c:288
VOID HalIrqSetAffinity(UINT32 irq, UINT32 cpuMask)
Definition: gic_v3.c:126
VOID HalIrqClear(UINT32 vector)
Definition: gic_v3.c:297
STATIC VOID GicSgi(UINT32 irq, UINT32 cpuMask)
Definition: gic_v3.c:96
STATIC UINT16 GicTargetList(UINT32 *base, UINT32 cpuMask, UINT64 cluster)
Definition: gic_v3.c:69
VOID HalIrqMask(UINT32 vector)
屏蔽中断
Definition: gic_v3.c:248
VOID HalIrqInitPercpu(VOID)
中断控制器与CPU之间的关系初始化
Definition: gic_v3.c:323
STATIC UINT32 g_curIrqNum
Definition: gic_v3.c:41
STATIC INLINE UINT64 MpidrToAffinity(UINT64 mpidr)
Definition: gic_v3.c:43
STATIC VOID GicdSetPmr(UINT32 irq, UINT8 priority)
Definition: gic_v3.c:178
STATIC VOID GicWaitForRwp(UINT64 reg)
Definition: gic_v3.c:136
CHAR * HalIrqVersion(VOID)
Definition: gic_v3.c:432
STATIC INLINE VOID GiccSetBpr0(UINT32 val)
Definition: gic_v3.h:197
STATIC INLINE VOID GiccSetCtlr(UINT32 val)
Definition: gic_v3.h:112
STATIC INLINE VOID GiccSetIgrpen1(UINT32 val)
Definition: gic_v3.h:135
STATIC INLINE UINT32 GiccGetSre(VOID)
Definition: gic_v3.h:145
STATIC INLINE UINT32 GiccGetIar(VOID)
Definition: gic_v3.h:176
STATIC INLINE VOID GiccSetEoir(UINT32 val)
Definition: gic_v3.h:166
STATIC INLINE VOID GiccSetPmr(UINT32 val)
Definition: gic_v3.h:122
STATIC INLINE VOID GiccSetSgi1r(UINT64 val)
Definition: gic_v3.h:190
STATIC INLINE VOID GiccSetIgrpen0(UINT32 val)
Definition: gic_v3.h:129
STATIC INLINE VOID GiccSetSre(UINT32 val)
Definition: gic_v3.h:156
LITE_OS_SEC_TEXT_INIT UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio, HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler, HwiIrqParam *irqParam)
创建一个硬中断 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时, handleIrq会调用该中断处理程序
Definition: los_hwi.c:429
STATIC INLINE UINT32 ArchCurrCpuid(VOID)
Definition: los_hw_cpu.h:168
VOID OsInterrupt(UINT32 intNum)
Definition: los_hwi.c:180
VOID OsMpWakeHandler(VOID)
硬中断唤醒处理函数
Definition: los_mp.c:83
VOID OsMpFuncCallHandler(VOID)
OsMpFuncCallHandler 回调向当前CPU注册过的函数
Definition: los_mp.c:182
VOID OsMpScheduleHandler(VOID)
硬中断调度处理函数
Definition: los_mp.c:88
@ LOS_MP_IPI_SCHEDULE
!< 唤醒CPU
Definition: los_mp.h:51
@ LOS_MP_IPI_WAKEUP
Definition: los_mp.h:50
@ LOS_MP_IPI_FUNC_CALL
!< 停止CPU
Definition: los_mp.h:54
@ LOS_MP_IPI_HALT
!< 调度CPU
Definition: los_mp.h:52
unsigned short UINT16
Definition: los_typedef.h:56
signed int INT32
Definition: los_typedef.h:60
long unsigned int UINT64
Definition: los_typedef.h:66
unsigned char UINT8
Definition: los_typedef.h:55
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63