gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
gic_v2.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010, 2013, 2015-2018, 2020-2022 Arm Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2005 The Regents of The University of Michigan
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
41#include "dev/arm/gic_v2.hh"
42
43#include "base/compiler.hh"
44#include "base/trace.hh"
45#include "cpu/base.hh"
46#include "debug/Checkpoint.hh"
47#include "debug/GIC.hh"
48#include "debug/IPI.hh"
49#include "debug/Interrupt.hh"
50#include "mem/packet.hh"
51#include "mem/packet_access.hh"
52#include "params/GicV2.hh"
53
54namespace gem5
55{
56
57const AddrRange GicV2::GICD_IGROUPR (0x080, 0x100);
58const AddrRange GicV2::GICD_ISENABLER (0x100, 0x180);
59const AddrRange GicV2::GICD_ICENABLER (0x180, 0x200);
60const AddrRange GicV2::GICD_ISPENDR (0x200, 0x280);
61const AddrRange GicV2::GICD_ICPENDR (0x280, 0x300);
62const AddrRange GicV2::GICD_ISACTIVER (0x300, 0x380);
63const AddrRange GicV2::GICD_ICACTIVER (0x380, 0x400);
64const AddrRange GicV2::GICD_IPRIORITYR(0x400, 0x800);
65const AddrRange GicV2::GICD_ITARGETSR (0x800, 0xc00);
66const AddrRange GicV2::GICD_ICFGR (0xc00, 0xd00);
67
68void
71 ContextID ctx, Addr daddr)
72{
73 auto val = from->readDistributor(ctx, daddr);
74 DPRINTF(GIC, "copy dist 0x%x 0x%08x\n", daddr, val);
75 to->writeDistributor(ctx, daddr, val);
76}
77
78void
81 ContextID ctx, Addr daddr)
82{
83 auto val = from->readCpu(ctx, daddr);
84 DPRINTF(GIC, "copy cpu 0x%x 0x%08x\n", daddr, val);
85 to->writeCpu(ctx, daddr, val);
86}
87
88void
91 Addr daddr, size_t size)
92{
93 for (int ctx = 0; ctx < sys->threads.size(); ++ctx)
94 for (auto a = daddr; a < daddr + size; a += 4)
95 copyDistRegister(from, to, ctx, a);
96}
97
98void
100 Addr daddr, size_t size)
101{
102 for (int ctx = 0; ctx < sys->threads.size(); ++ctx)
103 for (auto a = daddr; a < daddr + size; a += 4)
104 to->writeDistributor(ctx, a, 0xFFFFFFFF);
105}
106
107void
110 Addr daddr, size_t size)
111{
112 for (auto a = daddr; a < daddr + size; a += 4)
113 copyDistRegister(from, to, 0, a);
114}
115
116void
118{
119 for (auto a = daddr; a < daddr + size; a += 4)
120 to->writeDistributor(0, a, 0xFFFFFFFF);
121}
122
124 : BaseGic(p),
125 gicdPIDR(p.gicd_pidr),
126 gicdIIDR(p.gicd_iidr),
127 giccIIDR(p.gicc_iidr),
128 distRange(RangeSize(p.dist_addr, DIST_SIZE)),
129 cpuRange(RangeSize(p.cpu_addr, p.cpu_size)),
130 addrRanges{distRange, cpuRange},
131 distPioDelay(p.dist_pio_delay),
132 cpuPioDelay(p.cpu_pio_delay), intLatency(p.int_latency),
133 enabled(false), haveGem5Extensions(p.gem5_extensions),
134 itLines(p.it_lines),
141{
142 for (int x = 0; x < CPU_MAX; x++) {
143 iccrpr[x] = 0xff;
144 cpuControl[x] = 0;
145 cpuPriority[x] = 0xff;
147 // Initialize cpu highest int
149 postIntEvent[x] =
150 new EventFunctionWrapper([this, x]{ postDelayedInt(x); },
151 "Post Interrupt to CPU");
152 postFiqEvent[x] =
153 new EventFunctionWrapper([this, x]{ postDelayedFiq(x); },
154 "Post FIQ to CPU");
155 }
156 DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled(0),
157 cpuEnabled(1));
158
159 gem5ExtensionsEnabled = false;
160}
161
163{
164 for (int x = 0; x < CPU_MAX; x++) {
165 delete postIntEvent[x];
166 delete postFiqEvent[x];
167 }
168}
169
170Tick
172{
173 const Addr addr = pkt->getAddr();
174
175 if (distRange.contains(addr))
176 return readDistributor(pkt);
177 else if (cpuRange.contains(addr))
178 return readCpu(pkt);
179 else
180 panic("Read to unknown address %#x\n", pkt->getAddr());
181}
182
183
184Tick
186{
187 const Addr addr = pkt->getAddr();
188
189 if (distRange.contains(addr))
190 return writeDistributor(pkt);
191 else if (cpuRange.contains(addr))
192 return writeCpu(pkt);
193 else
194 panic("Write to unknown address %#x\n", pkt->getAddr());
195}
196
197Tick
199{
200 const Addr daddr = pkt->getAddr() - distRange.start();
201 const ContextID ctx = pkt->req->contextId();
202
203 const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize());
204
205 switch (pkt->getSize()) {
206 case 1:
207 pkt->setLE<uint8_t>(resp);
208 break;
209 case 2:
210 pkt->setLE<uint16_t>(resp);
211 break;
212 case 4:
213 pkt->setLE<uint32_t>(resp);
214 break;
215 default:
216 panic("Invalid size while reading Distributor regs in GIC: %d\n",
217 pkt->getSize());
218 }
219
220 pkt->makeAtomicResponse();
221 return distPioDelay;
222}
223
224uint32_t
225GicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
226{
227 if (GICD_IGROUPR.contains(daddr)) {
228 uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2;
229 assert(ix < 32);
230 DPRINTF(GIC, "gic distributor read GICD_IGROUPR%d (%#x)\n", ix, daddr);
231 return getIntGroup(ctx, ix);
232 }
233
234 if (GICD_ISENABLER.contains(daddr)) {
235 uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
236 assert(ix < 32);
237 DPRINTF(GIC, "gic distributor read GICD_ISENABLER%d (%#x)\n",
238 ix, daddr);
239 return getIntEnabled(ctx, ix);
240 }
241
242 if (GICD_ICENABLER.contains(daddr)) {
243 uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
244 assert(ix < 32);
245 DPRINTF(GIC, "gic distributor read GICD_ICENABLER%d (%#x)\n",
246 ix, daddr);
247 return getIntEnabled(ctx, ix);
248 }
249
250 if (GICD_ISPENDR.contains(daddr)) {
251 uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
252 assert(ix < 32);
253 DPRINTF(GIC, "gic distributor read GICD_ISPENDR%d (%#x)\n", ix, daddr);
254 return getPendingInt(ctx, ix);
255 }
256
257 if (GICD_ICPENDR.contains(daddr)) {
258 uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
259 assert(ix < 32);
260 DPRINTF(GIC, "gic distributor read GICD_ICPENDR%d (%#x)\n", ix, daddr);
261 return getPendingInt(ctx, ix);
262 }
263
264 if (GICD_ISACTIVER.contains(daddr)) {
265 uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
266 assert(ix < 32);
267 DPRINTF(GIC, "gic distributor read GICD_ISACTIVER%d (%#x)\n",
268 ix, daddr);
269 return getActiveInt(ctx, ix);
270 }
271
272 if (GICD_ICACTIVER.contains(daddr)) {
273 uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
274 assert(ix < 32);
275 DPRINTF(GIC, "gic distributor read GICD_ICACTIVER%d (%#x)\n",
276 ix, daddr);
277 return getActiveInt(ctx, ix);
278 }
279
280 if (GICD_IPRIORITYR.contains(daddr)) {
281 Addr int_num = daddr - GICD_IPRIORITYR.start();
282 assert(int_num < INT_LINES_MAX);
283 DPRINTF(GIC, "gic distributor read GICD_IPRIORITYR%d (%#x)\n",
284 int_num, daddr);
285
286 switch (resp_sz) {
287 default: // will panic() after return to caller anyway
288 case 1:
289 return getIntPriority(ctx, int_num);
290 case 2:
291 assert((int_num + 1) < INT_LINES_MAX);
292 return (getIntPriority(ctx, int_num) |
293 getIntPriority(ctx, int_num+1) << 8);
294 case 4:
295 assert((int_num + 3) < INT_LINES_MAX);
296 return (getIntPriority(ctx, int_num) |
297 getIntPriority(ctx, int_num+1) << 8 |
298 getIntPriority(ctx, int_num+2) << 16 |
299 getIntPriority(ctx, int_num+3) << 24);
300 }
301 }
302
303 if (GICD_ITARGETSR.contains(daddr)) {
304 Addr int_num = daddr - GICD_ITARGETSR.start();
305 DPRINTF(GIC, "gic distributor read GICD_ITARGETSR%d (%#x)\n",
306 int_num, daddr);
307 assert(int_num < INT_LINES_MAX);
308
309 if (resp_sz == 1) {
310 return getCpuTarget(ctx, int_num);
311 } else {
312 assert(resp_sz == 4);
313 int_num = mbits(int_num, 31, 2);
314 return (getCpuTarget(ctx, int_num) |
315 getCpuTarget(ctx, int_num+1) << 8 |
316 getCpuTarget(ctx, int_num+2) << 16 |
317 getCpuTarget(ctx, int_num+3) << 24) ;
318 }
319 }
320
321 if (GICD_ICFGR.contains(daddr)) {
322 uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
323 DPRINTF(GIC, "gic distributor read GICD_ICFGR%d (%#x)\n", ix, daddr);
324 return getIntConfig(ctx, ix);
325 }
326
327 switch(daddr) {
328 case GICD_CTLR:
329 DPRINTF(GIC, "gic distributor read GICD_CTLR (%#x)\n", daddr);
330 return enabled;
331 case GICD_TYPER:
332 /* The 0x100 is a made-up flag to show that gem5 extensions
333 * are available,
334 * write 0x200 to this register to enable it. */
335 DPRINTF(GIC, "gic distributor read GICD_TYPER (%#x)\n", daddr);
336 return (((sys->threads.numRunning() - 1) << 5) |
337 (itLines/INT_BITS_MAX -1) |
338 (haveGem5Extensions ? 0x100 : 0x0));
339 case GICD_PIDR0:
340 //ARM defined DevID
341 DPRINTF(GIC, "gic distributor read GICD_PIDR0 (%#x)\n", daddr);
342 return (gicdPIDR & 0xFF);
343 case GICD_PIDR1:
344 DPRINTF(GIC, "gic distributor read GICD_PIDR1 (%#x)\n", daddr);
345 return ((gicdPIDR >> 8) & 0xFF);
346 case GICD_PIDR2:
347 DPRINTF(GIC, "gic distributor read GICD_PIDR2 (%#x)\n", daddr);
348 return ((gicdPIDR >> 16) & 0xFF);
349 case GICD_PIDR3:
350 DPRINTF(GIC, "gic distributor read GICD_PIDR3 (%#x)\n", daddr);
351 return ((gicdPIDR >> 24) & 0xFF);
352 case GICD_IIDR:
353 /* revision id is resorted to 1 and variant to 0*/
354 DPRINTF(GIC, "gic distributor read GICD_IIDR (%#x)\n", daddr);
355 return gicdIIDR;
356 default:
357 panic("Tried to read Gic distributor at offset %#x\n", daddr);
358 break;
359 }
360}
361
362Tick
364{
365 const Addr daddr = pkt->getAddr() - cpuRange.start();
366
367 assert(pkt->req->hasContextId());
368 const ContextID ctx = pkt->req->contextId();
369 assert(ctx < sys->threads.numRunning());
370
371 pkt->setLE<uint32_t>(readCpu(ctx, daddr));
372
373 pkt->makeAtomicResponse();
374 return cpuPioDelay;
375}
376
377uint32_t
379{
380 switch(daddr) {
381 case GICC_IIDR:
382 DPRINTF(GIC, "gic cpu read GICC_IIDR (%#x) cpu context: %d\n",
383 daddr, ctx);
384 return giccIIDR;
385 case GICC_CTLR:
386 DPRINTF(GIC, "gic cpu read GICC_CTLR (%#x) cpu context: %d\n",
387 daddr, ctx);
388 return cpuControl[ctx];
389 case GICC_PMR:
390 DPRINTF(GIC, "gic cpu read GICC_PMR (%#x) cpu context: %d\n",
391 daddr, ctx);
392 return cpuPriority[ctx];
393 case GICC_BPR:
394 DPRINTF(GIC, "gic cpu read GICC_BPR (%#x) cpu context: %d\n",
395 daddr, ctx);
396 return cpuBpr[ctx];
397 case GICC_IAR:
398 DPRINTF(GIC, "gic cpu read GICC_IAR (%#x) cpu context: %d\n",
399 daddr, ctx);
400 if (enabled && cpuEnabled(ctx)) {
401 int active_int = cpuHighestInt[ctx];
402 IAR iar = 0;
403 iar.ack_id = active_int;
404 iar.cpu_id = 0;
405 if (active_int < SGI_MAX) {
406 // this is a software interrupt from another CPU
408 panic_if(!cpuSgiPending[active_int],
409 "Interrupt %d active but no CPU generated it?\n",
410 active_int);
411 for (int x = 0; x < sys->threads.numRunning(); x++) {
412 // See which CPU generated the interrupt
413 uint8_t cpugen =
414 bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
415 if (cpugen & (1 << ctx)) {
416 iar.cpu_id = x;
417 break;
418 }
419 }
420 uint64_t sgi_num = 1ULL << (ctx + 8 * iar.cpu_id);
421 cpuSgiActive[iar.ack_id] |= sgi_num;
422 cpuSgiPending[iar.ack_id] &= ~sgi_num;
423 } else {
424 uint64_t sgi_num = 1ULL << iar.ack_id;
425 cpuSgiActiveExt[ctx] |= sgi_num;
426 cpuSgiPendingExt[ctx] &= ~sgi_num;
427 }
428 } else if (active_int < (SGI_MAX + PPI_MAX) ) {
429 uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX);
430 cpuPpiActive[ctx] |= int_num;
431 updateRunPri();
432 if (!isLevelSensitive(ctx, active_int)) {
433 cpuPpiPending[ctx] &= ~int_num;
434 }
435
436 } else {
437 uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]);
438 getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num;
439 updateRunPri();
440 if (!isLevelSensitive(ctx, active_int)) {
442 &= ~int_num;
443 }
444 }
445
447 "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
448 ctx, iar.ack_id, iar.cpu_id, iar);
450 updateIntState(-1);
451 clearInt(ctx, active_int);
452 return iar;
453 } else {
454 return SPURIOUS_INT;
455 }
456
457 break;
458 case GICC_RPR:
459 DPRINTF(GIC, "gic cpu read GICC_RPR (%#x) cpu context: %d\n",
460 daddr, ctx);
461 return iccrpr[0];
462 case GICC_HPPIR:
463 panic("Need to implement HPIR");
464 break;
465 default:
466 panic("Tried to read Gic cpu at offset %#x\n", daddr);
467 break;
468 }
469}
470
471Tick
473{
474 const Addr daddr = pkt->getAddr() - distRange.start();
475
476 assert(pkt->req->hasContextId());
477 const ContextID ctx = pkt->req->contextId();
478 const size_t data_sz = pkt->getSize();
479
480 [[maybe_unused]] uint32_t pkt_data;
481 switch (data_sz)
482 {
483 case 1:
484 pkt_data = pkt->getLE<uint8_t>();
485 break;
486 case 2:
487 pkt_data = pkt->getLE<uint16_t>();
488 break;
489 case 4:
490 pkt_data = pkt->getLE<uint32_t>();
491 break;
492 default:
493 panic("Invalid size when writing to priority regs in Gic: %d\n",
494 data_sz);
495 }
496
497 writeDistributor(ctx, daddr, pkt_data, data_sz);
498
499 pkt->makeAtomicResponse();
500 return distPioDelay;
501}
502
503void
505 size_t data_sz)
506{
507 if (GICD_IGROUPR.contains(daddr)) {
508 uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2;
509 assert(ix < 32);
510 DPRINTF(GIC,
511 "gic distributor write GICD_IGROUPR%d (%#x) size %#x value %#x \n",
512 ix, daddr, data_sz, data);
513 getIntGroup(ctx, ix) = data;
514 return;
515 }
516
517 if (GICD_ISENABLER.contains(daddr)) {
518 uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
519 assert(ix < 32);
520 DPRINTF(GIC, "gic distributor write GICD_ISENABLER%d (%#x) "
521 "size %#x value %#x \n",
522 ix, daddr, data_sz, data);
523 getIntEnabled(ctx, ix) |= data;
524 return;
525 }
526
527 if (GICD_ICENABLER.contains(daddr)) {
528 uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
529 assert(ix < 32);
530 DPRINTF(GIC, "gic distributor write GICD_ICENABLER%d (%#x) "
531 "size %#x value %#x \n",
532 ix, daddr, data_sz, data);
533 getIntEnabled(ctx, ix) &= ~data;
534 return;
535 }
536
537 if (GICD_ISPENDR.contains(daddr)) {
538 uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
539 DPRINTF(GIC,
540 "gic distributor write GICD_ISPENDR%d (%#x) size %#x value %#x \n",
541 ix, daddr, data_sz, data);
542 auto mask = data;
543 if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
544 getPendingInt(ctx, ix) |= mask;
545 updateIntState(ix);
546 return;
547 }
548
549 if (GICD_ICPENDR.contains(daddr)) {
550 uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
551 DPRINTF(GIC, "gic distributor write GICD_ICPENDR%d (%#x) "
552 "size %#x value %#x \n",
553 ix, daddr, data_sz, data);
554 auto mask = data;
555 if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
556 getPendingInt(ctx, ix) &= ~mask;
557 updateIntState(ix);
558 return;
559 }
560
561 if (GICD_ISACTIVER.contains(daddr)) {
562 uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
563 DPRINTF(GIC, "gic distributor write GICD_ISACTIVER%d (%#x) "
564 "size %#x value %#x \n",
565 ix, daddr, data_sz, data);
566 getActiveInt(ctx, ix) |= data;
567 return;
568 }
569
570 if (GICD_ICACTIVER.contains(daddr)) {
571 uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
572 DPRINTF(GIC, "gic distributor write GICD_ICACTIVER%d (%#x) "
573 "size %#x value %#x \n",
574 ix, daddr, data_sz, data);
575 getActiveInt(ctx, ix) &= ~data;
576 return;
577 }
578
579 if (GICD_IPRIORITYR.contains(daddr)) {
580 Addr int_num = daddr - GICD_IPRIORITYR.start();
581 DPRINTF(GIC, "gic distributor write GICD_IPRIORITYR%d (%#x) "
582 "size %#x value %#x\n",
583 (int_num >> 2), daddr, data_sz, data);
584 switch(data_sz) {
585 case 1:
586 getIntPriority(ctx, int_num) = data;
587 break;
588 case 2: {
589 getIntPriority(ctx, int_num) = bits(data, 7, 0);
590 getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
591 break;
592 }
593 case 4: {
594 getIntPriority(ctx, int_num) = bits(data, 7, 0);
595 getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
596 getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
597 getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
598 break;
599 }
600 default:
601 panic("Invalid size when writing to priority regs in Gic: %d\n",
602 data_sz);
603 }
604
605 updateIntState(-1);
606 updateRunPri();
607 return;
608 }
609
610 if (GICD_ITARGETSR.contains(daddr)) {
611 Addr int_num = daddr - GICD_ITARGETSR.start();
612 // Interrupts 0-31 are read only
613 unsigned offset = SGI_MAX + PPI_MAX;
614 if (int_num >= offset) {
615 unsigned ix = int_num - offset; // index into cpuTarget array
616 DPRINTF(GIC, "gic distributor write GICD_ITARGETSR%d (%#x) "
617 "size %#x value %#x\n",
618 ix, daddr, data_sz, data);
619 if (data_sz == 1) {
620 cpuTarget[ix] = data & 0xff;
621 } else {
622 assert (data_sz == 4);
623 cpuTarget[ix] = bits(data, 7, 0);
624 cpuTarget[ix+1] = bits(data, 15, 8);
625 cpuTarget[ix+2] = bits(data, 23, 16);
626 cpuTarget[ix+3] = bits(data, 31, 24);
627 }
628 updateIntState(int_num >> 2);
629 }
630 return;
631 }
632
633 if (GICD_ICFGR.contains(daddr)) {
634 uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
635 // Since the GICD_ICFGR0 is RO (WI), we are discarding the write
636 // if ix = 0
637 if (ix != 0) {
638 DPRINTF(GIC, "gic distributor write GICD_ICFGR%d (%#x) "
639 "size %#x value %#x\n", ix, daddr, data_sz, data);
640 getIntConfig(ctx, ix) = data;
641 }
642 if (data & NN_CONFIG_MASK) {
643 warn("GIC N:N mode selected and not supported at this time\n");
644 }
645 return;
646 }
647
648 switch(daddr) {
649 case GICD_CTLR:
650 enabled = data;
651 DPRINTF(GIC, "gic distributor write GICD_CTLR (%#x) ",
652 daddr, data_sz, data);
653 DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
654 break;
655 case GICD_TYPER:
656 /* 0x200 is a made-up flag to enable gem5 extension functionality.
657 * This reg is not normally written.
658 */
660 DPRINTF(GIC, "gem5 extensions %s\n",
661 gem5ExtensionsEnabled ? "enabled" : "disabled");
662 break;
663 case GICD_SGIR:
664 DPRINTF(GIC, "gic distributor write GICD_SGIR (%#x) ",
665 daddr, data_sz, data);
666 softInt(ctx, data);
667 break;
668 default:
669 panic("Tried to write Gic distributor at offset %#x\n", daddr);
670 break;
671 }
672}
673
674Tick
676{
677 const Addr daddr = pkt->getAddr() - cpuRange.start();
678
679 assert(pkt->req->hasContextId());
680 const ContextID ctx = pkt->req->contextId();
681 const uint32_t data = pkt->getLE<uint32_t>();
682
683 writeCpu(ctx, daddr, data);
684
685 pkt->makeAtomicResponse();
686 return cpuPioDelay;
687}
688
689void
690GicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
691{
692 switch(daddr) {
693 case GICC_CTLR:
694 DPRINTF(GIC, "gic cpu write GICC_CTLR cpu:%d %#x val: %#x\n",
695 ctx, daddr, data);
696 cpuControl[ctx] = data;
697 break;
698 case GICC_PMR:
699 DPRINTF(GIC, "gic cpu write GICC_PMR cpu:%d %#x val: %#x\n",
700 ctx, daddr, data);
701 cpuPriority[ctx] = data;
702 break;
703 case GICC_BPR: {
704 auto bpr = data & 0x7;
705 if (bpr < GICC_BPR_MINIMUM)
706 bpr = GICC_BPR_MINIMUM;
707 DPRINTF(GIC, "gic cpu write GICC_BPR cpu:%d %#x val: %#x\n",
708 ctx, daddr, data);
709 cpuBpr[ctx] = bpr;
710 break;
711 }
712 case GICC_EOIR: {
713 DPRINTF(GIC, "gic cpu write GICC_EOIR cpu:%d %#x val: %#x\n",
714 ctx, daddr, data);
715 const IAR iar = data;
716 if (iar.ack_id < SGI_MAX) {
717 // Clear out the bit that corresponds to the cleared int
718 uint64_t clr_int = 1ULL << (ctx + 8 * iar.cpu_id);
719 if (!(cpuSgiActive[iar.ack_id] & clr_int) &&
720 !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id)))
721 panic("Done handling a SGI that isn't active?\n");
723 cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id);
724 else
725 cpuSgiActive[iar.ack_id] &= ~clr_int;
726 } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
727 uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
728 if (!(cpuPpiActive[ctx] & int_num))
729 warn("CPU %d Done handling a PPI interrupt "
730 "that isn't active?\n", ctx);
731 cpuPpiActive[ctx] &= ~int_num;
732 } else {
733 uint32_t int_num = 1 << intNumToBit(iar.ack_id);
734 if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num))
735 warn("Done handling interrupt that isn't active: %d\n",
736 intNumToBit(iar.ack_id));
737 getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num;
738 }
739 updateRunPri();
740 DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
741 ctx, iar.ack_id, iar.cpu_id);
742 break;
743 }
744 case GICC_APR0:
745 case GICC_APR1:
746 case GICC_APR2:
747 case GICC_APR3:
748 warn("GIC APRn write ignored because not implemented: %#x\n", daddr);
749 break;
750 case GICC_DIR:
751 warn("GIC DIR write ignored because not implemented: %#x\n", daddr);
752 break;
753 default:
754 panic("Tried to write Gic cpu at offset %#x\n", daddr);
755 break;
756 }
757 if (cpuEnabled(ctx)) updateIntState(-1);
758}
759
762 if (bankedRegs.size() <= ctx)
763 bankedRegs.resize(ctx + 1);
764
765 if (!bankedRegs[ctx])
766 bankedRegs[ctx] = new BankedRegs;
767 return *bankedRegs[ctx];
768}
769
770void
772{
774 switch (swi.list_type) {
775 case 0: {
776 // interrupt cpus specified
777 int dest = swi.cpu_list;
778 DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
779 ctx, dest);
780 if (cpuEnabled(dest)) {
781 cpuSgiPendingExt[dest] |= (1 << swi.sgi_id);
782 DPRINTF(IPI, "SGI[%d]=%#x\n", dest,
783 cpuSgiPendingExt[dest]);
784 }
785 } break;
786 case 1: {
787 // interrupt all
788 for (int i = 0; i < sys->threads.size(); i++) {
789 DPRINTF(IPI, "Processing CPU %d\n", i);
790 if (!cpuEnabled(i))
791 continue;
792 cpuSgiPendingExt[i] |= 1 << swi.sgi_id;
793 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
795 }
796 } break;
797 case 2: {
798 // Interrupt requesting cpu only
799 DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
800 ctx, ctx);
801 if (cpuEnabled(ctx)) {
802 cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id);
803 DPRINTF(IPI, "SGI[%d]=%#x\n", ctx,
804 cpuSgiPendingExt[ctx]);
805 }
806 } break;
807 }
808 } else {
809 switch (swi.list_type) {
810 case 1:
811 // interrupt all
812 uint8_t cpu_list;
813 cpu_list = 0;
814 for (int x = 0; x < sys->threads.size(); x++)
815 cpu_list |= cpuEnabled(x) ? 1 << x : 0;
816 swi.cpu_list = cpu_list;
817 break;
818 case 2:
819 // interrupt requesting cpu only
820 swi.cpu_list = 1 << ctx;
821 break;
822 // else interrupt cpus specified
823 }
824
825 DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx,
826 swi.cpu_list);
827 for (int i = 0; i < sys->threads.size(); i++) {
828 DPRINTF(IPI, "Processing CPU %d\n", i);
829 if (!cpuEnabled(i))
830 continue;
831 if (swi.cpu_list & (1 << i))
832 cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx);
833 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
834 cpuSgiPending[swi.sgi_id]);
835 }
836 }
837 updateIntState(-1);
838}
839
840uint64_t
842{
843 panic_if(cpu > sys->threads.size(), "Invalid CPU ID.");
844 return 0x0101010101010101ULL << cpu;
845}
846
847uint8_t
849{
850 // see Table 3-2 in IHI0048B.b (GICv2)
851 // mask some low-order priority bits per BPR value
852 // NB: the GIC prioritization scheme is upside down:
853 // lower values are higher priority; masking off bits
854 // actually creates a higher priority, not lower.
855 return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu]));
856}
857
858void
860{
861 if (blockIntUpdate())
862 return;
863
864 for (int cpu = 0; cpu < sys->threads.size(); cpu++) {
865 if (!cpuEnabled(cpu))
866 continue;
867
868 /*@todo use hint to do less work. */
869 int highest_int = SPURIOUS_INT;
870 // Priorities below that set in GICC_PMR can be ignored
871 uint8_t highest_pri = getCpuPriority(cpu);
872
873 // Check SGIs
874 for (int swi = 0; swi < SGI_MAX; swi++) {
875 if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu])
876 continue;
877 if ((cpuSgiPending[swi] & genSwiMask(cpu)) ||
878 (cpuSgiPendingExt[cpu] & (1 << swi)))
879 if (highest_pri > getIntPriority(cpu, swi)) {
880 highest_pri = getIntPriority(cpu, swi);
881 highest_int = swi;
882 }
883 }
884
885 // Check PPIs
886 if (cpuPpiPending[cpu]) {
887 for (int ppi_idx = 0, int_num = SGI_MAX;
888 int_num < PPI_MAX + SGI_MAX;
889 ppi_idx++, int_num++) {
890
891 const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx);
892 const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num);
893 const bool higher_priority =
894 highest_pri > getIntPriority(cpu, int_num);
895
896 if (ppi_pending && ppi_enabled && higher_priority) {
897 highest_pri = getIntPriority(cpu, int_num);
898 highest_int = int_num;
899 }
900 }
901 }
902
903 bool mp_sys = sys->threads.numRunning() > 1;
904 // Check other ints
905 for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
906 if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) {
907 for (int y = 0; y < INT_BITS_MAX; y++) {
908 uint32_t int_nm = x * INT_BITS_MAX + y;
909 DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
910 /* Set current pending int as highest int for current cpu
911 if the interrupt's priority higher than current priority
912 and if current cpu is the target (for mp configs only)
913 */
914 if ((bits(getIntEnabled(cpu, x), y)
915 &bits(getPendingInt(cpu, x), y)) &&
916 (getIntPriority(cpu, int_nm) < highest_pri))
917 if ((!mp_sys) ||
919 ? (getCpuTarget(cpu, int_nm) == cpu)
920 : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) {
921 highest_pri = getIntPriority(cpu, int_nm);
922 highest_int = int_nm;
923 }
924 }
925 }
926 }
927
928 uint32_t prev_highest = cpuHighestInt[cpu];
929 cpuHighestInt[cpu] = highest_int;
930
931 if (highest_int == SPURIOUS_INT) {
932 if (isLevelSensitive(cpu, prev_highest)) {
933
934 DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu);
935 clearInt(cpu, prev_highest);
936 }
937 continue;
938 }
939
940 /* @todo make this work for more than one cpu, need to handle 1:N, N:N
941 * models */
942 if (enabled && cpuEnabled(cpu) &&
943 (highest_pri < getCpuPriority(cpu)) &&
944 !(getActiveInt(cpu, intNumToWord(highest_int))
945 & (1 << intNumToBit(highest_int)))) {
946
947 DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
948 cpu);
949
950 if (isFiq(cpu, highest_int)) {
951 postFiq(cpu, curTick() + intLatency);
952 } else {
953 postInt(cpu, curTick() + intLatency);
954 }
955 }
956 }
957}
958
959void
961{
962 for (int cpu = 0; cpu < sys->threads.size(); cpu++) {
963 if (!cpuEnabled(cpu))
964 continue;
965 uint8_t maxPriority = 0xff;
966 for (int i = 0; i < itLines; i++) {
967 if (i < SGI_MAX) {
968 if (((cpuSgiActive[i] & genSwiMask(cpu)) ||
969 (cpuSgiActiveExt[cpu] & (1 << i))) &&
970 (getIntPriority(cpu, i) < maxPriority))
971 maxPriority = getIntPriority(cpu, i);
972 } else if (i < (SGI_MAX + PPI_MAX)) {
973 if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
974 (getIntPriority(cpu, i) < maxPriority))
975 maxPriority = getIntPriority(cpu, i);
976
977 } else {
978 if (getActiveInt(cpu, intNumToWord(i))
979 & (1 << intNumToBit(i)))
980 if (getIntPriority(cpu, i) < maxPriority)
981 maxPriority = getIntPriority(cpu, i);
982 }
983 }
984 iccrpr[cpu] = maxPriority;
985 }
986}
987
988void
989GicV2::sendInt(uint32_t num)
990{
991 uint8_t target = getCpuTarget(0, num);
992 DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
993 num, target);
994 if ((target & (target - 1)) && !gem5ExtensionsEnabled)
995 panic("Multiple targets for peripheral interrupts is not supported\n");
996 panic_if(num < SGI_MAX + PPI_MAX,
997 "sentInt() must only be used for interrupts 32 and higher");
998 getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num);
1000}
1001
1002void
1003GicV2::sendPPInt(uint32_t num, uint32_t cpu)
1004{
1005 DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n",
1006 num, cpu);
1007 cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
1009}
1010
1011void
1012GicV2::clearInt(uint32_t num)
1013{
1014 if (isLevelSensitive(0, num)) {
1015 uint8_t target = getCpuTarget(0, num);
1016
1018 "Received Clear interrupt number %d, cpuTarget %#x:\n",
1019 num, target);
1020
1021 getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num));
1023 } else {
1024 /* Nothing to do :
1025 * Edge-triggered interrupt remain pending until software
1026 * writes GICD_ICPENDR or reads GICC_IAR */
1027 }
1028}
1029
1030void
1031GicV2::clearPPInt(uint32_t num, uint32_t cpu)
1032{
1033 if (isLevelSensitive(cpu, num)) {
1034 DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n",
1035 num, cpu);
1036 cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX));
1038 } else {
1039 /* Nothing to do :
1040 * Edge-triggered interrupt remain pending until software
1041 * writes GICD_ICPENDR or reads GICC_IAR */
1042 }
1043}
1044
1045void
1046GicV2::clearInt(ContextID ctx, uint32_t int_num)
1047{
1048 auto tc = sys->threads[ctx];
1049 if (isFiq(ctx, int_num)) {
1050 tc->getCpuPtr()->clearInterrupt(tc->threadId(), ArmISA::INT_FIQ, 0);
1051 } else {
1052 tc->getCpuPtr()->clearInterrupt(tc->threadId(), ArmISA::INT_IRQ, 0);
1053 }
1054}
1055
1056void
1057GicV2::postInt(uint32_t cpu, Tick when)
1058{
1059 if (!(postIntEvent[cpu]->scheduled())) {
1061 eventq->schedule(postIntEvent[cpu], when);
1062 }
1063}
1064
1065void
1067{
1068 auto tc = sys->threads[cpu];
1069 tc->getCpuPtr()->postInterrupt(tc->threadId(), ArmISA::INT_IRQ, 0);
1071 assert(pendingDelayedInterrupts >= 0);
1072 if (pendingDelayedInterrupts == 0)
1074}
1075
1076void
1077GicV2::postFiq(uint32_t cpu, Tick when)
1078{
1079 if (!(postFiqEvent[cpu]->scheduled())) {
1081 eventq->schedule(postFiqEvent[cpu], when);
1082 }
1083}
1084
1085bool
1087{
1088 return version == GicVersion::GIC_V2;
1089}
1090
1091void
1093{
1094 auto tc = sys->threads[cpu];
1095 tc->getCpuPtr()->postInterrupt(tc->threadId(), ArmISA::INT_FIQ, 0);
1097 assert(pendingDelayedInterrupts >= 0);
1098 if (pendingDelayedInterrupts == 0)
1100}
1101
1104{
1105 if (pendingDelayedInterrupts == 0) {
1106 return DrainState::Drained;
1107 } else {
1108 return DrainState::Draining;
1109 }
1110}
1111
1112
1113void
1115{
1116 // There may be pending interrupts if checkpointed from Kvm; post them.
1117 updateIntState(-1);
1118}
1119
1120void
1122{
1123 Addr set, clear;
1124 size_t size;
1125
1127 // Copy CPU Interface Control Register (CTLR),
1128 // Interrupt Priority Mask Register (PMR), and
1129 // Binary Point Register (BPR)
1130 for (int ctx = 0; ctx < sys->threads.size(); ++ctx) {
1131 copyCpuRegister(from, to, ctx, GICC_CTLR);
1132 copyCpuRegister(from, to, ctx, GICC_PMR);
1133 copyCpuRegister(from, to, ctx, GICC_BPR);
1134 }
1135
1137 // Copy Distributor Control Register (CTLR)
1138 copyDistRegister(from, to, 0, GICD_CTLR);
1139
1140 // Copy interrupt-enabled statuses (I[CS]ENABLERn; R0 is per-CPU banked)
1141 set = GICD_ISENABLER.start();
1142 clear = GICD_ICENABLER.start();
1143 size = itLines / 8;
1144 clearBankedDistRange(sys, to, clear, 4);
1145 copyBankedDistRange(sys, from, to, set, 4);
1146
1147 set += 4, clear += 4, size -= 4;
1148 clearDistRange(to, clear, size);
1149 copyDistRange(from, to, set, size);
1150
1151 // Copy pending interrupts (I[CS]PENDRn; R0 is per-CPU banked)
1152 set = GICD_ISPENDR.start();
1153 clear = GICD_ICPENDR.start();
1154 size = itLines / 8;
1155 clearBankedDistRange(sys, to, clear, 4);
1156 copyBankedDistRange(sys, from, to, set, 4);
1157
1158 set += 4, clear += 4, size -= 4;
1159 clearDistRange(to, clear, size);
1160 copyDistRange(from, to, set, size);
1161
1162 // Copy active interrupts (I[CS]ACTIVERn; R0 is per-CPU banked)
1163 set = GICD_ISACTIVER.start();
1164 clear = GICD_ICACTIVER.start();
1165 size = itLines / 8;
1166 clearBankedDistRange(sys, to, clear, 4);
1167 copyBankedDistRange(sys, from, to, set, 4);
1168
1169 set += 4, clear += 4, size -= 4;
1170 clearDistRange(to, clear, size);
1171 copyDistRange(from, to, set, size);
1172
1173 // Copy interrupt priorities (IPRIORITYRn; R0-7 are per-CPU banked)
1174 set = GICD_IPRIORITYR.start();
1175 copyBankedDistRange(sys, from, to, set, 32);
1176
1177 set += 32;
1178 size = itLines - 32;
1179 copyDistRange(from, to, set, size);
1180
1181 // Copy interrupt processor target regs (ITARGETRn; R0-7 are read-only)
1182 set = GICD_ITARGETSR.start() + 32;
1183 size = itLines - 32;
1184 copyDistRange(from, to, set, size);
1185
1186 // Copy interrupt configuration registers (ICFGRn)
1187 set = GICD_ICFGR.start();
1188 size = itLines / 4;
1189 copyDistRange(from, to, set, size);
1190}
1191
1192void
1225
1226void
1236
1237void
1239{
1240 DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
1241
1262
1263 // Handle checkpoints from before we drained the GIC to prevent
1264 // in-flight interrupts.
1265 if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) {
1266 Tick interrupt_time[CPU_MAX];
1267 UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
1268
1269 for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
1270 if (interrupt_time[cpu])
1271 schedule(postIntEvent[cpu], interrupt_time[cpu]);
1272 }
1273 }
1274
1276 gem5ExtensionsEnabled = false;
1277
1278 for (uint32_t i=0; i < CPU_MAX; ++i) {
1279 ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i));
1280 if (cp.sectionExists(Serializable::currentSection())) {
1282 }
1283 }
1284}
1285
1286void
1296
1297} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition addr_range.hh:82
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
Definition base_gic.hh:130
BaseGic(const Params &p)
Definition base_gic.cc:52
EventQueue * eventq
A pointer to this object's event queue.
Definition eventq.hh:984
static void clearDistRange(GicV2Registers *to, Addr daddr, size_t size)
Definition gic_v2.cc:117
virtual uint32_t readDistributor(ContextID ctx, Addr daddr)=0
static void copyDistRange(GicV2Registers *from, GicV2Registers *to, Addr daddr, size_t size)
Definition gic_v2.cc:108
static void copyBankedDistRange(System *sys, GicV2Registers *from, GicV2Registers *to, Addr daddr, size_t size)
Definition gic_v2.cc:89
static void copyDistRegister(GicV2Registers *from, GicV2Registers *to, ContextID ctx, Addr daddr)
Definition gic_v2.cc:69
virtual uint32_t readCpu(ContextID ctx, Addr daddr)=0
static void clearBankedDistRange(System *sys, GicV2Registers *to, Addr daddr, size_t size)
Definition gic_v2.cc:99
static void copyCpuRegister(GicV2Registers *from, GicV2Registers *to, ContextID ctx, Addr daddr)
Definition gic_v2.cc:79
static const int GLOBAL_INT_LINES
Definition gic_v2.hh:158
const uint32_t gicdIIDR
Definition gic_v2.hh:112
const Tick distPioDelay
Latency for a distributor operation.
Definition gic_v2.hh:192
std::vector< BankedRegs * > bankedRegs
Definition gic_v2.hh:248
int intNumToBit(int num) const
Definition gic_v2.hh:492
EventFunctionWrapper * postIntEvent[CPU_MAX]
Definition gic_v2.hh:509
uint32_t itLines
Number of itLines enabled.
Definition gic_v2.hh:211
static const AddrRange GICD_IPRIORITYR
Definition gic_v2.hh:122
bool isFiq(ContextID ctx, uint32_t int_num)
This method checks if an interrupt ID must be signaled or has been signaled as a FIQ to the cpu.
Definition gic_v2.hh:419
static const AddrRange GICD_ICACTIVER
Definition gic_v2.hh:121
void postFiq(uint32_t cpu, Tick when)
Definition gic_v2.cc:1077
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
Definition gic_v2.hh:273
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
Definition gic_v2.hh:258
uint32_t intEnabled[INT_BITS_MAX-1]
GICD_I{S,C}ENABLER{1..31} interrupt enable bits for global interrupts 1b per interrupt,...
Definition gic_v2.hh:255
uint32_t cpuSgiPendingExt[CPU_MAX]
SGI pending arrays for gem5 GIC extension mode, which instead keeps 16 SGI pending bits for each of t...
Definition gic_v2.hh:466
static const AddrRange GICD_ICFGR
Definition gic_v2.hh:124
static const AddrRange GICD_ICENABLER
Definition gic_v2.hh:117
static const int INT_LINES_MAX
Definition gic_v2.hh:157
void softInt(ContextID ctx, SWI swi)
software generated interrupt
Definition gic_v2.cc:771
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
Definition gic_v2.hh:460
static const AddrRange GICD_ISPENDR
Definition gic_v2.hh:118
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
Definition gic_v2.cc:198
EndBitUnion(CTLR) protected const AddrRange cpuRange
Address range for the distributor interface.
Definition gic_v2.hh:179
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
Definition gic_v2.cc:472
uint8_t cpuPriority[CPU_MAX]
CPU priority.
Definition gic_v2.hh:447
int pendingDelayedInterrupts
Definition gic_v2.hh:511
uint32_t pendingInt[INT_BITS_MAX-1]
GICD_I{S,C}PENDR{1..31} interrupt pending bits for global interrupts 1b per interrupt,...
Definition gic_v2.hh:270
BankedRegs & getBankedRegs(ContextID)
Definition gic_v2.cc:761
static const int INT_BITS_MAX
Definition gic_v2.hh:156
void copyGicState(GicV2Registers *from, GicV2Registers *to)
GIC state transfer.
Definition gic_v2.cc:1121
static const int SGI_MAX
Definition gic_v2.hh:145
void postDelayedFiq(uint32_t cpu)
Definition gic_v2.cc:1092
EventFunctionWrapper * postFiqEvent[CPU_MAX]
Definition gic_v2.hh:510
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition gic_v2.cc:1103
uint32_t cpuPpiActive[CPU_MAX]
Definition gic_v2.hh:472
static const AddrRange GICD_ISACTIVER
Definition gic_v2.hh:120
static const AddrRange GICD_IGROUPR
Definition gic_v2.hh:115
uint8_t getCpuPriority(unsigned cpu)
Definition gic_v2.cc:848
int intNumToWord(int num) const
Definition gic_v2.hh:491
void drainResume() override
Resume execution after a successful drain.
Definition gic_v2.cc:1114
uint32_t & getIntGroup(ContextID ctx, uint32_t ix)
Definition gic_v2.hh:305
bool enabled
Gic enabled.
Definition gic_v2.hh:202
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
Definition gic_v2.hh:149
uint32_t intGroup[INT_BITS_MAX-1]
GICD_IGROUPR{1..31} interrupt group bits for global interrupts 1b per interrupt, 32 bits per word,...
Definition gic_v2.hh:302
uint32_t intConfig[INT_BITS_MAX *2 - 2]
GICD_ICFGR{2...63} 2 bit per interrupt signaling if it's level or edge sensitive and if it is 1:N or ...
Definition gic_v2.hh:339
const Tick intLatency
Latency for a interrupt to get to CPU.
Definition gic_v2.hh:198
void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
Definition gic_v2.cc:859
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
Definition gic_v2.cc:363
const bool haveGem5Extensions
Are gem5 extensions available?
Definition gic_v2.hh:205
bool isLevelSensitive(ContextID ctx, uint32_t int_num)
Definition gic_v2.hh:390
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu()
Definition gic_v2.cc:185
static const int CPU_MAX
Definition gic_v2.hh:154
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
Definition gic_v2.cc:1003
uint32_t & getIntConfig(ContextID ctx, uint32_t ix)
Reads the GICD_ICFGRn register.
Definition gic_v2.hh:348
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Linux...
Definition gic_v2.hh:162
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
Definition gic_v2.hh:451
uint64_t cpuSgiActive[SGI_MAX]
Definition gic_v2.hh:461
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
Definition gic_v2.cc:675
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
Definition gic_v2.hh:289
CTLR cpuControl[CPU_MAX]
GICC_CTLR: CPU interface control register.
Definition gic_v2.hh:444
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
Definition gic_v2.cc:960
uint32_t cpuSgiActiveExt[CPU_MAX]
Definition gic_v2.hh:467
static const AddrRange GICD_ISENABLER
Definition gic_v2.hh:116
const uint32_t giccIIDR
Definition gic_v2.hh:113
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
Definition gic_v2.cc:989
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
Definition gic_v2.hh:471
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
Definition gic_v2.hh:454
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu()
Definition gic_v2.cc:171
uint8_t cpuTarget[GLOBAL_INT_LINES]
GICD_ITARGETSR{8..255} an 8 bit cpu target id for each global interrupt.
Definition gic_v2.hh:362
GicV2(const Params &p)
Definition gic_v2.cc:123
bool cpuEnabled(ContextID ctx) const
CPU enabled: Checks if GICC_CTLR.EnableGrp0 or EnableGrp1 are set.
Definition gic_v2.hh:435
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition gic_v2.cc:1193
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
Definition gic_v2.cc:841
static const int SPURIOUS_INT
Definition gic_v2.hh:155
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
Definition gic_v2.hh:152
bool supportsVersion(GicVersion version) override
Check if version supported.
Definition gic_v2.cc:1086
const AddrRangeList addrRanges
All address ranges used by this GIC.
Definition gic_v2.hh:189
GicV2Params Params
Definition gic_v2.hh:514
void clearPPInt(uint32_t num, uint32_t cpu) override
Definition gic_v2.cc:1031
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
Definition gic_v2.hh:208
const uint32_t gicdPIDR
Definition gic_v2.hh:111
const Tick cpuPioDelay
Latency for a cpu operation.
Definition gic_v2.hh:195
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition gic_v2.cc:1238
uint8_t getCpuTarget(ContextID ctx, uint32_t ix) const
Definition gic_v2.hh:365
static const int PPI_MAX
Definition gic_v2.hh:146
static const AddrRange GICD_ITARGETSR
Definition gic_v2.hh:123
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
Definition gic_v2.hh:325
Bitfield< 23, 16 > cpu_list
Definition gic_v2.hh:166
uint8_t intPriority[GLOBAL_INT_LINES]
GICD_IPRIORITYR{8..255} an 8 bit priority (lower is higher priority) for each of the global (not repl...
Definition gic_v2.hh:322
void clearInt(ContextID ctx, uint32_t int_num)
Clears a cpu IRQ or FIQ signal.
Definition gic_v2.cc:1046
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
Definition gic_v2.cc:1057
uint32_t activeInt[INT_BITS_MAX-1]
GICD_I{S,C}ACTIVER{1..31} interrupt active bits for global interrupts 1b per interrupt,...
Definition gic_v2.hh:286
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
Definition gic_v2.hh:316
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
Definition gic_v2.cc:1066
static const AddrRange GICD_ICPENDR
Definition gic_v2.hh:119
Addr getAddr() const
Definition packet.hh:807
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
void makeAtomicResponse()
Definition packet.hh:1074
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
int size() const
Definition system.hh:215
Threads threads
Definition system.hh:315
Implementation of a GICv2.
AddrRange RangeSize(Addr start, Addr size)
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
Definition bitfield.hh:106
void signalDrainDone() const
Signal that an object is drained.
Definition drain.hh:310
DrainState
Object drain/handover states.
Definition drain.hh:76
@ Draining
Draining buffers pending serialization/handover.
Definition drain.hh:78
@ Drained
Buffers drained, ready for serialization/handover.
Definition drain.hh:79
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
#define UNSERIALIZE_OPT_SCALAR(scalar)
Definition serialize.hh:582
static const std::string & currentSection()
Gets the fully-qualified name of the active section.
Definition serialize.cc:130
#define UNSERIALIZE_ARRAY(member, size)
Definition serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition serialize.hh:610
#define warn(...)
Definition logging.hh:288
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 12, 11 > set
Bitfield< 0 > p
Bitfield< 25, 21 > to
Definition types.hh:96
Bitfield< 3 > x
Definition pagetable.hh:78
Bitfield< 63 > val
Definition misc.hh:804
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
uint64_t Tick
Tick count type.
Definition types.hh:58
Packet * PacketPtr
int ContextID
Globally unique thread context ID.
Definition types.hh:239
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
Registers "banked for each connected processor" per ARM IHI0048B.
Definition gic_v2.hh:215
uint32_t intEnabled
GICD_I{S,C}ENABLER0 interrupt enable bits for first 32 interrupts, 1b per interrupt.
Definition gic_v2.hh:218
uint32_t intGroup
GICD_IGROUPR0 interrupt group bits for first 32 interrupts, 1b per interrupt.
Definition gic_v2.hh:230
uint32_t activeInt
GICD_I{S,C}ACTIVER0 interrupt active bits for first 32 interrupts, 1b per interrupt.
Definition gic_v2.hh:226
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition gic_v2.cc:1287
uint8_t intPriority[SGI_MAX+PPI_MAX]
GICD_IPRIORITYR{0..7} interrupt priority for SGIs and PPIs.
Definition gic_v2.hh:238
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition gic_v2.cc:1227
uint32_t pendingInt
GICD_I{S,C}PENDR0 interrupt pending bits for first 32 interrupts, 1b per interrupt.
Definition gic_v2.hh:222
uint32_t intConfig[2]
GICD_ICFGR0, GICD_ICFGR1 interrupt config bits for first 32 interrupts, 2b per interrupt.
Definition gic_v2.hh:234

Generated on Mon Oct 27 2025 04:13:01 for gem5 by doxygen 1.14.0