gem5 v24.0.0.0
Loading...
Searching...
No Matches
gic_v3_distributor.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019-2022 Arm Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
42
43#include <algorithm>
44
45#include "base/compiler.hh"
46#include "base/intmath.hh"
47#include "debug/GIC.hh"
48#include "dev/arm/gic_v3.hh"
51
52namespace gem5
53{
54
55const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x0100);
56const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x0180);
57const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x0200);
58const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x0280);
59const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x0300);
60const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x0380);
61const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x0400);
62const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x0800);
63const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x0c00);
64const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0d00);
65const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d80);
66const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0f00);
67const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f20);
68const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f30);
69const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0);
70
72 : gic(gic),
73 itLines(it_lines),
74 ARE(true),
75 EnableGrp1S(0),
76 EnableGrp1NS(0),
77 EnableGrp0(0),
78 irqGroup(it_lines, 0),
79 irqEnabled(it_lines, false),
80 irqPending(it_lines, false),
81 irqPendingIspendr(it_lines, false),
82 irqActive(it_lines, false),
83 irqPriority(it_lines, 0xAA),
84 irqConfig(it_lines, Gicv3::INT_LEVEL_SENSITIVE),
85 irqGrpmod(it_lines, 0),
86 irqNsacr(it_lines, 0),
87 irqAffinityRouting(it_lines, 0),
88 gicdTyper(0),
89 gicdPidr0(0x92),
90 gicdPidr1(0xb4),
91 gicdPidr2(gic->params().gicv4 ? 0x4b : 0x3b),
92 gicdPidr3(0),
93 gicdPidr4(0x44)
94{
95 panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
96 /*
97 * RSS [26] == 1
98 * (The implementation does supports targeted SGIs with affinity
99 * level 0 values of 0 - 255)
100 * No1N [25] == 1
101 * (1 of N SPI interrupts are not supported)
102 * A3V [24] == 1
103 * (Supports nonzero values of Affinity level 3)
104 * IDbits [23:19] == 0xf
105 * (The number of interrupt identifier bits supported, minus one)
106 * DVIS [18] == 0
107 * (The implementation does not support Direct Virtual LPI
108 * injection)
109 * LPIS [17] == 1
110 * (The implementation does not support LPIs)
111 * MBIS [16] == 1
112 * (The implementation supports message-based interrupts
113 * by writing to Distributor registers)
114 * SecurityExtn [10] == X
115 * (The GIC implementation supports two Security states)
116 * CPUNumber [7:5] == 0
117 * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
118 * ITLinesNumber [4:0] == N
119 * (MaxSPIIntId = 32 (N + 1) - 1)
120 */
121 bool have_security = gic->getSystem()->has(ArmExtension::SECURITY);
122 int max_spi_int_id = itLines - 1;
123 int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1;
124 gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) |
125 (1 << 17) | (1 << 16) |
126 ((have_security ? 1 : 0) << 10) |
127 (it_lines_number << 0);
128
129 if (have_security) {
130 DS = false;
131 } else {
132 DS = true;
133 }
134}
135
136void
140
141uint64_t
142Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
143{
144 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
145 uint64_t val = 0x0;
146
147 if (!DS && !is_secure_access) {
148 // RAZ/WI for non-secure accesses
149 return 0;
150 }
151
152 int first_intid = (addr - GICD_IGROUPR.start()) * 8;
153
154 if (isNotSPI(first_intid)) {
155 return 0;
156 }
157
158 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
159 i++, int_id++) {
160 val |= irqGroup[int_id] << i;
161 }
162
163 return val;
164 } else if (GICD_ISENABLER.contains(addr)) {
165 // Interrupt Set-Enable Registers
166 uint64_t val = 0x0;
167 int first_intid = (addr - GICD_ISENABLER.start()) * 8;
168
169 if (isNotSPI(first_intid)) {
170 return 0;
171 }
172
173 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
174 i++, int_id++) {
175
176 if (nsAccessToSecInt(int_id, is_secure_access))
177 {
178 continue;
179 }
180
181 val |= irqEnabled[int_id] << i;
182 }
183
184 return val;
185 } else if (GICD_ICENABLER.contains(addr)) {
186 // Interrupt Clear-Enable Registers
187 uint64_t val = 0x0;
188 int first_intid = (addr - GICD_ICENABLER.start()) * 8;
189
190 if (isNotSPI(first_intid)) {
191 return 0;
192 }
193
194 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
195 i++, int_id++) {
196
197 if (nsAccessToSecInt(int_id, is_secure_access))
198 {
199 continue;
200 }
201
202 val |= (irqEnabled[int_id] << i);
203 }
204
205 return val;
206 } else if (GICD_ISPENDR.contains(addr)) {
207 // Interrupt Set-Pending Registers
208 uint64_t val = 0x0;
209 int first_intid = (addr - GICD_ISPENDR.start()) * 8;
210
211 if (isNotSPI(first_intid)) {
212 return 0;
213 }
214
215 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
216 i++, int_id++) {
217
218 if (nsAccessToSecInt(int_id, is_secure_access))
219 {
220 if (irqNsacr[int_id] == 0) {
221 // Group 0 or Secure Group 1 interrupts are RAZ/WI
222 continue;
223 }
224 }
225
226 val |= (irqPending[int_id] << i);
227 }
228
229 return val;
230 } else if (GICD_ICPENDR.contains(addr)) {
231 // Interrupt Clear-Pending Registers
232 uint64_t val = 0x0;
233 int first_intid = (addr - GICD_ICPENDR.start()) * 8;
234
235 if (isNotSPI(first_intid)) {
236 return 0;
237 }
238
239 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
240 i++, int_id++) {
241
242 if (nsAccessToSecInt(int_id, is_secure_access))
243 {
244 if (irqNsacr[int_id] < 2) {
245 // Group 0 or Secure Group 1 interrupts are RAZ/WI
246 continue;
247 }
248 }
249
250 val |= (irqPending[int_id] << i);
251 }
252
253 return val;
254 } else if (GICD_ISACTIVER.contains(addr)) {
255 // Interrupt Set-Active Registers
256 int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
257
258 if (isNotSPI(first_intid)) {
259 return 0;
260 }
261
262 uint64_t val = 0x0;
263
264 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
265 i++, int_id++) {
266
267 if (nsAccessToSecInt(int_id, is_secure_access))
268 {
269 // Group 0 or Secure Group 1 interrupts are RAZ/WI
270 if (irqNsacr[int_id] < 2) {
271 continue;
272 }
273 }
274
275 val |= (irqActive[int_id] << i);
276 }
277
278 return val;
279 } else if (GICD_ICACTIVER.contains(addr)) {
280 // Interrupt Clear-Active Registers
281 int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
282
283 if (isNotSPI(first_intid)) {
284 return 0;
285 }
286
287 uint64_t val = 0x0;
288
289 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
290 i++, int_id++) {
291
292 if (nsAccessToSecInt(int_id, is_secure_access))
293 {
294 if (irqNsacr[int_id] < 2) {
295 continue;
296 }
297 }
298
299 val |= (irqActive[int_id] << i);
300 }
301
302 return val;
303 } else if (GICD_IPRIORITYR.contains(addr)) {
304 // Interrupt Priority Registers
305 uint64_t val = 0x0;
306 int first_intid = addr - GICD_IPRIORITYR.start();
307
308 if (isNotSPI(first_intid)) {
309 return 0;
310 }
311
312 for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
313 i++, int_id++) {
314
315 uint8_t prio = irqPriority[int_id];
316
317 if (!DS && !is_secure_access) {
318 if (getIntGroup(int_id) != Gicv3::G1NS) {
319 // RAZ/WI for non-secure accesses for secure interrupts
320 continue;
321 } else {
322 // NS view
323 prio = (prio << 1) & 0xff;
324 }
325 }
326
327 val |= prio << (i * 8);
328 }
329
330 return val;
331 } else if (GICD_ITARGETSR.contains(addr)) {
332 // Interrupt Processor Targets Registers
333 // ARE always on, RAZ/WI
334 warn("Gicv3Distributor::read(): "
335 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
336 return 0;
337 } else if (GICD_ICFGR.contains(addr)) {
338 // Interrupt Configuration Registers
339 int first_intid = (addr - GICD_ICFGR.start()) * 4;
340
341 if (isNotSPI(first_intid)) {
342 return 0;
343 }
344
345 uint64_t val = 0x0;
346
347 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
348 i = i + 2, int_id++) {
349
350 if (nsAccessToSecInt(int_id, is_secure_access))
351 {
352 continue;
353 }
354
355 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
356 val |= (0x2 << i);
357 }
358 }
359
360 return val;
361 } else if (GICD_IGRPMODR.contains(addr)) {
362 // Interrupt Group Modifier Registers
363 if (DS) {
364 // RAZ/WI if security disabled
365 return 0;
366 } else {
367 if (!is_secure_access) {
368 // RAZ/WI for non-secure accesses
369 return 0;
370 } else {
371 int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
372
373 if (isNotSPI(first_intid)) {
374 return 0;
375 }
376
377 uint64_t val = 0x0;
378
379 for (int i = 0, int_id = first_intid;
380 i < 8 * size && int_id < itLines; i++, int_id++) {
381 val |= irqGrpmod[int_id] << i;
382 }
383
384 return val;
385 }
386 }
387 } else if (GICD_NSACR.contains(addr)) {
388 // Non-secure Access Control Registers
389 // 2 bits per interrupt
390 int first_intid = (addr - GICD_NSACR.start()) * 4;
391
392 if (isNotSPI(first_intid)) {
393 return 0;
394 }
395
396 if (DS || (!DS && !is_secure_access)) {
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 = i + 2, int_id++) {
404 val |= irqNsacr[int_id] << i;
405 }
406
407 return val;
408 } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
409 // ARE always on, RAZ/WI
410 warn("Gicv3Distributor::read(): "
411 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
412 return 0x0;
413 } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
414 // ARE always on, RAZ/WI
415 warn("Gicv3Distributor::read(): "
416 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
417 return 0x0;
418 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
419 // 64 bit registers. 2 or 1 access.
420 int int_id = (addr - GICD_IROUTER.start()) / 8;
421
422 if (isNotSPI(int_id)) {
423 return 0;
424 }
425
426 if (nsAccessToSecInt(int_id, is_secure_access))
427 {
428 if (irqNsacr[int_id] < 3) {
429 return 0;
430 }
431 }
432
433 if (size == 4) {
434 if (addr & 7) { // high half of 64 bit register
435 return irqAffinityRouting[int_id] >> 32;
436 } else { // high low of 64 bit register
437 return irqAffinityRouting[int_id] & 0xFFFFFFFF;
438 }
439 } else {
440 return irqAffinityRouting[int_id];
441 }
442 }
443
444 switch (addr) {
445 case GICD_CTLR: // Control Register
446 if (!DS) {
447 if (is_secure_access) {
448 // E1NWF [7] RAZ/WI
449 // DS [6] - Disable Security
450 // ARE_NS [5] RAO/WI
451 // ARE_S [4] RAO/WI
452 // EnableGrp1S [2]
453 // EnableGrp1NS [1]
454 // EnableGrp0 [0]
455 return (EnableGrp0 << 0) |
456 (EnableGrp1NS << 1) |
457 (EnableGrp1S << 2) |
458 (1 << 4) |
459 (1 << 5) |
460 (DS << 6);
461 } else {
462 // ARE_NS [4] RAO/WI;
463 // EnableGrp1A [1] is a read-write alias of the Secure
464 // GICD_CTLR.EnableGrp1NS
465 // EnableGrp1 [0] RES0
466 return (1 << 4) | (EnableGrp1NS << 1);
467 }
468 } else {
469 return (DS << 6) | (ARE << 4) |
470 (EnableGrp1NS << 1) | (EnableGrp0 << 0);
471 }
472
473 case GICD_TYPER: // Interrupt Controller Type Register
474 return gicdTyper;
475
476 case GICD_IIDR: // Implementer Identification Register
477 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
478 return 0;
479
480 case GICD_TYPER2: // Interrupt Controller Type Register 2
481 return 0; // RES0
482
483 case GICD_STATUSR: // Error Reporting Status Register
484 // Optional register, RAZ/WI
485 return 0x0;
486
487 case GICD_PIDR0: // Peripheral ID0 Register
488 return gicdPidr0;
489
490 case GICD_PIDR1: // Peripheral ID1 Register
491 return gicdPidr1;
492
493 case GICD_PIDR2: // Peripheral ID2 Register
494 return gicdPidr2;
495
496 case GICD_PIDR3: // Peripheral ID3 Register
497 return gicdPidr3;
498
499 case GICD_PIDR4: // Peripheral ID4 Register
500 return gicdPidr4;
501
502 case GICD_PIDR5: // Peripheral ID5 Register
503 case GICD_PIDR6: // Peripheral ID6 Register
504 case GICD_PIDR7: // Peripheral ID7 Register
505 return 0; // RES0
506
507 default:
508 gic->reserved("Gicv3Distributor::read(): invalid offset %#x\n", addr);
509 return 0; // RES0
510 }
511}
512
513void
514Gicv3Distributor::write(Addr addr, uint64_t data, size_t size,
515 bool is_secure_access)
516{
517 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
518 if (!DS && !is_secure_access) {
519 // RAZ/WI for non-secure accesses
520 return;
521 }
522
523 int first_intid = (addr - GICD_IGROUPR.start()) * 8;
524
525 if (isNotSPI(first_intid)) {
526 return;
527 }
528
529 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
530 i++, int_id++) {
531 irqGroup[int_id] = data & (1 << i) ? 1 : 0;
532 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
533 int_id, irqGroup[int_id]);
534 }
535
536 return;
537 } else if (GICD_ISENABLER.contains(addr)) {
538 // Interrupt Set-Enable Registers
539 int first_intid = (addr - GICD_ISENABLER.start()) * 8;
540
541 if (isNotSPI(first_intid)) {
542 return;
543 }
544
545 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
546 i++, int_id++) {
547
548 if (nsAccessToSecInt(int_id, is_secure_access))
549 {
550 continue;
551 }
552
553 bool enable = data & (1 << i) ? 1 : 0;
554
555 if (enable) {
556 if (!irqEnabled[int_id]) {
557 DPRINTF(GIC, "Gicv3Distributor::write(): "
558 "int_id %d enabled\n", int_id);
559 }
560
561 irqEnabled[int_id] = true;
562 }
563 }
564
565 return;
566 } else if (GICD_ICENABLER.contains(addr)) {
567 // Interrupt Clear-Enable Registers
568 int first_intid = (addr - GICD_ICENABLER.start()) * 8;
569
570 if (isNotSPI(first_intid)) {
571 return;
572 }
573
574 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
575 i++, int_id++) {
576
577 if (nsAccessToSecInt(int_id, is_secure_access))
578 {
579 continue;
580 }
581
582 bool disable = data & (1 << i) ? 1 : 0;
583
584 if (disable) {
585 if (irqEnabled[int_id]) {
586 DPRINTF(GIC, "Gicv3Distributor::write(): "
587 "int_id %d disabled\n", int_id);
588 }
589
590 irqEnabled[int_id] = false;
591 }
592 }
593
594 return;
595 } else if (GICD_ISPENDR.contains(addr)) {
596 // Interrupt Set-Pending Registers
597 int first_intid = (addr - GICD_ISPENDR.start()) * 8;
598
599 if (isNotSPI(first_intid)) {
600 return;
601 }
602
603 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
604 i++, int_id++) {
605
606 if (nsAccessToSecInt(int_id, is_secure_access))
607 {
608 if (irqNsacr[int_id] == 0) {
609 // Group 0 or Secure Group 1 interrupts are RAZ/WI
610 continue;
611 }
612 }
613
614 bool pending = data & (1 << i) ? 1 : 0;
615
616 if (pending) {
617 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
618 "int_id %d (SPI) pending bit set\n", int_id);
619 irqPending[int_id] = true;
620 irqPendingIspendr[int_id] = true;
621 }
622 }
623
624 update();
625 return;
626 } else if (GICD_ICPENDR.contains(addr)) {
627 // Interrupt Clear-Pending Registers
628 int first_intid = (addr - GICD_ICPENDR.start()) * 8;
629
630 if (isNotSPI(first_intid)) {
631 return;
632 }
633
634 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
635 i++, int_id++) {
636
637 if (nsAccessToSecInt(int_id, is_secure_access))
638 {
639 if (irqNsacr[int_id] < 2) {
640 // Group 0 or Secure Group 1 interrupts are RAZ/WI
641 continue;
642 }
643 }
644
645 bool clear = data & (1 << i) ? 1 : 0;
646
647 if (clear && treatAsEdgeTriggered(int_id)) {
648 irqPending[int_id] = false;
649 clearIrqCpuInterface(int_id);
650 }
651 }
652
653 update();
654 return;
655 } else if (GICD_ISACTIVER.contains(addr)) {
656 // Interrupt Set-Active Registers
657 int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
658
659 if (isNotSPI(first_intid)) {
660 return;
661 }
662
663 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
664 i++, int_id++) {
665
666 if (nsAccessToSecInt(int_id, is_secure_access))
667 {
668 continue;
669 }
670
671 bool active = data & (1 << i) ? 1 : 0;
672
673 if (active) {
674 irqActive[int_id] = 1;
675 }
676 }
677
678 return;
679 } else if (GICD_ICACTIVER.contains(addr)) {
680 // Interrupt Clear-Active Registers
681 int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
682
683 if (isNotSPI(first_intid)) {
684 return;
685 }
686
687 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
688 i++, int_id++) {
689
690 if (nsAccessToSecInt(int_id, is_secure_access))
691 {
692 continue;
693 }
694
695 bool clear = data & (1 << i) ? 1 : 0;
696
697 if (clear) {
698 if (irqActive[int_id]) {
699 DPRINTF(GIC, "Gicv3Distributor::write(): "
700 "int_id %d active cleared\n", int_id);
701 }
702
703 irqActive[int_id] = false;
704 }
705 }
706
707 return;
708 } else if (GICD_IPRIORITYR.contains(addr)) {
709 // Interrupt Priority Registers
710 int first_intid = addr - GICD_IPRIORITYR.start();
711
712 if (isNotSPI(first_intid)) {
713 return;
714 }
715
716 for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
717 i++, int_id++) {
718 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
719
720 if (!DS && !is_secure_access) {
721 if (getIntGroup(int_id) != Gicv3::G1NS) {
722 // RAZ/WI for non-secure accesses to secure interrupts
723 continue;
724 } else {
725 prio = 0x80 | (prio >> 1);
726 }
727 }
728
729 irqPriority[int_id] = prio;
730 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
731 int_id, irqPriority[int_id]);
732 }
733
734 return;
735 } else if (GICD_ITARGETSR.contains(addr)) {
736 // Interrupt Processor Targets Registers
737 // ARE always on, RAZ/WI
738 warn("Gicv3Distributor::write(): "
739 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
740 return;
741 } else if (GICD_ICFGR.contains(addr)) {
742 // Interrupt Configuration Registers
743 // for x = 0 to 15:
744 // GICD_ICFGR[2x] = RES0
745 // GICD_ICFGR[2x + 1] =
746 // 0 level-sensitive
747 // 1 edge-triggered
748 int first_intid = (addr - GICD_ICFGR.start()) * 4;
749
750 if (isNotSPI(first_intid)) {
751 return;
752 }
753
754 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
755 i = i + 2, int_id++) {
756
757 if (nsAccessToSecInt(int_id, is_secure_access)) {
758 continue;
759 }
760
761 irqConfig[int_id] = data & (0x2 << i) ?
764 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
765 int_id, irqConfig[int_id]);
766 }
767
768 return;
769 } else if (GICD_IGRPMODR.contains(addr)) {
770 // Interrupt Group Modifier Registers
771 if (DS) {
772 return;
773 } else {
774 if (!is_secure_access) {
775 // RAZ/WI for non-secure accesses
776 return;
777 } else {
778 int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
779
780 if (isNotSPI(first_intid)) {
781 return;
782 }
783
784 for (int i = 0, int_id = first_intid;
785 i < 8 * size && int_id < itLines; i++, int_id++) {
786 irqGrpmod[int_id] = bits(data, i);
787 }
788
789 return ;
790 }
791 }
792
793 } else if (GICD_NSACR.contains(addr)) {
794 // Non-secure Access Control Registers
795 // 2 bits per interrupt
796 int first_intid = (addr - GICD_NSACR.start()) * 4;
797
798 if (isNotSPI(first_intid)) {
799 return;
800 }
801
802 if (DS || (!DS && !is_secure_access)) {
803 return;
804 }
805
806 for (int i = 0, int_id = first_intid;
807 i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
808 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
809 }
810
811 return;
812 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
813 // 64 bit registers. 2 accesses.
814 int int_id = (addr - GICD_IROUTER.start()) / 8;
815
816 if (isNotSPI(int_id)) {
817 return;
818 }
819
820 if (nsAccessToSecInt(int_id, is_secure_access))
821 {
822 if (irqNsacr[int_id] < 3) {
823 // Group 0 or Secure Group 1 interrupts are RAZ/WI
824 return;
825 }
826 }
827
828 if (size == 4) {
829 if (addr & 7) { // high half of 64 bit register
830 irqAffinityRouting[int_id] =
831 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
832 } else { // low half of 64 bit register
833 irqAffinityRouting[int_id] =
834 (irqAffinityRouting[int_id] & 0xffffffff00000000) |
835 (data & 0xffffffff);
836 }
837 } else {
838 irqAffinityRouting[int_id] = data;
839 }
840
841 DPRINTF(GIC, "Gicv3Distributor::write(): "
842 "int_id %d GICD_IROUTER %#llx\n",
843 int_id, irqAffinityRouting[int_id]);
844 return;
845 }
846
847 switch (addr) {
848 case GICD_CTLR: // Control Register
849 if (DS) {
850 /*
851 * E1NWF [7]
852 * 1 of N wakeup functionality not supported, RAZ/WI
853 * DS [6] - RAO/WI
854 * ARE [4]
855 * affinity routing always on, no GICv2 legacy, RAO/WI
856 * EnableGrp1 [1]
857 * EnableGrp0 [0]
858 */
859 if ((data & (1 << 4)) == 0) {
860 warn("Gicv3Distributor::write(): "
861 "setting ARE to 0 is not supported!\n");
862 }
863
865 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
866 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
867 "EnableGrp1NS %d EnableGrp0 %d\n",
869 } else {
870 if (is_secure_access) {
871 /*
872 * E1NWF [7]
873 * 1 of N wakeup functionality not supported, RAZ/WI
874 * DS [6]
875 * ARE_NS [5]
876 * affinity routing always on, no GICv2 legacy, RAO/WI
877 * ARE_S [4]
878 * affinity routing always on, no GICv2 legacy, RAO/WI
879 * EnableGrp1S [2]
880 * EnableGrp1NS [1]
881 * EnableGrp0 [0]
882 */
883 if ((data & (1 << 5)) == 0) {
884 warn("Gicv3Distributor::write(): "
885 "setting ARE_NS to 0 is not supported!\n");
886 }
887
888 if ((data & (1 << 4)) == 0) {
889 warn("Gicv3Distributor::write(): "
890 "setting ARE_S to 0 is not supported!\n");
891 }
892
893 DS = data & GICD_CTLR_DS;
896 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
897 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
898 "DS %d "
899 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
901
902 if (data & GICD_CTLR_DS) {
903 EnableGrp1S = 0;
904 }
905 } else {
906 /*
907 * ARE_NS [4] RAO/WI;
908 * EnableGrp1A [1] is a read-write alias of the Secure
909 * GICD_CTLR.EnableGrp1NS
910 * EnableGrp1 [0] RES0
911 */
912 if ((data & (1 << 4)) == 0) {
913 warn("Gicv3Distributor::write(): "
914 "setting ARE_NS to 0 is not supported!\n");
915 }
916
918 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
919 "EnableGrp1NS %d\n", EnableGrp1NS);
920 }
921 }
922
923 update();
924
925 break;
926
927 case GICD_SGIR: // Error Reporting Status Register
928 // Only if affinity routing is disabled, RES0
929 break;
930
931 case GICD_SETSPI_NSR: {
932 // Writes to this register have no effect if:
933 // * The value written specifies an invalid SPI.
934 // * The SPI is already pending.
935 // * The value written specifies a Secure SPI, the value is
936 // written by a Non-secure access, and the value of the
937 // corresponding GICD_NSACR<n> register is 0.
938 const uint32_t intid = bits(data, 9, 0);
939 if (isNotSPI(intid) || irqPending[intid] ||
940 (nsAccessToSecInt(intid, is_secure_access) &&
941 irqNsacr[intid] == 0)) {
942 return;
943 } else {
944 // Valid SPI, set interrupt pending
945 sendInt(intid);
946 }
947 break;
948 }
949
950 case GICD_CLRSPI_NSR: {
951 // Writes to this register have no effect if:
952 // * The value written specifies an invalid SPI.
953 // * The SPI is not pending.
954 // * The value written specifies a Secure SPI, the value is
955 // written by a Non-secure access, and the value of the
956 // corresponding GICD_NSACR<n> register is less than 0b10.
957 const uint32_t intid = bits(data, 9, 0);
958 if (isNotSPI(intid) || !irqPending[intid] ||
959 (nsAccessToSecInt(intid, is_secure_access) &&
960 irqNsacr[intid] < 2)) {
961 return;
962 } else {
963 // Valid SPI, clear interrupt pending
964 deassertSPI(intid);
965 }
966 break;
967 }
968
969 case GICD_SETSPI_SR: {
970 // Writes to this register have no effect if:
971 // * GICD_CTLR.DS = 1 (WI)
972 // * The value written specifies an invalid SPI.
973 // * The SPI is already pending.
974 // * The value is written by a Non-secure access.
975 const uint32_t intid = bits(data, 9, 0);
976 if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) {
977 return;
978 } else {
979 // Valid SPI, set interrupt pending
980 sendInt(intid);
981 }
982 break;
983 }
984
985 case GICD_CLRSPI_SR: {
986 // Writes to this register have no effect if:
987 // * GICD_CTLR.DS = 1 (WI)
988 // * The value written specifies an invalid SPI.
989 // * The SPI is not pending.
990 // * The value is written by a Non-secure access.
991 const uint32_t intid = bits(data, 9, 0);
992 if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) {
993 return;
994 } else {
995 // Valid SPI, clear interrupt pending
996 deassertSPI(intid);
997 }
998 break;
999 }
1000
1001 default:
1002 gic->reserved("Gicv3Distributor::write(): invalid offset %#x\n", addr);
1003 break;
1004 }
1005}
1006
1007void
1009{
1010 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1011 panic_if(int_id > itLines, "Invalid SPI!");
1012 irqPending[int_id] = true;
1013 irqPendingIspendr[int_id] = false;
1014 DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
1015 "int_id %d (SPI) pending bit set\n", int_id);
1016 update();
1017}
1018
1019void
1021{
1022 // Edge-triggered interrupts remain pending until software
1023 // writes GICD_ICPENDR, GICD_CLRSPI_* or activates them via ICC_IAR
1024 if (isLevelSensitive(int_id)) {
1025 deassertSPI(int_id);
1026 }
1027}
1028
1029void
1031{
1032 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1033 panic_if(int_id > itLines, "Invalid SPI!");
1034 irqPending[int_id] = false;
1035 clearIrqCpuInterface(int_id);
1036
1037 update();
1038}
1039
1042{
1043 IROUTER affinity_routing = irqAffinityRouting[int_id];
1044 Gicv3Redistributor * target_redistributor = nullptr;
1045
1046 const Gicv3::GroupId int_group = getIntGroup(int_id);
1047
1048 if (affinity_routing.IRM) {
1049 // Interrupts routed to any PE defined as a participating node
1050 for (int i = 0; i < gic->getSystem()->threads.size(); i++) {
1051 Gicv3Redistributor * redistributor_i =
1053
1054 if (redistributor_i->
1055 canBeSelectedFor1toNInterrupt(int_group)) {
1056 target_redistributor = redistributor_i;
1057 break;
1058 }
1059 }
1060 } else {
1061 uint32_t affinity = (affinity_routing.Aff3 << 24) |
1062 (affinity_routing.Aff2 << 16) |
1063 (affinity_routing.Aff1 << 8) |
1064 (affinity_routing.Aff0 << 0);
1065 target_redistributor =
1067 }
1068
1069 if (!target_redistributor) {
1070 // Interrrupts targeting not present cpus must remain pending
1071 return nullptr;
1072 } else {
1073 return target_redistributor->getCPUInterface();
1074 }
1075}
1076
1077void
1079{
1080 auto cpu_interface = route(int_id);
1081 if (cpu_interface)
1082 cpu_interface->resetHppi(int_id);
1083}
1084
1085void
1087{
1088 if (gic->blockIntUpdate())
1089 return;
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()->threads.size(); i++) {
1120 }
1121}
1122
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]) {
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
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 GEM5_UNREACHABLE;
1167}
1168
1169void
1171{
1172 if (treatAsEdgeTriggered(int_id)) {
1173 irqPending[int_id] = false;
1174 }
1175 irqActive[int_id] = true;
1176}
1177
1178void
1180{
1181 irqActive[int_id] = false;
1182}
1183
1184void
1186{
1187 const size_t size = itLines / 8;
1188
1190
1194
1195 gic->copyDistRange(from, to, GICD_IGROUPR.start(), size);
1196 gic->copyDistRange(from, to, GICD_ISENABLER.start(), size);
1197 gic->copyDistRange(from, to, GICD_ISPENDR.start(), size);
1198 gic->copyDistRange(from, to, GICD_ISACTIVER.start(), size);
1199 gic->copyDistRange(from, to, GICD_IPRIORITYR.start(), size);
1200 gic->copyDistRange(from, to, GICD_ITARGETSR.start(), size);
1201 gic->copyDistRange(from, to, GICD_ICFGR.start(), size);
1202 gic->copyDistRange(from, to, GICD_IGRPMODR.start(), size);
1203 gic->copyDistRange(from, to, GICD_NSACR.start(), size);
1204 gic->copyDistRange(from, to, GICD_IROUTER.start(), size);
1205}
1206
1207void
1226
1227void
1246
1247} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
bool has(ArmExtension ext) const
Definition system.hh:158
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
Definition base_gic.hh:130
ArmSystem * getSystem() const
Definition base_gic.hh:114
std::vector< uint8_t > irqPriority
std::vector< bool > irqActive
static const AddrRange GICD_IGROUPR
static const AddrRange GICD_ISPENDR
static const AddrRange GICD_ICFGR
static const AddrRange GICD_ICACTIVER
std::vector< uint8_t > irqGrpmod
void sendInt(uint32_t int_id)
std::vector< bool > irqPending
void unserialize(CheckpointIn &cp) override
Unserialize an object.
std::vector< bool > irqEnabled
static const AddrRange GICD_NSACR
bool groupEnabled(Gicv3::GroupId group) const
bool isNotSPI(uint32_t int_id) const
std::vector< uint8_t > irqNsacr
void clearInt(uint32_t int_id)
static const AddrRange GICD_IGRPMODR
std::vector< uint8_t > irqGroup
std::vector< IROUTER > irqAffinityRouting
static const uint32_t IDBITS
static const AddrRange GICD_ISENABLER
bool treatAsEdgeTriggered(uint32_t int_id) const
This helper is used to check if an interrupt should be treated as edge triggered in the following sce...
Gicv3::IntStatus intStatus(uint32_t int_id) const
void copy(Gicv3Registers *from, Gicv3Registers *to)
static const uint32_t GICD_CTLR_ENABLEGRP1A
std::vector< Gicv3::IntTriggerType > irqConfig
static const AddrRange GICD_SPENDSGIR
void activateIRQ(uint32_t int_id)
Gicv3CPUInterface * route(uint32_t int_id)
static const AddrRange GICD_ICENABLER
static const AddrRange GICD_IROUTER
static const AddrRange GICD_ICPENDR
bool nsAccessToSecInt(uint32_t int_id, bool is_secure_access) const
std::vector< bool > irqPendingIspendr
bool isLevelSensitive(uint32_t int_id) const
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
static const AddrRange GICD_ITARGETSR
void deactivateIRQ(uint32_t int_id)
static const AddrRange GICD_IPRIORITYR
void deassertSPI(uint32_t int_id)
Gicv3::GroupId getIntGroup(int int_id) const
static const uint32_t GICD_CTLR_ENABLEGRP1NS
void clearIrqCpuInterface(uint32_t int_id)
Gicv3Distributor(Gicv3 *gic, uint32_t it_lines)
static const uint32_t GICD_CTLR_ENABLEGRP1S
uint64_t read(Addr addr, size_t size, bool is_secure_access)
static const AddrRange GICD_ISACTIVER
void serialize(CheckpointOut &cp) const override
Serialize an object.
static const uint32_t GICD_CTLR_DS
static const AddrRange GICD_CPENDSGIR
Gicv3CPUInterface * getCPUInterface() const
static void clearDistRange(Gicv3Registers *to, Addr daddr, size_t size)
Definition gic_v3.cc:124
static void copyDistRegister(Gicv3Registers *from, Gicv3Registers *to, Addr daddr)
Definition gic_v3.cc:58
static void copyDistRange(Gicv3Registers *from, Gicv3Registers *to, Addr daddr, size_t size)
Definition gic_v3.cc:115
static const int SGI_MAX
Definition gic_v3.hh:119
Gicv3Redistributor * getRedistributor(ContextID context_id) const
Definition gic_v3.hh:202
void reserved(const char *fmt, Args... args) const
Definition gic_v3.hh:172
@ INT_LEVEL_SENSITIVE
Definition gic_v3.hh:142
@ INT_EDGE_TRIGGERED
Definition gic_v3.hh:143
@ INT_ACTIVE_PENDING
Definition gic_v3.hh:129
static const int PPI_MAX
Definition gic_v3.hh:121
Gicv3Redistributor * getRedistributorByAffinity(const ArmISA::Affinity &aff) const
Definition gic_v3.cc:330
static const int INTID_SECURE
Definition gic_v3.hh:114
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr start() const
Get the start address of the range.
static constexpr T divCeil(const T &a, const U &b)
Definition intmath.hh:110
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
#define UNSERIALIZE_CONTAINER(member)
Definition serialize.hh:634
#define SERIALIZE_CONTAINER(member)
Definition serialize.hh:626
#define warn(...)
Definition logging.hh:256
Bitfield< 11, 0 > affinity
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 27, 24 > gic
Bitfield< 25, 21 > to
Definition types.hh:96
Bitfield< 11 > enable
Definition misc.hh:1086
Bitfield< 63 > val
Definition misc.hh:804
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568

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