gic_v3_redistributor.cc (14231:222f6512335e) gic_v3_redistributor.cc (14258:c75d22c32dec)
1/*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
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.
13 *
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
16 *
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.
27 *
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.
39 *
40 * Authors: Jairo Balart
41 */
42
43#include "dev/arm/gic_v3_redistributor.hh"
44
45#include "arch/arm/utility.hh"
46#include "debug/GIC.hh"
47#include "dev/arm/gic_v3_cpu_interface.hh"
48#include "dev/arm/gic_v3_distributor.hh"
49#include "mem/fs_translating_port_proxy.hh"
50
51const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
52 SGI_base + 0x041f);
53
54Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
55 : gic(gic),
56 distributor(nullptr),
57 cpuInterface(nullptr),
58 cpuId(cpu_id),
59 memProxy(nullptr),
1/*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
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.
13 *
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
16 *
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.
27 *
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.
39 *
40 * Authors: Jairo Balart
41 */
42
43#include "dev/arm/gic_v3_redistributor.hh"
44
45#include "arch/arm/utility.hh"
46#include "debug/GIC.hh"
47#include "dev/arm/gic_v3_cpu_interface.hh"
48#include "dev/arm/gic_v3_distributor.hh"
49#include "mem/fs_translating_port_proxy.hh"
50
51const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
52 SGI_base + 0x041f);
53
54Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
55 : gic(gic),
56 distributor(nullptr),
57 cpuInterface(nullptr),
58 cpuId(cpu_id),
59 memProxy(nullptr),
60 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
61 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
62 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
63 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
64 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
65 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
66 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
67 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
60 peInLowPowerState(true),
61 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
62 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
63 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
64 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
65 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
66 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX, Gicv3::INT_EDGE_TRIGGERED),
67 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
68 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
69 DPG1S(false),
70 DPG1NS(false),
71 DPG0(false),
72 EnableLPIs(false),
73 lpiConfigurationTablePtr(0),
74 lpiIDBits(0),
75 lpiPendingTablePtr(0),
68 addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
69{
70}
71
72void
73Gicv3Redistributor::init()
74{
75 distributor = gic->getDistributor();
76 cpuInterface = gic->getCPUInterface(cpuId);
77
78 memProxy = &gic->getSystem()->physProxy;
79}
80
76 addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
77{
78}
79
80void
81Gicv3Redistributor::init()
82{
83 distributor = gic->getDistributor();
84 cpuInterface = gic->getCPUInterface(cpuId);
85
86 memProxy = &gic->getSystem()->physProxy;
87}
88
81void
82Gicv3Redistributor::initState()
83{
84 reset();
85}
86
87void
88Gicv3Redistributor::reset()
89{
90 peInLowPowerState = true;
91 std::fill(irqGroup.begin(), irqGroup.end(), 0);
92 std::fill(irqEnabled.begin(), irqEnabled.end(), false);
93 std::fill(irqPending.begin(), irqPending.end(), false);
94 std::fill(irqActive.begin(), irqActive.end(), false);
95 std::fill(irqPriority.begin(), irqPriority.end(), 0);
96
97 // SGIs have edge-triggered behavior
98 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
99 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
100 }
101
102 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
103 std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
104 DPG1S = false;
105 DPG1NS = false;
106 DPG0 = false;
107 EnableLPIs = false;
108 lpiConfigurationTablePtr = 0;
109 lpiIDBits = 0;
110 lpiPendingTablePtr = 0;
111}
112
113uint64_t
114Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
115{
116 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
117 uint64_t value = 0;
118 int first_intid = addr - GICR_IPRIORITYR.start();
119
120 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
121 uint8_t prio = irqPriority[int_id];
122
123 if (!distributor->DS && !is_secure_access) {
124 if (getIntGroup(int_id) != Gicv3::G1NS) {
125 // RAZ/WI for non-secure accesses for secure interrupts
126 continue;
127 } else {
128 // NS view
129 prio = (prio << 1) & 0xff;
130 }
131 }
132
133 value |= prio << (i * 8);
134 }
135
136 return value;
137 }
138
139 switch (addr) {
140 case GICR_CTLR: { // Control Register
141 uint64_t value = 0;
142
143 if (DPG1S) {
144 value |= GICR_CTLR_DPG1S;
145 }
146
147 if (DPG1NS) {
148 value |= GICR_CTLR_DPG1NS;
149 }
150
151 if (DPG0) {
152 value |= GICR_CTLR_DPG0;
153 }
154
155 if (EnableLPIs) {
156 value |= GICR_CTLR_ENABLE_LPIS;
157 }
158
159 return value;
160 }
161
162 case GICR_IIDR: // Implementer Identification Register
163 //return 0x43b; // r0p0 GIC-500
164 return 0;
165
166 case GICR_TYPER: { // Type Register
167 /*
168 * Affinity_Value [63:32] == X
169 * (The identity of the PE associated with this Redistributor)
170 * CommonLPIAff [25:24] == 01
171 * (All Redistributors with the same Aff3 value must share an
172 * LPI Configuration table)
173 * Processor_Number [23:8] == X
174 * (A unique identifier for the PE)
175 * DPGS [5] == 1
176 * (GICR_CTLR.DPG* bits are supported)
177 * Last [4] == X
178 * (This Redistributor is the highest-numbered Redistributor in
179 * a series of contiguous Redistributor pages)
180 * DirectLPI [3] == 1
181 * (direct injection of LPIs supported)
182 * VLPIS [1] == 0
183 * (virtual LPIs not supported)
184 * PLPIS [0] == 1
185 * (physical LPIs supported)
186 */
187 uint64_t affinity = getAffinity();
188 int last = cpuId == (gic->getSystem()->numContexts() - 1);
189 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
190 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
191 }
192
193 case GICR_WAKER: // Wake Register
194 if (!distributor->DS && !is_secure_access) {
195 // RAZ/WI for non-secure accesses
196 return 0;
197 }
198
199 if (peInLowPowerState) {
200 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
201 } else {
202 return 0;
203 }
204
205 case GICR_PIDR0: { // Peripheral ID0 Register
206 return 0x92; // Part number, bits[7:0]
207 }
208
209 case GICR_PIDR1: { // Peripheral ID1 Register
210 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
211 uint8_t part_1 = 0x4; // Part number, bits[11:8]
212 return (des_0 << 4) | (part_1 << 0);
213 }
214
215 case GICR_PIDR2: { // Peripheral ID2 Register
216 uint8_t arch_rev = 0x3; // 0x3 GICv3
217 uint8_t jedec = 0x1; // JEP code
218 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
219 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
220 }
221
222 case GICR_PIDR3: // Peripheral ID3 Register
223 return 0x0; // Implementation defined
224
225 case GICR_PIDR4: { // Peripheral ID4 Register
226 uint8_t size = 0x4; // 64 KB software visible page
227 uint8_t des_2 = 0x4; // ARM implementation
228 return (size << 4) | (des_2 << 0);
229 }
230
231 case GICR_PIDR5: // Peripheral ID5 Register
232 case GICR_PIDR6: // Peripheral ID6 Register
233 case GICR_PIDR7: // Peripheral ID7 Register
234 return 0; // RES0
235
236 case GICR_IGROUPR0: { // Interrupt Group Register 0
237 uint64_t value = 0;
238
239 if (!distributor->DS && !is_secure_access) {
240 // RAZ/WI for non-secure accesses
241 return 0;
242 }
243
244 for (int int_id = 0; int_id < 8 * size; int_id++) {
245 value |= (irqGroup[int_id] << int_id);
246 }
247
248 return value;
249 }
250
251 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
252 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
253 uint64_t value = 0;
254
255 for (int int_id = 0; int_id < 8 * size; int_id++) {
256 if (!distributor->DS && !is_secure_access) {
257 // RAZ/WI for non-secure accesses for secure interrupts
258 if (getIntGroup(int_id) != Gicv3::G1NS) {
259 continue;
260 }
261 }
262
263 if (irqEnabled[int_id]) {
264 value |= (1 << int_id);
265 }
266 }
267
268 return value;
269 }
270
271 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
272 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
273 uint64_t value = 0;
274
275 for (int int_id = 0; int_id < 8 * size; int_id++) {
276 if (!distributor->DS && !is_secure_access) {
277 // RAZ/WI for non-secure accesses for secure interrupts
278 if (getIntGroup(int_id) != Gicv3::G1NS) {
279 continue;
280 }
281 }
282
283 value |= (irqPending[int_id] << int_id);
284 }
285
286 return value;
287 }
288
289 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
290 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
291 uint64_t value = 0;
292
293 for (int int_id = 0; int_id < 8 * size; int_id++) {
294 if (!distributor->DS && !is_secure_access) {
295 // RAZ/WI for non-secure accesses for secure interrupts
296 if (getIntGroup(int_id) != Gicv3::G1NS) {
297 continue;
298 }
299 }
300
301 value |= irqActive[int_id] << int_id;
302 }
303
304 return value;
305 }
306
307 case GICR_ICFGR0: // SGI Configuration Register
308 case GICR_ICFGR1: { // PPI Configuration Register
309 uint64_t value = 0;
310 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
311
312 for (int i = 0, int_id = first_int_id; i < 32;
313 i = i + 2, int_id++) {
314 if (!distributor->DS && !is_secure_access) {
315 // RAZ/WI for non-secure accesses for secure interrupts
316 if (getIntGroup(int_id) != Gicv3::G1NS) {
317 continue;
318 }
319 }
320
321 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
322 value |= (0x2) << i;
323 }
324 }
325
326 return value;
327 }
328
329 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
330 uint64_t value = 0;
331
332 if (distributor->DS) {
333 value = 0;
334 } else {
335 if (!is_secure_access) {
336 // RAZ/WI for non-secure accesses
337 value = 0;
338 } else {
339 for (int int_id = 0; int_id < 8 * size; int_id++) {
340 value |= irqGrpmod[int_id] << int_id;
341 }
342 }
343 }
344
345 return value;
346 }
347
348 case GICR_NSACR: { // Non-secure Access Control Register
349 uint64_t value = 0;
350
351 if (distributor->DS) {
352 // RAZ/WI
353 value = 0;
354 } else {
355 if (!is_secure_access) {
356 // RAZ/WI
357 value = 0;
358 } else {
359 for (int i = 0, int_id = 0; i < 8 * size;
360 i = i + 2, int_id++) {
361 value |= irqNsacr[int_id] << i;
362 }
363 }
364 }
365
366 return value;
367 }
368
369 case GICR_PROPBASER: // Redistributor Properties Base Address Register
370 // OuterCache, bits [58:56]
371 // 000 Memory type defined in InnerCache field
372 // Physical_Address, bits [51:12]
373 // Bits [51:12] of the physical address containing the LPI
374 // Configuration table
375 // Shareability, bits [11:10]
376 // 00 Non-shareable
377 // InnerCache, bits [9:7]
378 // 000 Device-nGnRnE
379 // IDbits, bits [4:0]
380 // limited by GICD_TYPER.IDbits
381 return lpiConfigurationTablePtr | lpiIDBits;
382
383 // Redistributor LPI Pending Table Base Address Register
384 case GICR_PENDBASER:
385 // PTZ, bit [62]
386 // Pending Table Zero
387 // OuterCache, bits [58:56]
388 // 000 Memory type defined in InnerCache field
389 // Physical_Address, bits [51:16]
390 // Bits [51:16] of the physical address containing the LPI Pending
391 // table
392 // Shareability, bits [11:10]
393 // 00 Non-shareable
394 // InnerCache, bits [9:7]
395 // 000 Device-nGnRnE
396 return lpiPendingTablePtr;
397
398 // Redistributor Synchronize Register
399 case GICR_SYNCR:
400 return 0;
401
402 default:
403 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
404 break;
405 }
406}
407
408void
409Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
410 bool is_secure_access)
411{
412 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
413 int first_intid = addr - GICR_IPRIORITYR.start();
414
415 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
416 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
417
418 if (!distributor->DS && !is_secure_access) {
419 if (getIntGroup(int_id) != Gicv3::G1NS) {
420 // RAZ/WI for non-secure accesses for secure interrupts
421 continue;
422 } else {
423 // NS view
424 prio = 0x80 | (prio >> 1);
425 }
426 }
427
428 irqPriority[int_id] = prio;
429 DPRINTF(GIC, "Gicv3Redistributor::write(): "
430 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
431 }
432
433 return;
434 }
435
436 switch (addr) {
437 case GICR_CTLR: {
438 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
439 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
440 DPG1S = data & GICR_CTLR_DPG1S;
441 DPG1NS = data & GICR_CTLR_DPG1NS;
442 DPG0 = data & GICR_CTLR_DPG0;
443 break;
444 }
445
446 case GICR_WAKER: // Wake Register
447 if (!distributor->DS && !is_secure_access) {
448 // RAZ/WI for non-secure accesses
449 return;
450 }
451
452 if (not peInLowPowerState and
453 (data & GICR_WAKER_ProcessorSleep)) {
454 DPRINTF(GIC, "Gicv3Redistributor::write(): "
455 "PE entering in low power state\n");
456 } else if (peInLowPowerState and
457 not(data & GICR_WAKER_ProcessorSleep)) {
458 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
459 }
460
461 peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
462 break;
463
464 case GICR_IGROUPR0: // Interrupt Group Register 0
465 if (!distributor->DS && !is_secure_access) {
466 // RAZ/WI for non-secure accesses
467 return;
468 }
469
470 for (int int_id = 0; int_id < 8 * size; int_id++) {
471 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
472 DPRINTF(GIC, "Gicv3Redistributor::write(): "
473 "int_id %d group %d\n", int_id, irqGroup[int_id]);
474 }
475
476 break;
477
478 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
479 for (int int_id = 0; int_id < 8 * size; int_id++) {
480 if (!distributor->DS && !is_secure_access) {
481 // RAZ/WI for non-secure accesses for secure interrupts
482 if (getIntGroup(int_id) != Gicv3::G1NS) {
483 continue;
484 }
485 }
486
487 bool enable = data & (1 << int_id) ? 1 : 0;
488
489 if (enable) {
490 irqEnabled[int_id] = true;
491 }
492
493 DPRINTF(GIC, "Gicv3Redistributor::write(): "
494 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
495 }
496
497 break;
498
499 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
500 for (int int_id = 0; int_id < 8 * size; int_id++) {
501 if (!distributor->DS && !is_secure_access) {
502 // RAZ/WI for non-secure accesses for secure interrupts
503 if (getIntGroup(int_id) != Gicv3::G1NS) {
504 continue;
505 }
506 }
507
508 bool disable = data & (1 << int_id) ? 1 : 0;
509
510 if (disable) {
511 irqEnabled[int_id] = false;
512 }
513
514 DPRINTF(GIC, "Gicv3Redistributor::write(): "
515 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
516 }
517
518 break;
519
520 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
521 for (int int_id = 0; int_id < 8 * size; int_id++) {
522 if (!distributor->DS && !is_secure_access) {
523 // RAZ/WI for non-secure accesses for secure interrupts
524 if (getIntGroup(int_id) != Gicv3::G1NS) {
525 continue;
526 }
527 }
528
529 bool pending = data & (1 << int_id) ? 1 : 0;
530
531 if (pending) {
532 DPRINTF(GIC, "Gicv3Redistributor::write() "
533 "(GICR_ISPENDR0): int_id %d (PPI) "
534 "pending bit set\n", int_id);
535 irqPending[int_id] = true;
536 }
537 }
538
539 updateDistributor();
540 break;
541
542 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
543 for (int int_id = 0; int_id < 8 * size; int_id++) {
544 if (!distributor->DS && !is_secure_access) {
545 // RAZ/WI for non-secure accesses for secure interrupts
546 if (getIntGroup(int_id) != Gicv3::G1NS) {
547 continue;
548 }
549 }
550
551 bool clear = data & (1 << int_id) ? 1 : 0;
552
553 if (clear) {
554 irqPending[int_id] = false;
555 }
556 }
557
558 break;
559
560 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
561 for (int int_id = 0; int_id < 8 * size; int_id++) {
562 if (!distributor->DS && !is_secure_access) {
563 // RAZ/WI for non-secure accesses for secure interrupts
564 if (getIntGroup(int_id) != Gicv3::G1NS) {
565 continue;
566 }
567 }
568
569 bool activate = data & (1 << int_id) ? 1 : 0;
570
571 if (activate) {
572 if (!irqActive[int_id]) {
573 DPRINTF(GIC, "Gicv3Redistributor::write(): "
574 "int_id %d active set\n", int_id);
575 }
576
577 irqActive[int_id] = true;
578 }
579 }
580
581 break;
582
583 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
584 for (int int_id = 0; int_id < 8 * size; int_id++) {
585 if (!distributor->DS && !is_secure_access) {
586 // RAZ/WI for non-secure accesses for secure interrupts
587 if (getIntGroup(int_id) != Gicv3::G1NS) {
588 continue;
589 }
590 }
591
592 bool clear = data & (1 << int_id) ? 1 : 0;
593
594 if (clear) {
595 if (irqActive[int_id]) {
596 DPRINTF(GIC, "Gicv3Redistributor::write(): "
597 "int_id %d active cleared\n", int_id);
598 }
599
600 irqActive[int_id] = false;
601 }
602 }
603
604 break;
605
606 case GICR_ICFGR1: { // PPI Configuration Register
607 int first_intid = Gicv3::SGI_MAX;
608
609 for (int i = 0, int_id = first_intid; i < 8 * size;
610 i = i + 2, int_id++) {
611 if (!distributor->DS && !is_secure_access) {
612 // RAZ/WI for non-secure accesses for secure interrupts
613 if (getIntGroup(int_id) != Gicv3::G1NS) {
614 continue;
615 }
616 }
617
618 irqConfig[int_id] = data & (0x2 << i) ?
619 Gicv3::INT_EDGE_TRIGGERED :
620 Gicv3::INT_LEVEL_SENSITIVE;
621 DPRINTF(GIC, "Gicv3Redistributor::write(): "
622 "int_id %d (PPI) config %d\n",
623 int_id, irqConfig[int_id]);
624 }
625
626 break;
627 }
628
629 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
630 if (distributor->DS) {
631 // RAZ/WI if secutiry disabled
632 } else {
633 for (int int_id = 0; int_id < 8 * size; int_id++) {
634 if (!is_secure_access) {
635 // RAZ/WI for non-secure accesses
636 continue;
637 }
638
639 irqGrpmod[int_id] = data & (1 << int_id);
640 }
641 }
642
643 break;
644 }
645
646 case GICR_NSACR: { // Non-secure Access Control Register
647 if (distributor->DS) {
648 // RAZ/WI
649 } else {
650 if (!is_secure_access) {
651 // RAZ/WI
652 } else {
653 for (int i = 0, int_id = 0; i < 8 * size;
654 i = i + 2, int_id++) {
655 irqNsacr[int_id] = (data >> i) & 0x3;
656 }
657 }
658 }
659
660 break;
661 }
662
663 case GICR_SETLPIR: // Set LPI Pending Register
664 setClrLPI(data, true);
665 break;
666
667 case GICR_CLRLPIR: // Clear LPI Pending Register
668 setClrLPI(data, false);
669 break;
670
671 case GICR_PROPBASER: { // Redistributor Properties Base Address Register
672 // OuterCache, bits [58:56]
673 // 000 Memory type defined in InnerCache field
674 // Physical_Address, bits [51:12]
675 // Bits [51:12] of the physical address containing the LPI
676 // Configuration table
677 // Shareability, bits [11:10]
678 // 00 Non-shareable
679 // InnerCache, bits [9:7]
680 // 000 Device-nGnRnE
681 // IDbits, bits [4:0]
682 // limited by GICD_TYPER.IDbits (= 0xf)
683 lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
684 lpiIDBits = data & 0x1f;
685
686 // 0xf here matches the value of GICD_TYPER.IDbits.
687 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
688 // value
689 if (lpiIDBits > 0xf) {
690 lpiIDBits = 0xf;
691 }
692
693 break;
694 }
695
696 // Redistributor LPI Pending Table Base Address Register
697 case GICR_PENDBASER:
698 // PTZ, bit [62]
699 // Pending Table Zero
700 // OuterCache, bits [58:56]
701 // 000 Memory type defined in InnerCache field
702 // Physical_Address, bits [51:16]
703 // Bits [51:16] of the physical address containing the LPI Pending
704 // table
705 // Shareability, bits [11:10]
706 // 00 Non-shareable
707 // InnerCache, bits [9:7]
708 // 000 Device-nGnRnE
709 lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
710 break;
711
712 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
713 // Do nothing: no caching supported
714 break;
715 }
716
717 case GICR_INVALLR: { // Redistributor Invalidate All Register
718 // Do nothing: no caching supported
719 break;
720 }
721
722 default:
723 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
724 break;
725 }
726}
727
728void
729Gicv3Redistributor::sendPPInt(uint32_t int_id)
730{
731 assert((int_id >= Gicv3::SGI_MAX) &&
732 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
733 irqPending[int_id] = true;
734 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
735 "int_id %d (PPI) pending bit set\n", int_id);
736 updateDistributor();
737}
738
739void
740Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
741{
742 assert(int_id < Gicv3::SGI_MAX);
743 Gicv3::GroupId int_group = getIntGroup(int_id);
744
745 bool forward = false;
746
747 if (ns) {
748 // Non-Secure EL1 and EL2 access
749 int nsaccess = irqNsacr[int_id];
750 if (int_group == Gicv3::G0S) {
751
752 forward = distributor->DS || (nsaccess >= 1);
753
754 } else if (int_group == Gicv3::G1S) {
755 forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
756 nsaccess == 2);
757 } else {
758 // G1NS
759 forward = group == Gicv3::G1NS;
760 }
761 } else {
762 // Secure EL1 and EL3 access
763 forward = (group == int_group) ||
764 (group == Gicv3::G1S && int_group == Gicv3::G0S &&
765 distributor->DS);
766 }
767
768 if (!forward) return;
769
770 irqPending[int_id] = true;
771 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
772 "int_id %d (SGI) pending bit set\n", int_id);
773 updateDistributor();
774}
775
776Gicv3::IntStatus
777Gicv3Redistributor::intStatus(uint32_t int_id) const
778{
779 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
780
781 if (irqPending[int_id]) {
782 if (irqActive[int_id]) {
783 return Gicv3::INT_ACTIVE_PENDING;
784 }
785
786 return Gicv3::INT_PENDING;
787 } else if (irqActive[int_id]) {
788 return Gicv3::INT_ACTIVE;
789 } else {
790 return Gicv3::INT_INACTIVE;
791 }
792}
793
794void
795Gicv3Redistributor::updateDistributor()
796{
797 distributor->update();
798}
799
800/*
801 * Recalculate the highest priority pending interrupt after a
802 * change to redistributor state.
803 */
804void
805Gicv3Redistributor::update()
806{
807 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
808 Gicv3::GroupId int_group = getIntGroup(int_id);
809 bool group_enabled = distributor->groupEnabled(int_group);
810
811 if (irqPending[int_id] && irqEnabled[int_id] &&
812 !irqActive[int_id] && group_enabled) {
813 if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
814 /*
815 * Multiple pending ints with same priority.
816 * Implementation choice which one to signal.
817 * Our implementation selects the one with the lower id.
818 */
819 (irqPriority[int_id] == cpuInterface->hppi.prio &&
820 int_id < cpuInterface->hppi.intid)) {
821 cpuInterface->hppi.intid = int_id;
822 cpuInterface->hppi.prio = irqPriority[int_id];
823 cpuInterface->hppi.group = int_group;
824 }
825 }
826 }
827
828 // Check LPIs
829 if (EnableLPIs) {
830
831 const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
832 const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
833
834 uint8_t lpi_pending_table[largest_lpi_id / 8];
835 uint8_t lpi_config_table[number_lpis];
836
837 memProxy->readBlob(lpiPendingTablePtr,
838 lpi_pending_table,
839 sizeof(lpi_pending_table));
840
841 memProxy->readBlob(lpiConfigurationTablePtr,
842 lpi_config_table,
843 sizeof(lpi_config_table));
844
845 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
846 lpi_id++) {
847 uint32_t lpi_pending_entry_byte = lpi_id / 8;
848 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
849 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
850 1 << lpi_pending_entry_bit_position;
851 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
852
853 LPIConfigurationTableEntry config_entry =
854 lpi_config_table[lpi_configuration_entry_index];
855
856 bool lpi_is_enable = config_entry.enable;
857
858 // LPIs are always Non-secure Group 1 interrupts,
859 // in a system where two Security states are enabled.
860 Gicv3::GroupId lpi_group = Gicv3::G1NS;
861 bool group_enabled = distributor->groupEnabled(lpi_group);
862
863 if (lpi_is_pending && lpi_is_enable && group_enabled) {
864 uint8_t lpi_priority = config_entry.priority << 2;
865
866 if ((lpi_priority < cpuInterface->hppi.prio) ||
867 (lpi_priority == cpuInterface->hppi.prio &&
868 lpi_id < cpuInterface->hppi.intid)) {
869 cpuInterface->hppi.intid = lpi_id;
870 cpuInterface->hppi.prio = lpi_priority;
871 cpuInterface->hppi.group = lpi_group;
872 }
873 }
874 }
875 }
876
877 cpuInterface->update();
878}
879
880uint8_t
881Gicv3Redistributor::readEntryLPI(uint32_t lpi_id)
882{
883 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
884
885 uint8_t lpi_pending_entry;
886 memProxy->readBlob(lpi_pending_entry_ptr,
887 &lpi_pending_entry,
888 sizeof(lpi_pending_entry));
889
890 return lpi_pending_entry;
891}
892
893void
894Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
895{
896 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
897
898 memProxy->writeBlob(lpi_pending_entry_ptr,
899 &lpi_pending_entry,
900 sizeof(lpi_pending_entry));
901}
902
903bool
904Gicv3Redistributor::isPendingLPI(uint32_t lpi_id)
905{
906 // Fetch the LPI pending entry from memory
907 uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
908
909 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
910 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
911
912 return is_set;
913}
914
915void
916Gicv3Redistributor::setClrLPI(uint64_t data, bool set)
917{
918 if (!EnableLPIs) {
919 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
920 // GICR_CTLR.EnableLPIs == 0.
921 return;
922 }
923
924 uint32_t lpi_id = data & 0xffffffff;
925 uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
926
927 if (lpi_id > largest_lpi_id) {
928 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
929 // pINTID value specifies an unimplemented LPI.
930 return;
931 }
932
933 // Fetch the LPI pending entry from memory
934 uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
935
936 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
937 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
938
939 if (set) {
940 if (is_set) {
941 // Writes to GICR_SETLPIR have not effect if the pINTID field
942 // corresponds to an LPI that is already pending.
943 return;
944 }
945
946 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
947 } else {
948 if (!is_set) {
949 // Writes to GICR_SETLPIR have not effect if the pINTID field
950 // corresponds to an LPI that is not pending.
951 return;
952 }
953
954 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
955 }
956
957 writeEntryLPI(lpi_id, lpi_pending_entry);
958
959 updateDistributor();
960}
961
962Gicv3::GroupId
963Gicv3Redistributor::getIntGroup(int int_id) const
964{
965 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
966
967 if (distributor->DS) {
968 if (irqGroup[int_id] == 0) {
969 return Gicv3::G0S;
970 } else {
971 return Gicv3::G1NS;
972 }
973 } else {
974 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
975 return Gicv3::G0S;
976 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
977 return Gicv3::G1NS;
978 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
979 return Gicv3::G1S;
980 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
981 return Gicv3::G1NS;
982 }
983 }
984
985 M5_UNREACHABLE;
986}
987
988void
989Gicv3Redistributor::activateIRQ(uint32_t int_id)
990{
991 irqPending[int_id] = false;
992 irqActive[int_id] = true;
993}
994
995void
996Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
997{
998 irqActive[int_id] = false;
999}
1000
1001uint32_t
1002Gicv3Redistributor::getAffinity() const
1003{
1004 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
1005 uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
1006 /*
1007 * Aff3 = MPIDR[39:32]
1008 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
1009 * Aff2 = MPIDR[23:16]
1010 * Aff1 = MPIDR[15:8]
1011 * Aff0 = MPIDR[7:0]
1012 * affinity = Aff3.Aff2.Aff1.Aff0
1013 */
1014 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
1015 return affinity;
1016}
1017
1018bool
1019Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
1020{
1021 if (peInLowPowerState) {
1022 return false;
1023 }
1024
1025 if (!distributor->groupEnabled(group)) {
1026 return false;
1027 }
1028
1029 if ((group == Gicv3::G1S) && DPG1S) {
1030 return false;
1031 }
1032
1033 if ((group == Gicv3::G1NS) && DPG1NS) {
1034 return false;
1035 }
1036
1037 if ((group == Gicv3::G0S) && DPG0) {
1038 return false;
1039 }
1040
1041 return true;
1042}
1043
1044void
1045Gicv3Redistributor::serialize(CheckpointOut & cp) const
1046{
1047 SERIALIZE_SCALAR(peInLowPowerState);
1048 SERIALIZE_CONTAINER(irqGroup);
1049 SERIALIZE_CONTAINER(irqEnabled);
1050 SERIALIZE_CONTAINER(irqPending);
1051 SERIALIZE_CONTAINER(irqActive);
1052 SERIALIZE_CONTAINER(irqPriority);
1053 SERIALIZE_CONTAINER(irqConfig);
1054 SERIALIZE_CONTAINER(irqGrpmod);
1055 SERIALIZE_CONTAINER(irqNsacr);
1056 SERIALIZE_SCALAR(DPG1S);
1057 SERIALIZE_SCALAR(DPG1NS);
1058 SERIALIZE_SCALAR(DPG0);
1059 SERIALIZE_SCALAR(EnableLPIs);
1060 SERIALIZE_SCALAR(lpiConfigurationTablePtr);
1061 SERIALIZE_SCALAR(lpiIDBits);
1062 SERIALIZE_SCALAR(lpiPendingTablePtr);
1063}
1064
1065void
1066Gicv3Redistributor::unserialize(CheckpointIn & cp)
1067{
1068 UNSERIALIZE_SCALAR(peInLowPowerState);
1069 UNSERIALIZE_CONTAINER(irqGroup);
1070 UNSERIALIZE_CONTAINER(irqEnabled);
1071 UNSERIALIZE_CONTAINER(irqPending);
1072 UNSERIALIZE_CONTAINER(irqActive);
1073 UNSERIALIZE_CONTAINER(irqPriority);
1074 UNSERIALIZE_CONTAINER(irqConfig);
1075 UNSERIALIZE_CONTAINER(irqGrpmod);
1076 UNSERIALIZE_CONTAINER(irqNsacr);
1077 UNSERIALIZE_SCALAR(DPG1S);
1078 UNSERIALIZE_SCALAR(DPG1NS);
1079 UNSERIALIZE_SCALAR(DPG0);
1080 UNSERIALIZE_SCALAR(EnableLPIs);
1081 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
1082 UNSERIALIZE_SCALAR(lpiIDBits);
1083 UNSERIALIZE_SCALAR(lpiPendingTablePtr);
1084}
89uint64_t
90Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
91{
92 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
93 uint64_t value = 0;
94 int first_intid = addr - GICR_IPRIORITYR.start();
95
96 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
97 uint8_t prio = irqPriority[int_id];
98
99 if (!distributor->DS && !is_secure_access) {
100 if (getIntGroup(int_id) != Gicv3::G1NS) {
101 // RAZ/WI for non-secure accesses for secure interrupts
102 continue;
103 } else {
104 // NS view
105 prio = (prio << 1) & 0xff;
106 }
107 }
108
109 value |= prio << (i * 8);
110 }
111
112 return value;
113 }
114
115 switch (addr) {
116 case GICR_CTLR: { // Control Register
117 uint64_t value = 0;
118
119 if (DPG1S) {
120 value |= GICR_CTLR_DPG1S;
121 }
122
123 if (DPG1NS) {
124 value |= GICR_CTLR_DPG1NS;
125 }
126
127 if (DPG0) {
128 value |= GICR_CTLR_DPG0;
129 }
130
131 if (EnableLPIs) {
132 value |= GICR_CTLR_ENABLE_LPIS;
133 }
134
135 return value;
136 }
137
138 case GICR_IIDR: // Implementer Identification Register
139 //return 0x43b; // r0p0 GIC-500
140 return 0;
141
142 case GICR_TYPER: { // Type Register
143 /*
144 * Affinity_Value [63:32] == X
145 * (The identity of the PE associated with this Redistributor)
146 * CommonLPIAff [25:24] == 01
147 * (All Redistributors with the same Aff3 value must share an
148 * LPI Configuration table)
149 * Processor_Number [23:8] == X
150 * (A unique identifier for the PE)
151 * DPGS [5] == 1
152 * (GICR_CTLR.DPG* bits are supported)
153 * Last [4] == X
154 * (This Redistributor is the highest-numbered Redistributor in
155 * a series of contiguous Redistributor pages)
156 * DirectLPI [3] == 1
157 * (direct injection of LPIs supported)
158 * VLPIS [1] == 0
159 * (virtual LPIs not supported)
160 * PLPIS [0] == 1
161 * (physical LPIs supported)
162 */
163 uint64_t affinity = getAffinity();
164 int last = cpuId == (gic->getSystem()->numContexts() - 1);
165 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
166 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
167 }
168
169 case GICR_WAKER: // Wake Register
170 if (!distributor->DS && !is_secure_access) {
171 // RAZ/WI for non-secure accesses
172 return 0;
173 }
174
175 if (peInLowPowerState) {
176 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
177 } else {
178 return 0;
179 }
180
181 case GICR_PIDR0: { // Peripheral ID0 Register
182 return 0x92; // Part number, bits[7:0]
183 }
184
185 case GICR_PIDR1: { // Peripheral ID1 Register
186 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
187 uint8_t part_1 = 0x4; // Part number, bits[11:8]
188 return (des_0 << 4) | (part_1 << 0);
189 }
190
191 case GICR_PIDR2: { // Peripheral ID2 Register
192 uint8_t arch_rev = 0x3; // 0x3 GICv3
193 uint8_t jedec = 0x1; // JEP code
194 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
195 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
196 }
197
198 case GICR_PIDR3: // Peripheral ID3 Register
199 return 0x0; // Implementation defined
200
201 case GICR_PIDR4: { // Peripheral ID4 Register
202 uint8_t size = 0x4; // 64 KB software visible page
203 uint8_t des_2 = 0x4; // ARM implementation
204 return (size << 4) | (des_2 << 0);
205 }
206
207 case GICR_PIDR5: // Peripheral ID5 Register
208 case GICR_PIDR6: // Peripheral ID6 Register
209 case GICR_PIDR7: // Peripheral ID7 Register
210 return 0; // RES0
211
212 case GICR_IGROUPR0: { // Interrupt Group Register 0
213 uint64_t value = 0;
214
215 if (!distributor->DS && !is_secure_access) {
216 // RAZ/WI for non-secure accesses
217 return 0;
218 }
219
220 for (int int_id = 0; int_id < 8 * size; int_id++) {
221 value |= (irqGroup[int_id] << int_id);
222 }
223
224 return value;
225 }
226
227 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
228 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
229 uint64_t value = 0;
230
231 for (int int_id = 0; int_id < 8 * size; int_id++) {
232 if (!distributor->DS && !is_secure_access) {
233 // RAZ/WI for non-secure accesses for secure interrupts
234 if (getIntGroup(int_id) != Gicv3::G1NS) {
235 continue;
236 }
237 }
238
239 if (irqEnabled[int_id]) {
240 value |= (1 << int_id);
241 }
242 }
243
244 return value;
245 }
246
247 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
248 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
249 uint64_t value = 0;
250
251 for (int int_id = 0; int_id < 8 * size; int_id++) {
252 if (!distributor->DS && !is_secure_access) {
253 // RAZ/WI for non-secure accesses for secure interrupts
254 if (getIntGroup(int_id) != Gicv3::G1NS) {
255 continue;
256 }
257 }
258
259 value |= (irqPending[int_id] << int_id);
260 }
261
262 return value;
263 }
264
265 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
266 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
267 uint64_t value = 0;
268
269 for (int int_id = 0; int_id < 8 * size; int_id++) {
270 if (!distributor->DS && !is_secure_access) {
271 // RAZ/WI for non-secure accesses for secure interrupts
272 if (getIntGroup(int_id) != Gicv3::G1NS) {
273 continue;
274 }
275 }
276
277 value |= irqActive[int_id] << int_id;
278 }
279
280 return value;
281 }
282
283 case GICR_ICFGR0: // SGI Configuration Register
284 case GICR_ICFGR1: { // PPI Configuration Register
285 uint64_t value = 0;
286 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
287
288 for (int i = 0, int_id = first_int_id; i < 32;
289 i = i + 2, int_id++) {
290 if (!distributor->DS && !is_secure_access) {
291 // RAZ/WI for non-secure accesses for secure interrupts
292 if (getIntGroup(int_id) != Gicv3::G1NS) {
293 continue;
294 }
295 }
296
297 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
298 value |= (0x2) << i;
299 }
300 }
301
302 return value;
303 }
304
305 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
306 uint64_t value = 0;
307
308 if (distributor->DS) {
309 value = 0;
310 } else {
311 if (!is_secure_access) {
312 // RAZ/WI for non-secure accesses
313 value = 0;
314 } else {
315 for (int int_id = 0; int_id < 8 * size; int_id++) {
316 value |= irqGrpmod[int_id] << int_id;
317 }
318 }
319 }
320
321 return value;
322 }
323
324 case GICR_NSACR: { // Non-secure Access Control Register
325 uint64_t value = 0;
326
327 if (distributor->DS) {
328 // RAZ/WI
329 value = 0;
330 } else {
331 if (!is_secure_access) {
332 // RAZ/WI
333 value = 0;
334 } else {
335 for (int i = 0, int_id = 0; i < 8 * size;
336 i = i + 2, int_id++) {
337 value |= irqNsacr[int_id] << i;
338 }
339 }
340 }
341
342 return value;
343 }
344
345 case GICR_PROPBASER: // Redistributor Properties Base Address Register
346 // OuterCache, bits [58:56]
347 // 000 Memory type defined in InnerCache field
348 // Physical_Address, bits [51:12]
349 // Bits [51:12] of the physical address containing the LPI
350 // Configuration table
351 // Shareability, bits [11:10]
352 // 00 Non-shareable
353 // InnerCache, bits [9:7]
354 // 000 Device-nGnRnE
355 // IDbits, bits [4:0]
356 // limited by GICD_TYPER.IDbits
357 return lpiConfigurationTablePtr | lpiIDBits;
358
359 // Redistributor LPI Pending Table Base Address Register
360 case GICR_PENDBASER:
361 // PTZ, bit [62]
362 // Pending Table Zero
363 // OuterCache, bits [58:56]
364 // 000 Memory type defined in InnerCache field
365 // Physical_Address, bits [51:16]
366 // Bits [51:16] of the physical address containing the LPI Pending
367 // table
368 // Shareability, bits [11:10]
369 // 00 Non-shareable
370 // InnerCache, bits [9:7]
371 // 000 Device-nGnRnE
372 return lpiPendingTablePtr;
373
374 // Redistributor Synchronize Register
375 case GICR_SYNCR:
376 return 0;
377
378 default:
379 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
380 break;
381 }
382}
383
384void
385Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
386 bool is_secure_access)
387{
388 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
389 int first_intid = addr - GICR_IPRIORITYR.start();
390
391 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
392 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
393
394 if (!distributor->DS && !is_secure_access) {
395 if (getIntGroup(int_id) != Gicv3::G1NS) {
396 // RAZ/WI for non-secure accesses for secure interrupts
397 continue;
398 } else {
399 // NS view
400 prio = 0x80 | (prio >> 1);
401 }
402 }
403
404 irqPriority[int_id] = prio;
405 DPRINTF(GIC, "Gicv3Redistributor::write(): "
406 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
407 }
408
409 return;
410 }
411
412 switch (addr) {
413 case GICR_CTLR: {
414 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
415 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
416 DPG1S = data & GICR_CTLR_DPG1S;
417 DPG1NS = data & GICR_CTLR_DPG1NS;
418 DPG0 = data & GICR_CTLR_DPG0;
419 break;
420 }
421
422 case GICR_WAKER: // Wake Register
423 if (!distributor->DS && !is_secure_access) {
424 // RAZ/WI for non-secure accesses
425 return;
426 }
427
428 if (not peInLowPowerState and
429 (data & GICR_WAKER_ProcessorSleep)) {
430 DPRINTF(GIC, "Gicv3Redistributor::write(): "
431 "PE entering in low power state\n");
432 } else if (peInLowPowerState and
433 not(data & GICR_WAKER_ProcessorSleep)) {
434 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
435 }
436
437 peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
438 break;
439
440 case GICR_IGROUPR0: // Interrupt Group Register 0
441 if (!distributor->DS && !is_secure_access) {
442 // RAZ/WI for non-secure accesses
443 return;
444 }
445
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]);
450 }
451
452 break;
453
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) {
459 continue;
460 }
461 }
462
463 bool enable = data & (1 << int_id) ? 1 : 0;
464
465 if (enable) {
466 irqEnabled[int_id] = true;
467 }
468
469 DPRINTF(GIC, "Gicv3Redistributor::write(): "
470 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
471 }
472
473 break;
474
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) {
480 continue;
481 }
482 }
483
484 bool disable = data & (1 << int_id) ? 1 : 0;
485
486 if (disable) {
487 irqEnabled[int_id] = false;
488 }
489
490 DPRINTF(GIC, "Gicv3Redistributor::write(): "
491 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
492 }
493
494 break;
495
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) {
501 continue;
502 }
503 }
504
505 bool pending = data & (1 << int_id) ? 1 : 0;
506
507 if (pending) {
508 DPRINTF(GIC, "Gicv3Redistributor::write() "
509 "(GICR_ISPENDR0): int_id %d (PPI) "
510 "pending bit set\n", int_id);
511 irqPending[int_id] = true;
512 }
513 }
514
515 updateDistributor();
516 break;
517
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) {
523 continue;
524 }
525 }
526
527 bool clear = data & (1 << int_id) ? 1 : 0;
528
529 if (clear) {
530 irqPending[int_id] = false;
531 }
532 }
533
534 break;
535
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) {
541 continue;
542 }
543 }
544
545 bool activate = data & (1 << int_id) ? 1 : 0;
546
547 if (activate) {
548 if (!irqActive[int_id]) {
549 DPRINTF(GIC, "Gicv3Redistributor::write(): "
550 "int_id %d active set\n", int_id);
551 }
552
553 irqActive[int_id] = true;
554 }
555 }
556
557 break;
558
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) {
564 continue;
565 }
566 }
567
568 bool clear = data & (1 << int_id) ? 1 : 0;
569
570 if (clear) {
571 if (irqActive[int_id]) {
572 DPRINTF(GIC, "Gicv3Redistributor::write(): "
573 "int_id %d active cleared\n", int_id);
574 }
575
576 irqActive[int_id] = false;
577 }
578 }
579
580 break;
581
582 case GICR_ICFGR1: { // PPI Configuration Register
583 int first_intid = Gicv3::SGI_MAX;
584
585 for (int i = 0, int_id = first_intid; i < 8 * size;
586 i = i + 2, int_id++) {
587 if (!distributor->DS && !is_secure_access) {
588 // RAZ/WI for non-secure accesses for secure interrupts
589 if (getIntGroup(int_id) != Gicv3::G1NS) {
590 continue;
591 }
592 }
593
594 irqConfig[int_id] = data & (0x2 << i) ?
595 Gicv3::INT_EDGE_TRIGGERED :
596 Gicv3::INT_LEVEL_SENSITIVE;
597 DPRINTF(GIC, "Gicv3Redistributor::write(): "
598 "int_id %d (PPI) config %d\n",
599 int_id, irqConfig[int_id]);
600 }
601
602 break;
603 }
604
605 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
606 if (distributor->DS) {
607 // RAZ/WI if secutiry disabled
608 } else {
609 for (int int_id = 0; int_id < 8 * size; int_id++) {
610 if (!is_secure_access) {
611 // RAZ/WI for non-secure accesses
612 continue;
613 }
614
615 irqGrpmod[int_id] = data & (1 << int_id);
616 }
617 }
618
619 break;
620 }
621
622 case GICR_NSACR: { // Non-secure Access Control Register
623 if (distributor->DS) {
624 // RAZ/WI
625 } else {
626 if (!is_secure_access) {
627 // RAZ/WI
628 } else {
629 for (int i = 0, int_id = 0; i < 8 * size;
630 i = i + 2, int_id++) {
631 irqNsacr[int_id] = (data >> i) & 0x3;
632 }
633 }
634 }
635
636 break;
637 }
638
639 case GICR_SETLPIR: // Set LPI Pending Register
640 setClrLPI(data, true);
641 break;
642
643 case GICR_CLRLPIR: // Clear LPI Pending Register
644 setClrLPI(data, false);
645 break;
646
647 case GICR_PROPBASER: { // Redistributor Properties Base Address Register
648 // OuterCache, bits [58:56]
649 // 000 Memory type defined in InnerCache field
650 // Physical_Address, bits [51:12]
651 // Bits [51:12] of the physical address containing the LPI
652 // Configuration table
653 // Shareability, bits [11:10]
654 // 00 Non-shareable
655 // InnerCache, bits [9:7]
656 // 000 Device-nGnRnE
657 // IDbits, bits [4:0]
658 // limited by GICD_TYPER.IDbits (= 0xf)
659 lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
660 lpiIDBits = data & 0x1f;
661
662 // 0xf here matches the value of GICD_TYPER.IDbits.
663 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
664 // value
665 if (lpiIDBits > 0xf) {
666 lpiIDBits = 0xf;
667 }
668
669 break;
670 }
671
672 // Redistributor LPI Pending Table Base Address Register
673 case GICR_PENDBASER:
674 // PTZ, bit [62]
675 // Pending Table Zero
676 // OuterCache, bits [58:56]
677 // 000 Memory type defined in InnerCache field
678 // Physical_Address, bits [51:16]
679 // Bits [51:16] of the physical address containing the LPI Pending
680 // table
681 // Shareability, bits [11:10]
682 // 00 Non-shareable
683 // InnerCache, bits [9:7]
684 // 000 Device-nGnRnE
685 lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
686 break;
687
688 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
689 // Do nothing: no caching supported
690 break;
691 }
692
693 case GICR_INVALLR: { // Redistributor Invalidate All Register
694 // Do nothing: no caching supported
695 break;
696 }
697
698 default:
699 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
700 break;
701 }
702}
703
704void
705Gicv3Redistributor::sendPPInt(uint32_t int_id)
706{
707 assert((int_id >= Gicv3::SGI_MAX) &&
708 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
709 irqPending[int_id] = true;
710 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
711 "int_id %d (PPI) pending bit set\n", int_id);
712 updateDistributor();
713}
714
715void
716Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
717{
718 assert(int_id < Gicv3::SGI_MAX);
719 Gicv3::GroupId int_group = getIntGroup(int_id);
720
721 bool forward = false;
722
723 if (ns) {
724 // Non-Secure EL1 and EL2 access
725 int nsaccess = irqNsacr[int_id];
726 if (int_group == Gicv3::G0S) {
727
728 forward = distributor->DS || (nsaccess >= 1);
729
730 } else if (int_group == Gicv3::G1S) {
731 forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
732 nsaccess == 2);
733 } else {
734 // G1NS
735 forward = group == Gicv3::G1NS;
736 }
737 } else {
738 // Secure EL1 and EL3 access
739 forward = (group == int_group) ||
740 (group == Gicv3::G1S && int_group == Gicv3::G0S &&
741 distributor->DS);
742 }
743
744 if (!forward) return;
745
746 irqPending[int_id] = true;
747 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
748 "int_id %d (SGI) pending bit set\n", int_id);
749 updateDistributor();
750}
751
752Gicv3::IntStatus
753Gicv3Redistributor::intStatus(uint32_t int_id) const
754{
755 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
756
757 if (irqPending[int_id]) {
758 if (irqActive[int_id]) {
759 return Gicv3::INT_ACTIVE_PENDING;
760 }
761
762 return Gicv3::INT_PENDING;
763 } else if (irqActive[int_id]) {
764 return Gicv3::INT_ACTIVE;
765 } else {
766 return Gicv3::INT_INACTIVE;
767 }
768}
769
770void
771Gicv3Redistributor::updateDistributor()
772{
773 distributor->update();
774}
775
776/*
777 * Recalculate the highest priority pending interrupt after a
778 * change to redistributor state.
779 */
780void
781Gicv3Redistributor::update()
782{
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);
786
787 if (irqPending[int_id] && irqEnabled[int_id] &&
788 !irqActive[int_id] && group_enabled) {
789 if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
790 /*
791 * Multiple pending ints with same priority.
792 * Implementation choice which one to signal.
793 * Our implementation selects the one with the lower id.
794 */
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;
800 }
801 }
802 }
803
804 // Check LPIs
805 if (EnableLPIs) {
806
807 const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
808 const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
809
810 uint8_t lpi_pending_table[largest_lpi_id / 8];
811 uint8_t lpi_config_table[number_lpis];
812
813 memProxy->readBlob(lpiPendingTablePtr,
814 lpi_pending_table,
815 sizeof(lpi_pending_table));
816
817 memProxy->readBlob(lpiConfigurationTablePtr,
818 lpi_config_table,
819 sizeof(lpi_config_table));
820
821 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
822 lpi_id++) {
823 uint32_t lpi_pending_entry_byte = lpi_id / 8;
824 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
825 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
826 1 << lpi_pending_entry_bit_position;
827 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
828
829 LPIConfigurationTableEntry config_entry =
830 lpi_config_table[lpi_configuration_entry_index];
831
832 bool lpi_is_enable = config_entry.enable;
833
834 // LPIs are always Non-secure Group 1 interrupts,
835 // in a system where two Security states are enabled.
836 Gicv3::GroupId lpi_group = Gicv3::G1NS;
837 bool group_enabled = distributor->groupEnabled(lpi_group);
838
839 if (lpi_is_pending && lpi_is_enable && group_enabled) {
840 uint8_t lpi_priority = config_entry.priority << 2;
841
842 if ((lpi_priority < cpuInterface->hppi.prio) ||
843 (lpi_priority == cpuInterface->hppi.prio &&
844 lpi_id < cpuInterface->hppi.intid)) {
845 cpuInterface->hppi.intid = lpi_id;
846 cpuInterface->hppi.prio = lpi_priority;
847 cpuInterface->hppi.group = lpi_group;
848 }
849 }
850 }
851 }
852
853 cpuInterface->update();
854}
855
856uint8_t
857Gicv3Redistributor::readEntryLPI(uint32_t lpi_id)
858{
859 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
860
861 uint8_t lpi_pending_entry;
862 memProxy->readBlob(lpi_pending_entry_ptr,
863 &lpi_pending_entry,
864 sizeof(lpi_pending_entry));
865
866 return lpi_pending_entry;
867}
868
869void
870Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
871{
872 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
873
874 memProxy->writeBlob(lpi_pending_entry_ptr,
875 &lpi_pending_entry,
876 sizeof(lpi_pending_entry));
877}
878
879bool
880Gicv3Redistributor::isPendingLPI(uint32_t lpi_id)
881{
882 // Fetch the LPI pending entry from memory
883 uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
884
885 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
886 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
887
888 return is_set;
889}
890
891void
892Gicv3Redistributor::setClrLPI(uint64_t data, bool set)
893{
894 if (!EnableLPIs) {
895 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
896 // GICR_CTLR.EnableLPIs == 0.
897 return;
898 }
899
900 uint32_t lpi_id = data & 0xffffffff;
901 uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
902
903 if (lpi_id > largest_lpi_id) {
904 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
905 // pINTID value specifies an unimplemented LPI.
906 return;
907 }
908
909 // Fetch the LPI pending entry from memory
910 uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
911
912 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
913 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
914
915 if (set) {
916 if (is_set) {
917 // Writes to GICR_SETLPIR have not effect if the pINTID field
918 // corresponds to an LPI that is already pending.
919 return;
920 }
921
922 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
923 } else {
924 if (!is_set) {
925 // Writes to GICR_SETLPIR have not effect if the pINTID field
926 // corresponds to an LPI that is not pending.
927 return;
928 }
929
930 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
931 }
932
933 writeEntryLPI(lpi_id, lpi_pending_entry);
934
935 updateDistributor();
936}
937
938Gicv3::GroupId
939Gicv3Redistributor::getIntGroup(int int_id) const
940{
941 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
942
943 if (distributor->DS) {
944 if (irqGroup[int_id] == 0) {
945 return Gicv3::G0S;
946 } else {
947 return Gicv3::G1NS;
948 }
949 } else {
950 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
951 return Gicv3::G0S;
952 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
953 return Gicv3::G1NS;
954 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
955 return Gicv3::G1S;
956 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
957 return Gicv3::G1NS;
958 }
959 }
960
961 M5_UNREACHABLE;
962}
963
964void
965Gicv3Redistributor::activateIRQ(uint32_t int_id)
966{
967 irqPending[int_id] = false;
968 irqActive[int_id] = true;
969}
970
971void
972Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
973{
974 irqActive[int_id] = false;
975}
976
977uint32_t
978Gicv3Redistributor::getAffinity() const
979{
980 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
981 uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
982 /*
983 * Aff3 = MPIDR[39:32]
984 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
985 * Aff2 = MPIDR[23:16]
986 * Aff1 = MPIDR[15:8]
987 * Aff0 = MPIDR[7:0]
988 * affinity = Aff3.Aff2.Aff1.Aff0
989 */
990 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
991 return affinity;
992}
993
994bool
995Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
996{
997 if (peInLowPowerState) {
998 return false;
999 }
1000
1001 if (!distributor->groupEnabled(group)) {
1002 return false;
1003 }
1004
1005 if ((group == Gicv3::G1S) && DPG1S) {
1006 return false;
1007 }
1008
1009 if ((group == Gicv3::G1NS) && DPG1NS) {
1010 return false;
1011 }
1012
1013 if ((group == Gicv3::G0S) && DPG0) {
1014 return false;
1015 }
1016
1017 return true;
1018}
1019
1020void
1021Gicv3Redistributor::serialize(CheckpointOut & cp) const
1022{
1023 SERIALIZE_SCALAR(peInLowPowerState);
1024 SERIALIZE_CONTAINER(irqGroup);
1025 SERIALIZE_CONTAINER(irqEnabled);
1026 SERIALIZE_CONTAINER(irqPending);
1027 SERIALIZE_CONTAINER(irqActive);
1028 SERIALIZE_CONTAINER(irqPriority);
1029 SERIALIZE_CONTAINER(irqConfig);
1030 SERIALIZE_CONTAINER(irqGrpmod);
1031 SERIALIZE_CONTAINER(irqNsacr);
1032 SERIALIZE_SCALAR(DPG1S);
1033 SERIALIZE_SCALAR(DPG1NS);
1034 SERIALIZE_SCALAR(DPG0);
1035 SERIALIZE_SCALAR(EnableLPIs);
1036 SERIALIZE_SCALAR(lpiConfigurationTablePtr);
1037 SERIALIZE_SCALAR(lpiIDBits);
1038 SERIALIZE_SCALAR(lpiPendingTablePtr);
1039}
1040
1041void
1042Gicv3Redistributor::unserialize(CheckpointIn & cp)
1043{
1044 UNSERIALIZE_SCALAR(peInLowPowerState);
1045 UNSERIALIZE_CONTAINER(irqGroup);
1046 UNSERIALIZE_CONTAINER(irqEnabled);
1047 UNSERIALIZE_CONTAINER(irqPending);
1048 UNSERIALIZE_CONTAINER(irqActive);
1049 UNSERIALIZE_CONTAINER(irqPriority);
1050 UNSERIALIZE_CONTAINER(irqConfig);
1051 UNSERIALIZE_CONTAINER(irqGrpmod);
1052 UNSERIALIZE_CONTAINER(irqNsacr);
1053 UNSERIALIZE_SCALAR(DPG1S);
1054 UNSERIALIZE_SCALAR(DPG1NS);
1055 UNSERIALIZE_SCALAR(DPG0);
1056 UNSERIALIZE_SCALAR(EnableLPIs);
1057 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
1058 UNSERIALIZE_SCALAR(lpiIDBits);
1059 UNSERIALIZE_SCALAR(lpiPendingTablePtr);
1060}