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