gem5 v24.0.0.0
Loading...
Searching...
No Matches
gic_v3_redistributor.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019-2022 Arm Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
42
43#include "arch/arm/utility.hh"
44#include "base/compiler.hh"
45#include "debug/GIC.hh"
48
49namespace gem5
50{
51
52using namespace ArmISA;
53
54const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
55 SGI_base + 0x0420);
56
58 : gic(gic),
59 distributor(nullptr),
60 cpuInterface(nullptr),
61 cpuId(cpu_id),
62 memProxy(nullptr),
63 peInLowPowerState(true),
64 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
65 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
66 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
67 irqPendingIspendr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
68 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
69 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
70 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX, Gicv3::INT_EDGE_TRIGGERED),
71 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
72 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
73 DPG1S(false),
74 DPG1NS(false),
75 DPG0(false),
76 EnableLPIs(false),
77 lpiConfigurationTablePtr(0),
78 lpiIDBits(0),
79 lpiPendingTablePtr(0),
80 addrRangeSize(gic->params().gicv4 ? 0x40000 : 0x20000)
81{
82}
83
84void
92
93uint64_t
94Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
95{
96 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
97 uint64_t value = 0;
98 int first_intid = addr - GICR_IPRIORITYR.start();
99
100 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
101 uint8_t prio = irqPriority[int_id];
102
103 if (!distributor->DS && !is_secure_access) {
104 if (getIntGroup(int_id) != Gicv3::G1NS) {
105 // RAZ/WI for non-secure accesses for secure interrupts
106 continue;
107 } else {
108 // NS view
109 prio = (prio << 1) & 0xff;
110 }
111 }
112
113 value |= prio << (i * 8);
114 }
115
116 return value;
117 }
118
119 switch (addr) {
120 case GICR_CTLR: { // Control Register
121 uint64_t value = 0;
122
123 if (DPG1S) {
124 value |= GICR_CTLR_DPG1S;
125 }
126
127 if (DPG1NS) {
128 value |= GICR_CTLR_DPG1NS;
129 }
130
131 if (DPG0) {
132 value |= GICR_CTLR_DPG0;
133 }
134
135 if (EnableLPIs) {
136 value |= GICR_CTLR_ENABLE_LPIS;
137 }
138
139 return value;
140 }
141
142 case GICR_IIDR: // Implementer Identification Register
143 //return 0x43b; // r0p0 GIC-500
144 return 0;
145
146 case GICR_TYPER: { // Type Register
147 /*
148 * Affinity_Value [63:32] == X
149 * (The identity of the PE associated with this Redistributor)
150 * CommonLPIAff [25:24] == 01
151 * (All Redistributors with the same Aff3 value must share an
152 * LPI Configuration table)
153 * Processor_Number [23:8] == X
154 * (A unique identifier for the PE)
155 * DPGS [5] == 1
156 * (GICR_CTLR.DPG* bits are supported)
157 * Last [4] == X
158 * (This Redistributor is the highest-numbered Redistributor in
159 * a series of contiguous Redistributor pages)
160 * DirectLPI [3] == 1
161 * (direct injection of LPIs supported)
162 * VLPIS [1] == 0
163 * (virtual LPIs not supported)
164 * PLPIS [0] == 1
165 * (physical LPIs supported)
166 */
167 uint64_t affinity = getAffinity();
168 int last = cpuId == (gic->getSystem()->threads.size() - 1);
169 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
170 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
171 }
172
173 case GICR_WAKER: // Wake Register
174 if (!distributor->DS && !is_secure_access) {
175 // RAZ/WI for non-secure accesses
176 return 0;
177 }
178
179 if (peInLowPowerState) {
181 } else {
182 return 0;
183 }
184
185 case GICR_PIDR0: { // Peripheral ID0 Register
186 return 0x92; // Part number, bits[7: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 return gic->getDistributor()->gicdPidr2;
197 }
198
199 case GICR_PIDR3: // Peripheral ID3 Register
200 return 0x0; // Implementation defined
201
202 case GICR_PIDR4: { // Peripheral ID4 Register
203 uint8_t size = 0x4; // 64 KB software visible page
204 uint8_t des_2 = 0x4; // ARM implementation
205 return (size << 4) | (des_2 << 0);
206 }
207
208 case GICR_PIDR5: // Peripheral ID5 Register
209 case GICR_PIDR6: // Peripheral ID6 Register
210 case GICR_PIDR7: // Peripheral ID7 Register
211 return 0; // RES0
212
213 case GICR_IGROUPR0: { // Interrupt Group Register 0
214 uint64_t value = 0;
215
216 if (!distributor->DS && !is_secure_access) {
217 // RAZ/WI for non-secure accesses
218 return 0;
219 }
220
221 for (int int_id = 0; int_id < 8 * size; int_id++) {
222 value |= (irqGroup[int_id] << int_id);
223 }
224
225 return value;
226 }
227
228 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
229 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
230 uint64_t value = 0;
231
232 for (int int_id = 0; int_id < 8 * size; int_id++) {
233 if (!distributor->DS && !is_secure_access) {
234 // RAZ/WI for non-secure accesses for secure interrupts
235 if (getIntGroup(int_id) != Gicv3::G1NS) {
236 continue;
237 }
238 }
239
240 if (irqEnabled[int_id]) {
241 value |= (1 << int_id);
242 }
243 }
244
245 return value;
246 }
247
248 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
249 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
250 uint64_t value = 0;
251
252 for (int int_id = 0; int_id < 8 * size; int_id++) {
253 if (!distributor->DS && !is_secure_access) {
254 // RAZ/WI for non-secure accesses for secure interrupts
255 if (getIntGroup(int_id) != Gicv3::G1NS) {
256 continue;
257 }
258 }
259
260 value |= (irqPending[int_id] << int_id);
261 }
262
263 return value;
264 }
265
266 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
267 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
268 uint64_t value = 0;
269
270 for (int int_id = 0; int_id < 8 * size; int_id++) {
271 if (!distributor->DS && !is_secure_access) {
272 // RAZ/WI for non-secure accesses for secure interrupts
273 if (getIntGroup(int_id) != Gicv3::G1NS) {
274 continue;
275 }
276 }
277
278 value |= irqActive[int_id] << int_id;
279 }
280
281 return value;
282 }
283
284 case GICR_ICFGR0: // SGI Configuration Register
285 case GICR_ICFGR1: { // PPI Configuration Register
286 uint64_t value = 0;
287 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
288
289 for (int i = 0, int_id = first_int_id; i < 32;
290 i = i + 2, int_id++) {
291 if (!distributor->DS && !is_secure_access) {
292 // RAZ/WI for non-secure accesses for secure interrupts
293 if (getIntGroup(int_id) != Gicv3::G1NS) {
294 continue;
295 }
296 }
297
298 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
299 value |= (0x2) << i;
300 }
301 }
302
303 return value;
304 }
305
306 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
307 uint64_t value = 0;
308
309 if (distributor->DS) {
310 value = 0;
311 } else {
312 if (!is_secure_access) {
313 // RAZ/WI for non-secure accesses
314 value = 0;
315 } else {
316 for (int int_id = 0; int_id < 8 * size; int_id++) {
317 value |= irqGrpmod[int_id] << int_id;
318 }
319 }
320 }
321
322 return value;
323 }
324
325 case GICR_NSACR: { // Non-secure Access Control Register
326 uint64_t value = 0;
327
328 if (distributor->DS) {
329 // RAZ/WI
330 value = 0;
331 } else {
332 if (!is_secure_access) {
333 // RAZ/WI
334 value = 0;
335 } else {
336 for (int i = 0, int_id = 0; i < 8 * size;
337 i = i + 2, int_id++) {
338 value |= irqNsacr[int_id] << i;
339 }
340 }
341 }
342
343 return value;
344 }
345
346 case GICR_PROPBASER: // Redistributor Properties Base Address Register
347 // OuterCache, bits [58:56]
348 // 000 Memory type defined in InnerCache field
349 // Physical_Address, bits [51:12]
350 // Bits [51:12] of the physical address containing the LPI
351 // Configuration table
352 // Shareability, bits [11:10]
353 // 00 Non-shareable
354 // InnerCache, bits [9:7]
355 // 000 Device-nGnRnE
356 // IDbits, bits [4:0]
357 // limited by GICD_TYPER.IDbits
359
360 // Redistributor LPI Pending Table Base Address Register
361 case GICR_PENDBASER:
362 // PTZ, bit [62]
363 // Pending Table Zero
364 // OuterCache, bits [58:56]
365 // 000 Memory type defined in InnerCache field
366 // Physical_Address, bits [51:16]
367 // Bits [51:16] of the physical address containing the LPI Pending
368 // table
369 // Shareability, bits [11:10]
370 // 00 Non-shareable
371 // InnerCache, bits [9:7]
372 // 000 Device-nGnRnE
373 return lpiPendingTablePtr;
374
375 // Redistributor Synchronize Register
376 case GICR_SYNCR:
377 return 0;
378
379 default:
380 gic->reserved("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
381 return 0; // RES0
382 }
383}
384
385void
387 bool is_secure_access)
388{
389 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
390 int first_intid = addr - GICR_IPRIORITYR.start();
391
392 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
393 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
394
395 if (!distributor->DS && !is_secure_access) {
396 if (getIntGroup(int_id) != Gicv3::G1NS) {
397 // RAZ/WI for non-secure accesses for secure interrupts
398 continue;
399 } else {
400 // NS view
401 prio = 0x80 | (prio >> 1);
402 }
403 }
404
405 irqPriority[int_id] = prio;
406 DPRINTF(GIC, "Gicv3Redistributor::write(): "
407 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
408 }
409
410 return;
411 }
412
413 switch (addr) {
414 case GICR_CTLR: {
415 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
416 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
420 break;
421 }
422
423 case GICR_WAKER: // Wake Register
424 {
425 if (!distributor->DS && !is_secure_access) {
426 // RAZ/WI for non-secure accesses
427 return;
428 }
429
430 bool pe_was_low_power = peInLowPowerState;
432 if (!pe_was_low_power && peInLowPowerState) {
433 DPRINTF(GIC, "Gicv3Redistributor::write(): "
434 "PE entering in low power state\n");
436 } else if (pe_was_low_power && !peInLowPowerState) {
437 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
440 }
441 break;
442 }
443
444 case GICR_IGROUPR0: // Interrupt Group Register 0
445 if (!distributor->DS && !is_secure_access) {
446 // RAZ/WI for non-secure accesses
447 return;
448 }
449
450 for (int int_id = 0; int_id < 8 * size; int_id++) {
451 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
452 DPRINTF(GIC, "Gicv3Redistributor::write(): "
453 "int_id %d group %d\n", int_id, irqGroup[int_id]);
454 }
455
456 break;
457
458 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
459 for (int int_id = 0; int_id < 8 * size; int_id++) {
460 if (!distributor->DS && !is_secure_access) {
461 // RAZ/WI for non-secure accesses for secure interrupts
462 if (getIntGroup(int_id) != Gicv3::G1NS) {
463 continue;
464 }
465 }
466
467 bool enable = data & (1 << int_id) ? 1 : 0;
468
469 if (enable) {
470 irqEnabled[int_id] = true;
471 }
472
473 DPRINTF(GIC, "Gicv3Redistributor::write(): "
474 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
475 }
476
477 break;
478
479 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
480 for (int int_id = 0; int_id < 8 * size; int_id++) {
481 if (!distributor->DS && !is_secure_access) {
482 // RAZ/WI for non-secure accesses for secure interrupts
483 if (getIntGroup(int_id) != Gicv3::G1NS) {
484 continue;
485 }
486 }
487
488 bool disable = data & (1 << int_id) ? 1 : 0;
489
490 if (disable) {
491 irqEnabled[int_id] = false;
492 }
493
494 DPRINTF(GIC, "Gicv3Redistributor::write(): "
495 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
496 }
497
498 break;
499
500 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
501 for (int int_id = 0; int_id < 8 * size; int_id++) {
502 if (!distributor->DS && !is_secure_access) {
503 // RAZ/WI for non-secure accesses for secure interrupts
504 if (getIntGroup(int_id) != Gicv3::G1NS) {
505 continue;
506 }
507 }
508
509 bool pending = data & (1 << int_id) ? 1 : 0;
510
511 if (pending) {
512 DPRINTF(GIC, "Gicv3Redistributor::write() "
513 "(GICR_ISPENDR0): int_id %d (PPI) "
514 "pending bit set\n", int_id);
515 irqPending[int_id] = true;
516 irqPendingIspendr[int_id] = true;
517 }
518 }
519
521 break;
522
523 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
524 for (int int_id = 0; int_id < 8 * size; int_id++) {
525 if (!distributor->DS && !is_secure_access) {
526 // RAZ/WI for non-secure accesses for secure interrupts
527 if (getIntGroup(int_id) != Gicv3::G1NS) {
528 continue;
529 }
530 }
531
532 bool clear = data & (1 << int_id) ? 1 : 0;
533
534 if (clear && treatAsEdgeTriggered(int_id)) {
535 irqPending[int_id] = false;
536 }
537 }
538
539 break;
540
541 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
542 for (int int_id = 0; int_id < 8 * size; int_id++) {
543 if (!distributor->DS && !is_secure_access) {
544 // RAZ/WI for non-secure accesses for secure interrupts
545 if (getIntGroup(int_id) != Gicv3::G1NS) {
546 continue;
547 }
548 }
549
550 bool activate = data & (1 << int_id) ? 1 : 0;
551
552 if (activate) {
553 if (!irqActive[int_id]) {
554 DPRINTF(GIC, "Gicv3Redistributor::write(): "
555 "int_id %d active set\n", int_id);
556 }
557
558 irqActive[int_id] = true;
559 }
560 }
561
562 break;
563
564 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
565 for (int int_id = 0; int_id < 8 * size; int_id++) {
566 if (!distributor->DS && !is_secure_access) {
567 // RAZ/WI for non-secure accesses for secure interrupts
568 if (getIntGroup(int_id) != Gicv3::G1NS) {
569 continue;
570 }
571 }
572
573 bool clear = data & (1 << int_id) ? 1 : 0;
574
575 if (clear) {
576 if (irqActive[int_id]) {
577 DPRINTF(GIC, "Gicv3Redistributor::write(): "
578 "int_id %d active cleared\n", int_id);
579 }
580
581 irqActive[int_id] = false;
582 }
583 }
584
585 break;
586
587 case GICR_ICFGR0: // SGI Configuration Register
588 // WI
589 return;
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) ?
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 break;
678 }
679
680 // Redistributor LPI Pending Table Base Address Register
681 case GICR_PENDBASER:
682 // PTZ, bit [62]
683 // Pending Table Zero
684 // OuterCache, bits [58:56]
685 // 000 Memory type defined in InnerCache field
686 // Physical_Address, bits [51:16]
687 // Bits [51:16] of the physical address containing the LPI Pending
688 // table
689 // Shareability, bits [11:10]
690 // 00 Non-shareable
691 // InnerCache, bits [9:7]
692 // 000 Device-nGnRnE
693 lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
694 break;
695
696 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
697 // Do nothing: no caching supported
698 break;
699 }
700
701 case GICR_INVALLR: { // Redistributor Invalidate All Register
702 // Do nothing: no caching supported
703 break;
704 }
705
706 default:
707 gic->reserved("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
708 break;
709 }
710}
711
712void
714{
715 assert((int_id >= Gicv3::SGI_MAX) &&
716 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
717 irqPending[int_id] = true;
718 irqPendingIspendr[int_id] = false;
719 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
720 "int_id %d (PPI) pending bit set\n", int_id);
722}
723
724void
726{
727 assert((int_id >= Gicv3::SGI_MAX) &&
728 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
729
730 if (isLevelSensitive(int_id)) {
731 irqPending[int_id] = false;
732 }
733}
734
735void
736Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
737{
738 assert(int_id < Gicv3::SGI_MAX);
739 Gicv3::GroupId int_group = getIntGroup(int_id);
740
741 bool forward = false;
742
743 if (ns) {
744 // Non-Secure EL1 and EL2 access
745 int nsaccess = irqNsacr[int_id];
746 if (int_group == Gicv3::G0S) {
747
748 forward = distributor->DS || (nsaccess >= 1);
749
750 } else if (int_group == Gicv3::G1S) {
751 forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
752 nsaccess == 2);
753 } else {
754 // G1NS
755 forward = group == Gicv3::G1NS;
756 }
757 } else {
758 // Secure EL1 and EL3 access
759 forward = (group == int_group) ||
760 (group == Gicv3::G1S && int_group == Gicv3::G0S &&
761 distributor->DS);
762 }
763
764 if (!forward) return;
765
766 irqPending[int_id] = true;
767 irqPendingIspendr[int_id] = false;
768 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
769 "int_id %d (SGI) pending bit set\n", int_id);
771}
772
774Gicv3Redistributor::intStatus(uint32_t int_id) const
775{
776 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
777
778 if (irqPending[int_id]) {
779 if (irqActive[int_id]) {
781 }
782
783 return Gicv3::INT_PENDING;
784 } else if (irqActive[int_id]) {
785 return Gicv3::INT_ACTIVE;
786 } else {
787 return Gicv3::INT_INACTIVE;
788 }
789}
790
791void
796
797/*
798 * Recalculate the highest priority pending interrupt after a
799 * change to redistributor state.
800 */
801void
803{
804 if (gic->blockIntUpdate())
805 return;
806
807 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
808 Gicv3::GroupId int_group = getIntGroup(int_id);
809 bool group_enabled = distributor->groupEnabled(int_group);
810
811 if (irqPending[int_id] && irqEnabled[int_id] &&
812 !irqActive[int_id] && group_enabled) {
813 if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
814 /*
815 * Multiple pending ints with same priority.
816 * Implementation choice which one to signal.
817 * Our implementation selects the one with the lower id.
818 */
819 (irqPriority[int_id] == cpuInterface->hppi.prio &&
820 int_id < cpuInterface->hppi.intid)) {
821 cpuInterface->hppi.intid = int_id;
823 cpuInterface->hppi.group = int_group;
824 }
825 }
826 }
827
828 // Check LPIs
829 if (EnableLPIs) {
830
831 const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
832 const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
833
834 uint8_t lpi_pending_table[largest_lpi_id / 8];
835 uint8_t lpi_config_table[number_lpis];
836
838 lpi_pending_table,
839 sizeof(lpi_pending_table));
840
842 lpi_config_table,
843 sizeof(lpi_config_table));
844
845 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
846 lpi_id++) {
847 uint32_t lpi_pending_entry_byte = lpi_id / 8;
848 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
849 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
850 1 << lpi_pending_entry_bit_position;
851 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
852
853 LPIConfigurationTableEntry config_entry =
854 lpi_config_table[lpi_configuration_entry_index];
855
856 bool lpi_is_enable = config_entry.enable;
857
858 // LPIs are always Non-secure Group 1 interrupts,
859 // in a system where two Security states are enabled.
860 Gicv3::GroupId lpi_group = Gicv3::G1NS;
861 bool group_enabled = distributor->groupEnabled(lpi_group);
862
863 if (lpi_is_pending && lpi_is_enable && group_enabled) {
864 uint8_t lpi_priority = config_entry.priority << 2;
865
866 if ((lpi_priority < cpuInterface->hppi.prio) ||
867 (lpi_priority == cpuInterface->hppi.prio &&
868 lpi_id < cpuInterface->hppi.intid)) {
869 cpuInterface->hppi.intid = lpi_id;
870 cpuInterface->hppi.prio = lpi_priority;
871 cpuInterface->hppi.group = lpi_group;
872 }
873 }
874 }
875 }
876
877 if (peInLowPowerState) {
881 }
882 } else {
884 }
885}
886
887uint8_t
889{
890 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
891
892 uint8_t lpi_pending_entry;
893 memProxy->readBlob(lpi_pending_entry_ptr,
894 &lpi_pending_entry,
895 sizeof(lpi_pending_entry));
896
897 return lpi_pending_entry;
898}
899
900void
901Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
902{
903 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
904
905 memProxy->writeBlob(lpi_pending_entry_ptr,
906 &lpi_pending_entry,
907 sizeof(lpi_pending_entry));
908}
909
910bool
912{
913 // Fetch the LPI pending entry from memory
914 uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
915
916 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
917 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
918
919 return is_set;
920}
921
922void
924{
925 if (!EnableLPIs) {
926 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
927 // GICR_CTLR.EnableLPIs == 0.
928 return;
929 }
930
931 uint32_t lpi_id = data & 0xffffffff;
932 uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
933
934 if (lpi_id > largest_lpi_id) {
935 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
936 // pINTID value specifies an unimplemented LPI.
937 return;
938 }
939
940 // Fetch the LPI pending entry from memory
941 uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
942
943 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
944 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
945
946 if (set) {
947 if (is_set) {
948 // Writes to GICR_SETLPIR have not effect if the pINTID field
949 // corresponds to an LPI that is already pending.
950 return;
951 }
952
953 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
954 } else {
955 if (!is_set) {
956 // Writes to GICR_SETLPIR have not effect if the pINTID field
957 // corresponds to an LPI that is not pending.
958 return;
959 }
960
961 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
962
963 // Remove the pending state from the cpu interface
964 cpuInterface->resetHppi(lpi_id);
965 }
966
967 writeEntryLPI(lpi_id, lpi_pending_entry);
968
970}
971
974{
975 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
976
977 if (distributor->DS) {
978 if (irqGroup[int_id] == 0) {
979 return Gicv3::G0S;
980 } else {
981 return Gicv3::G1NS;
982 }
983 } else {
984 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
985 return Gicv3::G0S;
986 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
987 return Gicv3::G1NS;
988 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
989 return Gicv3::G1S;
990 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
991 return Gicv3::G1NS;
992 }
993 }
994
995 GEM5_UNREACHABLE;
996}
997
998void
1000{
1001 if (treatAsEdgeTriggered(int_id)) {
1002 irqPending[int_id] = false;
1003 }
1004 irqActive[int_id] = true;
1005}
1006
1007void
1009{
1010 irqActive[int_id] = false;
1011}
1012
1013uint32_t
1019
1020bool
1022{
1023 if (peInLowPowerState) {
1024 return false;
1025 }
1026
1027 if (!distributor->groupEnabled(group)) {
1028 return false;
1029 }
1030
1031 if ((group == Gicv3::G1S) && DPG1S) {
1032 return false;
1033 }
1034
1035 if ((group == Gicv3::G1NS) && DPG1NS) {
1036 return false;
1037 }
1038
1039 if ((group == Gicv3::G0S) && DPG0) {
1040 return false;
1041 }
1042
1043 return true;
1044}
1045
1046void
1073
1074void
1095
1096void
1117
1118} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
Definition base_gic.hh:130
ArmSystem * getSystem() const
Definition base_gic.hh:114
void resetHppi(uint32_t intid)
bool groupEnabled(Gicv3::GroupId group) const
uint8_t readEntryLPI(uint32_t intid)
static const uint32_t GICR_WAKER_ProcessorSleep
void clearPPInt(uint32_t int_id)
bool isPendingLPI(uint32_t intid)
static const uint32_t GICR_CTLR_DPG1S
std::vector< uint8_t > irqGroup
std::vector< uint8_t > irqPriority
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
void activateIRQ(uint32_t int_id)
Gicv3Redistributor(Gicv3 *gic, uint32_t cpu_id)
static const uint32_t GICR_WAKER_ChildrenAsleep
std::vector< uint8_t > irqNsacr
void writeEntryLPI(uint32_t intid, uint8_t lpi_entry)
void sendPPInt(uint32_t int_id)
bool isLevelSensitive(uint32_t int_id) const
Gicv3::GroupId getIntGroup(int int_id) const
void serialize(CheckpointOut &cp) const override
Serialize an object.
void copy(Gicv3Registers *from, Gicv3Registers *to)
void deactivateIRQ(uint32_t int_id)
std::vector< Gicv3::IntTriggerType > irqConfig
static const uint32_t SMALLEST_LPI_ID
static const uint32_t GICR_CTLR_DPG1NS
static const uint32_t GICR_CTLR_DPG0
void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
bool treatAsEdgeTriggered(uint32_t int_id) const
This helper is used to check if an interrupt should be treated as edge triggered in the following sce...
static const AddrRange GICR_IPRIORITYR
Gicv3::IntStatus intStatus(uint32_t int_id) const
std::vector< uint8_t > irqGrpmod
Gicv3CPUInterface * cpuInterface
uint64_t read(Addr addr, size_t size, bool is_secure_access)
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void setClrLPI(uint64_t data, bool set)
std::vector< bool > irqPendingIspendr
static void clearRedistRegister(Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr)
Definition gic_v3.cc:98
static void copyRedistRange(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr, size_t size)
Definition gic_v3.cc:105
static void copyRedistRegister(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr)
Definition gic_v3.cc:68
static const int SGI_MAX
Definition gic_v3.hh:119
Gicv3Distributor * getDistributor() const
Definition gic_v3.hh:196
void reserved(const char *fmt, Args... args) const
Definition gic_v3.hh:172
Gicv3CPUInterface * getCPUInterface(int cpu_id) const
Definition gic_v3.hh:189
@ INT_LEVEL_SENSITIVE
Definition gic_v3.hh:142
@ INT_EDGE_TRIGGERED
Definition gic_v3.hh:143
@ INT_ACTIVE_PENDING
Definition gic_v3.hh:129
static const int PPI_MAX
Definition gic_v3.hh:121
void readBlob(Addr addr, void *p, uint64_t size) const
Higher level interfaces based on the above.
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
int size() const
Definition system.hh:210
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition system.hh:323
Threads threads
Definition system.hh:310
ThreadContext is the external interface to all thread state for anything outside of the CPU.
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr start() const
Get the start address of the range.
Addr size() const
Get the size of the address range.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
#define UNSERIALIZE_CONTAINER(member)
Definition serialize.hh:634
#define SERIALIZE_CONTAINER(member)
Definition serialize.hh:626
Affinity getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition utility.cc:221
Bitfield< 11, 0 > affinity
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 27, 24 > gic
Bitfield< 0 > ns
Bitfield< 12, 11 > set
Bitfield< 25, 21 > to
Definition types.hh:96
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
static void activate(const char *expr)
Definition debug.cc:71
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0