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