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
31 #include "dev/arm/gic_v3_redistributor.hh"
33 #include "arch/arm/utility.hh"
34 #include "debug/GIC.hh"
35 #include "dev/arm/gic_v3_cpu_interface.hh"
36 #include "dev/arm/gic_v3_distributor.hh"
37 #include "mem/fs_translating_port_proxy.hh"
39 const AddrRange
Gicv3Redistributor::GICR_IPRIORITYR(SGI_base
+ 0x0400,
42 Gicv3Redistributor::Gicv3Redistributor(Gicv3
* gic
, uint32_t cpu_id
)
45 cpuInterface(nullptr),
47 irqGroup(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
48 irqEnabled(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
49 irqPending(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
50 irqActive(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
51 irqPriority(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
52 irqConfig(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
53 irqGrpmod(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
54 irqNsacr(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
),
55 addrRangeSize(gic
->params()->gicv4
? 0x40000 : 0x20000)
60 Gicv3Redistributor::init()
62 distributor
= gic
->getDistributor();
63 cpuInterface
= gic
->getCPUInterface(cpuId
);
67 Gicv3Redistributor::initState()
73 Gicv3Redistributor::reset()
75 peInLowPowerState
= true;
76 std::fill(irqGroup
.begin(), irqGroup
.end(), 0);
77 std::fill(irqEnabled
.begin(), irqEnabled
.end(), false);
78 std::fill(irqPending
.begin(), irqPending
.end(), false);
79 std::fill(irqActive
.begin(), irqActive
.end(), false);
80 std::fill(irqPriority
.begin(), irqPriority
.end(), 0);
82 // SGIs have edge-triggered behavior
83 for (uint32_t int_id
= 0; int_id
< Gicv3::SGI_MAX
; int_id
++) {
84 irqConfig
[int_id
] = Gicv3::INT_EDGE_TRIGGERED
;
87 std::fill(irqGrpmod
.begin(), irqGrpmod
.end(), 0);
88 std::fill(irqNsacr
.begin(), irqNsacr
.end(), 0);
93 lpiConfigurationTablePtr
= 0;
95 lpiPendingTablePtr
= 0;
99 Gicv3Redistributor::read(Addr addr
, size_t size
, bool is_secure_access
)
101 if (GICR_IPRIORITYR
.contains(addr
)) { // Interrupt Priority Registers
103 int first_intid
= addr
- GICR_IPRIORITYR
.start();
105 for (int i
= 0, int_id
= first_intid
; i
< size
; i
++, int_id
++) {
106 uint8_t prio
= irqPriority
[int_id
];
108 if (!distributor
->DS
&& !is_secure_access
) {
109 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
110 // RAZ/WI for non-secure accesses for secure interrupts
114 prio
= (prio
<< 1) & 0xff;
118 value
|= prio
<< (i
* 8);
125 case GICR_CTLR
: { // Control Register
129 value
|= GICR_CTLR_DPG1S
;
133 value
|= GICR_CTLR_DPG1NS
;
137 value
|= GICR_CTLR_DPG0
;
141 value
|= GICR_CTLR_ENABLE_LPIS
;
147 case GICR_IIDR
: // Implementer Identification Register
148 //return 0x43b; // r0p0 GIC-500
151 case GICR_TYPER
: { // Type Register
153 * Affinity_Value [63:32] == X
154 * (The identity of the PE associated with this Redistributor)
155 * CommonLPIAff [25:24] == 01
156 * (All Redistributors with the same Aff3 value must share an
157 * LPI Configuration table)
158 * Processor_Number [23:8] == X
159 * (A unique identifier for the PE)
161 * (GICR_CTLR.DPG* bits are supported)
163 * (This Redistributor is the highest-numbered Redistributor in
164 * a series of contiguous Redistributor pages)
166 * (direct injection of LPIs supported)
168 * (virtual LPIs not supported)
170 * (physical LPIs supported)
172 uint64_t affinity
= getAffinity();
173 int last
= cpuId
== (gic
->getSystem()->numContexts() - 1);
174 return (affinity
<< 32) | (1 << 24) | (cpuId
<< 8) |
175 (1 << 5) | (last
<< 4) | (1 << 3) | (1 << 0);
178 case GICR_WAKER
: // Wake Register
179 if (!distributor
->DS
&& !is_secure_access
) {
180 // RAZ/WI for non-secure accesses
184 if (peInLowPowerState
) {
185 return GICR_WAKER_ChildrenAsleep
| GICR_WAKER_ProcessorSleep
;
190 case GICR_PIDR0
: { // Peripheral ID0 Register
191 return 0x92; // Part number, bits[7:0]
194 case GICR_PIDR1
: { // Peripheral ID1 Register
195 uint8_t des_0
= 0xB; // JEP106 identification code, bits[3:0]
196 uint8_t part_1
= 0x4; // Part number, bits[11:8]
197 return (des_0
<< 4) | (part_1
<< 0);
200 case GICR_PIDR2
: { // Peripheral ID2 Register
201 uint8_t arch_rev
= 0x3; // 0x3 GICv3
202 uint8_t jedec
= 0x1; // JEP code
203 uint8_t des_1
= 0x3; // JEP106 identification code, bits[6:4]
204 return (arch_rev
<< 4) | (jedec
<< 3) | (des_1
<< 0);
207 case GICR_PIDR3
: // Peripheral ID3 Register
208 return 0x0; // Implementation defined
210 case GICR_PIDR4
: { // Peripheral ID4 Register
211 uint8_t size
= 0x4; // 64 KB software visible page
212 uint8_t des_2
= 0x4; // ARM implementation
213 return (size
<< 4) | (des_2
<< 0);
216 case GICR_PIDR5
: // Peripheral ID5 Register
217 case GICR_PIDR6
: // Peripheral ID6 Register
218 case GICR_PIDR7
: // Peripheral ID7 Register
221 case GICR_IGROUPR0
: { // Interrupt Group Register 0
224 if (!distributor
->DS
&& !is_secure_access
) {
225 // RAZ/WI for non-secure accesses
229 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
230 value
|= (irqGroup
[int_id
] << int_id
);
236 case GICR_ISENABLER0
: // Interrupt Set-Enable Register 0
237 case GICR_ICENABLER0
: { // Interrupt Clear-Enable Register 0
240 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
241 if (!distributor
->DS
&& !is_secure_access
) {
242 // RAZ/WI for non-secure accesses for secure interrupts
243 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
248 if (irqEnabled
[int_id
]) {
249 value
|= (1 << int_id
);
256 case GICR_ISPENDR0
: // Interrupt Set-Pending Register 0
257 case GICR_ICPENDR0
: { // Interrupt Clear-Pending Register 0
260 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
261 if (!distributor
->DS
&& !is_secure_access
) {
262 // RAZ/WI for non-secure accesses for secure interrupts
263 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
268 value
|= (irqPending
[int_id
] << int_id
);
274 case GICR_ISACTIVER0
: // Interrupt Set-Active Register 0
275 case GICR_ICACTIVER0
: { // Interrupt Clear-Active Register 0
278 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
279 if (!distributor
->DS
&& !is_secure_access
) {
280 // RAZ/WI for non-secure accesses for secure interrupts
281 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
286 value
|= irqActive
[int_id
] << int_id
;
292 case GICR_ICFGR0
: // SGI Configuration Register
293 case GICR_ICFGR1
: { // PPI Configuration Register
295 uint32_t first_int_id
= addr
== GICR_ICFGR0
? 0 : Gicv3::SGI_MAX
;
297 for (int i
= 0, int_id
= first_int_id
; i
< 32;
298 i
= i
+ 2, int_id
++) {
299 if (!distributor
->DS
&& !is_secure_access
) {
300 // RAZ/WI for non-secure accesses for secure interrupts
301 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
306 if (irqConfig
[int_id
] == Gicv3::INT_EDGE_TRIGGERED
) {
314 case GICR_IGRPMODR0
: { // Interrupt Group Modifier Register 0
317 if (distributor
->DS
) {
320 if (!is_secure_access
) {
321 // RAZ/WI for non-secure accesses
324 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
325 value
|= irqGrpmod
[int_id
] << int_id
;
333 case GICR_NSACR
: { // Non-secure Access Control Register
336 if (distributor
->DS
) {
340 if (!is_secure_access
) {
344 for (int i
= 0, int_id
= 0; i
< 8 * size
;
345 i
= i
+ 2, int_id
++) {
346 value
|= irqNsacr
[int_id
] << i
;
354 case GICR_PROPBASER
: // Redistributor Properties Base Address Register
355 // OuterCache, bits [58:56]
356 // 000 Memory type defined in InnerCache field
357 // Physical_Address, bits [51:12]
358 // Bits [51:12] of the physical address containing the LPI
359 // Configuration table
360 // Shareability, bits [11:10]
362 // InnerCache, bits [9:7]
364 // IDbits, bits [4:0]
365 // limited by GICD_TYPER.IDbits
366 return lpiConfigurationTablePtr
| lpiIDBits
;
368 // Redistributor LPI Pending Table Base Address Register
371 // Pending Table Zero
372 // OuterCache, bits [58:56]
373 // 000 Memory type defined in InnerCache field
374 // Physical_Address, bits [51:16]
375 // Bits [51:16] of the physical address containing the LPI Pending
377 // Shareability, bits [11:10]
379 // InnerCache, bits [9:7]
381 return lpiPendingTablePtr
;
383 // Redistributor Synchronize Register
388 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr
);
394 Gicv3Redistributor::write(Addr addr
, uint64_t data
, size_t size
,
395 bool is_secure_access
)
397 if (GICR_IPRIORITYR
.contains(addr
)) { // Interrupt Priority Registers
398 int first_intid
= addr
- GICR_IPRIORITYR
.start();
400 for (int i
= 0, int_id
= first_intid
; i
< size
; i
++, int_id
++) {
401 uint8_t prio
= bits(data
, (i
+ 1) * 8 - 1, (i
* 8));
403 if (!distributor
->DS
&& !is_secure_access
) {
404 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
405 // RAZ/WI for non-secure accesses for secure interrupts
409 prio
= 0x80 | (prio
>> 1);
413 irqPriority
[int_id
] = prio
;
414 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
415 "int_id %d priority %d\n", int_id
, irqPriority
[int_id
]);
423 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
424 EnableLPIs
= data
& GICR_CTLR_ENABLE_LPIS
;
425 DPG1S
= data
& GICR_CTLR_DPG1S
;
426 DPG1NS
= data
& GICR_CTLR_DPG1NS
;
427 DPG0
= data
& GICR_CTLR_DPG0
;
431 case GICR_WAKER
: // Wake Register
432 if (!distributor
->DS
&& !is_secure_access
) {
433 // RAZ/WI for non-secure accesses
437 if (not peInLowPowerState
and
438 (data
& GICR_WAKER_ProcessorSleep
)) {
439 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
440 "PE entering in low power state\n");
441 } else if (peInLowPowerState
and
442 not(data
& GICR_WAKER_ProcessorSleep
)) {
443 DPRINTF(GIC
, "Gicv3Redistributor::write(): powering up PE\n");
446 peInLowPowerState
= data
& GICR_WAKER_ProcessorSleep
;
449 case GICR_IGROUPR0
: // Interrupt Group Register 0
450 if (!distributor
->DS
&& !is_secure_access
) {
451 // RAZ/WI for non-secure accesses
455 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
456 irqGroup
[int_id
] = data
& (1 << int_id
) ? 1 : 0;
457 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
458 "int_id %d group %d\n", int_id
, irqGroup
[int_id
]);
463 case GICR_ISENABLER0
: // Interrupt Set-Enable Register 0
464 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
465 if (!distributor
->DS
&& !is_secure_access
) {
466 // RAZ/WI for non-secure accesses for secure interrupts
467 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
472 bool enable
= data
& (1 << int_id
) ? 1 : 0;
475 irqEnabled
[int_id
] = true;
478 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
479 "int_id %d enable %i\n", int_id
, irqEnabled
[int_id
]);
484 case GICR_ICENABLER0
: // Interrupt Clear-Enable Register 0
485 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
486 if (!distributor
->DS
&& !is_secure_access
) {
487 // RAZ/WI for non-secure accesses for secure interrupts
488 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
493 bool disable
= data
& (1 << int_id
) ? 1 : 0;
496 irqEnabled
[int_id
] = false;
499 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
500 "int_id %d enable %i\n", int_id
, irqEnabled
[int_id
]);
505 case GICR_ISPENDR0
: // Interrupt Set-Pending Register 0
506 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
507 if (!distributor
->DS
&& !is_secure_access
) {
508 // RAZ/WI for non-secure accesses for secure interrupts
509 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
514 bool pending
= data
& (1 << int_id
) ? 1 : 0;
517 DPRINTF(GIC
, "Gicv3Redistributor::write() "
518 "(GICR_ISPENDR0): int_id %d (PPI) "
519 "pending bit set\n", int_id
);
520 irqPending
[int_id
] = true;
524 updateAndInformCPUInterface();
527 case GICR_ICPENDR0
:// Interrupt Clear-Pending Register 0
528 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
529 if (!distributor
->DS
&& !is_secure_access
) {
530 // RAZ/WI for non-secure accesses for secure interrupts
531 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
536 bool clear
= data
& (1 << int_id
) ? 1 : 0;
539 irqPending
[int_id
] = false;
545 case GICR_ISACTIVER0
: // Interrupt Set-Active Register 0
546 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
547 if (!distributor
->DS
&& !is_secure_access
) {
548 // RAZ/WI for non-secure accesses for secure interrupts
549 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
554 bool activate
= data
& (1 << int_id
) ? 1 : 0;
557 if (!irqActive
[int_id
]) {
558 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
559 "int_id %d active set\n", int_id
);
562 irqActive
[int_id
] = true;
568 case GICR_ICACTIVER0
: // Interrupt Clear-Active Register 0
569 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
570 if (!distributor
->DS
&& !is_secure_access
) {
571 // RAZ/WI for non-secure accesses for secure interrupts
572 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
577 bool clear
= data
& (1 << int_id
) ? 1 : 0;
580 if (irqActive
[int_id
]) {
581 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
582 "int_id %d active cleared\n", int_id
);
585 irqActive
[int_id
] = false;
591 case GICR_ICFGR1
: { // PPI Configuration Register
592 int first_intid
= Gicv3::SGI_MAX
;
594 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
;
595 i
= i
+ 2, int_id
++) {
596 if (!distributor
->DS
&& !is_secure_access
) {
597 // RAZ/WI for non-secure accesses for secure interrupts
598 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
603 irqConfig
[int_id
] = data
& (0x2 << i
) ?
604 Gicv3::INT_EDGE_TRIGGERED
:
605 Gicv3::INT_LEVEL_SENSITIVE
;
606 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
607 "int_id %d (PPI) config %d\n",
608 int_id
, irqConfig
[int_id
]);
614 case GICR_IGRPMODR0
: { // Interrupt Group Modifier Register 0
615 if (distributor
->DS
) {
616 // RAZ/WI if secutiry disabled
618 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
619 if (!is_secure_access
) {
620 // RAZ/WI for non-secure accesses
624 irqGrpmod
[int_id
] = data
& (1 << int_id
);
631 case GICR_NSACR
: { // Non-secure Access Control Register
632 if (distributor
->DS
) {
635 if (!is_secure_access
) {
638 for (int i
= 0, int_id
= 0; i
< 8 * size
;
639 i
= i
+ 2, int_id
++) {
640 irqNsacr
[int_id
] = (data
>> i
) & 0x3;
648 case GICR_SETLPIR
: // Set LPI Pending Register
649 setClrLPI(data
, true);
652 case GICR_CLRLPIR
: // Clear LPI Pending Register
653 setClrLPI(data
, false);
656 case GICR_PROPBASER
: { // Redistributor Properties Base Address Register
657 // OuterCache, bits [58:56]
658 // 000 Memory type defined in InnerCache field
659 // Physical_Address, bits [51:12]
660 // Bits [51:12] of the physical address containing the LPI
661 // Configuration table
662 // Shareability, bits [11:10]
664 // InnerCache, bits [9:7]
666 // IDbits, bits [4:0]
667 // limited by GICD_TYPER.IDbits (= 0xf)
668 lpiConfigurationTablePtr
= data
& 0xFFFFFFFFFF000;
669 lpiIDBits
= data
& 0x1f;
671 // 0xf here matches the value of GICD_TYPER.IDbits.
672 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
674 if (lpiIDBits
> 0xf) {
681 // Redistributor LPI Pending Table Base Address Register
684 // Pending Table Zero
685 // OuterCache, bits [58:56]
686 // 000 Memory type defined in InnerCache field
687 // Physical_Address, bits [51:16]
688 // Bits [51:16] of the physical address containing the LPI Pending
690 // Shareability, bits [11:10]
692 // InnerCache, bits [9:7]
694 lpiPendingTablePtr
= data
& 0xFFFFFFFFF0000;
697 case GICR_INVLPIR
: { // Redistributor Invalidate LPI Register
698 // Do nothing: no caching supported
702 case GICR_INVALLR
: { // Redistributor Invalidate All Register
703 // Do nothing: no caching supported
708 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr
);
714 Gicv3Redistributor::sendPPInt(uint32_t int_id
)
716 assert((int_id
>= Gicv3::SGI_MAX
) &&
717 (int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
));
718 irqPending
[int_id
] = true;
719 DPRINTF(GIC
, "Gicv3Redistributor::sendPPInt(): "
720 "int_id %d (PPI) pending bit set\n", int_id
);
721 updateAndInformCPUInterface();
725 Gicv3Redistributor::sendSGI(uint32_t int_id
, Gicv3::GroupId group
, bool ns
)
727 assert(int_id
< Gicv3::SGI_MAX
);
728 Gicv3::GroupId int_group
= getIntGroup(int_id
);
730 // asked for secure group 1
731 // configured as group 0
733 if (int_group
== Gicv3::G0S
&& group
== Gicv3::G1S
) {
737 if (group
== Gicv3::G0S
and int_group
!= Gicv3::G0S
) {
741 if (ns
&& distributor
->DS
== 0) {
742 int nsaccess
= irqNsacr
[int_id
];
744 if ((int_group
== Gicv3::G0S
&& nsaccess
< 1) ||
745 (int_group
== Gicv3::G1S
&& nsaccess
< 2)) {
750 irqPending
[int_id
] = true;
751 DPRINTF(GIC
, "Gicv3ReDistributor::sendSGI(): "
752 "int_id %d (SGI) pending bit set\n", int_id
);
753 updateAndInformCPUInterface();
757 Gicv3Redistributor::intStatus(uint32_t int_id
) const
759 assert(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
);
761 if (irqPending
[int_id
]) {
762 if (irqActive
[int_id
]) {
763 return Gicv3::INT_ACTIVE_PENDING
;
766 return Gicv3::INT_PENDING
;
767 } else if (irqActive
[int_id
]) {
768 return Gicv3::INT_ACTIVE
;
770 return Gicv3::INT_INACTIVE
;
775 * Recalculate the highest priority pending interrupt after a
776 * change to redistributor state.
779 Gicv3Redistributor::update()
781 bool new_hppi
= false;
783 for (int int_id
= 0; int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
; int_id
++) {
784 Gicv3::GroupId int_group
= getIntGroup(int_id
);
785 bool group_enabled
= distributor
->groupEnabled(int_group
);
787 if (irqPending
[int_id
] && irqEnabled
[int_id
] &&
788 !irqActive
[int_id
] && group_enabled
) {
789 if ((irqPriority
[int_id
] < cpuInterface
->hppi
.prio
) ||
791 * Multiple pending ints with same priority.
792 * Implementation choice which one to signal.
793 * Our implementation selects the one with the lower id.
795 (irqPriority
[int_id
] == cpuInterface
->hppi
.prio
&&
796 int_id
< cpuInterface
->hppi
.intid
)) {
797 cpuInterface
->hppi
.intid
= int_id
;
798 cpuInterface
->hppi
.prio
= irqPriority
[int_id
];
799 cpuInterface
->hppi
.group
= int_group
;
807 ThreadContext
* tc
= gic
->getSystem()->getThreadContext(cpuId
);
809 const uint32_t largest_lpi_id
= 1 << (lpiIDBits
+ 1);
810 const uint32_t number_lpis
= largest_lpi_id
- SMALLEST_LPI_ID
+ 1;
812 uint8_t lpi_pending_table
[largest_lpi_id
/ 8];
813 uint8_t lpi_config_table
[number_lpis
];
815 tc
->getPhysProxy().readBlob(lpiPendingTablePtr
,
816 (uint8_t *) lpi_pending_table
,
817 sizeof(lpi_pending_table
));
819 tc
->getPhysProxy().readBlob(lpiConfigurationTablePtr
,
820 (uint8_t*) lpi_config_table
,
821 sizeof(lpi_config_table
));
823 for (int lpi_id
= SMALLEST_LPI_ID
; lpi_id
< largest_lpi_id
;
825 uint32_t lpi_pending_entry_byte
= lpi_id
/ 8;
826 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
827 bool lpi_is_pending
= lpi_pending_table
[lpi_pending_entry_byte
] &
828 1 << lpi_pending_entry_bit_position
;
829 uint32_t lpi_configuration_entry_index
= lpi_id
- SMALLEST_LPI_ID
;
831 LPIConfigurationTableEntry config_entry
=
832 lpi_config_table
[lpi_configuration_entry_index
];
834 bool lpi_is_enable
= config_entry
.enable
;
836 // LPIs are always Non-secure Group 1 interrupts,
837 // in a system where two Security states are enabled.
838 Gicv3::GroupId lpi_group
= Gicv3::G1NS
;
839 bool group_enabled
= distributor
->groupEnabled(lpi_group
);
841 if (lpi_is_pending
&& lpi_is_enable
&& group_enabled
) {
842 uint8_t lpi_priority
= config_entry
.priority
<< 2;
844 if ((lpi_priority
< cpuInterface
->hppi
.prio
) ||
845 (lpi_priority
== cpuInterface
->hppi
.prio
&&
846 lpi_id
< cpuInterface
->hppi
.intid
)) {
847 cpuInterface
->hppi
.intid
= lpi_id
;
848 cpuInterface
->hppi
.prio
= lpi_priority
;
849 cpuInterface
->hppi
.group
= lpi_group
;
856 if (!new_hppi
&& cpuInterface
->hppi
.prio
!= 0xff &&
857 (cpuInterface
->hppi
.intid
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
||
858 cpuInterface
->hppi
.intid
> SMALLEST_LPI_ID
)) {
859 distributor
->fullUpdate();
864 Gicv3Redistributor::setClrLPI(uint64_t data
, bool set
)
867 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
868 // GICR_CTLR.EnableLPIs == 0.
872 uint32_t lpi_id
= data
& 0xffffffff;
873 uint32_t largest_lpi_id
= 1 << (lpiIDBits
+ 1);
875 if (lpi_id
> largest_lpi_id
) {
876 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
877 // pINTID value specifies an unimplemented LPI.
881 Addr lpi_pending_entry_ptr
= lpiPendingTablePtr
+ (lpi_id
/ 8);
882 uint8_t lpi_pending_entry
;
883 ThreadContext
* tc
= gic
->getSystem()->getThreadContext(cpuId
);
884 tc
->getPhysProxy().readBlob(lpi_pending_entry_ptr
,
885 (uint8_t*) &lpi_pending_entry
,
886 sizeof(lpi_pending_entry
));
887 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
888 bool is_set
= lpi_pending_entry
& (1 << lpi_pending_entry_bit_position
);
892 // Writes to GICR_SETLPIR have not effect if the pINTID field
893 // corresponds to an LPI that is already pending.
897 lpi_pending_entry
|= 1 << (lpi_pending_entry_bit_position
);
900 // Writes to GICR_SETLPIR have not effect if the pINTID field
901 // corresponds to an LPI that is not pending.
905 lpi_pending_entry
&= ~(1 << (lpi_pending_entry_bit_position
));
908 tc
->getPhysProxy().writeBlob(lpi_pending_entry_ptr
,
909 (uint8_t*) &lpi_pending_entry
,
910 sizeof(lpi_pending_entry
));
911 updateAndInformCPUInterface();
915 Gicv3Redistributor::updateAndInformCPUInterface()
918 cpuInterface
->update();
922 Gicv3Redistributor::getIntGroup(int int_id
) const
924 assert(int_id
< (Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
));
926 if (distributor
->DS
) {
927 if (irqGroup
[int_id
] == 0) {
933 if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 0) {
935 } else if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 1) {
937 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 0) {
939 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 1) {
948 Gicv3Redistributor::activateIRQ(uint32_t int_id
)
950 irqPending
[int_id
] = false;
951 irqActive
[int_id
] = true;
955 Gicv3Redistributor::deactivateIRQ(uint32_t int_id
)
957 irqActive
[int_id
] = false;
961 Gicv3Redistributor::getAffinity() const
963 ThreadContext
* tc
= gic
->getSystem()->getThreadContext(cpuId
);
964 uint64_t mpidr
= getMPIDR(gic
->getSystem(), tc
);
966 * Aff3 = MPIDR[39:32]
967 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
968 * Aff2 = MPIDR[23:16]
971 * affinity = Aff3.Aff2.Aff1.Aff0
973 uint64_t affinity
= ((mpidr
& 0xff00000000) >> 8) | (mpidr
& (0xffffff));
978 Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group
) const
980 if (peInLowPowerState
) {
984 if (!distributor
->groupEnabled(group
)) {
988 if ((group
== Gicv3::G1S
) && DPG1S
) {
992 if ((group
== Gicv3::G1NS
) && DPG1NS
) {
996 if ((group
== Gicv3::G0S
) && DPG0
) {
1004 Gicv3Redistributor::serialize(CheckpointOut
& cp
) const
1006 SERIALIZE_SCALAR(peInLowPowerState
);
1007 SERIALIZE_CONTAINER(irqGroup
);
1008 SERIALIZE_CONTAINER(irqEnabled
);
1009 SERIALIZE_CONTAINER(irqPending
);
1010 SERIALIZE_CONTAINER(irqActive
);
1011 SERIALIZE_CONTAINER(irqPriority
);
1012 SERIALIZE_CONTAINER(irqConfig
);
1013 SERIALIZE_CONTAINER(irqGrpmod
);
1014 SERIALIZE_CONTAINER(irqNsacr
);
1015 SERIALIZE_SCALAR(DPG1S
);
1016 SERIALIZE_SCALAR(DPG1NS
);
1017 SERIALIZE_SCALAR(DPG0
);
1018 SERIALIZE_SCALAR(EnableLPIs
);
1019 SERIALIZE_SCALAR(lpiConfigurationTablePtr
);
1020 SERIALIZE_SCALAR(lpiIDBits
);
1021 SERIALIZE_SCALAR(lpiPendingTablePtr
);
1025 Gicv3Redistributor::unserialize(CheckpointIn
& cp
)
1027 UNSERIALIZE_SCALAR(peInLowPowerState
);
1028 UNSERIALIZE_CONTAINER(irqGroup
);
1029 UNSERIALIZE_CONTAINER(irqEnabled
);
1030 UNSERIALIZE_CONTAINER(irqPending
);
1031 UNSERIALIZE_CONTAINER(irqActive
);
1032 UNSERIALIZE_CONTAINER(irqPriority
);
1033 UNSERIALIZE_CONTAINER(irqConfig
);
1034 UNSERIALIZE_CONTAINER(irqGrpmod
);
1035 UNSERIALIZE_CONTAINER(irqNsacr
);
1036 UNSERIALIZE_SCALAR(DPG1S
);
1037 UNSERIALIZE_SCALAR(DPG1NS
);
1038 UNSERIALIZE_SCALAR(DPG0
);
1039 UNSERIALIZE_SCALAR(EnableLPIs
);
1040 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr
);
1041 UNSERIALIZE_SCALAR(lpiIDBits
);
1042 UNSERIALIZE_SCALAR(lpiPendingTablePtr
);