Go to the documentation of this file.
44 #include "debug/Checkpoint.hh"
45 #include "debug/GIC.hh"
46 #include "debug/IPI.hh"
47 #include "debug/Interrupt.hh"
64 gicdPIDR(
p->gicd_pidr),
65 gicdIIDR(
p->gicd_iidr),
66 giccIIDR(
p->gicc_iidr),
70 distPioDelay(
p->dist_pio_delay),
71 cpuPioDelay(
p->cpu_pio_delay), intLatency(
p->int_latency),
72 enabled(
false), haveGem5Extensions(
p->gem5_extensions),
74 intEnabled {}, pendingInt {}, activeInt {},
75 intPriority {}, intConfig {}, cpuTarget {},
76 cpuSgiPending {}, cpuSgiActive {},
77 cpuSgiPendingExt {}, cpuSgiActiveExt {},
78 cpuPpiPending {}, cpuPpiActive {},
79 pendingDelayedInterrupts(0)
81 for (
int x = 0;
x < CPU_MAX;
x++) {
84 cpuPriority[
x] = 0xff;
85 cpuBpr[
x] = GICC_BPR_MINIMUM;
87 cpuHighestInt[
x] = SPURIOUS_INT;
90 "Post Interrupt to CPU");
95 DPRINTF(Interrupt,
"cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled(0),
98 gem5ExtensionsEnabled =
false;
114 if (distRange.contains(
addr))
128 if (distRange.contains(
addr))
133 panic(
"Write to unknown address %#x\n", pkt->
getAddr());
139 const Addr daddr = pkt->
getAddr() - distRange.start();
142 DPRINTF(GIC,
"gic distributor read register %#x\n", daddr);
148 pkt->
setLE<uint8_t>(resp);
151 pkt->
setLE<uint16_t>(resp);
154 pkt->
setLE<uint32_t>(resp);
157 panic(
"Invalid size while reading Distributor regs in GIC: %d\n",
213 DPRINTF(Interrupt,
"Reading interrupt priority at int# %#x \n",
235 DPRINTF(GIC,
"Reading processor target register for int# %#x \n",
242 assert(resp_sz == 4);
243 int_num =
mbits(int_num, 31, 2);
279 panic(
"Tried to read Gic distributor at offset %#x\n", daddr);
289 assert(pkt->
req->hasContextId());
291 assert(ctx < sys->threads.numRunning());
293 DPRINTF(GIC,
"gic cpu read register %#x cpu context: %d\n", daddr, ctx);
317 iar.ack_id = active_int;
323 "Interrupt %d active but no CPU generated it?\n",
329 if (cpugen & (1 << ctx)) {
334 uint64_t sgi_num =
ULL(1) << (ctx + 8 * iar.cpu_id);
338 uint64_t sgi_num =
ULL(1) << iar.ack_id;
361 "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
362 ctx, iar.ack_id, iar.cpu_id, iar);
375 panic(
"Need to implement HPIR");
378 panic(
"Tried to read Gic cpu at offset %#x\n", daddr);
386 const Addr daddr = pkt->
getAddr() - distRange.start();
388 assert(pkt->
req->hasContextId());
390 const size_t data_sz = pkt->
getSize();
392 uint32_t pkt_data M5_VAR_USED;
396 pkt_data = pkt->
getLE<uint8_t>();
399 pkt_data = pkt->
getLE<uint16_t>();
402 pkt_data = pkt->
getLE<uint32_t>();
405 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
409 DPRINTF(GIC,
"gic distributor write register %#x size %#x value %#x \n",
410 daddr, data_sz, pkt_data);
492 panic(
"Invalid size when writing to priority regs in Gic: %d\n",
506 unsigned ix = int_num -
offset;
510 assert (data_sz == 4);
528 warn(
"GIC N:N mode selected and not supported at this time\n");
535 DPRINTF(Interrupt,
"Distributor enable flag set to = %d\n",
enabled);
542 DPRINTF(GIC,
"gem5 extensions %s\n",
549 panic(
"Tried to write Gic distributor at offset %#x\n", daddr);
559 assert(pkt->
req->hasContextId());
561 const uint32_t
data = pkt->
getLE<uint32_t>();
563 DPRINTF(GIC,
"gic cpu write register cpu:%d %#x val: %#x\n",
583 auto bpr =
data & 0x7;
590 const IAR iar =
data;
593 uint64_t clr_int =
ULL(1) << (ctx + 8 * iar.cpu_id);
596 panic(
"Done handling a SGI that isn't active?\n");
602 uint32_t int_num = 1 << (iar.ack_id -
SGI_MAX);
604 warn(
"CPU %d Done handling a PPI interrupt "
605 "that isn't active?\n", ctx);
610 warn(
"Done handling interrupt that isn't active: %d\n",
615 DPRINTF(Interrupt,
"CPU %d done handling intr IAR = %d from cpu %d\n",
616 ctx, iar.ack_id, iar.cpu_id);
623 warn(
"GIC APRn write ignored because not implemented: %#x\n", daddr);
626 warn(
"GIC DIR write ignored because not implemented: %#x\n", daddr);
629 panic(
"Tried to write Gic cpu at offset %#x\n", daddr);
649 switch (swi.list_type) {
652 int dest = swi.cpu_list;
653 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
657 DPRINTF(IPI,
"SGI[%d]=%#x\n", dest,
664 DPRINTF(IPI,
"Processing CPU %d\n",
i);
668 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
674 DPRINTF(IPI,
"Generating softIRQ from CPU %d for CPU %d\n",
678 DPRINTF(IPI,
"SGI[%d]=%#x\n", ctx,
684 switch (swi.list_type) {
695 swi.cpu_list = 1 << ctx;
700 DPRINTF(IPI,
"Generating softIRQ from CPU %d for %#x\n", ctx,
703 DPRINTF(IPI,
"Processing CPU %d\n",
i);
706 if (swi.cpu_list & (1 <<
i))
708 DPRINTF(IPI,
"SGI[%d]=%#x\n", swi.sgi_id,
719 return ULL(0x0101010101010101) << cpu;
746 for (
int swi = 0; swi <
SGI_MAX; swi++) {
759 for (
int ppi_idx = 0, int_num =
SGI_MAX;
761 ppi_idx++, int_num++) {
765 const bool higher_priority =
768 if (ppi_pending && ppi_enabled && higher_priority) {
770 highest_int = int_num;
781 DPRINTF(GIC,
"Checking for interrupt# %d \n",int_nm);
794 highest_int = int_nm;
806 DPRINTF(Interrupt,
"Clear IRQ for cpu%d\n", cpu);
819 DPRINTF(Interrupt,
"Posting interrupt %d to cpu%d\n", highest_int,
822 if (
isFiq(cpu, highest_int)) {
837 uint8_t maxPriority = 0xff;
856 iccrpr[cpu] = maxPriority;
864 DPRINTF(Interrupt,
"Received Interrupt number %d, cpuTarget %#x: \n",
867 panic(
"Multiple targets for peripheral interrupts is not supported\n");
869 "sentInt() must only be used for interrupts 32 and higher");
877 DPRINTF(Interrupt,
"Received PPI %d, cpuTarget %#x: \n",
890 "Received Clear interrupt number %d, cpuTarget %#x:\n",
906 DPRINTF(Interrupt,
"Clearing PPI %d, cpuTarget %#x: \n",
920 if (
isFiq(ctx, int_num)) {
992 DPRINTF(Checkpoint,
"Serializing Arm GIC\n");
1037 DPRINTF(Checkpoint,
"Unserializing Arm GIC\n");
1066 for (uint32_t cpu = 0; cpu <
CPU_MAX; cpu++) {
1067 if (interrupt_time[cpu])
1095 GicV2Params::create()
1097 return new GicV2(
this);
uint32_t intGroup
GICD_IGROUPR0 interrupt group bits for first 32 interrupts, 1b per interrupt.
uint32_t & getIntConfig(ContextID ctx, uint32_t ix)
Reads the GICD_ICFGRn register.
void makeAtomicResponse()
uint32_t pendingInt[INT_BITS_MAX-1]
GICD_I{S,C}PENDR{1..31} interrupt pending bits for global interrupts 1b per interrupt,...
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
void clear(int cpu_id, int int_num, int index)
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu()
static const AddrRange GICD_ISENABLER
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
void post(int cpu_id, int int_num, int index)
#define UNSERIALIZE_SCALAR(scalar)
const Tick intLatency
Latency for a interrupt to get to CPU.
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Linux...
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 ...
uint32_t cpuSgiActiveExt[CPU_MAX]
void clearInt(ContextID ctx, uint32_t int_num)
Clears a cpu IRQ or FIQ signal.
const Tick distPioDelay
Latency for a distributor operation.
Bitfield< 23, 16 > cpu_list
static const int GLOBAL_INT_LINES
int ContextID
Globally unique thread context ID.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint64_t Tick
Tick count type.
uint32_t intEnabled[INT_BITS_MAX-1]
GICD_I{S,C}ENABLER{1..31} interrupt enable bits for global interrupts 1b per interrupt,...
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu()
void softInt(ContextID ctx, SWI swi)
software generated interrupt
uint32_t cpuPpiActive[CPU_MAX]
bool contains(const Addr &a) const
Determine if the range contains an address.
RequestPtr req
A pointer to the original request.
T mbits(T val, int first, int last)
Mask off the given bits in place like bits() but without shifting.
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.
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
CTLR cpuControl[CPU_MAX]
GICC_CTLR: CPU interface control register.
static const int INT_LINES_MAX
EventFunctionWrapper * postFiqEvent[CPU_MAX]
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
bool isLevelSensitive(ContextID ctx, uint32_t int_num)
static const AddrRange GICD_ICENABLER
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 unserialize(CheckpointIn &cp) override
Unserialize an object.
uint32_t intGroup[INT_BITS_MAX-1]
GICD_IGROUPR{1..31} interrupt group bits for global interrupts 1b per interrupt, 32 bits per word,...
virtual void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
int intNumToWord(int num) const
static const int SPURIOUS_INT
@ Drained
Buffers drained, ready for serialization/handover.
DrainState
Object drain/handover states.
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
const std::string DIST_SIZE
Unique key for "size" param (distributed gem5 runs)
void schedule(Event &event, Tick when)
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
uint8_t intPriority[SGI_MAX+PPI_MAX]
GICD_IPRIORITYR{0..7} interrupt priority for SGIs and PPIs.
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
static const AddrRange GICD_ISACTIVER
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
static const AddrRange GICD_IPRIORITYR
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
uint8_t cpuPriority[CPU_MAX]
CPU priority.
AddrRange RangeSize(Addr start, Addr size)
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
#define UNSERIALIZE_OPT_SCALAR(scalar)
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
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,...
void serialize(CheckpointOut &cp) const override
Serialize an object.
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
Platform * platform
Platform this GIC belongs to.
void signalDrainDone() const
Signal that an object is drained.
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
uint64_t cpuSgiActive[SGI_MAX]
bool supportsVersion(GicVersion version) override
Check if version supported.
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
#define SERIALIZE_ARRAY(member, size)
int pendingDelayedInterrupts
void postDelayedFiq(uint32_t cpu)
uint32_t activeInt
GICD_I{S,C}ACTIVER0 interrupt active bits for first 32 interrupts, 1b per interrupt.
uint32_t itLines
Number of itLines enabled.
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
EventFunctionWrapper * postIntEvent[CPU_MAX]
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint8_t getCpuTarget(ContextID ctx, uint32_t ix) const
#define SERIALIZE_SCALAR(scalar)
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
uint32_t intConfig[2]
GICD_ICFGR0, GICD_ICFGR1 interrupt config bits for first 32 interrupts, 2b per interrupt.
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
uint8_t getCpuPriority(unsigned cpu)
bool cpuEnabled(ContextID ctx) const
CPU enabled: Checks if GICC_CTLR.EnableGrp0 or EnableGrp1 are set.
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.
std::vector< BankedRegs * > bankedRegs
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 int INT_BITS_MAX
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
static const AddrRange GICD_ISPENDR
uint32_t & getIntGroup(ContextID ctx, uint32_t ix)
Addr start() const
Get the start address of the range.
#define UNSERIALIZE_ARRAY(member, size)
void clearPPInt(uint32_t num, uint32_t cpu) override
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
static const AddrRange GICD_ITARGETSR
static const AddrRange GICD_ICPENDR
Registers "banked for each connected processor" per ARM IHI0048B.
EventQueue * eventq
A pointer to this object's event queue.
void drainResume() override
Resume execution after a successful drain.
void setLE(T v)
Set the value in the data pointer to v as little endian.
const bool haveGem5Extensions
Are gem5 extensions available?
std::ostream CheckpointOut
int intNumToBit(int num) const
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
static const std::string & currentSection()
Gets the fully-qualified name of the active section.
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.
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
void postFiq(uint32_t cpu, Tick when)
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
BankedRegs & getBankedRegs(ContextID)
uint32_t intEnabled
GICD_I{S,C}ENABLER0 interrupt enable bits for first 32 interrupts, 1b per interrupt.
const EndBitUnion(CTLR) protected AddrRange cpuRange
Address range for the distributor interface.
const Tick cpuPioDelay
Latency for a cpu operation.
std::string csprintf(const char *format, const Args &...args)
#define ULL(N)
uint64_t constant
@ Draining
Draining buffers pending serialization/handover.
static const AddrRange GICD_IGROUPR
#define panic(...)
This implements a cprintf based panic() function.
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
Tick curTick()
The current simulated tick.
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17