47 #include "debug/Checkpoint.hh"
48 #include "debug/GIC.hh"
49 #include "debug/IPI.hh"
50 #include "debug/Interrupt.hh"
68 distRange(
RangeSize(p->dist_addr, DIST_SIZE)),
69 cpuRange(
RangeSize(p->cpu_addr, CPU_SIZE)),
71 distPioDelay(
p->dist_pio_delay),
72 cpuPioDelay(
p->cpu_pio_delay), intLatency(
p->int_latency),
73 enabled(
false), haveGem5Extensions(
p->gem5_extensions),
75 intEnabled {}, pendingInt {}, activeInt {},
76 intPriority {}, cpuTarget {}, intConfig {},
77 cpuSgiPending {}, cpuSgiActive {},
78 cpuSgiPendingExt {}, cpuSgiActiveExt {},
79 cpuPpiPending {}, cpuPpiActive {},
81 pendingDelayedInterrupts(0)
83 for (
int x = 0;
x < CPU_MAX;
x++) {
85 cpuEnabled[
x] =
false;
86 cpuPriority[
x] = 0xff;
87 cpuBpr[
x] = GICC_BPR_MINIMUM;
89 cpuHighestInt[
x] = SPURIOUS_INT;
90 postIntEvent[
x] =
new PostIntEvent(*
this,
x);
92 DPRINTF(Interrupt,
"cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
95 gem5ExtensionsEnabled =
false;
103 if (distRange.contains(addr))
117 if (distRange.contains(addr))
122 panic(
"Write to unknown address %#x\n", pkt->
getAddr());
128 const Addr daddr = pkt->
getAddr() - distRange.start();
131 DPRINTF(GIC,
"gic distributor read register %#x\n", daddr);
137 pkt->
set<uint8_t>(resp);
140 pkt->
set<uint16_t>(resp);
143 pkt->
set<uint32_t>(resp);
146 panic(
"Invalid size while reading Distributor regs in GIC: %d\n",
200 DPRINTF(Interrupt,
"Reading interrupt priority at int# %#x \n",int_num);
221 DPRINTF(GIC,
"Reading processor target register for int# %#x \n",
228 assert(resp_sz == 4);
229 int_num =
mbits(int_num, 31, 2);
256 panic(
"Tried to read Gic distributor at offset %#x\n", daddr);
268 assert(ctx < sys->numRunningContexts());
270 DPRINTF(GIC,
"gic cpu read register %#x cpu context: %d\n", daddr,
295 iar.ack_id = active_int;
301 "Interrupt %d active but no CPU generated it?\n",
307 if (cpugen & (1 << ctx)) {
312 uint64_t sgi_num =
ULL(1) << (ctx + 8 * iar.cpu_id);
316 uint64_t sgi_num =
ULL(1) << iar.ack_id;
334 DPRINTF(Interrupt,
"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
335 ctx, iar.ack_id, iar.cpu_id, iar);
348 panic(
"Need to implement HPIR");
351 panic(
"Tried to read Gic cpu at offset %#x\n", daddr);
359 const Addr daddr = pkt->
getAddr() - distRange.start();
363 const size_t data_sz = pkt->
getSize();
369 pkt_data = pkt->
get<uint8_t>();
372 pkt_data = pkt->
get<uint16_t>();
375 pkt_data = pkt->
get<uint32_t>();
378 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
382 DPRINTF(GIC,
"gic distributor write register %#x size %#x value %#x \n",
383 daddr, data_sz, pkt_data);
462 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
475 if (int_num >= offset) {
476 unsigned ix = int_num -
offset;
480 assert (data_sz == 4);
496 warn(
"GIC N:N mode selected and not supported at this time\n");
503 DPRINTF(Interrupt,
"Distributor enable flag set to = %d\n",
enabled);
510 DPRINTF(GIC,
"gem5 extensions %s\n",
517 panic(
"Tried to write Gic distributor at offset %#x\n", daddr);
529 const uint32_t
data = pkt->
get<uint32_t>();
531 DPRINTF(GIC,
"gic cpu write register cpu:%d %#x val: %#x\n",
551 auto bpr = data & 0x7;
558 const IAR iar =
data;
561 uint64_t clr_int =
ULL(1) << (ctx + 8 * iar.cpu_id);
564 panic(
"Done handling a SGI that isn't active?\n");
570 uint32_t int_num = 1 << (iar.ack_id -
SGI_MAX);
572 panic(
"CPU %d Done handling a PPI interrupt "
573 "that isn't active?\n", ctx);
578 warn(
"Done handling interrupt that isn't active: %d\n",
583 DPRINTF(Interrupt,
"CPU %d done handling intr IAR = %d from cpu %d\n",
584 ctx, iar.ack_id, iar.cpu_id);
588 panic(
"Tried to write Gic cpu at offset %#x\n", daddr);
608 switch (swi.list_type) {
611 int dest = swi.cpu_list;
612 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
616 DPRINTF(IPI,
"SGI[%d]=%#x\n", dest,
623 DPRINTF(IPI,
"Processing CPU %d\n",
i);
627 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
633 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
637 DPRINTF(IPI,
"SGI[%d]=%#x\n", ctx,
643 switch (swi.list_type) {
654 swi.cpu_list = 1 << ctx;
659 DPRINTF(IPI,
"Generating softIRQ from CPU %d for %#x\n", ctx,
662 DPRINTF(IPI,
"Processing CPU %d\n",
i);
665 if (swi.cpu_list & (1 << i))
667 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
678 panic(
"Invalid CPU ID\n");
679 return ULL(0x0101010101010101) << cpu;
706 for (
int swi = 0; swi <
SGI_MAX; swi++) {
719 for (
int ppi = 0; ppi <
PPI_MAX; ppi++) {
723 highest_int = SGI_MAX + ppi;
733 uint32_t int_nm =
x * INT_BITS_MAX + y;
734 DPRINTF(GIC,
"Checking for interrupt# %d \n",int_nm);
747 highest_int = int_nm;
765 DPRINTF(Interrupt,
"Posting interrupt %d to cpu%d\n", highest_int,
778 uint8_t maxPriority = 0xff;
797 iccrpr[cpu] = maxPriority;
805 DPRINTF(Interrupt,
"Received Interrupt number %d, cpuTarget %#x: \n",
808 panic(
"Multiple targets for peripheral interrupts is not supported\n");
810 "sentInt() must only be used for interrupts 32 and higher");
818 DPRINTF(Interrupt,
"Received PPI %d, cpuTarget %#x: \n",
833 DPRINTF(Interrupt,
"Clearing PPI %d, cpuTarget %#x: \n",
871 DPRINTF(Checkpoint,
"Serializing Arm GIC\n");
914 DPRINTF(Checkpoint,
"Unserializing Arm GIC\n");
943 for (uint32_t cpu = 0; cpu <
CPU_MAX; cpu++) {
944 if (interrupt_time[cpu])
970 Pl390Params::create()
972 return new Pl390(
this);
990 DPRINTF(GIC,
" Enabling Irq\n");
999 DPRINTF(GIC,
"Driving Legacy Irq\n");
EventQueue * eventq
A pointer to this object's event queue.
AddrRange RangeSize(Addr start, Addr size)
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu() ...
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
void clearInt(uint32_t number) override
Clear an interrupt from a device that is connected to the GIC.
Platform * platform
Platform this GIC belongs to.
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
Addr start() const
Get the start address of the range.
std::vector< BankedRegs * > bankedRegs
ContextID contextId() const
Accessor function for context ID.
DrainState
Object drain/handover states.
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.
static const AddrRange GICD_ITARGETSR
void serialize(CheckpointOut &cp) const override
Serialize an object.
#define UNSERIALIZE_OPT_SCALAR(scalar)
uint32_t itLines
Number of itLines enabled.
void post(int cpu_id, int int_num, int index)
EndBitUnion(IAR) protected const AddrRange cpuRange
Address range for the distributor interface.
uint8_t getCpuPriority(unsigned cpu)
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
panic_if(!root,"Invalid expression\n")
static const AddrRange GICD_ISACTIVER
static const int SPURIOUS_INT
static const int INT_BITS_MAX
Bitfield< 23, 16 > cpu_list
uint32_t pendingInt
GICD_I{S,C}PENDR0 interrupt pending bits for first 32 interrupts, 1b per interrupt.
const Tick intLatency
Latency for a interrupt to get to CPU.
bool contains(const Addr &a) const
Determine if the range contains an address.
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu() ...
static const AddrRange GICD_ISENABLER
static const AddrRange GICD_ISPENDR
const Tick distPioDelay
Latency for a distributor operation.
static const AddrRange GICD_ICACTIVER
void clearPPInt(uint32_t num, uint32_t cpu) override
const bool haveGem5Extensions
Are gem5 extensions available?
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
int numRunningContexts()
Return number of running (non-halted) thread contexts in system.
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
bool hasContextId() const
int intNumToBit(int num) const
uint32_t activeInt
GICD_I{S,C}ACTIVER0 interrupt active bits for first 32 interrupts, 1b per interrupt.
uint32_t intEnabled
GICD_I{S,C}ENABLER0 interrupt enable bits for first 32 interrupts, 1b per interrupt.
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
#define UNSERIALIZE_SCALAR(scalar)
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
Tick curTick()
The current simulated tick.
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
std::string csprintf(const char *format, const Args &...args)
void driveLegFIQ(bool state)
uint8_t cpuTarget[GLOBAL_INT_LINES]
GICD_ITARGETSR{8..255} an 8 bit cpu target id for each global interrupt.
void driveLegIRQ(bool state)
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
void makeAtomicResponse()
uint64_t Tick
Tick count type.
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.
uint32_t cpuSgiActiveExt[CPU_MAX]
uint32_t cpuSgiPendingExt[CPU_MAX]
SGI pending arrays for gem5 GIC extension mode, which instead keeps 16 SGI pending bits for each of t...
void driveSPI(uint32_t spi)
void serialize(CheckpointOut &cp) const override
Serialize an object.
#define SERIALIZE_ARRAY(member, size)
static const AddrRange GICD_ICPENDR
const RequestPtr req
A pointer to the original request.
uint8_t getCpuTarget(ContextID ctx, uint32_t ix)
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...
Registers "banked for each connected processor" per ARM IHI0048B.
uint32_t cpuPpiActive[CPU_MAX]
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
Draining buffers pending serialization/handover.
#define ULL(N)
uint64_t constant
struct BaseGicParams Params
DrainState drain() override
Notify an object that it needs to drain its state.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
bool cpuEnabled[CPU_MAX]
CPU enabled.
Implementation of a PL390 GIC.
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
uint8_t cpuPriority[CPU_MAX]
CPU priority.
#define SERIALIZE_SCALAR(scalar)
#define UNSERIALIZE_ARRAY(member, size)
static const int NumArgumentRegs M5_VAR_USED
static const int INT_LINES_MAX
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
int intNumToWord(int num) const
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 ...
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
Declaration of the Packet class.
std::ostream CheckpointOut
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
static const AddrRange GICD_ICFGR
uint8_t intPriority[SGI_MAX+PPI_MAX]
GICD_IPRIORITYR{0..7} interrupt priority for SGIs and PPIs.
bool sectionExists(const std::string §ion)
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.
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
static const AddrRange GICD_IPRIORITYR
void signalDrainDone() const
Signal that an object is drained.
uint64_t cpuSgiActive[SGI_MAX]
static const std::string & currentSection()
Get the fully-qualified name of the active section.
void driveIrqEn(bool state)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
bool irqEnable
IRQ Enable Used for debug.
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
void schedule(Event &event, Tick when)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
static const AddrRange GICD_IGROUPR
static const AddrRange GICD_ICENABLER
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
static const int GLOBAL_INT_LINES
bool entryExists(const std::string §ion, const std::string &entry)
int pendingDelayedInterrupts
PostIntEvent * postIntEvent[CPU_MAX]
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Lin...
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)
Scoped checkpoint section helper class.
void softInt(ContextID ctx, SWI swi)
software generated interrupt
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
int ContextID
Globally unique thread context ID.
BankedRegs & getBankedRegs(ContextID)
const Tick cpuPioDelay
Latency for a cpu operation.
void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.