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

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