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