2 * Copyright (c) 2019 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "dev/arm/gic_v3_redistributor.hh"
43 #include "arch/arm/utility.hh"
44 #include "debug/GIC.hh"
45 #include "dev/arm/gic_v3_cpu_interface.hh"
46 #include "dev/arm/gic_v3_distributor.hh"
48 const AddrRange
Gicv3Redistributor::GICR_IPRIORITYR(SGI_base
+ 0x0400,
51 Gicv3Redistributor::Gicv3Redistributor(Gicv3
* gic
, uint32_t cpu_id
)
54 cpuInterface(nullptr),
57 peInLowPowerState(true),
58 irqGroup(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
59 irqEnabled(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, false),
60 irqPending(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, false),
61 irqActive(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, false),
62 irqPriority(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
63 irqConfig(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, Gicv3::INT_EDGE_TRIGGERED
),
64 irqGrpmod(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
65 irqNsacr(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
70 lpiConfigurationTablePtr(0),
72 lpiPendingTablePtr(0),
73 addrRangeSize(gic
->params()->gicv4
? 0x40000 : 0x20000)
78 Gicv3Redistributor::init()
80 distributor
= gic
->getDistributor();
81 cpuInterface
= gic
->getCPUInterface(cpuId
);
83 memProxy
= &gic
->getSystem()->physProxy
;
87 Gicv3Redistributor::read(Addr addr
, size_t size
, bool is_secure_access
)
89 if (GICR_IPRIORITYR
.contains(addr
)) { // Interrupt Priority Registers
91 int first_intid
= addr
- GICR_IPRIORITYR
.start();
93 for (int i
= 0, int_id
= first_intid
; i
< size
; i
++, int_id
++) {
94 uint8_t prio
= irqPriority
[int_id
];
96 if (!distributor
->DS
&& !is_secure_access
) {
97 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
98 // RAZ/WI for non-secure accesses for secure interrupts
102 prio
= (prio
<< 1) & 0xff;
106 value
|= prio
<< (i
* 8);
113 case GICR_CTLR
: { // Control Register
117 value
|= GICR_CTLR_DPG1S
;
121 value
|= GICR_CTLR_DPG1NS
;
125 value
|= GICR_CTLR_DPG0
;
129 value
|= GICR_CTLR_ENABLE_LPIS
;
135 case GICR_IIDR
: // Implementer Identification Register
136 //return 0x43b; // r0p0 GIC-500
139 case GICR_TYPER
: { // Type Register
141 * Affinity_Value [63:32] == X
142 * (The identity of the PE associated with this Redistributor)
143 * CommonLPIAff [25:24] == 01
144 * (All Redistributors with the same Aff3 value must share an
145 * LPI Configuration table)
146 * Processor_Number [23:8] == X
147 * (A unique identifier for the PE)
149 * (GICR_CTLR.DPG* bits are supported)
151 * (This Redistributor is the highest-numbered Redistributor in
152 * a series of contiguous Redistributor pages)
154 * (direct injection of LPIs supported)
156 * (virtual LPIs not supported)
158 * (physical LPIs supported)
160 uint64_t affinity
= getAffinity();
161 int last
= cpuId
== (gic
->getSystem()->threads
.size() - 1);
162 return (affinity
<< 32) | (1 << 24) | (cpuId
<< 8) |
163 (1 << 5) | (last
<< 4) | (1 << 3) | (1 << 0);
166 case GICR_WAKER
: // Wake Register
167 if (!distributor
->DS
&& !is_secure_access
) {
168 // RAZ/WI for non-secure accesses
172 if (peInLowPowerState
) {
173 return GICR_WAKER_ChildrenAsleep
| GICR_WAKER_ProcessorSleep
;
178 case GICR_PIDR0
: { // Peripheral ID0 Register
179 return 0x92; // Part number, bits[7:0]
182 case GICR_PIDR1
: { // Peripheral ID1 Register
183 uint8_t des_0
= 0xB; // JEP106 identification code, bits[3:0]
184 uint8_t part_1
= 0x4; // Part number, bits[11:8]
185 return (des_0
<< 4) | (part_1
<< 0);
188 case GICR_PIDR2
: { // Peripheral ID2 Register
189 uint8_t arch_rev
= 0x3; // 0x3 GICv3
190 uint8_t jedec
= 0x1; // JEP code
191 uint8_t des_1
= 0x3; // JEP106 identification code, bits[6:4]
192 return (arch_rev
<< 4) | (jedec
<< 3) | (des_1
<< 0);
195 case GICR_PIDR3
: // Peripheral ID3 Register
196 return 0x0; // Implementation defined
198 case GICR_PIDR4
: { // Peripheral ID4 Register
199 uint8_t size
= 0x4; // 64 KB software visible page
200 uint8_t des_2
= 0x4; // ARM implementation
201 return (size
<< 4) | (des_2
<< 0);
204 case GICR_PIDR5
: // Peripheral ID5 Register
205 case GICR_PIDR6
: // Peripheral ID6 Register
206 case GICR_PIDR7
: // Peripheral ID7 Register
209 case GICR_IGROUPR0
: { // Interrupt Group Register 0
212 if (!distributor
->DS
&& !is_secure_access
) {
213 // RAZ/WI for non-secure accesses
217 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
218 value
|= (irqGroup
[int_id
] << int_id
);
224 case GICR_ISENABLER0
: // Interrupt Set-Enable Register 0
225 case GICR_ICENABLER0
: { // Interrupt Clear-Enable Register 0
228 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
229 if (!distributor
->DS
&& !is_secure_access
) {
230 // RAZ/WI for non-secure accesses for secure interrupts
231 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
236 if (irqEnabled
[int_id
]) {
237 value
|= (1 << int_id
);
244 case GICR_ISPENDR0
: // Interrupt Set-Pending Register 0
245 case GICR_ICPENDR0
: { // Interrupt Clear-Pending Register 0
248 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
249 if (!distributor
->DS
&& !is_secure_access
) {
250 // RAZ/WI for non-secure accesses for secure interrupts
251 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
256 value
|= (irqPending
[int_id
] << int_id
);
262 case GICR_ISACTIVER0
: // Interrupt Set-Active Register 0
263 case GICR_ICACTIVER0
: { // Interrupt Clear-Active Register 0
266 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
267 if (!distributor
->DS
&& !is_secure_access
) {
268 // RAZ/WI for non-secure accesses for secure interrupts
269 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
274 value
|= irqActive
[int_id
] << int_id
;
280 case GICR_ICFGR0
: // SGI Configuration Register
281 case GICR_ICFGR1
: { // PPI Configuration Register
283 uint32_t first_int_id
= addr
== GICR_ICFGR0
? 0 : Gicv3::SGI_MAX
;
285 for (int i
= 0, int_id
= first_int_id
; i
< 32;
286 i
= i
+ 2, int_id
++) {
287 if (!distributor
->DS
&& !is_secure_access
) {
288 // RAZ/WI for non-secure accesses for secure interrupts
289 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
294 if (irqConfig
[int_id
] == Gicv3::INT_EDGE_TRIGGERED
) {
302 case GICR_IGRPMODR0
: { // Interrupt Group Modifier Register 0
305 if (distributor
->DS
) {
308 if (!is_secure_access
) {
309 // RAZ/WI for non-secure accesses
312 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
313 value
|= irqGrpmod
[int_id
] << int_id
;
321 case GICR_NSACR
: { // Non-secure Access Control Register
324 if (distributor
->DS
) {
328 if (!is_secure_access
) {
332 for (int i
= 0, int_id
= 0; i
< 8 * size
;
333 i
= i
+ 2, int_id
++) {
334 value
|= irqNsacr
[int_id
] << i
;
342 case GICR_PROPBASER
: // Redistributor Properties Base Address Register
343 // OuterCache, bits [58:56]
344 // 000 Memory type defined in InnerCache field
345 // Physical_Address, bits [51:12]
346 // Bits [51:12] of the physical address containing the LPI
347 // Configuration table
348 // Shareability, bits [11:10]
350 // InnerCache, bits [9:7]
352 // IDbits, bits [4:0]
353 // limited by GICD_TYPER.IDbits
354 return lpiConfigurationTablePtr
| lpiIDBits
;
356 // Redistributor LPI Pending Table Base Address Register
359 // Pending Table Zero
360 // OuterCache, bits [58:56]
361 // 000 Memory type defined in InnerCache field
362 // Physical_Address, bits [51:16]
363 // Bits [51:16] of the physical address containing the LPI Pending
365 // Shareability, bits [11:10]
367 // InnerCache, bits [9:7]
369 return lpiPendingTablePtr
;
371 // Redistributor Synchronize Register
376 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr
);
382 Gicv3Redistributor::write(Addr addr
, uint64_t data
, size_t size
,
383 bool is_secure_access
)
385 if (GICR_IPRIORITYR
.contains(addr
)) { // Interrupt Priority Registers
386 int first_intid
= addr
- GICR_IPRIORITYR
.start();
388 for (int i
= 0, int_id
= first_intid
; i
< size
; i
++, int_id
++) {
389 uint8_t prio
= bits(data
, (i
+ 1) * 8 - 1, (i
* 8));
391 if (!distributor
->DS
&& !is_secure_access
) {
392 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
393 // RAZ/WI for non-secure accesses for secure interrupts
397 prio
= 0x80 | (prio
>> 1);
401 irqPriority
[int_id
] = prio
;
402 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
403 "int_id %d priority %d\n", int_id
, irqPriority
[int_id
]);
411 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
412 EnableLPIs
= data
& GICR_CTLR_ENABLE_LPIS
;
413 DPG1S
= data
& GICR_CTLR_DPG1S
;
414 DPG1NS
= data
& GICR_CTLR_DPG1NS
;
415 DPG0
= data
& GICR_CTLR_DPG0
;
419 case GICR_WAKER
: // Wake Register
421 if (!distributor
->DS
&& !is_secure_access
) {
422 // RAZ/WI for non-secure accesses
426 bool pe_was_low_power
= peInLowPowerState
;
427 peInLowPowerState
= data
& GICR_WAKER_ProcessorSleep
;
428 if (!pe_was_low_power
&& peInLowPowerState
) {
429 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
430 "PE entering in low power state\n");
432 } else if (pe_was_low_power
&& !peInLowPowerState
) {
433 DPRINTF(GIC
, "Gicv3Redistributor::write(): powering up PE\n");
434 cpuInterface
->deassertWakeRequest();
440 case GICR_IGROUPR0
: // Interrupt Group Register 0
441 if (!distributor
->DS
&& !is_secure_access
) {
442 // RAZ/WI for non-secure accesses
446 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
447 irqGroup
[int_id
] = data
& (1 << int_id
) ? 1 : 0;
448 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
449 "int_id %d group %d\n", int_id
, irqGroup
[int_id
]);
454 case GICR_ISENABLER0
: // Interrupt Set-Enable Register 0
455 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
456 if (!distributor
->DS
&& !is_secure_access
) {
457 // RAZ/WI for non-secure accesses for secure interrupts
458 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
463 bool enable
= data
& (1 << int_id
) ? 1 : 0;
466 irqEnabled
[int_id
] = true;
469 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
470 "int_id %d enable %i\n", int_id
, irqEnabled
[int_id
]);
475 case GICR_ICENABLER0
: // Interrupt Clear-Enable Register 0
476 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
477 if (!distributor
->DS
&& !is_secure_access
) {
478 // RAZ/WI for non-secure accesses for secure interrupts
479 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
484 bool disable
= data
& (1 << int_id
) ? 1 : 0;
487 irqEnabled
[int_id
] = false;
490 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
491 "int_id %d enable %i\n", int_id
, irqEnabled
[int_id
]);
496 case GICR_ISPENDR0
: // Interrupt Set-Pending Register 0
497 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
498 if (!distributor
->DS
&& !is_secure_access
) {
499 // RAZ/WI for non-secure accesses for secure interrupts
500 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
505 bool pending
= data
& (1 << int_id
) ? 1 : 0;
508 DPRINTF(GIC
, "Gicv3Redistributor::write() "
509 "(GICR_ISPENDR0): int_id %d (PPI) "
510 "pending bit set\n", int_id
);
511 irqPending
[int_id
] = true;
518 case GICR_ICPENDR0
:// Interrupt Clear-Pending Register 0
519 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
520 if (!distributor
->DS
&& !is_secure_access
) {
521 // RAZ/WI for non-secure accesses for secure interrupts
522 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
527 bool clear
= data
& (1 << int_id
) ? 1 : 0;
530 irqPending
[int_id
] = false;
536 case GICR_ISACTIVER0
: // Interrupt Set-Active Register 0
537 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
538 if (!distributor
->DS
&& !is_secure_access
) {
539 // RAZ/WI for non-secure accesses for secure interrupts
540 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
545 bool activate
= data
& (1 << int_id
) ? 1 : 0;
548 if (!irqActive
[int_id
]) {
549 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
550 "int_id %d active set\n", int_id
);
553 irqActive
[int_id
] = true;
559 case GICR_ICACTIVER0
: // Interrupt Clear-Active Register 0
560 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
561 if (!distributor
->DS
&& !is_secure_access
) {
562 // RAZ/WI for non-secure accesses for secure interrupts
563 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
568 bool clear
= data
& (1 << int_id
) ? 1 : 0;
571 if (irqActive
[int_id
]) {
572 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
573 "int_id %d active cleared\n", int_id
);
576 irqActive
[int_id
] = false;
582 case GICR_ICFGR0
: // SGI Configuration Register
585 case GICR_ICFGR1
: { // PPI Configuration Register
586 int first_intid
= Gicv3::SGI_MAX
;
588 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
;
589 i
= i
+ 2, int_id
++) {
590 if (!distributor
->DS
&& !is_secure_access
) {
591 // RAZ/WI for non-secure accesses for secure interrupts
592 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
597 irqConfig
[int_id
] = data
& (0x2 << i
) ?
598 Gicv3::INT_EDGE_TRIGGERED
:
599 Gicv3::INT_LEVEL_SENSITIVE
;
600 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
601 "int_id %d (PPI) config %d\n",
602 int_id
, irqConfig
[int_id
]);
608 case GICR_IGRPMODR0
: { // Interrupt Group Modifier Register 0
609 if (distributor
->DS
) {
610 // RAZ/WI if secutiry disabled
612 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
613 if (!is_secure_access
) {
614 // RAZ/WI for non-secure accesses
618 irqGrpmod
[int_id
] = data
& (1 << int_id
);
625 case GICR_NSACR
: { // Non-secure Access Control Register
626 if (distributor
->DS
) {
629 if (!is_secure_access
) {
632 for (int i
= 0, int_id
= 0; i
< 8 * size
;
633 i
= i
+ 2, int_id
++) {
634 irqNsacr
[int_id
] = (data
>> i
) & 0x3;
642 case GICR_SETLPIR
: // Set LPI Pending Register
643 setClrLPI(data
, true);
646 case GICR_CLRLPIR
: // Clear LPI Pending Register
647 setClrLPI(data
, false);
650 case GICR_PROPBASER
: { // Redistributor Properties Base Address Register
651 // OuterCache, bits [58:56]
652 // 000 Memory type defined in InnerCache field
653 // Physical_Address, bits [51:12]
654 // Bits [51:12] of the physical address containing the LPI
655 // Configuration table
656 // Shareability, bits [11:10]
658 // InnerCache, bits [9:7]
660 // IDbits, bits [4:0]
661 // limited by GICD_TYPER.IDbits (= 0xf)
662 lpiConfigurationTablePtr
= data
& 0xFFFFFFFFFF000;
663 lpiIDBits
= data
& 0x1f;
665 // 0xf here matches the value of GICD_TYPER.IDbits.
666 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
668 if (lpiIDBits
> 0xf) {
675 // Redistributor LPI Pending Table Base Address Register
678 // Pending Table Zero
679 // OuterCache, bits [58:56]
680 // 000 Memory type defined in InnerCache field
681 // Physical_Address, bits [51:16]
682 // Bits [51:16] of the physical address containing the LPI Pending
684 // Shareability, bits [11:10]
686 // InnerCache, bits [9:7]
688 lpiPendingTablePtr
= data
& 0xFFFFFFFFF0000;
691 case GICR_INVLPIR
: { // Redistributor Invalidate LPI Register
692 // Do nothing: no caching supported
696 case GICR_INVALLR
: { // Redistributor Invalidate All Register
697 // Do nothing: no caching supported
702 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr
);
708 Gicv3Redistributor::sendPPInt(uint32_t int_id
)
710 assert((int_id
>= Gicv3::SGI_MAX
) &&
711 (int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
));
712 irqPending
[int_id
] = true;
713 DPRINTF(GIC
, "Gicv3Redistributor::sendPPInt(): "
714 "int_id %d (PPI) pending bit set\n", int_id
);
719 Gicv3Redistributor::sendSGI(uint32_t int_id
, Gicv3::GroupId group
, bool ns
)
721 assert(int_id
< Gicv3::SGI_MAX
);
722 Gicv3::GroupId int_group
= getIntGroup(int_id
);
724 bool forward
= false;
727 // Non-Secure EL1 and EL2 access
728 int nsaccess
= irqNsacr
[int_id
];
729 if (int_group
== Gicv3::G0S
) {
731 forward
= distributor
->DS
|| (nsaccess
>= 1);
733 } else if (int_group
== Gicv3::G1S
) {
734 forward
= ((group
== Gicv3::G1S
|| group
== Gicv3::G1NS
) &&
738 forward
= group
== Gicv3::G1NS
;
741 // Secure EL1 and EL3 access
742 forward
= (group
== int_group
) ||
743 (group
== Gicv3::G1S
&& int_group
== Gicv3::G0S
&&
747 if (!forward
) return;
749 irqPending
[int_id
] = true;
750 DPRINTF(GIC
, "Gicv3ReDistributor::sendSGI(): "
751 "int_id %d (SGI) pending bit set\n", int_id
);
756 Gicv3Redistributor::intStatus(uint32_t int_id
) const
758 assert(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
);
760 if (irqPending
[int_id
]) {
761 if (irqActive
[int_id
]) {
762 return Gicv3::INT_ACTIVE_PENDING
;
765 return Gicv3::INT_PENDING
;
766 } else if (irqActive
[int_id
]) {
767 return Gicv3::INT_ACTIVE
;
769 return Gicv3::INT_INACTIVE
;
774 Gicv3Redistributor::updateDistributor()
776 distributor
->update();
780 * Recalculate the highest priority pending interrupt after a
781 * change to redistributor state.
784 Gicv3Redistributor::update()
786 for (int int_id
= 0; int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
; int_id
++) {
787 Gicv3::GroupId int_group
= getIntGroup(int_id
);
788 bool group_enabled
= distributor
->groupEnabled(int_group
);
790 if (irqPending
[int_id
] && irqEnabled
[int_id
] &&
791 !irqActive
[int_id
] && group_enabled
) {
792 if ((irqPriority
[int_id
] < cpuInterface
->hppi
.prio
) ||
794 * Multiple pending ints with same priority.
795 * Implementation choice which one to signal.
796 * Our implementation selects the one with the lower id.
798 (irqPriority
[int_id
] == cpuInterface
->hppi
.prio
&&
799 int_id
< cpuInterface
->hppi
.intid
)) {
800 cpuInterface
->hppi
.intid
= int_id
;
801 cpuInterface
->hppi
.prio
= irqPriority
[int_id
];
802 cpuInterface
->hppi
.group
= int_group
;
810 const uint32_t largest_lpi_id
= 1 << (lpiIDBits
+ 1);
811 const uint32_t number_lpis
= largest_lpi_id
- SMALLEST_LPI_ID
+ 1;
813 uint8_t lpi_pending_table
[largest_lpi_id
/ 8];
814 uint8_t lpi_config_table
[number_lpis
];
816 memProxy
->readBlob(lpiPendingTablePtr
,
818 sizeof(lpi_pending_table
));
820 memProxy
->readBlob(lpiConfigurationTablePtr
,
822 sizeof(lpi_config_table
));
824 for (int lpi_id
= SMALLEST_LPI_ID
; lpi_id
< largest_lpi_id
;
826 uint32_t lpi_pending_entry_byte
= lpi_id
/ 8;
827 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
828 bool lpi_is_pending
= lpi_pending_table
[lpi_pending_entry_byte
] &
829 1 << lpi_pending_entry_bit_position
;
830 uint32_t lpi_configuration_entry_index
= lpi_id
- SMALLEST_LPI_ID
;
832 LPIConfigurationTableEntry config_entry
=
833 lpi_config_table
[lpi_configuration_entry_index
];
835 bool lpi_is_enable
= config_entry
.enable
;
837 // LPIs are always Non-secure Group 1 interrupts,
838 // in a system where two Security states are enabled.
839 Gicv3::GroupId lpi_group
= Gicv3::G1NS
;
840 bool group_enabled
= distributor
->groupEnabled(lpi_group
);
842 if (lpi_is_pending
&& lpi_is_enable
&& group_enabled
) {
843 uint8_t lpi_priority
= config_entry
.priority
<< 2;
845 if ((lpi_priority
< cpuInterface
->hppi
.prio
) ||
846 (lpi_priority
== cpuInterface
->hppi
.prio
&&
847 lpi_id
< cpuInterface
->hppi
.intid
)) {
848 cpuInterface
->hppi
.intid
= lpi_id
;
849 cpuInterface
->hppi
.prio
= lpi_priority
;
850 cpuInterface
->hppi
.group
= lpi_group
;
856 if (peInLowPowerState
) {
857 if (cpuInterface
->havePendingInterrupts()) {
858 cpuInterface
->assertWakeRequest();
859 cpuInterface
->clearPendingInterrupts();
862 cpuInterface
->update();
867 Gicv3Redistributor::readEntryLPI(uint32_t lpi_id
)
869 Addr lpi_pending_entry_ptr
= lpiPendingTablePtr
+ (lpi_id
/ 8);
871 uint8_t lpi_pending_entry
;
872 memProxy
->readBlob(lpi_pending_entry_ptr
,
874 sizeof(lpi_pending_entry
));
876 return lpi_pending_entry
;
880 Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id
, uint8_t lpi_pending_entry
)
882 Addr lpi_pending_entry_ptr
= lpiPendingTablePtr
+ (lpi_id
/ 8);
884 memProxy
->writeBlob(lpi_pending_entry_ptr
,
886 sizeof(lpi_pending_entry
));
890 Gicv3Redistributor::isPendingLPI(uint32_t lpi_id
)
892 // Fetch the LPI pending entry from memory
893 uint8_t lpi_pending_entry
= readEntryLPI(lpi_id
);
895 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
896 bool is_set
= lpi_pending_entry
& (1 << lpi_pending_entry_bit_position
);
902 Gicv3Redistributor::setClrLPI(uint64_t data
, bool set
)
905 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
906 // GICR_CTLR.EnableLPIs == 0.
910 uint32_t lpi_id
= data
& 0xffffffff;
911 uint32_t largest_lpi_id
= 1 << (lpiIDBits
+ 1);
913 if (lpi_id
> largest_lpi_id
) {
914 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
915 // pINTID value specifies an unimplemented LPI.
919 // Fetch the LPI pending entry from memory
920 uint8_t lpi_pending_entry
= readEntryLPI(lpi_id
);
922 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
923 bool is_set
= lpi_pending_entry
& (1 << lpi_pending_entry_bit_position
);
927 // Writes to GICR_SETLPIR have not effect if the pINTID field
928 // corresponds to an LPI that is already pending.
932 lpi_pending_entry
|= 1 << (lpi_pending_entry_bit_position
);
935 // Writes to GICR_SETLPIR have not effect if the pINTID field
936 // corresponds to an LPI that is not pending.
940 lpi_pending_entry
&= ~(1 << (lpi_pending_entry_bit_position
));
942 // Remove the pending state from the cpu interface
943 cpuInterface
->resetHppi(lpi_id
);
946 writeEntryLPI(lpi_id
, lpi_pending_entry
);
952 Gicv3Redistributor::getIntGroup(int int_id
) const
954 assert(int_id
< (Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
));
956 if (distributor
->DS
) {
957 if (irqGroup
[int_id
] == 0) {
963 if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 0) {
965 } else if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 1) {
967 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 0) {
969 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 1) {
978 Gicv3Redistributor::activateIRQ(uint32_t int_id
)
980 irqPending
[int_id
] = false;
981 irqActive
[int_id
] = true;
985 Gicv3Redistributor::deactivateIRQ(uint32_t int_id
)
987 irqActive
[int_id
] = false;
991 Gicv3Redistributor::getAffinity() const
993 ThreadContext
*tc
= gic
->getSystem()->threads
[cpuId
];
994 uint64_t mpidr
= getMPIDR(gic
->getSystem(), tc
);
996 * Aff3 = MPIDR[39:32]
997 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
998 * Aff2 = MPIDR[23:16]
1001 * affinity = Aff3.Aff2.Aff1.Aff0
1003 uint64_t affinity
= ((mpidr
& 0xff00000000) >> 8) | (mpidr
& (0xffffff));
1008 Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group
) const
1010 if (peInLowPowerState
) {
1014 if (!distributor
->groupEnabled(group
)) {
1018 if ((group
== Gicv3::G1S
) && DPG1S
) {
1022 if ((group
== Gicv3::G1NS
) && DPG1NS
) {
1026 if ((group
== Gicv3::G0S
) && DPG0
) {
1034 Gicv3Redistributor::serialize(CheckpointOut
& cp
) const
1036 SERIALIZE_SCALAR(peInLowPowerState
);
1037 SERIALIZE_CONTAINER(irqGroup
);
1038 SERIALIZE_CONTAINER(irqEnabled
);
1039 SERIALIZE_CONTAINER(irqPending
);
1040 SERIALIZE_CONTAINER(irqActive
);
1041 SERIALIZE_CONTAINER(irqPriority
);
1042 SERIALIZE_CONTAINER(irqConfig
);
1043 SERIALIZE_CONTAINER(irqGrpmod
);
1044 SERIALIZE_CONTAINER(irqNsacr
);
1045 SERIALIZE_SCALAR(DPG1S
);
1046 SERIALIZE_SCALAR(DPG1NS
);
1047 SERIALIZE_SCALAR(DPG0
);
1048 SERIALIZE_SCALAR(EnableLPIs
);
1049 SERIALIZE_SCALAR(lpiConfigurationTablePtr
);
1050 SERIALIZE_SCALAR(lpiIDBits
);
1051 SERIALIZE_SCALAR(lpiPendingTablePtr
);
1055 Gicv3Redistributor::unserialize(CheckpointIn
& cp
)
1057 UNSERIALIZE_SCALAR(peInLowPowerState
);
1058 UNSERIALIZE_CONTAINER(irqGroup
);
1059 UNSERIALIZE_CONTAINER(irqEnabled
);
1060 UNSERIALIZE_CONTAINER(irqPending
);
1061 UNSERIALIZE_CONTAINER(irqActive
);
1062 UNSERIALIZE_CONTAINER(irqPriority
);
1063 UNSERIALIZE_CONTAINER(irqConfig
);
1064 UNSERIALIZE_CONTAINER(irqGrpmod
);
1065 UNSERIALIZE_CONTAINER(irqNsacr
);
1066 UNSERIALIZE_SCALAR(DPG1S
);
1067 UNSERIALIZE_SCALAR(DPG1NS
);
1068 UNSERIALIZE_SCALAR(DPG0
);
1069 UNSERIALIZE_SCALAR(EnableLPIs
);
1070 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr
);
1071 UNSERIALIZE_SCALAR(lpiIDBits
);
1072 UNSERIALIZE_SCALAR(lpiPendingTablePtr
);