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