46#include "debug/Checkpoint.hh"
47#include "debug/GIC.hh"
48#include "debug/IPI.hh"
49#include "debug/Interrupt.hh"
73 DPRINTF(GIC,
"copy dist 0x%x 0x%08x\n", daddr,
val);
74 to->writeDistributor(ctx, daddr,
val);
83 DPRINTF(GIC,
"copy cpu 0x%x 0x%08x\n", daddr,
val);
84 to->writeCpu(ctx, daddr,
val);
90 Addr daddr,
size_t size)
93 for (
auto a = daddr;
a < daddr + size;
a += 4)
99 Addr daddr,
size_t size)
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);
109 Addr daddr,
size_t size)
111 for (
auto a = daddr;
a < daddr + size;
a += 4)
118 for (
auto a = daddr;
a < daddr + size;
a += 4)
119 to->writeDistributor(0,
a, 0xFFFFFFFF);
124 gicdPIDR(
p.gicd_pidr),
125 gicdIIDR(
p.gicd_iidr),
126 giccIIDR(
p.gicc_iidr),
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),
134 intEnabled {}, pendingInt {}, activeInt {}, intGroup {},
135 intPriority {}, intConfig {}, cpuTarget {},
136 cpuSgiPending {}, cpuSgiActive {},
137 cpuSgiPendingExt {}, cpuSgiActiveExt {},
138 cpuPpiPending {}, cpuPpiActive {},
139 pendingDelayedInterrupts(0)
150 "Post Interrupt to CPU");
174 if (distRange.contains(
addr))
188 if (distRange.contains(
addr))
193 panic(
"Write to unknown address %#x\n", pkt->
getAddr());
199 const Addr daddr = pkt->
getAddr() - distRange.start();
206 pkt->
setLE<uint8_t>(resp);
209 pkt->
setLE<uint16_t>(resp);
212 pkt->
setLE<uint32_t>(resp);
215 panic(
"Invalid size while reading Distributor regs in GIC: %d\n",
229 DPRINTF(GIC,
"gic distributor read GICD_IGROUPR%d (%#x)\n", ix, daddr);
236 DPRINTF(GIC,
"gic distributor read GICD_ISENABLER%d (%#x)\n",
244 DPRINTF(GIC,
"gic distributor read GICD_ICENABLER%d (%#x)\n",
252 DPRINTF(GIC,
"gic distributor read GICD_ISPENDR%d (%#x)\n", ix, daddr);
259 DPRINTF(GIC,
"gic distributor read GICD_ICPENDR%d (%#x)\n", ix, daddr);
266 DPRINTF(GIC,
"gic distributor read GICD_ISACTIVER%d (%#x)\n",
274 DPRINTF(GIC,
"gic distributor read GICD_ICACTIVER%d (%#x)\n",
282 DPRINTF(GIC,
"gic distributor read GICD_IPRIORITYR%d (%#x)\n",
304 DPRINTF(GIC,
"gic distributor read GICD_ITARGETSR%d (%#x)\n",
311 assert(resp_sz == 4);
312 int_num =
mbits(int_num, 31, 2);
322 DPRINTF(GIC,
"gic distributor read GICD_ICFGR%d (%#x)\n", ix, daddr);
328 DPRINTF(GIC,
"gic distributor read GICD_CTLR (%#x)\n", daddr);
334 DPRINTF(GIC,
"gic distributor read GICD_TYPER (%#x)\n", daddr);
340 DPRINTF(GIC,
"gic distributor read GICD_PIDR0 (%#x)\n", daddr);
343 DPRINTF(GIC,
"gic distributor read GICD_PIDR1 (%#x)\n", daddr);
346 DPRINTF(GIC,
"gic distributor read GICD_PIDR2 (%#x)\n", daddr);
349 DPRINTF(GIC,
"gic distributor read GICD_PIDR3 (%#x)\n", daddr);
353 DPRINTF(GIC,
"gic distributor read GICD_IIDR (%#x)\n", daddr);
356 panic(
"Tried to read Gic distributor at offset %#x\n", daddr);
366 assert(pkt->
req->hasContextId());
368 assert(ctx < sys->threads.numRunning());
381 DPRINTF(GIC,
"gic cpu read GICC_IIDR (%#x) cpu context: %d\n",
385 DPRINTF(GIC,
"gic cpu read GICC_CTLR (%#x) cpu context: %d\n",
389 DPRINTF(GIC,
"gic cpu read GICC_PMR (%#x) cpu context: %d\n",
393 DPRINTF(GIC,
"gic cpu read GICC_BPR (%#x) cpu context: %d\n",
397 DPRINTF(GIC,
"gic cpu read GICC_IAR (%#x) cpu context: %d\n",
402 iar.ack_id = active_int;
408 "Interrupt %d active but no CPU generated it?\n",
414 if (cpugen & (1 << ctx)) {
419 uint64_t sgi_num = 1ULL << (ctx + 8 * iar.cpu_id);
423 uint64_t sgi_num = 1ULL << iar.ack_id;
446 "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
447 ctx, iar.ack_id, iar.cpu_id, iar);
458 DPRINTF(GIC,
"gic cpu read GICC_RPR (%#x) cpu context: %d\n",
462 panic(
"Need to implement HPIR");
465 panic(
"Tried to read Gic cpu at offset %#x\n", daddr);
473 const Addr daddr = pkt->
getAddr() - distRange.start();
475 assert(pkt->
req->hasContextId());
477 const size_t data_sz = pkt->
getSize();
479 [[maybe_unused]] uint32_t pkt_data;
483 pkt_data = pkt->
getLE<uint8_t>();
486 pkt_data = pkt->
getLE<uint16_t>();
489 pkt_data = pkt->
getLE<uint32_t>();
492 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
510 "gic distributor write GICD_IGROUPR%d (%#x) size %#x value %#x \n",
511 ix, daddr, data_sz,
data);
519 DPRINTF(GIC,
"gic distributor write GICD_ISENABLER%d (%#x) "
520 "size %#x value %#x \n",
521 ix, daddr, data_sz,
data);
529 DPRINTF(GIC,
"gic distributor write GICD_ICENABLER%d (%#x) "
530 "size %#x value %#x \n",
531 ix, daddr, data_sz,
data);
539 "gic distributor write GICD_ISPENDR%d (%#x) size %#x value %#x \n",
540 ix, daddr, data_sz,
data);
550 DPRINTF(GIC,
"gic distributor write GICD_ICPENDR%d (%#x) "
551 "size %#x value %#x \n",
552 ix, daddr, data_sz,
data);
562 DPRINTF(GIC,
"gic distributor write GICD_ISACTIVER%d (%#x) "
563 "size %#x value %#x \n",
564 ix, daddr, data_sz,
data);
571 DPRINTF(GIC,
"gic distributor write GICD_ICACTIVER%d (%#x) "
572 "size %#x value %#x \n",
573 ix, daddr, data_sz,
data);
580 DPRINTF(GIC,
"gic distributor write GICD_IPRIORITYR%d (%#x) "
581 "size %#x value %#x\n",
582 (int_num >> 2), daddr, data_sz,
data);
600 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
614 unsigned ix = int_num -
offset;
615 DPRINTF(GIC,
"gic distributor write GICD_ITARGETSR%d (%#x) "
616 "size %#x value %#x\n",
617 ix, daddr, data_sz,
data);
621 assert (data_sz == 4);
637 DPRINTF(GIC,
"gic distributor write GICD_ICFGR%d (%#x) "
638 "size %#x value %#x\n", ix, daddr, data_sz,
data);
642 warn(
"GIC N:N mode selected and not supported at this time\n");
650 DPRINTF(GIC,
"gic distributor write GICD_CTLR (%#x) ",
651 daddr, data_sz,
data);
659 DPRINTF(GIC,
"gem5 extensions %s\n",
663 DPRINTF(GIC,
"gic distributor write GICD_SGIR (%#x) ",
664 daddr, data_sz,
data);
668 panic(
"Tried to write Gic distributor at offset %#x\n", daddr);
678 assert(pkt->
req->hasContextId());
680 const uint32_t
data = pkt->
getLE<uint32_t>();
693 DPRINTF(GIC,
"gic cpu write GICC_CTLR cpu:%d %#x val: %#x\n",
698 DPRINTF(GIC,
"gic cpu write GICC_PMR cpu:%d %#x val: %#x\n",
703 auto bpr =
data & 0x7;
706 DPRINTF(GIC,
"gic cpu write GICC_BPR cpu:%d %#x val: %#x\n",
712 DPRINTF(GIC,
"gic cpu write GICC_EOIR cpu:%d %#x val: %#x\n",
714 const IAR iar =
data;
717 uint64_t clr_int = 1ULL << (ctx + 8 * iar.cpu_id);
720 panic(
"Done handling a SGI that isn't active?\n");
726 uint32_t int_num = 1 << (iar.ack_id -
SGI_MAX);
728 warn(
"CPU %d Done handling a PPI interrupt "
729 "that isn't active?\n", ctx);
734 warn(
"Done handling interrupt that isn't active: %d\n",
740 ctx, iar.ack_id, iar.cpu_id);
747 warn(
"GIC APRn write ignored because not implemented: %#x\n", daddr);
750 warn(
"GIC DIR write ignored because not implemented: %#x\n", daddr);
753 panic(
"Tried to write Gic cpu at offset %#x\n", daddr);
773 switch (swi.list_type) {
776 int dest = swi.cpu_list;
777 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
781 DPRINTF(IPI,
"SGI[%d]=%#x\n", dest,
788 DPRINTF(IPI,
"Processing CPU %d\n",
i);
792 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
798 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
802 DPRINTF(IPI,
"SGI[%d]=%#x\n", ctx,
808 switch (swi.list_type) {
819 swi.cpu_list = 1 << ctx;
824 DPRINTF(IPI,
"Generating softIRQ from CPU %d for %#x\n", ctx,
827 DPRINTF(IPI,
"Processing CPU %d\n",
i);
830 if (swi.cpu_list & (1 <<
i))
832 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
843 return 0x0101010101010101ULL << cpu;
873 for (
int swi = 0; swi <
SGI_MAX; swi++) {
886 for (
int ppi_idx = 0, int_num =
SGI_MAX;
888 ppi_idx++, int_num++) {
892 const bool higher_priority =
895 if (ppi_pending && ppi_enabled && higher_priority) {
897 highest_int = int_num;
908 DPRINTF(GIC,
"Checking for interrupt# %d \n",int_nm);
921 highest_int = int_nm;
949 if (
isFiq(cpu, highest_int)) {
964 uint8_t maxPriority = 0xff;
983 iccrpr[cpu] = maxPriority;
994 panic(
"Multiple targets for peripheral interrupts is not supported\n");
996 "sentInt() must only be used for interrupts 32 and higher");
1017 "Received Clear interrupt number %d, cpuTarget %#x:\n",
1048 if (
isFiq(ctx, int_num)) {
1146 set += 4, clear += 4, size -= 4;
1157 set += 4, clear += 4, size -= 4;
1168 set += 4, clear += 4, size -= 4;
1194 DPRINTF(Checkpoint,
"Serializing Arm GIC\n");
1239 DPRINTF(Checkpoint,
"Unserializing Arm GIC\n");
1268 for (uint32_t cpu = 0; cpu <
CPU_MAX; cpu++) {
1269 if (interrupt_time[cpu])
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
EventQueue * eventq
A pointer to this object's event queue.
static void clearDistRange(GicV2Registers *to, Addr daddr, size_t size)
virtual uint32_t readDistributor(ContextID ctx, Addr daddr)=0
static void copyDistRange(GicV2Registers *from, GicV2Registers *to, Addr daddr, size_t size)
static void copyBankedDistRange(System *sys, GicV2Registers *from, GicV2Registers *to, Addr daddr, size_t size)
static void copyDistRegister(GicV2Registers *from, GicV2Registers *to, ContextID ctx, Addr daddr)
virtual uint32_t readCpu(ContextID ctx, Addr daddr)=0
static void clearBankedDistRange(System *sys, GicV2Registers *to, Addr daddr, size_t size)
static void copyCpuRegister(GicV2Registers *from, GicV2Registers *to, ContextID ctx, Addr daddr)
static const int GLOBAL_INT_LINES
const Tick distPioDelay
Latency for a distributor operation.
std::vector< BankedRegs * > bankedRegs
int intNumToBit(int num) const
EventFunctionWrapper * postIntEvent[CPU_MAX]
uint32_t itLines
Number of itLines enabled.
static const AddrRange GICD_IPRIORITYR
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.
static const AddrRange GICD_ICACTIVER
void postFiq(uint32_t cpu, Tick when)
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
uint32_t intEnabled[INT_BITS_MAX-1]
GICD_I{S,C}ENABLER{1..31} interrupt enable bits for global interrupts 1b per interrupt,...
uint32_t cpuSgiPendingExt[CPU_MAX]
SGI pending arrays for gem5 GIC extension mode, which instead keeps 16 SGI pending bits for each of t...
static const AddrRange GICD_ICFGR
static const AddrRange GICD_ICENABLER
static const int INT_LINES_MAX
void softInt(ContextID ctx, SWI swi)
software generated interrupt
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
static const AddrRange GICD_ISPENDR
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
EndBitUnion(CTLR) protected const AddrRange cpuRange
Address range for the distributor interface.
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
uint8_t cpuPriority[CPU_MAX]
CPU priority.
int pendingDelayedInterrupts
uint32_t pendingInt[INT_BITS_MAX-1]
GICD_I{S,C}PENDR{1..31} interrupt pending bits for global interrupts 1b per interrupt,...
BankedRegs & getBankedRegs(ContextID)
static const int INT_BITS_MAX
void copyGicState(GicV2Registers *from, GicV2Registers *to)
GIC state transfer.
void postDelayedFiq(uint32_t cpu)
EventFunctionWrapper * postFiqEvent[CPU_MAX]
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
uint32_t cpuPpiActive[CPU_MAX]
static const AddrRange GICD_ISACTIVER
static const AddrRange GICD_IGROUPR
uint8_t getCpuPriority(unsigned cpu)
int intNumToWord(int num) const
void drainResume() override
Resume execution after a successful drain.
uint32_t & getIntGroup(ContextID ctx, uint32_t ix)
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
uint32_t intGroup[INT_BITS_MAX-1]
GICD_IGROUPR{1..31} interrupt group bits for global interrupts 1b per interrupt, 32 bits per word,...
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 ...
const Tick intLatency
Latency for a interrupt to get to CPU.
void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
const bool haveGem5Extensions
Are gem5 extensions available?
bool isLevelSensitive(ContextID ctx, uint32_t int_num)
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu()
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
uint32_t & getIntConfig(ContextID ctx, uint32_t ix)
Reads the GICD_ICFGRn register.
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Linux...
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
uint64_t cpuSgiActive[SGI_MAX]
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
CTLR cpuControl[CPU_MAX]
GICC_CTLR: CPU interface control register.
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
uint32_t cpuSgiActiveExt[CPU_MAX]
static const AddrRange GICD_ISENABLER
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu()
uint8_t cpuTarget[GLOBAL_INT_LINES]
GICD_ITARGETSR{8..255} an 8 bit cpu target id for each global interrupt.
bool cpuEnabled(ContextID ctx) const
CPU enabled: Checks if GICC_CTLR.EnableGrp0 or EnableGrp1 are set.
void serialize(CheckpointOut &cp) const override
Serialize an object.
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
static const int SPURIOUS_INT
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
bool supportsVersion(GicVersion version) override
Check if version supported.
void clearPPInt(uint32_t num, uint32_t cpu) override
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
const Tick cpuPioDelay
Latency for a cpu operation.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint8_t getCpuTarget(ContextID ctx, uint32_t ix) const
static const AddrRange GICD_ITARGETSR
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
Bitfield< 23, 16 > cpu_list
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...
void clearInt(ContextID ctx, uint32_t int_num)
Clears a cpu IRQ or FIQ signal.
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
uint32_t activeInt[INT_BITS_MAX-1]
GICD_I{S,C}ACTIVER{1..31} interrupt active bits for global interrupts 1b per interrupt,...
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
static const AddrRange GICD_ICPENDR
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
void makeAtomicResponse()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
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.
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
void signalDrainDone() const
Signal that an object is drained.
DrainState
Object drain/handover states.
@ 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.
void schedule(Event &event, Tick when)
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
bool entryExists(const std::string §ion, const std::string &entry)
#define UNSERIALIZE_OPT_SCALAR(scalar)
static const std::string & currentSection()
Gets the fully-qualified name of the active section.
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
bool sectionExists(const std::string §ion)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
int ContextID
Globally unique thread context ID.
std::string csprintf(const char *format, const Args &...args)
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
Registers "banked for each connected processor" per ARM IHI0048B.
uint32_t intEnabled
GICD_I{S,C}ENABLER0 interrupt enable bits for first 32 interrupts, 1b per interrupt.
uint32_t intGroup
GICD_IGROUPR0 interrupt group bits for first 32 interrupts, 1b per interrupt.
uint32_t activeInt
GICD_I{S,C}ACTIVER0 interrupt active bits for first 32 interrupts, 1b per interrupt.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint8_t intPriority[SGI_MAX+PPI_MAX]
GICD_IPRIORITYR{0..7} interrupt priority for SGIs and PPIs.
void serialize(CheckpointOut &cp) const override
Serialize an object.
uint32_t pendingInt
GICD_I{S,C}PENDR0 interrupt pending bits for first 32 interrupts, 1b per interrupt.
uint32_t intConfig[2]
GICD_ICFGR0, GICD_ICFGR1 interrupt config bits for first 32 interrupts, 2b per interrupt.