2 * Copyright (c) 2018 Metempsy Technology Consulting
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Jairo Balart
30 #include "dev/arm/gic_v3_distributor.hh"
34 #include "debug/GIC.hh"
35 #include "dev/arm/gic_v3.hh"
36 #include "dev/arm/gic_v3_cpu_interface.hh"
37 #include "dev/arm/gic_v3_redistributor.hh"
39 const AddrRange
Gicv3Distributor::GICD_IGROUPR(0x0080, 0x00ff);
40 const AddrRange
Gicv3Distributor::GICD_ISENABLER(0x0100, 0x017f);
41 const AddrRange
Gicv3Distributor::GICD_ICENABLER(0x0180, 0x01ff);
42 const AddrRange
Gicv3Distributor::GICD_ISPENDR(0x0200, 0x027f);
43 const AddrRange
Gicv3Distributor::GICD_ICPENDR(0x0280, 0x02ff);
44 const AddrRange
Gicv3Distributor::GICD_ISACTIVER(0x0300, 0x037f);
45 const AddrRange
Gicv3Distributor::GICD_ICACTIVER(0x0380, 0x03ff);
46 const AddrRange
Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
47 const AddrRange
Gicv3Distributor::GICD_ITARGETSR(0x0800, 0x08ff);
48 const AddrRange
Gicv3Distributor::GICD_ICFGR(0x0c00, 0x0cff);
49 const AddrRange
Gicv3Distributor::GICD_IGRPMODR(0x0d00, 0x0d7f);
50 const AddrRange
Gicv3Distributor::GICD_NSACR(0x0e00, 0x0eff);
51 const AddrRange
Gicv3Distributor::GICD_CPENDSGIR(0x0f10, 0x0f1f);
52 const AddrRange
Gicv3Distributor::GICD_SPENDSGIR(0x0f20, 0x0f2f);
53 const AddrRange
Gicv3Distributor::GICD_IROUTER(0x6000, 0x7fe0);
55 Gicv3Distributor::Gicv3Distributor(Gicv3
* gic
, uint32_t it_lines
)
62 irqPriority(it_lines
),
66 irqAffinityRouting(it_lines
)
68 panic_if(it_lines
> Gicv3::INTID_SECURE
, "Invalid value for it_lines!");
71 Gicv3Distributor::~Gicv3Distributor()
76 Gicv3Distributor::init()
81 Gicv3Distributor::initState()
87 Gicv3Distributor::reset()
89 std::fill(irqGroup
.begin(), irqGroup
.end(), 0);
90 // Imp. defined reset value
91 std::fill(irqEnabled
.begin(), irqEnabled
.end(), false);
92 std::fill(irqPending
.begin(), irqPending
.end(), false);
93 std::fill(irqActive
.begin(), irqActive
.end(), false);
94 // Imp. defined reset value
95 std::fill(irqPriority
.begin(), irqPriority
.end(), 0xAAAAAAAA);
96 std::fill(irqConfig
.begin(), irqConfig
.end(),
97 Gicv3::INT_LEVEL_SENSITIVE
); // Imp. defined reset value
98 std::fill(irqGrpmod
.begin(), irqGrpmod
.end(), 0);
99 std::fill(irqNsacr
.begin(), irqNsacr
.end(), 0);
101 * For our implementation affinity routing is always enabled,
106 if (gic
->getSystem()->haveSecurity()) {
118 Gicv3Distributor::read(Addr addr
, size_t size
, bool is_secure_access
)
120 if (GICD_IGROUPR
.contains(addr
)) { // Interrupt Group Registers
123 if (!DS
&& !is_secure_access
) {
124 // RAZ/WI for non-secure accesses
128 int first_intid
= (addr
- GICD_IGROUPR
.start()) * 8;
130 if (isNotSPI(first_intid
)) {
134 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
136 val
|= irqGroup
[int_id
] << i
;
140 // Interrupt Set-Enable Registers
141 } else if (GICD_ISENABLER
.contains(addr
)) {
143 int first_intid
= (addr
- GICD_ISENABLER
.start()) * 8;
145 if (isNotSPI(first_intid
)) {
149 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
151 if (nsAccessToSecInt(int_id
, is_secure_access
))
156 val
|= irqEnabled
[int_id
] << i
;
160 } else if (GICD_ICENABLER
.contains(addr
)) {
161 // Interrupt Clear-Enable Registers
163 int first_intid
= (addr
- GICD_ICENABLER
.start()) * 8;
165 if (isNotSPI(first_intid
)) {
169 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
171 if (nsAccessToSecInt(int_id
, is_secure_access
))
176 val
|= (irqEnabled
[int_id
] << i
);
180 } else if (GICD_ISPENDR
.contains(addr
)) {
182 int first_intid
= (addr
- GICD_ISPENDR
.start()) * 8;
184 if (isNotSPI(first_intid
)) {
188 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
190 if (nsAccessToSecInt(int_id
, is_secure_access
))
192 if (irqNsacr
[int_id
] == 0) {
193 // Group 0 or Secure Group 1 interrupts are RAZ/WI
198 val
|= (irqPending
[int_id
] << i
);
202 } else if (GICD_ICPENDR
.contains(addr
)) {
204 int first_intid
= (addr
- GICD_ICPENDR
.start()) * 8;
206 if (isNotSPI(first_intid
)) {
210 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
212 if (nsAccessToSecInt(int_id
, is_secure_access
))
214 if (irqNsacr
[int_id
] < 2) {
215 // Group 0 or Secure Group 1 interrupts are RAZ/WI
220 val
|= (irqPending
[int_id
] << i
);
224 // Interrupt Set-Active Registers
225 } else if (GICD_ISACTIVER
.contains(addr
)) {
226 int first_intid
= (addr
- GICD_ISACTIVER
.start()) * 8;
228 if (isNotSPI(first_intid
)) {
234 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
236 if (nsAccessToSecInt(int_id
, is_secure_access
))
238 // Group 0 or Secure Group 1 interrupts are RAZ/WI
239 if (irqNsacr
[int_id
] < 2) {
244 val
|= (irqActive
[int_id
] << i
);
248 // Interrupt Clear-Active Registers
249 } else if (GICD_ICACTIVER
.contains(addr
)) {
250 int first_intid
= (addr
- GICD_ICACTIVER
.start()) * 8;
252 if (isNotSPI(first_intid
)) {
258 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
260 if (nsAccessToSecInt(int_id
, is_secure_access
))
262 if (irqNsacr
[int_id
] < 2) {
267 val
|= (irqActive
[int_id
] << i
);
271 // Interrupt Priority Registers
272 } else if (GICD_IPRIORITYR
.contains(addr
)) {
274 int first_intid
= addr
- GICD_IPRIORITYR
.start();
276 if (isNotSPI(first_intid
)) {
280 for (int i
= 0, int_id
= first_intid
; i
< size
&& int_id
< itLines
;
282 uint8_t prio
= irqPriority
[int_id
];
284 if (!DS
&& !is_secure_access
) {
285 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
286 // RAZ/WI for non-secure accesses for secure interrupts
290 prio
= (prio
<< 1) & 0xff;
294 val
|= prio
<< (i
* 8);
298 } else if (GICD_ITARGETSR
.contains(addr
)) {
299 // Interrupt Processor Targets Registers
300 // ARE always on, RAZ/WI
301 warn("Gicv3Distributor::read(): "
302 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
304 // Interrupt Configuration Registers
305 } else if (GICD_ICFGR
.contains(addr
)) {
306 int first_intid
= (addr
- GICD_ICFGR
.start()) * 4;
308 if (isNotSPI(first_intid
)) {
314 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
315 i
= i
+ 2, int_id
++) {
316 if (nsAccessToSecInt(int_id
, is_secure_access
))
321 if (irqConfig
[int_id
] == Gicv3::INT_EDGE_TRIGGERED
) {
327 } else if (GICD_IGRPMODR
.contains(addr
)) {
328 // Interrupt Group Modifier Registers
330 // RAZ/WI if security disabled
333 if (!is_secure_access
) {
334 // RAZ/WI for non-secure accesses
337 int first_intid
= (addr
- GICD_IGRPMODR
.start()) * 8;
339 if (isNotSPI(first_intid
)) {
345 for (int i
= 0, int_id
= first_intid
;
346 i
< 8 * size
&& int_id
< itLines
; i
++, int_id
++) {
347 val
|= irqGrpmod
[int_id
] << i
;
354 // Non-secure Access Control Registers
355 } else if (GICD_NSACR
.contains(addr
)) {
356 // 2 bits per interrupt
357 int first_intid
= (addr
- GICD_NSACR
.start()) * 4;
359 if (isNotSPI(first_intid
)) {
363 if (DS
|| (!DS
&& !is_secure_access
)) {
369 for (int i
= 0, int_id
= first_intid
;
370 i
< 8 * size
&& int_id
< itLines
; i
= i
+ 2, int_id
++) {
371 val
|= irqNsacr
[int_id
] << i
;
375 } else if (GICD_CPENDSGIR
.contains(addr
)) { // SGI Clear-Pending Registers
376 // ARE always on, RAZ/WI
377 warn("Gicv3Distributor::read(): "
378 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
380 } else if (GICD_SPENDSGIR
.contains(addr
)) { // SGI Set-Pending Registers
381 // ARE always on, RAZ/WI
382 warn("Gicv3Distributor::read(): "
383 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
385 } else if (GICD_IROUTER
.contains(addr
)) { // Interrupt Routing Registers
386 // 64 bit registers. 2 or 1 access.
387 int int_id
= (addr
- GICD_IROUTER
.start()) / 8;
389 if (isNotSPI(int_id
)) {
393 if (nsAccessToSecInt(int_id
, is_secure_access
))
395 if (irqNsacr
[int_id
] < 3) {
401 if (addr
& 7) { // high half of 64 bit register
402 return irqAffinityRouting
[int_id
] >> 32;
403 } else { // high low of 64 bit register
404 return irqAffinityRouting
[int_id
] & 0xFFFFFFFF;
407 return irqAffinityRouting
[int_id
];
412 case GICD_CTLR
: // Control Register
414 if (is_secure_access
) {
416 // DS [6] - Disable Security
422 return (EnableGrp0
<< 0) |
423 (EnableGrp1NS
<< 1) |
429 // ARE_NS [4] RAO/WI;
430 // EnableGrp1A [1] is a read-write alias of the Secure
431 // GICD_CTLR.EnableGrp1NS
432 // EnableGrp1 [0] RES0
433 return (1 << 4) | (EnableGrp1NS
<< 1);
436 return (DS
<< 6) | (ARE
<< 4) |
437 (EnableGrp1NS
<< 1) | (EnableGrp0
<< 0);
440 case GICD_TYPER
: // Interrupt Controller Type Register
443 * (The implementation does supports targeted SGIs with affinity
444 * level 0 values of 0 - 255)
446 * (1 of N SPI interrupts are not supported)
448 * (Supports nonzero values of Affinity level 3)
449 * IDbits [23:19] == 0xf
450 * (The number of interrupt identifier bits supported, minus one)
452 * (The implementation does not support Direct Virtual LPI
455 * (The implementation does not support LPIs)
457 * (The implementation does not support message-based interrupts
458 * by writing to Distributor registers)
459 * SecurityExtn [10] == X
460 * (The GIC implementation supports two Security states)
461 * CPUNumber [7:5] == 0
462 * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
463 * ITLinesNumber [4:0] == N
464 * (MaxSPIIntId = 32 (N + 1) - 1)
467 int max_spi_int_id
= itLines
- 1;
468 int it_lines_number
= ceil((max_spi_int_id
+ 1) / 32.0) - 1;
469 return (1 << 26) | (1 << 25) | (1 << 24) | (0xf << 19) |
470 (gic
->getSystem()->haveSecurity() << 10) |
471 (it_lines_number
<< 0);
474 case GICD_IIDR
: // Implementer Identification Register
475 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
478 case GICD_STATUSR
: // Error Reporting Status Register
479 // Optional register, RAZ/WI
482 case GICD_PIDR0
: { // Peripheral ID0 Register
483 uint8_t part_0
= 0x92; // Part number, bits[7:0]
487 case GICD_PIDR1
: { // Peripheral ID1 Register
488 uint8_t des_0
= 0xB; // JEP106 identification code, bits[3:0]
489 uint8_t part_1
= 0x4; // Part number, bits[11:8]
490 return (des_0
<< 4) | (part_1
<< 0);
493 case GICD_PIDR2
: { // Peripheral ID2 Register
494 uint8_t arch_rev
= 0x3; // 0x3 GICv3
495 uint8_t jdec
= 0x1; // JEP code
496 uint8_t des_1
= 0x3; // JEP106 identification code, bits[6:4]
497 return (arch_rev
<< 4) | (jdec
<< 3) | (des_1
<< 0);
500 case GICD_PIDR3
: // Peripheral ID3 Register
501 return 0x0; // Implementation defined
503 case GICD_PIDR4
: { // Peripheral ID4 Register
504 uint8_t size
= 0x4; // 64 KB software visible page
505 uint8_t des_2
= 0x4; // ARM implementation
506 return (size
<< 4) | (des_2
<< 0);
509 case GICD_PIDR5
: // Peripheral ID5 Register
510 case GICD_PIDR6
: // Peripheral ID6 Register
511 case GICD_PIDR7
: // Peripheral ID7 Register
515 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr
);
521 Gicv3Distributor::write(Addr addr
, uint64_t data
, size_t size
,
522 bool is_secure_access
)
524 if (GICD_IGROUPR
.contains(addr
)) { // Interrupt Group Registers
525 if (!DS
&& !is_secure_access
) {
526 // RAZ/WI for non-secure accesses
530 int first_intid
= (addr
- GICD_IGROUPR
.start()) * 8;
532 if (isNotSPI(first_intid
)) {
536 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
538 irqGroup
[int_id
] = data
& (1 << i
) ? 1 : 0;
539 DPRINTF(GIC
, "Gicv3Distributor::write(): int_id %d group %d\n",
540 int_id
, irqGroup
[int_id
]);
544 // Interrupt Set-Enable Registers
545 } else if (GICD_ISENABLER
.contains(addr
)) {
546 int first_intid
= (addr
- GICD_ISENABLER
.start()) * 8;
548 if (isNotSPI(first_intid
)) {
552 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
554 if (nsAccessToSecInt(int_id
, is_secure_access
))
559 bool enable
= data
& (1 << i
) ? 1 : 0;
562 if (!irqEnabled
[int_id
]) {
563 DPRINTF(GIC
, "Gicv3Distributor::write(): "
564 "int_id %d enabled\n", int_id
);
567 irqEnabled
[int_id
] = true;
572 } else if (GICD_ICENABLER
.contains(addr
)) {
573 // Interrupt Clear-Enable Registers
574 int first_intid
= (addr
- GICD_ICENABLER
.start()) * 8;
576 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
578 if (nsAccessToSecInt(int_id
, is_secure_access
))
583 bool disable
= data
& (1 << i
) ? 1 : 0;
586 if (irqEnabled
[int_id
]) {
587 DPRINTF(GIC
, "Gicv3Distributor::write(): "
588 "int_id %d disabled\n", int_id
);
591 irqEnabled
[int_id
] = false;
596 } else if (GICD_ISPENDR
.contains(addr
)) {
597 int first_intid
= (addr
- GICD_ISPENDR
.start()) * 8;
599 if (isNotSPI(first_intid
)) {
603 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
605 if (nsAccessToSecInt(int_id
, is_secure_access
))
607 if (irqNsacr
[int_id
] == 0) {
608 // Group 0 or Secure Group 1 interrupts are RAZ/WI
613 bool pending
= data
& (1 << i
) ? 1 : 0;
616 DPRINTF(GIC
, "Gicv3Distributor::write() (GICD_ISPENDR): "
617 "int_id %d (SPI) pending bit set\n", int_id
);
618 irqPending
[int_id
] = true;
622 updateAndInformCPUInterfaces();
624 } else if (GICD_ICPENDR
.contains(addr
)) {
625 int first_intid
= (addr
- GICD_ICPENDR
.start()) * 8;
627 if (isNotSPI(first_intid
)) {
631 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
633 if (nsAccessToSecInt(int_id
, is_secure_access
))
635 if (irqNsacr
[int_id
] < 2) {
636 // Group 0 or Secure Group 1 interrupts are RAZ/WI
641 bool clear
= data
& (1 << i
) ? 1 : 0;
644 irqPending
[int_id
] = false;
648 updateAndInformCPUInterfaces();
650 // Interrupt Set-Active Registers
651 } else if (GICD_ISACTIVER
.contains(addr
)) {
652 int first_intid
= (addr
- GICD_ISACTIVER
.start()) * 8;
654 if (isNotSPI(first_intid
)) {
658 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
660 if (nsAccessToSecInt(int_id
, is_secure_access
))
665 bool active
= data
& (1 << i
) ? 1 : 0;
668 irqActive
[int_id
] = 1;
673 } else if (GICD_ICACTIVER
.contains(addr
)) {
674 // Interrupt Clear-Active Registers
675 int first_intid
= (addr
- GICD_ICACTIVER
.start()) * 8;
677 if (isNotSPI(first_intid
)) {
681 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
683 if (nsAccessToSecInt(int_id
, is_secure_access
))
688 bool clear
= data
& (1 << i
) ? 1 : 0;
691 if (irqActive
[int_id
]) {
692 DPRINTF(GIC
, "Gicv3Distributor::write(): "
693 "int_id %d active cleared\n", int_id
);
696 irqActive
[int_id
] = false;
701 // Interrupt Priority Registers
702 } else if (GICD_IPRIORITYR
.contains(addr
)) {
703 int first_intid
= addr
- GICD_IPRIORITYR
.start();
705 if (isNotSPI(first_intid
)) {
709 for (int i
= 0, int_id
= first_intid
; i
< size
&& int_id
< itLines
;
711 uint8_t prio
= bits(data
, (i
+ 1) * 8 - 1, (i
* 8));
713 if (!DS
&& !is_secure_access
) {
714 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
715 // RAZ/WI for non-secure accesses to secure interrupts
718 prio
= 0x80 | (prio
>> 1);
722 irqPriority
[int_id
] = prio
;
723 DPRINTF(GIC
, "Gicv3Distributor::write(): int_id %d priority %d\n",
724 int_id
, irqPriority
[int_id
]);
728 } else if (GICD_ITARGETSR
.contains(addr
)) {
729 // Interrupt Processor Targets Registers
730 // ARE always on, RAZ/WI
731 warn("Gicv3Distributor::write(): "
732 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
734 // Interrupt Configuration Registers
735 } else if (GICD_ICFGR
.contains(addr
)) {
736 /* Here only the odd bits are used; even bits are RES0 */
737 int first_intid
= (addr
- GICD_ICFGR
.start()) * 4;
739 if (isNotSPI(first_intid
)) {
743 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
&& int_id
< itLines
;
744 i
= i
+ 2, int_id
++) {
745 irqConfig
[int_id
] = data
& (0x2 << i
) ?
746 Gicv3::INT_EDGE_TRIGGERED
:
747 Gicv3::INT_LEVEL_SENSITIVE
;
748 DPRINTF(GIC
, "Gicv3Distributor::write(): int_id %d config %d\n",
749 int_id
, irqConfig
[int_id
]);
753 } else if (GICD_IGRPMODR
.contains(addr
)) {
754 // Interrupt Group Modifier Registers
758 if (!is_secure_access
) {
759 // RAZ/WI for non-secure accesses
762 int first_intid
= (addr
- GICD_IGRPMODR
.start()) * 8;
764 if (isNotSPI(first_intid
)) {
768 for (int i
= 0, int_id
= first_intid
;
769 i
< 8 * size
&& int_id
< itLines
; i
++, int_id
++) {
770 irqGrpmod
[int_id
] = data
& (0x1 << i
);
777 // Non-secure Access Control Registers
778 } else if (GICD_NSACR
.contains(addr
)) {
779 // 2 bits per interrupt
780 int first_intid
= (addr
- GICD_NSACR
.start()) * 4;
782 if (isNotSPI(first_intid
)) {
786 if (DS
|| (!DS
&& !is_secure_access
)) {
790 for (int i
= 0, int_id
= first_intid
;
791 i
< 8 * size
&& int_id
< itLines
; i
= i
+ 2, int_id
++) {
792 irqNsacr
[int_id
] = (data
>> (2 * int_id
)) & 0x3;
796 } else if (GICD_IROUTER
.contains(addr
)) { // Interrupt Routing Registers
797 // 64 bit registers. 2 accesses.
798 int int_id
= (addr
- GICD_IROUTER
.start()) / 8;
800 if (isNotSPI(int_id
)) {
804 if (nsAccessToSecInt(int_id
, is_secure_access
))
806 if (irqNsacr
[int_id
] < 3) {
807 // Group 0 or Secure Group 1 interrupts are RAZ/WI
813 if (addr
& 7) { // high half of 64 bit register
814 irqAffinityRouting
[int_id
] =
815 (irqAffinityRouting
[int_id
] & 0xffffffff) | (data
<< 32);
816 } else { // low half of 64 bit register
817 irqAffinityRouting
[int_id
] =
818 (irqAffinityRouting
[int_id
] & 0xffffffff00000000) |
822 irqAffinityRouting
[int_id
] = data
;
825 DPRINTF(GIC
, "Gicv3Distributor::write(): "
826 "int_id %d GICD_IROUTER %#llx\n",
827 int_id
, irqAffinityRouting
[int_id
]);
832 case GICD_CTLR
: // Control Register
836 * 1 of N wakeup functionality not supported, RAZ/WI
839 * affinity routing always on, no GICv2 legacy, RAO/WI
843 if ((data
& (1 << 4)) == 0) {
844 warn("Gicv3Distributor::write(): "
845 "setting ARE to 0 is not supported!\n");
848 EnableGrp1NS
= data
& GICD_CTLR_ENABLEGRP1NS
;
849 EnableGrp0
= data
& GICD_CTLR_ENABLEGRP0
;
850 DPRINTF(GIC
, "Gicv3Distributor::write(): (DS 1)"
851 "EnableGrp1NS %d EnableGrp0 %d\n",
852 EnableGrp1NS
, EnableGrp0
);
854 if (is_secure_access
) {
857 * 1 of N wakeup functionality not supported, RAZ/WI
860 * affinity routing always on, no GICv2 legacy, RAO/WI
862 * affinity routing always on, no GICv2 legacy, RAO/WI
867 if ((data
& (1 << 5)) == 0) {
868 warn("Gicv3Distributor::write(): "
869 "setting ARE_NS to 0 is not supported!\n");
872 if ((data
& (1 << 4)) == 0) {
873 warn("Gicv3Distributor::write(): "
874 "setting ARE_S to 0 is not supported!\n");
877 DS
= data
& GICD_CTLR_DS
;
878 EnableGrp1S
= data
& GICD_CTLR_ENABLEGRP1S
;
879 EnableGrp1NS
= data
& GICD_CTLR_ENABLEGRP1NS
;
880 EnableGrp0
= data
& GICD_CTLR_ENABLEGRP0
;
881 DPRINTF(GIC
, "Gicv3Distributor::write(): (DS 0 secure)"
883 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
884 DS
, EnableGrp1S
, EnableGrp1NS
, EnableGrp0
);
886 if (data
& GICD_CTLR_DS
) {
892 * EnableGrp1A [1] is a read-write alias of the Secure
893 * GICD_CTLR.EnableGrp1NS
894 * EnableGrp1 [0] RES0
896 if ((data
& (1 << 4)) == 0) {
897 warn("Gicv3Distributor::write(): "
898 "setting ARE_NS to 0 is not supported!\n");
901 EnableGrp1NS
= data
& GICD_CTLR_ENABLEGRP1A
;
902 DPRINTF(GIC
, "Gicv3Distributor::write(): (DS 0 non-secure)"
903 "EnableGrp1NS %d\n", EnableGrp1NS
);
910 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr
);
916 Gicv3Distributor::sendInt(uint32_t int_id
)
918 panic_if(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, "Invalid SPI!");
919 panic_if(int_id
> itLines
, "Invalid SPI!");
920 irqPending
[int_id
] = true;
921 DPRINTF(GIC
, "Gicv3Distributor::sendInt(): "
922 "int_id %d (SPI) pending bit set\n", int_id
);
923 updateAndInformCPUInterfaces();
927 Gicv3Distributor::intDeasserted(uint32_t int_id
)
929 panic_if(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, "Invalid SPI!");
930 panic_if(int_id
> itLines
, "Invalid SPI!");
931 irqPending
[int_id
] = false;
932 updateAndInformCPUInterfaces();
936 Gicv3Distributor::updateAndInformCPUInterfaces()
940 for (int i
= 0; i
< gic
->getSystem()->numContexts(); i
++) {
941 gic
->getCPUInterface(i
)->update();
946 Gicv3Distributor::fullUpdate()
948 for (int i
= 0; i
< gic
->getSystem()->numContexts(); i
++) {
949 Gicv3CPUInterface
* cpu_interface_i
= gic
->getCPUInterface(i
);
950 cpu_interface_i
->hppi
.prio
= 0xff;
955 for (int i
= 0; i
< gic
->getSystem()->numContexts(); i
++) {
956 Gicv3Redistributor
* redistributor_i
= gic
->getRedistributor(i
);
957 redistributor_i
->update();
962 Gicv3Distributor::update()
964 std::vector
<bool> new_hppi(gic
->getSystem()->numContexts(), false);
966 // Find the highest priority pending SPI
967 for (int int_id
= Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
; int_id
< itLines
;
969 Gicv3::GroupId int_group
= getIntGroup(int_id
);
970 bool group_enabled
= groupEnabled(int_group
);
972 if (irqPending
[int_id
] && irqEnabled
[int_id
] &&
973 !irqActive
[int_id
] && group_enabled
) {
974 IROUTER affinity_routing
= irqAffinityRouting
[int_id
];
975 Gicv3Redistributor
* target_redistributor
= nullptr;
977 if (affinity_routing
.IRM
) {
978 // Interrupts routed to any PE defined as a participating node
979 for (int i
= 0; i
< gic
->getSystem()->numContexts(); i
++) {
980 Gicv3Redistributor
* redistributor_i
=
981 gic
->getRedistributor(i
);
983 if (redistributor_i
->
984 canBeSelectedFor1toNInterrupt(int_group
)) {
985 target_redistributor
= redistributor_i
;
990 uint32_t affinity
= (affinity_routing
.Aff3
<< 24) |
991 (affinity_routing
.Aff3
<< 16) |
992 (affinity_routing
.Aff1
<< 8) |
993 (affinity_routing
.Aff0
<< 0);
994 target_redistributor
=
995 gic
->getRedistributorByAffinity(affinity
);
998 if (!target_redistributor
) {
999 // Interrrupts targeting not present cpus must remain pending
1003 Gicv3CPUInterface
* target_cpu_interface
=
1004 target_redistributor
->getCPUInterface();
1005 uint32_t target_cpu
= target_redistributor
->cpuId
;
1007 if ((irqPriority
[int_id
] < target_cpu_interface
->hppi
.prio
) ||
1009 * Multiple pending ints with same priority.
1010 * Implementation choice which one to signal.
1011 * Our implementation selects the one with the lower id.
1013 (irqPriority
[int_id
] == target_cpu_interface
->hppi
.prio
&&
1014 int_id
< target_cpu_interface
->hppi
.intid
)) {
1015 target_cpu_interface
->hppi
.intid
= int_id
;
1016 target_cpu_interface
->hppi
.prio
= irqPriority
[int_id
];
1017 target_cpu_interface
->hppi
.group
= int_group
;
1018 new_hppi
[target_cpu
] = true;
1023 for (int i
= 0; i
< gic
->getSystem()->numContexts(); i
++) {
1024 Gicv3Redistributor
* redistributor_i
= gic
->getRedistributor(i
);
1025 Gicv3CPUInterface
* cpu_interface_i
=
1026 redistributor_i
->getCPUInterface();
1028 if (!new_hppi
[i
] && cpu_interface_i
->hppi
.prio
!= 0xff &&
1029 cpu_interface_i
->hppi
.intid
>=
1030 (Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
) &&
1031 cpu_interface_i
->hppi
.intid
< Gicv3::INTID_SECURE
) {
1038 Gicv3Distributor::intStatus(uint32_t int_id
)
1040 panic_if(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, "Invalid SPI!");
1041 panic_if(int_id
> itLines
, "Invalid SPI!");
1043 if (irqPending
[int_id
]) {
1044 if (irqActive
[int_id
]) {
1045 return Gicv3::INT_ACTIVE_PENDING
;
1048 return Gicv3::INT_PENDING
;
1049 } else if (irqActive
[int_id
]) {
1050 return Gicv3::INT_ACTIVE
;
1052 return Gicv3::INT_INACTIVE
;
1057 Gicv3Distributor::getIntGroup(int int_id
)
1059 panic_if(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, "Invalid SPI!");
1060 panic_if(int_id
> itLines
, "Invalid SPI!");
1063 if (irqGroup
[int_id
] == 1) {
1069 if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 0) {
1071 } else if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 1) {
1073 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 0) {
1075 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 1) {
1084 Gicv3Distributor::activateIRQ(uint32_t int_id
)
1086 irqPending
[int_id
] = false;
1087 irqActive
[int_id
] = true;
1091 Gicv3Distributor::deactivateIRQ(uint32_t int_id
)
1093 irqActive
[int_id
] = false;
1097 Gicv3Distributor::serialize(CheckpointOut
& cp
) const
1099 SERIALIZE_SCALAR(ARE
);
1100 SERIALIZE_SCALAR(DS
);
1101 SERIALIZE_SCALAR(EnableGrp1S
);
1102 SERIALIZE_SCALAR(EnableGrp1NS
);
1103 SERIALIZE_SCALAR(EnableGrp0
);
1104 SERIALIZE_CONTAINER(irqGroup
);
1105 SERIALIZE_CONTAINER(irqEnabled
);
1106 SERIALIZE_CONTAINER(irqPending
);
1107 SERIALIZE_CONTAINER(irqActive
);
1108 SERIALIZE_CONTAINER(irqPriority
);
1109 SERIALIZE_CONTAINER(irqConfig
);
1110 SERIALIZE_CONTAINER(irqGrpmod
);
1111 SERIALIZE_CONTAINER(irqNsacr
);
1112 SERIALIZE_CONTAINER(irqAffinityRouting
);
1116 Gicv3Distributor::unserialize(CheckpointIn
& cp
)
1118 UNSERIALIZE_SCALAR(ARE
);
1119 UNSERIALIZE_SCALAR(DS
);
1120 UNSERIALIZE_SCALAR(EnableGrp1S
);
1121 UNSERIALIZE_SCALAR(EnableGrp1NS
);
1122 UNSERIALIZE_SCALAR(EnableGrp0
);
1123 UNSERIALIZE_CONTAINER(irqGroup
);
1124 UNSERIALIZE_CONTAINER(irqEnabled
);
1125 UNSERIALIZE_CONTAINER(irqPending
);
1126 UNSERIALIZE_CONTAINER(irqActive
);
1127 UNSERIALIZE_CONTAINER(irqPriority
);
1128 UNSERIALIZE_CONTAINER(irqConfig
);
1129 UNSERIALIZE_CONTAINER(irqGrpmod
);
1130 UNSERIALIZE_CONTAINER(irqNsacr
);
1131 UNSERIALIZE_CONTAINER(irqAffinityRouting
);