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