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"
47 #include "mem/fs_translating_port_proxy.hh"
49 const AddrRange
Gicv3Redistributor::GICR_IPRIORITYR(SGI_base
+ 0x0400,
52 Gicv3Redistributor::Gicv3Redistributor(Gicv3
* gic
, uint32_t cpu_id
)
55 cpuInterface(nullptr),
58 peInLowPowerState(true),
59 irqGroup(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
60 irqEnabled(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, false),
61 irqPending(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, false),
62 irqActive(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, false),
63 irqPriority(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
64 irqConfig(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, Gicv3::INT_EDGE_TRIGGERED
),
65 irqGrpmod(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
66 irqNsacr(Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
, 0),
71 lpiConfigurationTablePtr(0),
73 lpiPendingTablePtr(0),
74 addrRangeSize(gic
->params()->gicv4
? 0x40000 : 0x20000)
79 Gicv3Redistributor::init()
81 distributor
= gic
->getDistributor();
82 cpuInterface
= gic
->getCPUInterface(cpuId
);
84 memProxy
= &gic
->getSystem()->physProxy
;
88 Gicv3Redistributor::read(Addr addr
, size_t size
, bool is_secure_access
)
90 if (GICR_IPRIORITYR
.contains(addr
)) { // Interrupt Priority Registers
92 int first_intid
= addr
- GICR_IPRIORITYR
.start();
94 for (int i
= 0, int_id
= first_intid
; i
< size
; i
++, int_id
++) {
95 uint8_t prio
= irqPriority
[int_id
];
97 if (!distributor
->DS
&& !is_secure_access
) {
98 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
99 // RAZ/WI for non-secure accesses for secure interrupts
103 prio
= (prio
<< 1) & 0xff;
107 value
|= prio
<< (i
* 8);
114 case GICR_CTLR
: { // Control Register
118 value
|= GICR_CTLR_DPG1S
;
122 value
|= GICR_CTLR_DPG1NS
;
126 value
|= GICR_CTLR_DPG0
;
130 value
|= GICR_CTLR_ENABLE_LPIS
;
136 case GICR_IIDR
: // Implementer Identification Register
137 //return 0x43b; // r0p0 GIC-500
140 case GICR_TYPER
: { // Type Register
142 * Affinity_Value [63:32] == X
143 * (The identity of the PE associated with this Redistributor)
144 * CommonLPIAff [25:24] == 01
145 * (All Redistributors with the same Aff3 value must share an
146 * LPI Configuration table)
147 * Processor_Number [23:8] == X
148 * (A unique identifier for the PE)
150 * (GICR_CTLR.DPG* bits are supported)
152 * (This Redistributor is the highest-numbered Redistributor in
153 * a series of contiguous Redistributor pages)
155 * (direct injection of LPIs supported)
157 * (virtual LPIs not supported)
159 * (physical LPIs supported)
161 uint64_t affinity
= getAffinity();
162 int last
= cpuId
== (gic
->getSystem()->numContexts() - 1);
163 return (affinity
<< 32) | (1 << 24) | (cpuId
<< 8) |
164 (1 << 5) | (last
<< 4) | (1 << 3) | (1 << 0);
167 case GICR_WAKER
: // Wake Register
168 if (!distributor
->DS
&& !is_secure_access
) {
169 // RAZ/WI for non-secure accesses
173 if (peInLowPowerState
) {
174 return GICR_WAKER_ChildrenAsleep
| GICR_WAKER_ProcessorSleep
;
179 case GICR_PIDR0
: { // Peripheral ID0 Register
180 return 0x92; // Part number, bits[7:0]
183 case GICR_PIDR1
: { // Peripheral ID1 Register
184 uint8_t des_0
= 0xB; // JEP106 identification code, bits[3:0]
185 uint8_t part_1
= 0x4; // Part number, bits[11:8]
186 return (des_0
<< 4) | (part_1
<< 0);
189 case GICR_PIDR2
: { // Peripheral ID2 Register
190 uint8_t arch_rev
= 0x3; // 0x3 GICv3
191 uint8_t jedec
= 0x1; // JEP code
192 uint8_t des_1
= 0x3; // JEP106 identification code, bits[6:4]
193 return (arch_rev
<< 4) | (jedec
<< 3) | (des_1
<< 0);
196 case GICR_PIDR3
: // Peripheral ID3 Register
197 return 0x0; // Implementation defined
199 case GICR_PIDR4
: { // Peripheral ID4 Register
200 uint8_t size
= 0x4; // 64 KB software visible page
201 uint8_t des_2
= 0x4; // ARM implementation
202 return (size
<< 4) | (des_2
<< 0);
205 case GICR_PIDR5
: // Peripheral ID5 Register
206 case GICR_PIDR6
: // Peripheral ID6 Register
207 case GICR_PIDR7
: // Peripheral ID7 Register
210 case GICR_IGROUPR0
: { // Interrupt Group Register 0
213 if (!distributor
->DS
&& !is_secure_access
) {
214 // RAZ/WI for non-secure accesses
218 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
219 value
|= (irqGroup
[int_id
] << int_id
);
225 case GICR_ISENABLER0
: // Interrupt Set-Enable Register 0
226 case GICR_ICENABLER0
: { // Interrupt Clear-Enable Register 0
229 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
230 if (!distributor
->DS
&& !is_secure_access
) {
231 // RAZ/WI for non-secure accesses for secure interrupts
232 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
237 if (irqEnabled
[int_id
]) {
238 value
|= (1 << int_id
);
245 case GICR_ISPENDR0
: // Interrupt Set-Pending Register 0
246 case GICR_ICPENDR0
: { // Interrupt Clear-Pending Register 0
249 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
250 if (!distributor
->DS
&& !is_secure_access
) {
251 // RAZ/WI for non-secure accesses for secure interrupts
252 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
257 value
|= (irqPending
[int_id
] << int_id
);
263 case GICR_ISACTIVER0
: // Interrupt Set-Active Register 0
264 case GICR_ICACTIVER0
: { // Interrupt Clear-Active Register 0
267 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
268 if (!distributor
->DS
&& !is_secure_access
) {
269 // RAZ/WI for non-secure accesses for secure interrupts
270 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
275 value
|= irqActive
[int_id
] << int_id
;
281 case GICR_ICFGR0
: // SGI Configuration Register
282 case GICR_ICFGR1
: { // PPI Configuration Register
284 uint32_t first_int_id
= addr
== GICR_ICFGR0
? 0 : Gicv3::SGI_MAX
;
286 for (int i
= 0, int_id
= first_int_id
; i
< 32;
287 i
= i
+ 2, int_id
++) {
288 if (!distributor
->DS
&& !is_secure_access
) {
289 // RAZ/WI for non-secure accesses for secure interrupts
290 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
295 if (irqConfig
[int_id
] == Gicv3::INT_EDGE_TRIGGERED
) {
303 case GICR_IGRPMODR0
: { // Interrupt Group Modifier Register 0
306 if (distributor
->DS
) {
309 if (!is_secure_access
) {
310 // RAZ/WI for non-secure accesses
313 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
314 value
|= irqGrpmod
[int_id
] << int_id
;
322 case GICR_NSACR
: { // Non-secure Access Control Register
325 if (distributor
->DS
) {
329 if (!is_secure_access
) {
333 for (int i
= 0, int_id
= 0; i
< 8 * size
;
334 i
= i
+ 2, int_id
++) {
335 value
|= irqNsacr
[int_id
] << i
;
343 case GICR_PROPBASER
: // Redistributor Properties Base Address Register
344 // OuterCache, bits [58:56]
345 // 000 Memory type defined in InnerCache field
346 // Physical_Address, bits [51:12]
347 // Bits [51:12] of the physical address containing the LPI
348 // Configuration table
349 // Shareability, bits [11:10]
351 // InnerCache, bits [9:7]
353 // IDbits, bits [4:0]
354 // limited by GICD_TYPER.IDbits
355 return lpiConfigurationTablePtr
| lpiIDBits
;
357 // Redistributor LPI Pending Table Base Address Register
360 // Pending Table Zero
361 // OuterCache, bits [58:56]
362 // 000 Memory type defined in InnerCache field
363 // Physical_Address, bits [51:16]
364 // Bits [51:16] of the physical address containing the LPI Pending
366 // Shareability, bits [11:10]
368 // InnerCache, bits [9:7]
370 return lpiPendingTablePtr
;
372 // Redistributor Synchronize Register
377 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr
);
383 Gicv3Redistributor::write(Addr addr
, uint64_t data
, size_t size
,
384 bool is_secure_access
)
386 if (GICR_IPRIORITYR
.contains(addr
)) { // Interrupt Priority Registers
387 int first_intid
= addr
- GICR_IPRIORITYR
.start();
389 for (int i
= 0, int_id
= first_intid
; i
< size
; i
++, int_id
++) {
390 uint8_t prio
= bits(data
, (i
+ 1) * 8 - 1, (i
* 8));
392 if (!distributor
->DS
&& !is_secure_access
) {
393 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
394 // RAZ/WI for non-secure accesses for secure interrupts
398 prio
= 0x80 | (prio
>> 1);
402 irqPriority
[int_id
] = prio
;
403 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
404 "int_id %d priority %d\n", int_id
, irqPriority
[int_id
]);
412 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
413 EnableLPIs
= data
& GICR_CTLR_ENABLE_LPIS
;
414 DPG1S
= data
& GICR_CTLR_DPG1S
;
415 DPG1NS
= data
& GICR_CTLR_DPG1NS
;
416 DPG0
= data
& GICR_CTLR_DPG0
;
420 case GICR_WAKER
: // Wake Register
421 if (!distributor
->DS
&& !is_secure_access
) {
422 // RAZ/WI for non-secure accesses
426 if (not peInLowPowerState
and
427 (data
& GICR_WAKER_ProcessorSleep
)) {
428 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
429 "PE entering in low power state\n");
430 } else if (peInLowPowerState
and
431 not(data
& GICR_WAKER_ProcessorSleep
)) {
432 DPRINTF(GIC
, "Gicv3Redistributor::write(): powering up PE\n");
435 peInLowPowerState
= data
& GICR_WAKER_ProcessorSleep
;
438 case GICR_IGROUPR0
: // Interrupt Group Register 0
439 if (!distributor
->DS
&& !is_secure_access
) {
440 // RAZ/WI for non-secure accesses
444 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
445 irqGroup
[int_id
] = data
& (1 << int_id
) ? 1 : 0;
446 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
447 "int_id %d group %d\n", int_id
, irqGroup
[int_id
]);
452 case GICR_ISENABLER0
: // Interrupt Set-Enable Register 0
453 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
454 if (!distributor
->DS
&& !is_secure_access
) {
455 // RAZ/WI for non-secure accesses for secure interrupts
456 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
461 bool enable
= data
& (1 << int_id
) ? 1 : 0;
464 irqEnabled
[int_id
] = true;
467 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
468 "int_id %d enable %i\n", int_id
, irqEnabled
[int_id
]);
473 case GICR_ICENABLER0
: // Interrupt Clear-Enable Register 0
474 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
475 if (!distributor
->DS
&& !is_secure_access
) {
476 // RAZ/WI for non-secure accesses for secure interrupts
477 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
482 bool disable
= data
& (1 << int_id
) ? 1 : 0;
485 irqEnabled
[int_id
] = false;
488 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
489 "int_id %d enable %i\n", int_id
, irqEnabled
[int_id
]);
494 case GICR_ISPENDR0
: // Interrupt Set-Pending Register 0
495 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
496 if (!distributor
->DS
&& !is_secure_access
) {
497 // RAZ/WI for non-secure accesses for secure interrupts
498 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
503 bool pending
= data
& (1 << int_id
) ? 1 : 0;
506 DPRINTF(GIC
, "Gicv3Redistributor::write() "
507 "(GICR_ISPENDR0): int_id %d (PPI) "
508 "pending bit set\n", int_id
);
509 irqPending
[int_id
] = true;
516 case GICR_ICPENDR0
:// Interrupt Clear-Pending Register 0
517 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
518 if (!distributor
->DS
&& !is_secure_access
) {
519 // RAZ/WI for non-secure accesses for secure interrupts
520 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
525 bool clear
= data
& (1 << int_id
) ? 1 : 0;
528 irqPending
[int_id
] = false;
534 case GICR_ISACTIVER0
: // Interrupt Set-Active Register 0
535 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
536 if (!distributor
->DS
&& !is_secure_access
) {
537 // RAZ/WI for non-secure accesses for secure interrupts
538 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
543 bool activate
= data
& (1 << int_id
) ? 1 : 0;
546 if (!irqActive
[int_id
]) {
547 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
548 "int_id %d active set\n", int_id
);
551 irqActive
[int_id
] = true;
557 case GICR_ICACTIVER0
: // Interrupt Clear-Active Register 0
558 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
559 if (!distributor
->DS
&& !is_secure_access
) {
560 // RAZ/WI for non-secure accesses for secure interrupts
561 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
566 bool clear
= data
& (1 << int_id
) ? 1 : 0;
569 if (irqActive
[int_id
]) {
570 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
571 "int_id %d active cleared\n", int_id
);
574 irqActive
[int_id
] = false;
580 case GICR_ICFGR0
: // SGI Configuration Register
583 case GICR_ICFGR1
: { // PPI Configuration Register
584 int first_intid
= Gicv3::SGI_MAX
;
586 for (int i
= 0, int_id
= first_intid
; i
< 8 * size
;
587 i
= i
+ 2, int_id
++) {
588 if (!distributor
->DS
&& !is_secure_access
) {
589 // RAZ/WI for non-secure accesses for secure interrupts
590 if (getIntGroup(int_id
) != Gicv3::G1NS
) {
595 irqConfig
[int_id
] = data
& (0x2 << i
) ?
596 Gicv3::INT_EDGE_TRIGGERED
:
597 Gicv3::INT_LEVEL_SENSITIVE
;
598 DPRINTF(GIC
, "Gicv3Redistributor::write(): "
599 "int_id %d (PPI) config %d\n",
600 int_id
, irqConfig
[int_id
]);
606 case GICR_IGRPMODR0
: { // Interrupt Group Modifier Register 0
607 if (distributor
->DS
) {
608 // RAZ/WI if secutiry disabled
610 for (int int_id
= 0; int_id
< 8 * size
; int_id
++) {
611 if (!is_secure_access
) {
612 // RAZ/WI for non-secure accesses
616 irqGrpmod
[int_id
] = data
& (1 << int_id
);
623 case GICR_NSACR
: { // Non-secure Access Control Register
624 if (distributor
->DS
) {
627 if (!is_secure_access
) {
630 for (int i
= 0, int_id
= 0; i
< 8 * size
;
631 i
= i
+ 2, int_id
++) {
632 irqNsacr
[int_id
] = (data
>> i
) & 0x3;
640 case GICR_SETLPIR
: // Set LPI Pending Register
641 setClrLPI(data
, true);
644 case GICR_CLRLPIR
: // Clear LPI Pending Register
645 setClrLPI(data
, false);
648 case GICR_PROPBASER
: { // Redistributor Properties Base Address Register
649 // OuterCache, bits [58:56]
650 // 000 Memory type defined in InnerCache field
651 // Physical_Address, bits [51:12]
652 // Bits [51:12] of the physical address containing the LPI
653 // Configuration table
654 // Shareability, bits [11:10]
656 // InnerCache, bits [9:7]
658 // IDbits, bits [4:0]
659 // limited by GICD_TYPER.IDbits (= 0xf)
660 lpiConfigurationTablePtr
= data
& 0xFFFFFFFFFF000;
661 lpiIDBits
= data
& 0x1f;
663 // 0xf here matches the value of GICD_TYPER.IDbits.
664 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
666 if (lpiIDBits
> 0xf) {
673 // Redistributor LPI Pending Table Base Address Register
676 // Pending Table Zero
677 // OuterCache, bits [58:56]
678 // 000 Memory type defined in InnerCache field
679 // Physical_Address, bits [51:16]
680 // Bits [51:16] of the physical address containing the LPI Pending
682 // Shareability, bits [11:10]
684 // InnerCache, bits [9:7]
686 lpiPendingTablePtr
= data
& 0xFFFFFFFFF0000;
689 case GICR_INVLPIR
: { // Redistributor Invalidate LPI Register
690 // Do nothing: no caching supported
694 case GICR_INVALLR
: { // Redistributor Invalidate All Register
695 // Do nothing: no caching supported
700 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr
);
706 Gicv3Redistributor::sendPPInt(uint32_t int_id
)
708 assert((int_id
>= Gicv3::SGI_MAX
) &&
709 (int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
));
710 irqPending
[int_id
] = true;
711 DPRINTF(GIC
, "Gicv3Redistributor::sendPPInt(): "
712 "int_id %d (PPI) pending bit set\n", int_id
);
717 Gicv3Redistributor::sendSGI(uint32_t int_id
, Gicv3::GroupId group
, bool ns
)
719 assert(int_id
< Gicv3::SGI_MAX
);
720 Gicv3::GroupId int_group
= getIntGroup(int_id
);
722 bool forward
= false;
725 // Non-Secure EL1 and EL2 access
726 int nsaccess
= irqNsacr
[int_id
];
727 if (int_group
== Gicv3::G0S
) {
729 forward
= distributor
->DS
|| (nsaccess
>= 1);
731 } else if (int_group
== Gicv3::G1S
) {
732 forward
= ((group
== Gicv3::G1S
|| group
== Gicv3::G1NS
) &&
736 forward
= group
== Gicv3::G1NS
;
739 // Secure EL1 and EL3 access
740 forward
= (group
== int_group
) ||
741 (group
== Gicv3::G1S
&& int_group
== Gicv3::G0S
&&
745 if (!forward
) return;
747 irqPending
[int_id
] = true;
748 DPRINTF(GIC
, "Gicv3ReDistributor::sendSGI(): "
749 "int_id %d (SGI) pending bit set\n", int_id
);
754 Gicv3Redistributor::intStatus(uint32_t int_id
) const
756 assert(int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
);
758 if (irqPending
[int_id
]) {
759 if (irqActive
[int_id
]) {
760 return Gicv3::INT_ACTIVE_PENDING
;
763 return Gicv3::INT_PENDING
;
764 } else if (irqActive
[int_id
]) {
765 return Gicv3::INT_ACTIVE
;
767 return Gicv3::INT_INACTIVE
;
772 Gicv3Redistributor::updateDistributor()
774 distributor
->update();
778 * Recalculate the highest priority pending interrupt after a
779 * change to redistributor state.
782 Gicv3Redistributor::update()
784 for (int int_id
= 0; int_id
< Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
; int_id
++) {
785 Gicv3::GroupId int_group
= getIntGroup(int_id
);
786 bool group_enabled
= distributor
->groupEnabled(int_group
);
788 if (irqPending
[int_id
] && irqEnabled
[int_id
] &&
789 !irqActive
[int_id
] && group_enabled
) {
790 if ((irqPriority
[int_id
] < cpuInterface
->hppi
.prio
) ||
792 * Multiple pending ints with same priority.
793 * Implementation choice which one to signal.
794 * Our implementation selects the one with the lower id.
796 (irqPriority
[int_id
] == cpuInterface
->hppi
.prio
&&
797 int_id
< cpuInterface
->hppi
.intid
)) {
798 cpuInterface
->hppi
.intid
= int_id
;
799 cpuInterface
->hppi
.prio
= irqPriority
[int_id
];
800 cpuInterface
->hppi
.group
= int_group
;
808 const uint32_t largest_lpi_id
= 1 << (lpiIDBits
+ 1);
809 const uint32_t number_lpis
= largest_lpi_id
- SMALLEST_LPI_ID
+ 1;
811 uint8_t lpi_pending_table
[largest_lpi_id
/ 8];
812 uint8_t lpi_config_table
[number_lpis
];
814 memProxy
->readBlob(lpiPendingTablePtr
,
816 sizeof(lpi_pending_table
));
818 memProxy
->readBlob(lpiConfigurationTablePtr
,
820 sizeof(lpi_config_table
));
822 for (int lpi_id
= SMALLEST_LPI_ID
; lpi_id
< largest_lpi_id
;
824 uint32_t lpi_pending_entry_byte
= lpi_id
/ 8;
825 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
826 bool lpi_is_pending
= lpi_pending_table
[lpi_pending_entry_byte
] &
827 1 << lpi_pending_entry_bit_position
;
828 uint32_t lpi_configuration_entry_index
= lpi_id
- SMALLEST_LPI_ID
;
830 LPIConfigurationTableEntry config_entry
=
831 lpi_config_table
[lpi_configuration_entry_index
];
833 bool lpi_is_enable
= config_entry
.enable
;
835 // LPIs are always Non-secure Group 1 interrupts,
836 // in a system where two Security states are enabled.
837 Gicv3::GroupId lpi_group
= Gicv3::G1NS
;
838 bool group_enabled
= distributor
->groupEnabled(lpi_group
);
840 if (lpi_is_pending
&& lpi_is_enable
&& group_enabled
) {
841 uint8_t lpi_priority
= config_entry
.priority
<< 2;
843 if ((lpi_priority
< cpuInterface
->hppi
.prio
) ||
844 (lpi_priority
== cpuInterface
->hppi
.prio
&&
845 lpi_id
< cpuInterface
->hppi
.intid
)) {
846 cpuInterface
->hppi
.intid
= lpi_id
;
847 cpuInterface
->hppi
.prio
= lpi_priority
;
848 cpuInterface
->hppi
.group
= lpi_group
;
854 cpuInterface
->update();
858 Gicv3Redistributor::readEntryLPI(uint32_t lpi_id
)
860 Addr lpi_pending_entry_ptr
= lpiPendingTablePtr
+ (lpi_id
/ 8);
862 uint8_t lpi_pending_entry
;
863 memProxy
->readBlob(lpi_pending_entry_ptr
,
865 sizeof(lpi_pending_entry
));
867 return lpi_pending_entry
;
871 Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id
, uint8_t lpi_pending_entry
)
873 Addr lpi_pending_entry_ptr
= lpiPendingTablePtr
+ (lpi_id
/ 8);
875 memProxy
->writeBlob(lpi_pending_entry_ptr
,
877 sizeof(lpi_pending_entry
));
881 Gicv3Redistributor::isPendingLPI(uint32_t lpi_id
)
883 // Fetch the LPI pending entry from memory
884 uint8_t lpi_pending_entry
= readEntryLPI(lpi_id
);
886 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
887 bool is_set
= lpi_pending_entry
& (1 << lpi_pending_entry_bit_position
);
893 Gicv3Redistributor::setClrLPI(uint64_t data
, bool set
)
896 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
897 // GICR_CTLR.EnableLPIs == 0.
901 uint32_t lpi_id
= data
& 0xffffffff;
902 uint32_t largest_lpi_id
= 1 << (lpiIDBits
+ 1);
904 if (lpi_id
> largest_lpi_id
) {
905 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
906 // pINTID value specifies an unimplemented LPI.
910 // Fetch the LPI pending entry from memory
911 uint8_t lpi_pending_entry
= readEntryLPI(lpi_id
);
913 uint8_t lpi_pending_entry_bit_position
= lpi_id
% 8;
914 bool is_set
= lpi_pending_entry
& (1 << lpi_pending_entry_bit_position
);
918 // Writes to GICR_SETLPIR have not effect if the pINTID field
919 // corresponds to an LPI that is already pending.
923 lpi_pending_entry
|= 1 << (lpi_pending_entry_bit_position
);
926 // Writes to GICR_SETLPIR have not effect if the pINTID field
927 // corresponds to an LPI that is not pending.
931 lpi_pending_entry
&= ~(1 << (lpi_pending_entry_bit_position
));
933 // Remove the pending state from the cpu interface
934 cpuInterface
->resetHppi(lpi_id
);
937 writeEntryLPI(lpi_id
, lpi_pending_entry
);
943 Gicv3Redistributor::getIntGroup(int int_id
) const
945 assert(int_id
< (Gicv3::SGI_MAX
+ Gicv3::PPI_MAX
));
947 if (distributor
->DS
) {
948 if (irqGroup
[int_id
] == 0) {
954 if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 0) {
956 } else if (irqGrpmod
[int_id
] == 0 && irqGroup
[int_id
] == 1) {
958 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 0) {
960 } else if (irqGrpmod
[int_id
] == 1 && irqGroup
[int_id
] == 1) {
969 Gicv3Redistributor::activateIRQ(uint32_t int_id
)
971 irqPending
[int_id
] = false;
972 irqActive
[int_id
] = true;
976 Gicv3Redistributor::deactivateIRQ(uint32_t int_id
)
978 irqActive
[int_id
] = false;
982 Gicv3Redistributor::getAffinity() const
984 ThreadContext
* tc
= gic
->getSystem()->getThreadContext(cpuId
);
985 uint64_t mpidr
= getMPIDR(gic
->getSystem(), tc
);
987 * Aff3 = MPIDR[39:32]
988 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
989 * Aff2 = MPIDR[23:16]
992 * affinity = Aff3.Aff2.Aff1.Aff0
994 uint64_t affinity
= ((mpidr
& 0xff00000000) >> 8) | (mpidr
& (0xffffff));
999 Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group
) const
1001 if (peInLowPowerState
) {
1005 if (!distributor
->groupEnabled(group
)) {
1009 if ((group
== Gicv3::G1S
) && DPG1S
) {
1013 if ((group
== Gicv3::G1NS
) && DPG1NS
) {
1017 if ((group
== Gicv3::G0S
) && DPG0
) {
1025 Gicv3Redistributor::serialize(CheckpointOut
& cp
) const
1027 SERIALIZE_SCALAR(peInLowPowerState
);
1028 SERIALIZE_CONTAINER(irqGroup
);
1029 SERIALIZE_CONTAINER(irqEnabled
);
1030 SERIALIZE_CONTAINER(irqPending
);
1031 SERIALIZE_CONTAINER(irqActive
);
1032 SERIALIZE_CONTAINER(irqPriority
);
1033 SERIALIZE_CONTAINER(irqConfig
);
1034 SERIALIZE_CONTAINER(irqGrpmod
);
1035 SERIALIZE_CONTAINER(irqNsacr
);
1036 SERIALIZE_SCALAR(DPG1S
);
1037 SERIALIZE_SCALAR(DPG1NS
);
1038 SERIALIZE_SCALAR(DPG0
);
1039 SERIALIZE_SCALAR(EnableLPIs
);
1040 SERIALIZE_SCALAR(lpiConfigurationTablePtr
);
1041 SERIALIZE_SCALAR(lpiIDBits
);
1042 SERIALIZE_SCALAR(lpiPendingTablePtr
);
1046 Gicv3Redistributor::unserialize(CheckpointIn
& cp
)
1048 UNSERIALIZE_SCALAR(peInLowPowerState
);
1049 UNSERIALIZE_CONTAINER(irqGroup
);
1050 UNSERIALIZE_CONTAINER(irqEnabled
);
1051 UNSERIALIZE_CONTAINER(irqPending
);
1052 UNSERIALIZE_CONTAINER(irqActive
);
1053 UNSERIALIZE_CONTAINER(irqPriority
);
1054 UNSERIALIZE_CONTAINER(irqConfig
);
1055 UNSERIALIZE_CONTAINER(irqGrpmod
);
1056 UNSERIALIZE_CONTAINER(irqNsacr
);
1057 UNSERIALIZE_SCALAR(DPG1S
);
1058 UNSERIALIZE_SCALAR(DPG1NS
);
1059 UNSERIALIZE_SCALAR(DPG0
);
1060 UNSERIALIZE_SCALAR(EnableLPIs
);
1061 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr
);
1062 UNSERIALIZE_SCALAR(lpiIDBits
);
1063 UNSERIALIZE_SCALAR(lpiPendingTablePtr
);