dev-arm: Add a VExpress_GEM5_V2 platform with GICv3 support
[gem5.git] / src / dev / arm / gic_v3_redistributor.cc
1 /*
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
38 const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
39 SGI_base + 0x041f);
40
41 Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
42 : gic(gic),
43 distributor(nullptr),
44 cpuInterface(nullptr),
45 cpuId(cpu_id),
46 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
47 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
48 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
49 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
50 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
51 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
52 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
53 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX)
54 {
55 }
56
57 Gicv3Redistributor::~Gicv3Redistributor()
58 {
59 }
60
61 void
62 Gicv3Redistributor::init()
63 {
64 distributor = gic->getDistributor();
65 cpuInterface = gic->getCPUInterface(cpuId);
66 }
67
68 void
69 Gicv3Redistributor::initState()
70 {
71 reset();
72 }
73
74 void
75 Gicv3Redistributor::reset()
76 {
77 peInLowPowerState = true;
78 std::fill(irqGroup.begin(), irqGroup.end(), 0);
79 std::fill(irqEnabled.begin(), irqEnabled.end(), false);
80 std::fill(irqPending.begin(), irqPending.end(), false);
81 std::fill(irqActive.begin(), irqActive.end(), false);
82 std::fill(irqPriority.begin(), irqPriority.end(), 0);
83
84 // SGIs have edge-triggered behavior
85 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
86 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
87 }
88
89 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
90 std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
91 DPG1S = false;
92 DPG1NS = false;
93 DPG0 = false;
94 }
95
96 uint64_t
97 Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
98 {
99 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
100 uint64_t value = 0;
101 int first_intid = addr - GICR_IPRIORITYR.start();
102
103 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
104 uint8_t prio = irqPriority[int_id];
105
106 if (!distributor->DS && !is_secure_access) {
107 if (getIntGroup(int_id) != Gicv3::G1NS) {
108 // RAZ/WI for non-secure accesses for secure interrupts
109 continue;
110 } else {
111 // NS view
112 prio = (prio << 1) & 0xff;
113 }
114 }
115
116 value |= prio << (i * 8);
117 }
118
119 return value;
120 }
121
122 switch (addr) {
123 case GICR_CTLR: { // Control Register
124 uint64_t value = 0;
125
126 if (DPG1S) {
127 value |= GICR_CTLR_DPG1S;
128 }
129
130 if (DPG1NS) {
131 value |= GICR_CTLR_DPG1NS;
132 }
133
134 if (DPG0) {
135 value |= GICR_CTLR_DPG0;
136 }
137
138 return value;
139 }
140
141 case GICR_IIDR: // Implementer Identification Register
142 //return 0x43b; // r0p0 GIC-500
143 return 0;
144
145 case GICR_TYPER: { // Type Register
146 /*
147 * Affinity_Value [63:32] == X
148 * (The identity of the PE associated with this Redistributor)
149 * CommonLPIAff [25:24] == 01
150 * (All Redistributors with the same Aff3 value must share an
151 * LPI Configuration table)
152 * Processor_Number [23:8] == X
153 * (A unique identifier for the PE)
154 * DPGS [5] == 1
155 * (GICR_CTLR.DPG* bits are supported)
156 * Last [4] == X
157 * (This Redistributor is the highest-numbered Redistributor in
158 * a series of contiguous Redistributor pages)
159 * DirectLPI [3] == 0
160 * (direct injection of LPIs not supported)
161 * VLPIS [1] == 0
162 * (virtual LPIs not supported)
163 * PLPIS [0] == 0
164 * (physical LPIs not supported)
165 */
166 uint64_t affinity = getAffinity();
167 int last = cpuId == (gic->getSystem()->numContexts() - 1);
168 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
169 (1 << 5) | (last << 4);
170 }
171
172 case GICR_WAKER: // Wake Register
173 if (!distributor->DS && !is_secure_access) {
174 // RAZ/WI for non-secure accesses
175 return 0;
176 }
177
178 if (peInLowPowerState) {
179 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
180 } else {
181 return 0;
182 }
183
184 case GICR_PIDR0: { // Peripheral ID0 Register
185 uint8_t part_0 = 0x92; // Part number, bits[7:0]
186 return part_0;
187 }
188
189 case GICR_PIDR1: { // Peripheral ID1 Register
190 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
191 uint8_t part_1 = 0x4; // Part number, bits[11:8]
192 return (des_0 << 4) | (part_1 << 0);
193 }
194
195 case GICR_PIDR2: { // Peripheral ID2 Register
196 uint8_t arch_rev = 0x3; // 0x3 GICv3
197 uint8_t jedec = 0x1; // JEP code
198 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
199 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
200 }
201
202 case GICR_PIDR3: // Peripheral ID3 Register
203 return 0x0; // Implementation defined
204
205 case GICR_PIDR4: { // Peripheral ID4 Register
206 uint8_t size = 0x4; // 64 KB software visible page
207 uint8_t des_2 = 0x4; // ARM implementation
208 return (size << 4) | (des_2 << 0);
209 }
210
211 case GICR_PIDR5: // Peripheral ID5 Register
212 case GICR_PIDR6: // Peripheral ID6 Register
213 case GICR_PIDR7: // Peripheral ID7 Register
214 return 0; // RES0
215
216 case GICR_IGROUPR0: { // Interrupt Group Register 0
217 uint64_t value = 0;
218
219 if (!distributor->DS && !is_secure_access) {
220 // RAZ/WI for non-secure accesses
221 return 0;
222 }
223
224 for (int int_id = 0; int_id < 8 * size; int_id++) {
225 value |= (irqGroup[int_id] << int_id);
226 }
227
228 return value;
229 }
230
231 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
232 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
233 uint64_t value = 0;
234
235 for (int int_id = 0; int_id < 8 * size; int_id++) {
236 if (!distributor->DS && !is_secure_access) {
237 // RAZ/WI for non-secure accesses for secure interrupts
238 if (getIntGroup(int_id) != Gicv3::G1NS) {
239 continue;
240 }
241 }
242
243 if (irqEnabled[int_id]) {
244 value |= (1 << int_id);
245 }
246 }
247
248 return value;
249 }
250
251 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
252 case GICR_ICPENDR0: { // Interrupt Clear-Pending 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 value |= (irqPending[int_id] << int_id);
264 }
265
266 return value;
267 }
268
269 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
270 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
271 uint64_t value = 0;
272
273 for (int int_id = 0; int_id < 8 * size; int_id++) {
274 if (!distributor->DS && !is_secure_access) {
275 // RAZ/WI for non-secure accesses for secure interrupts
276 if (getIntGroup(int_id) != Gicv3::G1NS) {
277 continue;
278 }
279 }
280
281 value |= irqActive[int_id] << int_id;
282 }
283
284 return value;
285 }
286
287 case GICR_ICFGR0: // SGI Configuration Register
288 case GICR_ICFGR1: { // PPI Configuration Register
289 uint64_t value = 0;
290 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
291
292 for (int i = 0, int_id = first_int_id; i < 32;
293 i = i + 2, 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 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
302 value |= (0x2) << i;
303 }
304 }
305
306 return value;
307 }
308
309 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
310 uint64_t value = 0;
311
312 if (distributor->DS) {
313 value = 0;
314 } else {
315 if (!is_secure_access) {
316 // RAZ/WI for non-secure accesses
317 value = 0;
318 } else {
319 for (int int_id = 0; int_id < 8 * size; int_id++) {
320 value |= irqGrpmod[int_id] << int_id;
321 }
322 }
323 }
324
325 return value;
326 }
327
328 case GICR_NSACR: { // Non-secure Access Control Register
329 uint64_t value = 0;
330
331 if (distributor->DS) {
332 // RAZ/WI
333 value = 0;
334 } else {
335 if (!is_secure_access) {
336 // RAZ/WI
337 value = 0;
338 } else {
339 for (int i = 0, int_id = 0; i < 8 * size;
340 i = i + 2, int_id++) {
341 value |= irqNsacr[int_id] << i;
342 }
343 }
344 }
345
346 return value;
347 }
348
349 default:
350 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
351 break;
352 }
353 }
354
355 void
356 Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
357 bool is_secure_access)
358 {
359 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
360 int first_intid = addr - GICR_IPRIORITYR.start();
361
362 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
363 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
364
365 if (!distributor->DS && !is_secure_access) {
366 if (getIntGroup(int_id) != Gicv3::G1NS) {
367 // RAZ/WI for non-secure accesses for secure interrupts
368 continue;
369 } else {
370 // NS view
371 prio = 0x80 | (prio >> 1);
372 }
373 }
374
375 irqPriority[int_id] = prio;
376 DPRINTF(GIC, "Gicv3Redistributor::write(): "
377 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
378 }
379
380 return;
381 }
382
383 switch (addr) {
384 case GICR_CTLR: {
385 // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
386 DPG1S = data & GICR_CTLR_DPG1S;
387 DPG1NS = data & GICR_CTLR_DPG1NS;
388 DPG0 = data & GICR_CTLR_DPG0;
389 break;
390 }
391
392 case GICR_WAKER: // Wake Register
393 if (!distributor->DS && !is_secure_access) {
394 // RAZ/WI for non-secure accesses
395 return;
396 }
397
398 if (not peInLowPowerState and
399 (data & GICR_WAKER_ProcessorSleep)) {
400 DPRINTF(GIC, "Gicv3Redistributor::write(): "
401 "PE entering in low power state\n");
402 } else if (peInLowPowerState and
403 not(data & GICR_WAKER_ProcessorSleep)) {
404 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
405 }
406
407 peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
408 break;
409
410 case GICR_IGROUPR0: // Interrupt Group Register 0
411 if (!distributor->DS && !is_secure_access) {
412 // RAZ/WI for non-secure accesses
413 return;
414 }
415
416 for (int int_id = 0; int_id < 8 * size; int_id++) {
417 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
418 DPRINTF(GIC, "Gicv3Redistributor::write(): "
419 "int_id %d group %d\n", int_id, irqGroup[int_id]);
420 }
421
422 break;
423
424 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
425 for (int int_id = 0; int_id < 8 * size; int_id++) {
426 if (!distributor->DS && !is_secure_access) {
427 // RAZ/WI for non-secure accesses for secure interrupts
428 if (getIntGroup(int_id) != Gicv3::G1NS) {
429 continue;
430 }
431 }
432
433 bool enable = data & (1 << int_id) ? 1 : 0;
434
435 if (enable) {
436 irqEnabled[int_id] = true;
437 }
438
439 DPRINTF(GIC, "Gicv3Redistributor::write(): "
440 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
441 }
442
443 break;
444
445 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
446 for (int int_id = 0; int_id < 8 * size; int_id++) {
447 if (!distributor->DS && !is_secure_access) {
448 // RAZ/WI for non-secure accesses for secure interrupts
449 if (getIntGroup(int_id) != Gicv3::G1NS) {
450 continue;
451 }
452 }
453
454 bool disable = data & (1 << int_id) ? 1 : 0;
455
456 if (disable) {
457 irqEnabled[int_id] = false;
458 }
459
460 DPRINTF(GIC, "Gicv3Redistributor::write(): "
461 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
462 }
463
464 break;
465
466 case GICR_ISPENDR0: // Interrupt Set-Pending 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 pending = data & (1 << int_id) ? 1 : 0;
476
477 if (pending) {
478 DPRINTF(GIC, "Gicv3Redistributor::write() "
479 "(GICR_ISPENDR0): int_id %d (PPI) "
480 "pending bit set\n", int_id);
481 irqPending[int_id] = true;
482 }
483 }
484
485 updateAndInformCPUInterface();
486 break;
487
488 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
489 for (int int_id = 0; int_id < 8 * size; int_id++) {
490 if (!distributor->DS && !is_secure_access) {
491 // RAZ/WI for non-secure accesses for secure interrupts
492 if (getIntGroup(int_id) != Gicv3::G1NS) {
493 continue;
494 }
495 }
496
497 bool clear = data & (1 << int_id) ? 1 : 0;
498
499 if (clear) {
500 irqPending[int_id] = false;
501 }
502 }
503
504 break;
505
506 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
507 for (int int_id = 0; int_id < 8 * size; int_id++) {
508 if (!distributor->DS && !is_secure_access) {
509 // RAZ/WI for non-secure accesses for secure interrupts
510 if (getIntGroup(int_id) != Gicv3::G1NS) {
511 continue;
512 }
513 }
514
515 bool activate = data & (1 << int_id) ? 1 : 0;
516
517 if (activate) {
518 if (!irqActive[int_id]) {
519 DPRINTF(GIC, "Gicv3Redistributor::write(): "
520 "int_id %d active set\n", int_id);
521 }
522
523 irqActive[int_id] = true;
524 }
525 }
526
527 break;
528
529 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
530 for (int int_id = 0; int_id < 8 * size; int_id++) {
531 if (!distributor->DS && !is_secure_access) {
532 // RAZ/WI for non-secure accesses for secure interrupts
533 if (getIntGroup(int_id) != Gicv3::G1NS) {
534 continue;
535 }
536 }
537
538 bool clear = data & (1 << int_id) ? 1 : 0;
539
540 if (clear) {
541 if (irqActive[int_id]) {
542 DPRINTF(GIC, "Gicv3Redistributor::write(): "
543 "int_id %d active cleared\n", int_id);
544 }
545
546 irqActive[int_id] = false;
547 }
548 }
549
550 break;
551
552 case GICR_ICFGR1: { // PPI Configuration Register
553 int first_intid = Gicv3::SGI_MAX;
554
555 for (int i = 0, int_id = first_intid; i < 8 * size;
556 i = i + 2, int_id++) {
557 if (!distributor->DS && !is_secure_access) {
558 // RAZ/WI for non-secure accesses for secure interrupts
559 if (getIntGroup(int_id) != Gicv3::G1NS) {
560 continue;
561 }
562 }
563
564 irqConfig[int_id] = data & (0x2 << i)
565 ? Gicv3::INT_EDGE_TRIGGERED :
566 Gicv3::INT_LEVEL_SENSITIVE;
567 DPRINTF(GIC, "Gicv3Redistributor::write(): "
568 "int_id %d (PPI) config %d\n",
569 int_id, irqConfig[int_id]);
570 }
571
572 break;
573 }
574
575 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
576 if (distributor->DS) {
577 // RAZ/WI if secutiry disabled
578 } else {
579 for (int int_id = 0; int_id < 8 * size; int_id++) {
580 if (!is_secure_access) {
581 // RAZ/WI for non-secure accesses
582 continue;
583 }
584
585 irqGrpmod[int_id] = data & (1 << int_id);
586 }
587 }
588
589 break;
590 }
591
592 case GICR_NSACR: { // Non-secure Access Control Register
593 if (distributor->DS) {
594 // RAZ/WI
595 } else {
596 if (!is_secure_access) {
597 // RAZ/WI
598 } else {
599 for (int i = 0, int_id = 0; i < 8 * size;
600 i = i + 2, int_id++) {
601 irqNsacr[int_id] = (data >> i) & 0x3;
602 }
603 }
604 }
605
606 break;
607 }
608
609 default:
610 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
611 break;
612 }
613 }
614
615 void
616 Gicv3Redistributor::sendPPInt(uint32_t int_id)
617 {
618 assert((int_id >= Gicv3::SGI_MAX) &&
619 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
620 irqPending[int_id] = true;
621 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
622 "int_id %d (PPI) pending bit set\n", int_id);
623 updateAndInformCPUInterface();
624 }
625
626 void
627 Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
628 {
629 assert(int_id < Gicv3::SGI_MAX);
630 Gicv3::GroupId int_group = getIntGroup(int_id);
631
632 // asked for secure group 1
633 // configured as group 0
634 // send group 0
635 if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
636 group = Gicv3::G0S;
637 }
638
639 if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
640 return;
641 }
642
643 if (ns && distributor->DS == 0) {
644 int nsaccess = irqNsacr[int_id];
645
646 if ((int_group == Gicv3::G0S && nsaccess < 1) ||
647 (int_group == Gicv3::G1S && nsaccess < 2)) {
648 return;
649 }
650 }
651
652 irqPending[int_id] = true;
653 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
654 "int_id %d (SGI) pending bit set\n", int_id);
655 updateAndInformCPUInterface();
656 }
657
658 Gicv3::IntStatus
659 Gicv3Redistributor::intStatus(uint32_t int_id)
660 {
661 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
662
663 if (irqPending[int_id]) {
664 if (irqActive[int_id]) {
665 return Gicv3::INT_ACTIVE_PENDING;
666 }
667
668 return Gicv3::INT_PENDING;
669 } else if (irqActive[int_id]) {
670 return Gicv3::INT_ACTIVE;
671 } else {
672 return Gicv3::INT_INACTIVE;
673 }
674 }
675
676 /*
677 * Recalculate the highest priority pending interrupt after a
678 * change to redistributor state.
679 */
680 void
681 Gicv3Redistributor::update()
682 {
683 bool new_hppi = false;
684
685 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
686 Gicv3::GroupId int_group = getIntGroup(int_id);
687 bool group_enabled = distributor->groupEnabled(int_group);
688
689 if (irqPending[int_id] && irqEnabled[int_id] &&
690 !irqActive[int_id] && group_enabled) {
691 if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
692 /*
693 * Multiple pending ints with same priority.
694 * Implementation choice which one to signal.
695 * Our implementation selects the one with the lower id.
696 */
697 (irqPriority[int_id] == cpuInterface->hppi.prio &&
698 int_id < cpuInterface->hppi.intid)) {
699 cpuInterface->hppi.intid = int_id;
700 cpuInterface->hppi.prio = irqPriority[int_id];
701 cpuInterface->hppi.group = int_group;
702 new_hppi = true;
703 }
704 }
705 }
706
707 if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
708 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
709 distributor->fullUpdate();
710 }
711 }
712
713 void
714 Gicv3Redistributor::updateAndInformCPUInterface()
715 {
716 update();
717 cpuInterface->update();
718 }
719
720 Gicv3::GroupId
721 Gicv3Redistributor::getIntGroup(int int_id)
722 {
723 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
724
725 if (distributor->DS) {
726 if (irqGroup[int_id] == 0) {
727 return Gicv3::G0S;
728 } else {
729 return Gicv3::G1NS;
730 }
731 } else {
732 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
733 return Gicv3::G0S;
734 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
735 return Gicv3::G1NS;
736 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
737 return Gicv3::G1S;
738 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
739 return Gicv3::G1NS;
740 }
741 }
742
743 M5_UNREACHABLE;
744 }
745
746 void
747 Gicv3Redistributor::activateIRQ(uint32_t int_id)
748 {
749 irqPending[int_id] = false;
750 irqActive[int_id] = true;
751 }
752
753 void
754 Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
755 {
756 irqActive[int_id] = false;
757 }
758
759 uint32_t
760 Gicv3Redistributor::getAffinity()
761 {
762 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
763 uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
764 /*
765 * Aff3 = MPIDR[39:32]
766 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
767 * Aff2 = MPIDR[23:16]
768 * Aff1 = MPIDR[15:8]
769 * Aff0 = MPIDR[7:0]
770 * affinity = Aff3.Aff2.Aff1.Aff0
771 */
772 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
773 return affinity;
774 }
775
776 bool
777 Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group)
778 {
779 if (peInLowPowerState) {
780 return false;
781 }
782
783 if (!distributor->groupEnabled(group)) {
784 return false;
785 }
786
787 if ((group == Gicv3::G1S) && DPG1S) {
788 return false;
789 }
790
791 if ((group == Gicv3::G1NS) && DPG1NS) {
792 return false;
793 }
794
795 if ((group == Gicv3::G0S) && DPG0) {
796 return false;
797 }
798
799 return true;
800 }
801
802 void
803 Gicv3Redistributor::serialize(CheckpointOut & cp) const
804 {
805 SERIALIZE_SCALAR(peInLowPowerState);
806 SERIALIZE_CONTAINER(irqGroup);
807 SERIALIZE_CONTAINER(irqEnabled);
808 SERIALIZE_CONTAINER(irqPending);
809 SERIALIZE_CONTAINER(irqActive);
810 SERIALIZE_CONTAINER(irqPriority);
811 SERIALIZE_CONTAINER(irqConfig);
812 SERIALIZE_CONTAINER(irqGrpmod);
813 SERIALIZE_CONTAINER(irqNsacr);
814 SERIALIZE_SCALAR(DPG1S);
815 SERIALIZE_SCALAR(DPG1NS);
816 SERIALIZE_SCALAR(DPG0);
817 }
818
819 void
820 Gicv3Redistributor::unserialize(CheckpointIn & cp)
821 {
822 UNSERIALIZE_SCALAR(peInLowPowerState);
823 UNSERIALIZE_CONTAINER(irqGroup);
824 UNSERIALIZE_CONTAINER(irqEnabled);
825 UNSERIALIZE_CONTAINER(irqPending);
826 UNSERIALIZE_CONTAINER(irqActive);
827 UNSERIALIZE_CONTAINER(irqPriority);
828 UNSERIALIZE_CONTAINER(irqConfig);
829 UNSERIALIZE_CONTAINER(irqGrpmod);
830 UNSERIALIZE_CONTAINER(irqNsacr);
831 UNSERIALIZE_SCALAR(DPG1S);
832 UNSERIALIZE_SCALAR(DPG1NS);
833 UNSERIALIZE_SCALAR(DPG0);
834 }