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