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