47 #include "debug/Checkpoint.hh" 48 #include "debug/GIC.hh" 49 #include "debug/IPI.hh" 50 #include "debug/Interrupt.hh" 67 gicdPIDR(p->gicd_pidr),
68 gicdIIDR(p->gicd_iidr),
69 giccIIDR(p->gicc_iidr),
70 distRange(
RangeSize(p->dist_addr, DIST_SIZE)),
71 cpuRange(
RangeSize(p->cpu_addr, p->cpu_size)),
93 "Post Interrupt to CPU");
117 if (distRange.contains(addr))
131 if (distRange.contains(addr))
136 panic(
"Write to unknown address %#x\n", pkt->
getAddr());
142 const Addr daddr = pkt->
getAddr() - distRange.start();
145 DPRINTF(GIC,
"gic distributor read register %#x\n", daddr);
151 pkt->
setLE<uint8_t>(resp);
154 pkt->
setLE<uint16_t>(resp);
157 pkt->
setLE<uint32_t>(resp);
160 panic(
"Invalid size while reading Distributor regs in GIC: %d\n",
216 DPRINTF(Interrupt,
"Reading interrupt priority at int# %#x \n",
238 DPRINTF(GIC,
"Reading processor target register for int# %#x \n",
245 assert(resp_sz == 4);
246 int_num =
mbits(int_num, 31, 2);
285 panic(
"Tried to read Gic distributor at offset %#x\n", daddr);
295 assert(pkt->
req->hasContextId());
297 assert(ctx < sys->numRunningContexts());
299 DPRINTF(GIC,
"gic cpu read register %#x cpu context: %d\n", daddr,
324 iar.ack_id = active_int;
330 "Interrupt %d active but no CPU generated it?\n",
336 if (cpugen & (1 << ctx)) {
341 uint64_t sgi_num =
ULL(1) << (ctx + 8 * iar.cpu_id);
345 uint64_t sgi_num =
ULL(1) << iar.ack_id;
366 "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
367 ctx, iar.ack_id, iar.cpu_id, iar);
380 panic(
"Need to implement HPIR");
383 panic(
"Tried to read Gic cpu at offset %#x\n", daddr);
391 const Addr daddr = pkt->
getAddr() - distRange.start();
393 assert(pkt->
req->hasContextId());
395 const size_t data_sz = pkt->
getSize();
401 pkt_data = pkt->
getLE<uint8_t>();
404 pkt_data = pkt->
getLE<uint16_t>();
407 pkt_data = pkt->
getLE<uint32_t>();
410 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
414 DPRINTF(GIC,
"gic distributor write register %#x size %#x value %#x \n",
415 daddr, data_sz, pkt_data);
497 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
510 if (int_num >= offset) {
511 unsigned ix = int_num -
offset;
515 assert (data_sz == 4);
531 warn(
"GIC N:N mode selected and not supported at this time\n");
538 DPRINTF(Interrupt,
"Distributor enable flag set to = %d\n",
enabled);
545 DPRINTF(GIC,
"gem5 extensions %s\n",
552 panic(
"Tried to write Gic distributor at offset %#x\n", daddr);
562 assert(pkt->
req->hasContextId());
564 const uint32_t
data = pkt->
getLE<uint32_t>();
566 DPRINTF(GIC,
"gic cpu write register cpu:%d %#x val: %#x\n",
586 auto bpr = data & 0x7;
593 const IAR iar =
data;
596 uint64_t clr_int =
ULL(1) << (ctx + 8 * iar.cpu_id);
599 panic(
"Done handling a SGI that isn't active?\n");
605 uint32_t int_num = 1 << (iar.ack_id -
SGI_MAX);
607 warn(
"CPU %d Done handling a PPI interrupt " 608 "that isn't active?\n", ctx);
613 warn(
"Done handling interrupt that isn't active: %d\n",
618 DPRINTF(Interrupt,
"CPU %d done handling intr IAR = %d from cpu %d\n",
619 ctx, iar.ack_id, iar.cpu_id);
626 warn(
"GIC APRn write ignored because not implemented: %#x\n", daddr);
629 warn(
"GIC DIR write ignored because not implemented: %#x\n", daddr);
632 panic(
"Tried to write Gic cpu at offset %#x\n", daddr);
652 switch (swi.list_type) {
655 int dest = swi.cpu_list;
656 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
660 DPRINTF(IPI,
"SGI[%d]=%#x\n", dest,
667 DPRINTF(IPI,
"Processing CPU %d\n",
i);
671 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
677 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
681 DPRINTF(IPI,
"SGI[%d]=%#x\n", ctx,
687 switch (swi.list_type) {
698 swi.cpu_list = 1 << ctx;
703 DPRINTF(IPI,
"Generating softIRQ from CPU %d for %#x\n", ctx,
706 DPRINTF(IPI,
"Processing CPU %d\n",
i);
709 if (swi.cpu_list & (1 <<
i))
711 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
722 panic(
"Invalid CPU ID\n");
723 return ULL(0x0101010101010101) << cpu;
750 for (
int swi = 0; swi <
SGI_MAX; swi++) {
763 for (
int ppi_idx = 0, int_num = SGI_MAX;
765 ppi_idx++, int_num++) {
769 const bool higher_priority =
772 if (ppi_pending && ppi_enabled && higher_priority) {
774 highest_int = int_num;
784 uint32_t int_nm =
x * INT_BITS_MAX + y;
785 DPRINTF(GIC,
"Checking for interrupt# %d \n",int_nm);
798 highest_int = int_nm;
810 DPRINTF(Interrupt,
"Clear IRQ for cpu%d\n", cpu);
823 DPRINTF(Interrupt,
"Posting interrupt %d to cpu%d\n", highest_int,
826 if (
isFiq(cpu, highest_int)) {
841 uint8_t maxPriority = 0xff;
860 iccrpr[cpu] = maxPriority;
868 DPRINTF(Interrupt,
"Received Interrupt number %d, cpuTarget %#x: \n",
871 panic(
"Multiple targets for peripheral interrupts is not supported\n");
873 "sentInt() must only be used for interrupts 32 and higher");
881 DPRINTF(Interrupt,
"Received PPI %d, cpuTarget %#x: \n",
894 "Received Clear interrupt number %d, cpuTarget %#x:\n",
909 DPRINTF(Interrupt,
"Clearing PPI %d, cpuTarget %#x: \n",
918 if (
isFiq(ctx, int_num)) {
990 DPRINTF(Checkpoint,
"Serializing Arm GIC\n");
1034 DPRINTF(Checkpoint,
"Unserializing Arm GIC\n");
1063 for (uint32_t cpu = 0; cpu <
CPU_MAX; cpu++) {
1064 if (interrupt_time[cpu])
1091 GicV2Params::create()
1093 return new GicV2(
this);
EventQueue * eventq
A pointer to this object's event queue.
#define panic(...)
This implements a cprintf based panic() function.
uint32_t cpuSgiActiveExt[CPU_MAX]
void clearInt(ContextID ctx, uint32_t int_num)
Clears a cpu IRQ or FIQ signal.
static const int GLOBAL_INT_LINES
Bitfield< 23, 16 > cpu_list
AddrRange RangeSize(Addr start, Addr size)
static const AddrRange GICD_IGROUPR
EndBitUnion(CTLR) protected const AddrRange cpuRange
Address range for the distributor interface.
Platform * platform
Platform this GIC belongs to.
Registers "banked for each connected processor" per ARM IHI0048B.
uint32_t intEnabled[INT_BITS_MAX-1]
GICD_I{S,C}ENABLER{1..31} interrupt enable bits for global interrupts 1b per interrupt, 32 bits per word, 31 words.
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
DrainState
Object drain/handover states.
#define UNSERIALIZE_OPT_SCALAR(scalar)
static const AddrRange GICD_ISENABLER
CTLR cpuControl[CPU_MAX]
GICC_CTLR: CPU interface control register.
void post(int cpu_id, int int_num, int index)
static const AddrRange GICD_ICENABLER
bool contains(const Addr &a) const
Determine if the range contains an address.
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 softInt(ContextID ctx, SWI swi)
software generated interrupt
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
uint32_t pendingInt[INT_BITS_MAX-1]
GICD_I{S,C}PENDR{1..31} interrupt pending bits for global interrupts 1b per interrupt, 32 bits per word, 31 words.
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
void signalDrainDone() const
Signal that an object is drained.
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu() ...
EventFunctionWrapper * postFiqEvent[CPU_MAX]
static const int INT_LINES_MAX
void unserialize(CheckpointIn &cp) override
Unserialize an object.
const Tick intLatency
Latency for a interrupt to get to CPU.
virtual void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
static const AddrRange GICD_ISACTIVER
static const AddrRange GICD_IPRIORITYR
bool isLevelSensitive(ContextID ctx, uint32_t ix)
const Tick distPioDelay
Latency for a distributor operation.
int numRunningContexts()
Return number of running (non-halted) thread contexts in system.
void setLE(T v)
Set the value in the data pointer to v as little endian.
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
void serialize(CheckpointOut &cp) const override
Serialize an object.
RequestPtr req
A pointer to the original request.
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu() ...
uint32_t cpuPpiActive[CPU_MAX]
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
#define UNSERIALIZE_SCALAR(scalar)
static const int SPURIOUS_INT
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
Tick curTick()
The current simulated tick.
std::string csprintf(const char *format, const Args &...args)
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
void makeAtomicResponse()
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
uint32_t intGroup[INT_BITS_MAX-1]
GICD_IGROUPR{1..31} interrupt group bits for global interrupts 1b per interrupt, 32 bits per word...
uint64_t Tick
Tick count type.
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
int intNumToWord(int num) const
bool supportsVersion(GicVersion version) override
Check if version supported.
uint64_t cpuSgiActive[SGI_MAX]
#define SERIALIZE_ARRAY(member, size)
bool cpuEnabled(ContextID ctx) const
CPU enabled: Checks if GICC_CTLR.EnableGrp0 or EnableGrp1 are set.
unsigned numContexts() const
uint8_t cpuPriority[CPU_MAX]
CPU priority.
DrainState drain() override
Notify an object that it needs to drain its state.
static const int INT_BITS_MAX
static const AddrRange GICD_ICACTIVER
uint32_t activeInt[INT_BITS_MAX-1]
GICD_I{S,C}ACTIVER{1..31} interrupt active bits for global interrupts 1b per interrupt, 32 bits per word, 31 words.
uint32_t & getIntGroup(ContextID ctx, uint32_t ix)
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Draining buffers pending serialization/handover.
#define ULL(N)
uint64_t constant
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
static const AddrRange GICD_ICPENDR
std::vector< BankedRegs * > bankedRegs
#define SERIALIZE_SCALAR(scalar)
#define UNSERIALIZE_ARRAY(member, size)
EventFunctionWrapper * postIntEvent[CPU_MAX]
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void clearPPInt(uint32_t num, uint32_t cpu) override
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
Declaration of the Packet class.
int pendingDelayedInterrupts
std::ostream CheckpointOut
BankedRegs & getBankedRegs(ContextID)
void postDelayedFiq(uint32_t cpu)
uint8_t getCpuPriority(unsigned cpu)
uint8_t getCpuTarget(ContextID ctx, uint32_t ix)
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
uint32_t cpuSgiPendingExt[CPU_MAX]
SGI pending arrays for gem5 GIC extension mode, which instead keeps 16 SGI pending bits for each of t...
uint32_t itLines
Number of itLines enabled.
bool sectionExists(const std::string §ion)
Implementation of a GICv2.
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
const Tick cpuPioDelay
Latency for a cpu operation.
static const std::string & currentSection()
Get the fully-qualified name of the active section.
void schedule(Event &event, Tick when)
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...
bool entryExists(const std::string §ion, const std::string &entry)
static const AddrRange GICD_ITARGETSR
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Addr start() const
Get the start address of the range.
void drainResume() override
Resume execution after a successful drain.
static const AddrRange GICD_ICFGR
uint8_t cpuTarget[GLOBAL_INT_LINES]
GICD_ITARGETSR{8..255} an 8 bit cpu target id for each global interrupt.
static const AddrRange GICD_ISPENDR
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
static const int NumArgumentRegs M5_VAR_USED
T mbits(T val, int first, int last)
Mask off the given bits in place like bits() but without shifting.
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
void clear(int cpu_id, int int_num, int index)
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
Scoped checkpoint section helper class.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
void postFiq(uint32_t cpu, Tick when)
int ContextID
Globally unique thread context ID.
uint32_t intConfig[INT_BITS_MAX *2]
2 bit per interrupt signaling if it's level or edge sensitive and if it is 1:N or N:N ...
const bool haveGem5Extensions
Are gem5 extensions available?
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Linux...
int intNumToBit(int num) const