Deleted Added
sdiff udiff text old ( 14257:0398747c0a91 ) new ( 14258:c75d22c32dec )
full compact
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 * Authors: Jairo Balart
41 */
42
43#include "dev/arm/gic_v3_distributor.hh"
44
45#include <algorithm>
46
47#include "base/intmath.hh"
48#include "debug/GIC.hh"
49#include "dev/arm/gic_v3.hh"
50#include "dev/arm/gic_v3_cpu_interface.hh"
51#include "dev/arm/gic_v3_redistributor.hh"
52
53const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff);
54const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f);
55const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff);
56const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f);
57const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff);
58const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f);
59const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff);
60const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
61const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff);
62const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff);
63const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f);
64const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff);
65const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f);
66const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f);
67const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0);
68
69Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines)
70 : gic(gic),
71 itLines(it_lines),
72 irqGroup(it_lines),
73 irqEnabled(it_lines),
74 irqPending(it_lines),
75 irqActive(it_lines),
76 irqPriority(it_lines),
77 irqConfig(it_lines),
78 irqGrpmod(it_lines),
79 irqNsacr(it_lines),
80 irqAffinityRouting(it_lines),
81 gicdTyper(0),
82 gicdPidr0(0x92),
83 gicdPidr1(0xb4),
84 gicdPidr2(0x3b),
85 gicdPidr3(0),
86 gicdPidr4(0x44)
87{
88 panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
89 /*
90 * RSS [26] == 1
91 * (The implementation does supports targeted SGIs with affinity
92 * level 0 values of 0 - 255)
93 * No1N [25] == 1
94 * (1 of N SPI interrupts are not supported)
95 * A3V [24] == 1
96 * (Supports nonzero values of Affinity level 3)
97 * IDbits [23:19] == 0xf
98 * (The number of interrupt identifier bits supported, minus one)
99 * DVIS [18] == 0
100 * (The implementation does not support Direct Virtual LPI
101 * injection)
102 * LPIS [17] == 1
103 * (The implementation does not support LPIs)
104 * MBIS [16] == 1
105 * (The implementation supports message-based interrupts
106 * by writing to Distributor registers)
107 * SecurityExtn [10] == X
108 * (The GIC implementation supports two Security states)
109 * CPUNumber [7:5] == 0
110 * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
111 * ITLinesNumber [4:0] == N
112 * (MaxSPIIntId = 32 (N + 1) - 1)
113 */
114 int max_spi_int_id = itLines - 1;
115 int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1;
116 gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) |
117 (1 << 17) | (1 << 16) |
118 ((gic->getSystem()->haveSecurity() ? 1 : 0) << 10) |
119 (it_lines_number << 0);
120}
121
122void
123Gicv3Distributor::init()
124{
125}
126
127void
128Gicv3Distributor::initState()
129{
130 reset();
131}
132
133void
134Gicv3Distributor::reset()
135{
136 std::fill(irqGroup.begin(), irqGroup.end(), 0);
137 // Imp. defined reset value
138 std::fill(irqEnabled.begin(), irqEnabled.end(), false);
139 std::fill(irqPending.begin(), irqPending.end(), false);
140 std::fill(irqActive.begin(), irqActive.end(), false);
141 // Imp. defined reset value
142 std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA);
143 std::fill(irqConfig.begin(), irqConfig.end(),
144 Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value
145 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
146 std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
147 /*
148 * For our implementation affinity routing is always enabled,
149 * no GICv2 legacy
150 */
151 ARE = true;
152
153 if (gic->getSystem()->haveSecurity()) {
154 DS = false;
155 } else {
156 DS = true;
157 }
158
159 EnableGrp0 = 0;
160 EnableGrp1NS = 0;
161 EnableGrp1S = 0;
162}
163
164uint64_t
165Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
166{
167 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
168 uint64_t val = 0x0;
169
170 if (!DS && !is_secure_access) {
171 // RAZ/WI for non-secure accesses
172 return 0;
173 }
174
175 int first_intid = (addr - GICD_IGROUPR.start()) * 8;
176
177 if (isNotSPI(first_intid)) {
178 return 0;
179 }
180
181 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
182 i++, int_id++) {
183 val |= irqGroup[int_id] << i;
184 }
185
186 return val;
187 } else if (GICD_ISENABLER.contains(addr)) {
188 // Interrupt Set-Enable Registers
189 uint64_t val = 0x0;
190 int first_intid = (addr - GICD_ISENABLER.start()) * 8;
191
192 if (isNotSPI(first_intid)) {
193 return 0;
194 }
195
196 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
197 i++, int_id++) {
198
199 if (nsAccessToSecInt(int_id, is_secure_access))
200 {
201 continue;
202 }
203
204 val |= irqEnabled[int_id] << i;
205 }
206
207 return val;
208 } else if (GICD_ICENABLER.contains(addr)) {
209 // Interrupt Clear-Enable Registers
210 uint64_t val = 0x0;
211 int first_intid = (addr - GICD_ICENABLER.start()) * 8;
212
213 if (isNotSPI(first_intid)) {
214 return 0;
215 }
216
217 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
218 i++, int_id++) {
219
220 if (nsAccessToSecInt(int_id, is_secure_access))
221 {
222 continue;
223 }
224
225 val |= (irqEnabled[int_id] << i);
226 }
227
228 return val;
229 } else if (GICD_ISPENDR.contains(addr)) {
230 // Interrupt Set-Pending Registers
231 uint64_t val = 0x0;
232 int first_intid = (addr - GICD_ISPENDR.start()) * 8;
233
234 if (isNotSPI(first_intid)) {
235 return 0;
236 }
237
238 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
239 i++, int_id++) {
240
241 if (nsAccessToSecInt(int_id, is_secure_access))
242 {
243 if (irqNsacr[int_id] == 0) {
244 // Group 0 or Secure Group 1 interrupts are RAZ/WI
245 continue;
246 }
247 }
248
249 val |= (irqPending[int_id] << i);
250 }
251
252 return val;
253 } else if (GICD_ICPENDR.contains(addr)) {
254 // Interrupt Clear-Pending Registers
255 uint64_t val = 0x0;
256 int first_intid = (addr - GICD_ICPENDR.start()) * 8;
257
258 if (isNotSPI(first_intid)) {
259 return 0;
260 }
261
262 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
263 i++, int_id++) {
264
265 if (nsAccessToSecInt(int_id, is_secure_access))
266 {
267 if (irqNsacr[int_id] < 2) {
268 // Group 0 or Secure Group 1 interrupts are RAZ/WI
269 continue;
270 }
271 }
272
273 val |= (irqPending[int_id] << i);
274 }
275
276 return val;
277 } else if (GICD_ISACTIVER.contains(addr)) {
278 // Interrupt Set-Active Registers
279 int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
280
281 if (isNotSPI(first_intid)) {
282 return 0;
283 }
284
285 uint64_t val = 0x0;
286
287 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
288 i++, int_id++) {
289
290 if (nsAccessToSecInt(int_id, is_secure_access))
291 {
292 // Group 0 or Secure Group 1 interrupts are RAZ/WI
293 if (irqNsacr[int_id] < 2) {
294 continue;
295 }
296 }
297
298 val |= (irqActive[int_id] << i);
299 }
300
301 return val;
302 } else if (GICD_ICACTIVER.contains(addr)) {
303 // Interrupt Clear-Active Registers
304 int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
305
306 if (isNotSPI(first_intid)) {
307 return 0;
308 }
309
310 uint64_t val = 0x0;
311
312 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
313 i++, int_id++) {
314
315 if (nsAccessToSecInt(int_id, is_secure_access))
316 {
317 if (irqNsacr[int_id] < 2) {
318 continue;
319 }
320 }
321
322 val |= (irqActive[int_id] << i);
323 }
324
325 return val;
326 } else if (GICD_IPRIORITYR.contains(addr)) {
327 // Interrupt Priority Registers
328 uint64_t val = 0x0;
329 int first_intid = addr - GICD_IPRIORITYR.start();
330
331 if (isNotSPI(first_intid)) {
332 return 0;
333 }
334
335 for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
336 i++, int_id++) {
337
338 uint8_t prio = irqPriority[int_id];
339
340 if (!DS && !is_secure_access) {
341 if (getIntGroup(int_id) != Gicv3::G1NS) {
342 // RAZ/WI for non-secure accesses for secure interrupts
343 continue;
344 } else {
345 // NS view
346 prio = (prio << 1) & 0xff;
347 }
348 }
349
350 val |= prio << (i * 8);
351 }
352
353 return val;
354 } else if (GICD_ITARGETSR.contains(addr)) {
355 // Interrupt Processor Targets Registers
356 // ARE always on, RAZ/WI
357 warn("Gicv3Distributor::read(): "
358 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
359 return 0;
360 } else if (GICD_ICFGR.contains(addr)) {
361 // Interrupt Configuration Registers
362 int first_intid = (addr - GICD_ICFGR.start()) * 4;
363
364 if (isNotSPI(first_intid)) {
365 return 0;
366 }
367
368 uint64_t val = 0x0;
369
370 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
371 i = i + 2, int_id++) {
372
373 if (nsAccessToSecInt(int_id, is_secure_access))
374 {
375 continue;
376 }
377
378 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
379 val |= (0x2 << i);
380 }
381 }
382
383 return val;
384 } else if (GICD_IGRPMODR.contains(addr)) {
385 // Interrupt Group Modifier Registers
386 if (DS) {
387 // RAZ/WI if security disabled
388 return 0;
389 } else {
390 if (!is_secure_access) {
391 // RAZ/WI for non-secure accesses
392 return 0;
393 } else {
394 int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
395
396 if (isNotSPI(first_intid)) {
397 return 0;
398 }
399
400 uint64_t val = 0x0;
401
402 for (int i = 0, int_id = first_intid;
403 i < 8 * size && int_id < itLines; i++, int_id++) {
404 val |= irqGrpmod[int_id] << i;
405 }
406
407 return val;
408 }
409 }
410 } else if (GICD_NSACR.contains(addr)) {
411 // Non-secure Access Control Registers
412 // 2 bits per interrupt
413 int first_intid = (addr - GICD_NSACR.start()) * 4;
414
415 if (isNotSPI(first_intid)) {
416 return 0;
417 }
418
419 if (DS || (!DS && !is_secure_access)) {
420 return 0;
421 }
422
423 uint64_t val = 0x0;
424
425 for (int i = 0, int_id = first_intid;
426 i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
427 val |= irqNsacr[int_id] << i;
428 }
429
430 return val;
431 } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
432 // ARE always on, RAZ/WI
433 warn("Gicv3Distributor::read(): "
434 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
435 return 0x0;
436 } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
437 // ARE always on, RAZ/WI
438 warn("Gicv3Distributor::read(): "
439 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
440 return 0x0;
441 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
442 // 64 bit registers. 2 or 1 access.
443 int int_id = (addr - GICD_IROUTER.start()) / 8;
444
445 if (isNotSPI(int_id)) {
446 return 0;
447 }
448
449 if (nsAccessToSecInt(int_id, is_secure_access))
450 {
451 if (irqNsacr[int_id] < 3) {
452 return 0;
453 }
454 }
455
456 if (size == 4) {
457 if (addr & 7) { // high half of 64 bit register
458 return irqAffinityRouting[int_id] >> 32;
459 } else { // high low of 64 bit register
460 return irqAffinityRouting[int_id] & 0xFFFFFFFF;
461 }
462 } else {
463 return irqAffinityRouting[int_id];
464 }
465 }
466
467 switch (addr) {
468 case GICD_CTLR: // Control Register
469 if (!DS) {
470 if (is_secure_access) {
471 // E1NWF [7] RAZ/WI
472 // DS [6] - Disable Security
473 // ARE_NS [5] RAO/WI
474 // ARE_S [4] RAO/WI
475 // EnableGrp1S [2]
476 // EnableGrp1NS [1]
477 // EnableGrp0 [0]
478 return (EnableGrp0 << 0) |
479 (EnableGrp1NS << 1) |
480 (EnableGrp1S << 2) |
481 (1 << 4) |
482 (1 << 5) |
483 (DS << 6);
484 } else {
485 // ARE_NS [4] RAO/WI;
486 // EnableGrp1A [1] is a read-write alias of the Secure
487 // GICD_CTLR.EnableGrp1NS
488 // EnableGrp1 [0] RES0
489 return (1 << 4) | (EnableGrp1NS << 1);
490 }
491 } else {
492 return (DS << 6) | (ARE << 4) |
493 (EnableGrp1NS << 1) | (EnableGrp0 << 0);
494 }
495
496 case GICD_TYPER: // Interrupt Controller Type Register
497 return gicdTyper;
498
499 case GICD_IIDR: // Implementer Identification Register
500 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
501 return 0;
502
503 case GICD_STATUSR: // Error Reporting Status Register
504 // Optional register, RAZ/WI
505 return 0x0;
506
507 case GICD_PIDR0: // Peripheral ID0 Register
508 return gicdPidr0;
509
510 case GICD_PIDR1: // Peripheral ID1 Register
511 return gicdPidr1;
512
513 case GICD_PIDR2: // Peripheral ID2 Register
514 return gicdPidr2;
515
516 case GICD_PIDR3: // Peripheral ID3 Register
517 return gicdPidr3;
518
519 case GICD_PIDR4: // Peripheral ID4 Register
520 return gicdPidr4;
521
522 case GICD_PIDR5: // Peripheral ID5 Register
523 case GICD_PIDR6: // Peripheral ID6 Register
524 case GICD_PIDR7: // Peripheral ID7 Register
525 return 0; // RES0
526
527 default:
528 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr);
529 break;
530 }
531}
532
533void
534Gicv3Distributor::write(Addr addr, uint64_t data, size_t size,
535 bool is_secure_access)
536{
537 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
538 if (!DS && !is_secure_access) {
539 // RAZ/WI for non-secure accesses
540 return;
541 }
542
543 int first_intid = (addr - GICD_IGROUPR.start()) * 8;
544
545 if (isNotSPI(first_intid)) {
546 return;
547 }
548
549 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
550 i++, int_id++) {
551 irqGroup[int_id] = data & (1 << i) ? 1 : 0;
552 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
553 int_id, irqGroup[int_id]);
554 }
555
556 return;
557 } else if (GICD_ISENABLER.contains(addr)) {
558 // Interrupt Set-Enable Registers
559 int first_intid = (addr - GICD_ISENABLER.start()) * 8;
560
561 if (isNotSPI(first_intid)) {
562 return;
563 }
564
565 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
566 i++, int_id++) {
567
568 if (nsAccessToSecInt(int_id, is_secure_access))
569 {
570 continue;
571 }
572
573 bool enable = data & (1 << i) ? 1 : 0;
574
575 if (enable) {
576 if (!irqEnabled[int_id]) {
577 DPRINTF(GIC, "Gicv3Distributor::write(): "
578 "int_id %d enabled\n", int_id);
579 }
580
581 irqEnabled[int_id] = true;
582 }
583 }
584
585 return;
586 } else if (GICD_ICENABLER.contains(addr)) {
587 // Interrupt Clear-Enable Registers
588 int first_intid = (addr - GICD_ICENABLER.start()) * 8;
589
590 if (isNotSPI(first_intid)) {
591 return;
592 }
593
594 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
595 i++, int_id++) {
596
597 if (nsAccessToSecInt(int_id, is_secure_access))
598 {
599 continue;
600 }
601
602 bool disable = data & (1 << i) ? 1 : 0;
603
604 if (disable) {
605 if (irqEnabled[int_id]) {
606 DPRINTF(GIC, "Gicv3Distributor::write(): "
607 "int_id %d disabled\n", int_id);
608 }
609
610 irqEnabled[int_id] = false;
611 }
612 }
613
614 return;
615 } else if (GICD_ISPENDR.contains(addr)) {
616 // Interrupt Set-Pending Registers
617 int first_intid = (addr - GICD_ISPENDR.start()) * 8;
618
619 if (isNotSPI(first_intid)) {
620 return;
621 }
622
623 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
624 i++, int_id++) {
625
626 if (nsAccessToSecInt(int_id, is_secure_access))
627 {
628 if (irqNsacr[int_id] == 0) {
629 // Group 0 or Secure Group 1 interrupts are RAZ/WI
630 continue;
631 }
632 }
633
634 bool pending = data & (1 << i) ? 1 : 0;
635
636 if (pending) {
637 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
638 "int_id %d (SPI) pending bit set\n", int_id);
639 irqPending[int_id] = true;
640 }
641 }
642
643 update();
644 return;
645 } else if (GICD_ICPENDR.contains(addr)) {
646 // Interrupt Clear-Pending Registers
647 int first_intid = (addr - GICD_ICPENDR.start()) * 8;
648
649 if (isNotSPI(first_intid)) {
650 return;
651 }
652
653 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
654 i++, int_id++) {
655
656 if (nsAccessToSecInt(int_id, is_secure_access))
657 {
658 if (irqNsacr[int_id] < 2) {
659 // Group 0 or Secure Group 1 interrupts are RAZ/WI
660 continue;
661 }
662 }
663
664 bool clear = data & (1 << i) ? 1 : 0;
665
666 if (clear) {
667 irqPending[int_id] = false;
668 clearIrqCpuInterface(int_id);
669 }
670 }
671
672 update();
673 return;
674 } else if (GICD_ISACTIVER.contains(addr)) {
675 // Interrupt Set-Active Registers
676 int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
677
678 if (isNotSPI(first_intid)) {
679 return;
680 }
681
682 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
683 i++, int_id++) {
684
685 if (nsAccessToSecInt(int_id, is_secure_access))
686 {
687 continue;
688 }
689
690 bool active = data & (1 << i) ? 1 : 0;
691
692 if (active) {
693 irqActive[int_id] = 1;
694 }
695 }
696
697 return;
698 } else if (GICD_ICACTIVER.contains(addr)) {
699 // Interrupt Clear-Active Registers
700 int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
701
702 if (isNotSPI(first_intid)) {
703 return;
704 }
705
706 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
707 i++, int_id++) {
708
709 if (nsAccessToSecInt(int_id, is_secure_access))
710 {
711 continue;
712 }
713
714 bool clear = data & (1 << i) ? 1 : 0;
715
716 if (clear) {
717 if (irqActive[int_id]) {
718 DPRINTF(GIC, "Gicv3Distributor::write(): "
719 "int_id %d active cleared\n", int_id);
720 }
721
722 irqActive[int_id] = false;
723 }
724 }
725
726 return;
727 } else if (GICD_IPRIORITYR.contains(addr)) {
728 // Interrupt Priority Registers
729 int first_intid = addr - GICD_IPRIORITYR.start();
730
731 if (isNotSPI(first_intid)) {
732 return;
733 }
734
735 for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
736 i++, int_id++) {
737 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
738
739 if (!DS && !is_secure_access) {
740 if (getIntGroup(int_id) != Gicv3::G1NS) {
741 // RAZ/WI for non-secure accesses to secure interrupts
742 continue;
743 } else {
744 prio = 0x80 | (prio >> 1);
745 }
746 }
747
748 irqPriority[int_id] = prio;
749 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
750 int_id, irqPriority[int_id]);
751 }
752
753 return;
754 } else if (GICD_ITARGETSR.contains(addr)) {
755 // Interrupt Processor Targets Registers
756 // ARE always on, RAZ/WI
757 warn("Gicv3Distributor::write(): "
758 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
759 return;
760 } else if (GICD_ICFGR.contains(addr)) {
761 // Interrupt Configuration Registers
762 // for x = 0 to 15:
763 // GICD_ICFGR[2x] = RES0
764 // GICD_ICFGR[2x + 1] =
765 // 0 level-sensitive
766 // 1 edge-triggered
767 int first_intid = (addr - GICD_ICFGR.start()) * 4;
768
769 if (isNotSPI(first_intid)) {
770 return;
771 }
772
773 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
774 i = i + 2, int_id++) {
775 irqConfig[int_id] = data & (0x2 << i) ?
776 Gicv3::INT_EDGE_TRIGGERED :
777 Gicv3::INT_LEVEL_SENSITIVE;
778 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
779 int_id, irqConfig[int_id]);
780 }
781
782 return;
783 } else if (GICD_IGRPMODR.contains(addr)) {
784 // Interrupt Group Modifier Registers
785 if (DS) {
786 return;
787 } else {
788 if (!is_secure_access) {
789 // RAZ/WI for non-secure accesses
790 return;
791 } else {
792 int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
793
794 if (isNotSPI(first_intid)) {
795 return;
796 }
797
798 for (int i = 0, int_id = first_intid;
799 i < 8 * size && int_id < itLines; i++, int_id++) {
800 irqGrpmod[int_id] = bits(data, i);
801 }
802
803 return ;
804 }
805 }
806
807 } else if (GICD_NSACR.contains(addr)) {
808 // Non-secure Access Control Registers
809 // 2 bits per interrupt
810 int first_intid = (addr - GICD_NSACR.start()) * 4;
811
812 if (isNotSPI(first_intid)) {
813 return;
814 }
815
816 if (DS || (!DS && !is_secure_access)) {
817 return;
818 }
819
820 for (int i = 0, int_id = first_intid;
821 i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
822 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
823 }
824
825 return;
826 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
827 // 64 bit registers. 2 accesses.
828 int int_id = (addr - GICD_IROUTER.start()) / 8;
829
830 if (isNotSPI(int_id)) {
831 return;
832 }
833
834 if (nsAccessToSecInt(int_id, is_secure_access))
835 {
836 if (irqNsacr[int_id] < 3) {
837 // Group 0 or Secure Group 1 interrupts are RAZ/WI
838 return;
839 }
840 }
841
842 if (size == 4) {
843 if (addr & 7) { // high half of 64 bit register
844 irqAffinityRouting[int_id] =
845 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
846 } else { // low half of 64 bit register
847 irqAffinityRouting[int_id] =
848 (irqAffinityRouting[int_id] & 0xffffffff00000000) |
849 (data & 0xffffffff);
850 }
851 } else {
852 irqAffinityRouting[int_id] = data;
853 }
854
855 DPRINTF(GIC, "Gicv3Distributor::write(): "
856 "int_id %d GICD_IROUTER %#llx\n",
857 int_id, irqAffinityRouting[int_id]);
858 return;
859 }
860
861 switch (addr) {
862 case GICD_CTLR: // Control Register
863 if (DS) {
864 /*
865 * E1NWF [7]
866 * 1 of N wakeup functionality not supported, RAZ/WI
867 * DS [6] - RAO/WI
868 * ARE [4]
869 * affinity routing always on, no GICv2 legacy, RAO/WI
870 * EnableGrp1 [1]
871 * EnableGrp0 [0]
872 */
873 if ((data & (1 << 4)) == 0) {
874 warn("Gicv3Distributor::write(): "
875 "setting ARE to 0 is not supported!\n");
876 }
877
878 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
879 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
880 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
881 "EnableGrp1NS %d EnableGrp0 %d\n",
882 EnableGrp1NS, EnableGrp0);
883 } else {
884 if (is_secure_access) {
885 /*
886 * E1NWF [7]
887 * 1 of N wakeup functionality not supported, RAZ/WI
888 * DS [6]
889 * ARE_NS [5]
890 * affinity routing always on, no GICv2 legacy, RAO/WI
891 * ARE_S [4]
892 * affinity routing always on, no GICv2 legacy, RAO/WI
893 * EnableGrp1S [2]
894 * EnableGrp1NS [1]
895 * EnableGrp0 [0]
896 */
897 if ((data & (1 << 5)) == 0) {
898 warn("Gicv3Distributor::write(): "
899 "setting ARE_NS to 0 is not supported!\n");
900 }
901
902 if ((data & (1 << 4)) == 0) {
903 warn("Gicv3Distributor::write(): "
904 "setting ARE_S to 0 is not supported!\n");
905 }
906
907 DS = data & GICD_CTLR_DS;
908 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S;
909 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
910 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
911 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
912 "DS %d "
913 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
914 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0);
915
916 if (data & GICD_CTLR_DS) {
917 EnableGrp1S = 0;
918 }
919 } else {
920 /*
921 * ARE_NS [4] RAO/WI;
922 * EnableGrp1A [1] is a read-write alias of the Secure
923 * GICD_CTLR.EnableGrp1NS
924 * EnableGrp1 [0] RES0
925 */
926 if ((data & (1 << 4)) == 0) {
927 warn("Gicv3Distributor::write(): "
928 "setting ARE_NS to 0 is not supported!\n");
929 }
930
931 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A;
932 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
933 "EnableGrp1NS %d\n", EnableGrp1NS);
934 }
935 }
936
937 update();
938
939 break;
940
941 case GICD_SGIR: // Error Reporting Status Register
942 // Only if affinity routing is disabled, RES0
943 break;
944
945 case GICD_SETSPI_NSR: {
946 // Writes to this register have no effect if:
947 // * The value written specifies an invalid SPI.
948 // * The SPI is already pending.
949 // * The value written specifies a Secure SPI, the value is
950 // written by a Non-secure access, and the value of the
951 // corresponding GICD_NSACR<n> register is 0.
952 const uint32_t intid = bits(data, 9, 0);
953 if (isNotSPI(intid) || irqPending[intid] ||
954 (nsAccessToSecInt(intid, is_secure_access) &&
955 irqNsacr[intid] == 0)) {
956 return;
957 } else {
958 // Valid SPI, set interrupt pending
959 sendInt(intid);
960 }
961 break;
962 }
963
964 case GICD_CLRSPI_NSR: {
965 // Writes to this register have no effect if:
966 // * The value written specifies an invalid SPI.
967 // * The SPI is not pending.
968 // * The value written specifies a Secure SPI, the value is
969 // written by a Non-secure access, and the value of the
970 // corresponding GICD_NSACR<n> register is less than 0b10.
971 const uint32_t intid = bits(data, 9, 0);
972 if (isNotSPI(intid) || !irqPending[intid] ||
973 (nsAccessToSecInt(intid, is_secure_access) &&
974 irqNsacr[intid] < 2)) {
975 return;
976 } else {
977 // Valid SPI, clear interrupt pending
978 deassertSPI(intid);
979 }
980 break;
981 }
982
983 case GICD_SETSPI_SR: {
984 // Writes to this register have no effect if:
985 // * GICD_CTLR.DS = 1 (WI)
986 // * The value written specifies an invalid SPI.
987 // * The SPI is already pending.
988 // * The value is written by a Non-secure access.
989 const uint32_t intid = bits(data, 9, 0);
990 if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) {
991 return;
992 } else {
993 // Valid SPI, set interrupt pending
994 sendInt(intid);
995 }
996 break;
997 }
998
999 case GICD_CLRSPI_SR: {
1000 // Writes to this register have no effect if:
1001 // * GICD_CTLR.DS = 1 (WI)
1002 // * The value written specifies an invalid SPI.
1003 // * The SPI is not pending.
1004 // * The value is written by a Non-secure access.
1005 const uint32_t intid = bits(data, 9, 0);
1006 if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) {
1007 return;
1008 } else {
1009 // Valid SPI, clear interrupt pending
1010 deassertSPI(intid);
1011 }
1012 break;
1013 }
1014
1015 default:
1016 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr);
1017 break;
1018 }
1019}
1020
1021void
1022Gicv3Distributor::sendInt(uint32_t int_id)
1023{
1024 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1025 panic_if(int_id > itLines, "Invalid SPI!");
1026 irqPending[int_id] = true;
1027 DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
1028 "int_id %d (SPI) pending bit set\n", int_id);
1029 update();
1030}
1031
1032void
1033Gicv3Distributor::deassertSPI(uint32_t int_id)
1034{
1035 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1036 panic_if(int_id > itLines, "Invalid SPI!");
1037 irqPending[int_id] = false;
1038 clearIrqCpuInterface(int_id);
1039
1040 update();
1041}
1042
1043Gicv3CPUInterface*
1044Gicv3Distributor::route(uint32_t int_id)
1045{
1046 IROUTER affinity_routing = irqAffinityRouting[int_id];
1047 Gicv3Redistributor * target_redistributor = nullptr;
1048
1049 const Gicv3::GroupId int_group = getIntGroup(int_id);
1050
1051 if (affinity_routing.IRM) {
1052 // Interrupts routed to any PE defined as a participating node
1053 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1054 Gicv3Redistributor * redistributor_i =
1055 gic->getRedistributor(i);
1056
1057 if (redistributor_i->
1058 canBeSelectedFor1toNInterrupt(int_group)) {
1059 target_redistributor = redistributor_i;
1060 break;
1061 }
1062 }
1063 } else {
1064 uint32_t affinity = (affinity_routing.Aff3 << 24) |
1065 (affinity_routing.Aff2 << 16) |
1066 (affinity_routing.Aff1 << 8) |
1067 (affinity_routing.Aff0 << 0);
1068 target_redistributor =
1069 gic->getRedistributorByAffinity(affinity);
1070 }
1071
1072 if (!target_redistributor) {
1073 // Interrrupts targeting not present cpus must remain pending
1074 return nullptr;
1075 } else {
1076 return target_redistributor->getCPUInterface();
1077 }
1078}
1079
1080void
1081Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id)
1082{
1083 auto cpu_interface = route(int_id);
1084 if (cpu_interface)
1085 cpu_interface->hppi.prio = 0xff;
1086}
1087
1088void
1089Gicv3Distributor::update()
1090{
1091 // Find the highest priority pending SPI
1092 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
1093 int_id++) {
1094 Gicv3::GroupId int_group = getIntGroup(int_id);
1095 bool group_enabled = groupEnabled(int_group);
1096
1097 if (irqPending[int_id] && irqEnabled[int_id] &&
1098 !irqActive[int_id] && group_enabled) {
1099
1100 // Find the cpu interface where to route the interrupt
1101 Gicv3CPUInterface *target_cpu_interface = route(int_id);
1102
1103 // Invalid routing
1104 if (!target_cpu_interface) continue;
1105
1106 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
1107 (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
1108 int_id < target_cpu_interface->hppi.intid)) {
1109
1110 target_cpu_interface->hppi.intid = int_id;
1111 target_cpu_interface->hppi.prio = irqPriority[int_id];
1112 target_cpu_interface->hppi.group = int_group;
1113 }
1114 }
1115 }
1116
1117 // Update all redistributors
1118 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1119 gic->getRedistributor(i)->update();
1120 }
1121}
1122
1123Gicv3::IntStatus
1124Gicv3Distributor::intStatus(uint32_t int_id) const
1125{
1126 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1127 panic_if(int_id > itLines, "Invalid SPI!");
1128
1129 if (irqPending[int_id]) {
1130 if (irqActive[int_id]) {
1131 return Gicv3::INT_ACTIVE_PENDING;
1132 }
1133
1134 return Gicv3::INT_PENDING;
1135 } else if (irqActive[int_id]) {
1136 return Gicv3::INT_ACTIVE;
1137 } else {
1138 return Gicv3::INT_INACTIVE;
1139 }
1140}
1141
1142Gicv3::GroupId
1143Gicv3Distributor::getIntGroup(int int_id) const
1144{
1145 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1146 panic_if(int_id > itLines, "Invalid SPI!");
1147
1148 if (DS) {
1149 if (irqGroup[int_id] == 1) {
1150 return Gicv3::G1NS;
1151 } else {
1152 return Gicv3::G0S;
1153 }
1154 } else {
1155 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
1156 return Gicv3::G0S;
1157 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
1158 return Gicv3::G1NS;
1159 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
1160 return Gicv3::G1S;
1161 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
1162 return Gicv3::G1NS;
1163 }
1164 }
1165
1166 M5_UNREACHABLE;
1167}
1168
1169void
1170Gicv3Distributor::activateIRQ(uint32_t int_id)
1171{
1172 irqPending[int_id] = false;
1173 irqActive[int_id] = true;
1174}
1175
1176void
1177Gicv3Distributor::deactivateIRQ(uint32_t int_id)
1178{
1179 irqActive[int_id] = false;
1180}
1181
1182void
1183Gicv3Distributor::serialize(CheckpointOut & cp) const
1184{
1185 SERIALIZE_SCALAR(ARE);
1186 SERIALIZE_SCALAR(DS);
1187 SERIALIZE_SCALAR(EnableGrp1S);
1188 SERIALIZE_SCALAR(EnableGrp1NS);
1189 SERIALIZE_SCALAR(EnableGrp0);
1190 SERIALIZE_CONTAINER(irqGroup);
1191 SERIALIZE_CONTAINER(irqEnabled);
1192 SERIALIZE_CONTAINER(irqPending);
1193 SERIALIZE_CONTAINER(irqActive);
1194 SERIALIZE_CONTAINER(irqPriority);
1195 SERIALIZE_CONTAINER(irqConfig);
1196 SERIALIZE_CONTAINER(irqGrpmod);
1197 SERIALIZE_CONTAINER(irqNsacr);
1198 SERIALIZE_CONTAINER(irqAffinityRouting);
1199}
1200
1201void
1202Gicv3Distributor::unserialize(CheckpointIn & cp)
1203{
1204 UNSERIALIZE_SCALAR(ARE);
1205 UNSERIALIZE_SCALAR(DS);
1206 UNSERIALIZE_SCALAR(EnableGrp1S);
1207 UNSERIALIZE_SCALAR(EnableGrp1NS);
1208 UNSERIALIZE_SCALAR(EnableGrp0);
1209 UNSERIALIZE_CONTAINER(irqGroup);
1210 UNSERIALIZE_CONTAINER(irqEnabled);
1211 UNSERIALIZE_CONTAINER(irqPending);
1212 UNSERIALIZE_CONTAINER(irqActive);
1213 UNSERIALIZE_CONTAINER(irqPriority);
1214 UNSERIALIZE_CONTAINER(irqConfig);
1215 UNSERIALIZE_CONTAINER(irqGrpmod);
1216 UNSERIALIZE_CONTAINER(irqNsacr);
1217 UNSERIALIZE_CONTAINER(irqAffinityRouting);
1218}