{
}
-Gicv3::~Gicv3()
-{
-}
-
void
Gicv3::init()
{
"Invalid redistributor_id!");
panic_if(!redistributors[redistributor_id], "Redistributor is null!");
resp = redistributors[redistributor_id]->read(daddr, size,
- is_secure_access);
+ is_secure_access);
delay = params()->redist_pio_delay;
DPRINTF(GIC, "Gicv3::read(): (redistributor %d) context_id %d "
"register %#x size %d is_secure_access %d (value %#x)\n",
void
Gicv3::clearInt(uint32_t number)
{
- distributor->intDeasserted(number);
+ distributor->deassertSPI(number);
}
void
void
Gicv3::postInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
{
- postDelayedInt(cpu, int_type);
+ platform->intrctrl->post(cpu, int_type, 0);
}
void
platform->intrctrl->clear(cpu, int_type, 0);
}
-void
-Gicv3::postDelayedInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
-{
- platform->intrctrl->post(cpu, int_type, 0);
-}
-
Gicv3Redistributor *
-Gicv3::getRedistributorByAffinity(uint32_t affinity)
+Gicv3::getRedistributorByAffinity(uint32_t affinity) const
{
for (auto & redistributor : redistributors) {
if (redistributor->getAffinity() == affinity) {
distributor->serializeSection(cp, "distributor");
for (uint32_t redistributor_id = 0;
- redistributor_id < redistributors.size();
- redistributor_id++)
+ redistributor_id < redistributors.size(); redistributor_id++)
redistributors[redistributor_id]->serializeSection(cp,
csprintf("redistributors.%i", redistributor_id));
for (uint32_t cpu_interface_id = 0;
- cpu_interface_id < cpuInterfaces.size();
- cpu_interface_id++)
+ cpu_interface_id < cpuInterfaces.size(); cpu_interface_id++)
cpuInterfaces[cpu_interface_id]->serializeSection(cp,
csprintf("cpuInterface.%i", cpu_interface_id));
}
distributor->unserializeSection(cp, "distributor");
for (uint32_t redistributor_id = 0;
- redistributor_id < redistributors.size();
- redistributor_id++)
+ redistributor_id < redistributors.size(); redistributor_id++)
redistributors[redistributor_id]->unserializeSection(cp,
csprintf("redistributors.%i", redistributor_id));
for (uint32_t cpu_interface_id = 0;
- cpu_interface_id < cpuInterfaces.size();
- cpu_interface_id++)
+ cpu_interface_id < cpuInterfaces.size(); cpu_interface_id++)
cpuInterfaces[cpu_interface_id]->unserializeSection(cp,
csprintf("cpuInterface.%i", cpu_interface_id));
}
#include "dev/arm/base_gic.hh"
#include "params/Gicv3.hh"
+class Gicv3CPUInterface;
class Gicv3Distributor;
class Gicv3Redistributor;
-class Gicv3CPUInterface;
class Gicv3 : public BaseGic
{
protected:
+ typedef Gicv3Params Params;
Gicv3Distributor * distributor;
std::vector<Gicv3Redistributor *> redistributors;
std::vector<Gicv3CPUInterface *> cpuInterfaces;
public:
- // Special interrupt IDs
+ // Special interrupt IDs, as per SPEC 2.2.1 section
static const int INTID_SECURE = 1020;
static const int INTID_NONSECURE = 1021;
static const int INTID_SPURIOUS = 1023;
// Number of Private Peripheral Interrupts
static const int PPI_MAX = 16;
+ // Interrupt states for PPIs, SGIs and SPIs, as per SPEC 4.1.2 section
typedef enum {
INT_INACTIVE,
INT_PENDING,
INT_ACTIVE_PENDING,
} IntStatus;
+ // Interrupt groups, as per SPEC section 4.6
typedef enum {
G0S,
G1S,
INT_EDGE_TRIGGERED,
} IntTriggerType;
- typedef Gicv3Params Params;
+ protected:
- const Params *
- params() const
+ void clearInt(uint32_t int_id) override;
+ void clearPPInt(uint32_t int_id, uint32_t cpu) override;
+
+ inline AddrRangeList
+ getAddrRanges() const override
{
- return dynamic_cast<const Params *>(_params);
+ return addrRanges;
}
- Gicv3(const Params * p);
- ~Gicv3();
void init() override;
void initState() override;
- AddrRangeList
- getAddrRanges() const override
+ const Params *
+ params() const
{
- return addrRanges;
+ return dynamic_cast<const Params *>(_params);
}
Tick read(PacketPtr pkt) override;
- Tick write(PacketPtr pkt) override;
+ void reset();
void sendInt(uint32_t int_id) override;
- void clearInt(uint32_t int_id) override;
void sendPPInt(uint32_t int_id, uint32_t cpu) override;
- void clearPPInt(uint32_t int_id, uint32_t cpu) override;
-
void serialize(CheckpointOut & cp) const override;
void unserialize(CheckpointIn & cp) override;
+ Tick write(PacketPtr pkt) override;
- Gicv3Distributor *
- getDistributor() const
- {
- return distributor;
- }
+ public:
- Gicv3CPUInterface *
+ Gicv3(const Params * p);
+ void deassertInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
+
+ inline Gicv3CPUInterface *
getCPUInterface(int cpu_id) const
{
assert(cpu_id < cpuInterfaces.size() and cpuInterfaces[cpu_id]);
return cpuInterfaces[cpu_id];
}
- Gicv3Redistributor *
+ inline Gicv3Distributor *
+ getDistributor() const
+ {
+ return distributor;
+ }
+
+ inline Gicv3Redistributor *
getRedistributor(ContextID context_id) const
{
assert(context_id < redistributors.size() and
return redistributors[context_id];
}
- Gicv3Redistributor * getRedistributorByAffinity(uint32_t affinity);
+ Gicv3Redistributor *
+ getRedistributorByAffinity(uint32_t affinity) const;
void postInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
- void postDelayedInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
- void deassertInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
-
- protected:
-
- void reset();
};
#endif //__DEV_ARM_GICV3_H__
*
* Authors: Jairo Balart
*/
+
#include "dev/arm/gic_v3_distributor.hh"
#include <algorithm>
#include "dev/arm/gic_v3_cpu_interface.hh"
#include "dev/arm/gic_v3_redistributor.hh"
-const AddrRange Gicv3Distributor::GICD_IGROUPR(0x0080, 0x00ff);
-const AddrRange Gicv3Distributor::GICD_ISENABLER(0x0100, 0x017f);
-const AddrRange Gicv3Distributor::GICD_ICENABLER(0x0180, 0x01ff);
-const AddrRange Gicv3Distributor::GICD_ISPENDR(0x0200, 0x027f);
-const AddrRange Gicv3Distributor::GICD_ICPENDR(0x0280, 0x02ff);
-const AddrRange Gicv3Distributor::GICD_ISACTIVER(0x0300, 0x037f);
-const AddrRange Gicv3Distributor::GICD_ICACTIVER(0x0380, 0x03ff);
+const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff);
+const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f);
+const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff);
+const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f);
+const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff);
+const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f);
+const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff);
const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
-const AddrRange Gicv3Distributor::GICD_ITARGETSR(0x0800, 0x08ff);
-const AddrRange Gicv3Distributor::GICD_ICFGR(0x0c00, 0x0cff);
-const AddrRange Gicv3Distributor::GICD_IGRPMODR(0x0d00, 0x0d7f);
-const AddrRange Gicv3Distributor::GICD_NSACR(0x0e00, 0x0eff);
-const AddrRange Gicv3Distributor::GICD_CPENDSGIR(0x0f10, 0x0f1f);
-const AddrRange Gicv3Distributor::GICD_SPENDSGIR(0x0f20, 0x0f2f);
-const AddrRange Gicv3Distributor::GICD_IROUTER(0x6000, 0x7fe0);
+const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff);
+const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff);
+const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f);
+const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff);
+const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f);
+const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f);
+const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0);
Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines)
: gic(gic),
panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
}
-Gicv3Distributor::~Gicv3Distributor()
-{
-}
-
void
Gicv3Distributor::init()
{
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
val |= irqGroup[int_id] << i;
}
return val;
- // Interrupt Set-Enable Registers
} else if (GICD_ISENABLER.contains(addr)) {
+ // Interrupt Set-Enable Registers
uint64_t val = 0x0;
int first_intid = (addr - GICD_ISENABLER.start()) * 8;
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
return val;
} else if (GICD_ISPENDR.contains(addr)) {
+ // Interrupt Set-Pending Registers
uint64_t val = 0x0;
int first_intid = (addr - GICD_ISPENDR.start()) * 8;
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
if (irqNsacr[int_id] == 0) {
return val;
} else if (GICD_ICPENDR.contains(addr)) {
+ // Interrupt Clear-Pending Registers
uint64_t val = 0x0;
int first_intid = (addr - GICD_ICPENDR.start()) * 8;
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
if (irqNsacr[int_id] < 2) {
}
return val;
- // Interrupt Set-Active Registers
} else if (GICD_ISACTIVER.contains(addr)) {
+ // Interrupt Set-Active Registers
int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
if (isNotSPI(first_intid)) {
uint64_t val = 0x0;
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
// Group 0 or Secure Group 1 interrupts are RAZ/WI
}
return val;
- // Interrupt Clear-Active Registers
} else if (GICD_ICACTIVER.contains(addr)) {
+ // Interrupt Clear-Active Registers
int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
if (isNotSPI(first_intid)) {
uint64_t val = 0x0;
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
if (irqNsacr[int_id] < 2) {
}
return val;
- // Interrupt Priority Registers
} else if (GICD_IPRIORITYR.contains(addr)) {
+ // Interrupt Priority Registers
uint64_t val = 0x0;
int first_intid = addr - GICD_IPRIORITYR.start();
}
for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
uint8_t prio = irqPriority[int_id];
if (!DS && !is_secure_access) {
warn("Gicv3Distributor::read(): "
"GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
return 0;
- // Interrupt Configuration Registers
} else if (GICD_ICFGR.contains(addr)) {
+ // Interrupt Configuration Registers
int first_intid = (addr - GICD_ICFGR.start()) * 4;
if (isNotSPI(first_intid)) {
uint64_t val = 0x0;
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i = i + 2, int_id++) {
+ i = i + 2, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
uint64_t val = 0x0;
for (int i = 0, int_id = first_intid;
- i < 8 * size && int_id < itLines; i++, int_id++) {
+ i < 8 * size && int_id < itLines; i++, int_id++) {
val |= irqGrpmod[int_id] << i;
}
return val;
}
}
-
- // Non-secure Access Control Registers
} else if (GICD_NSACR.contains(addr)) {
+ // Non-secure Access Control Registers
// 2 bits per interrupt
int first_intid = (addr - GICD_NSACR.start()) * 4;
uint64_t val = 0x0;
for (int i = 0, int_id = first_intid;
- i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
+ i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
val |= irqNsacr[int_id] << i;
}
// Optional register, RAZ/WI
return 0x0;
- case GICD_PIDR0: { // Peripheral ID0 Register
- uint8_t part_0 = 0x92; // Part number, bits[7:0]
- return part_0;
- }
+ case GICD_PIDR0: // Peripheral ID0 Register
+ return 0x92; // Part number, bits[7:0]
case GICD_PIDR1: { // Peripheral ID1 Register
uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
irqGroup[int_id] = data & (1 << i) ? 1 : 0;
DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
int_id, irqGroup[int_id]);
}
return;
- // Interrupt Set-Enable Registers
} else if (GICD_ISENABLER.contains(addr)) {
+ // Interrupt Set-Enable Registers
int first_intid = (addr - GICD_ISENABLER.start()) * 8;
if (isNotSPI(first_intid)) {
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
int first_intid = (addr - GICD_ICENABLER.start()) * 8;
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
return;
} else if (GICD_ISPENDR.contains(addr)) {
+ // Interrupt Set-Pending Registers
int first_intid = (addr - GICD_ISPENDR.start()) * 8;
if (isNotSPI(first_intid)) {
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
if (irqNsacr[int_id] == 0) {
updateAndInformCPUInterfaces();
return;
} else if (GICD_ICPENDR.contains(addr)) {
+ // Interrupt Clear-Pending Registers
int first_intid = (addr - GICD_ICPENDR.start()) * 8;
if (isNotSPI(first_intid)) {
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
if (irqNsacr[int_id] < 2) {
updateAndInformCPUInterfaces();
return;
- // Interrupt Set-Active Registers
} else if (GICD_ISACTIVER.contains(addr)) {
+ // Interrupt Set-Active Registers
int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
if (isNotSPI(first_intid)) {
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i++, int_id++) {
+ i++, int_id++) {
+
if (nsAccessToSecInt(int_id, is_secure_access))
{
continue;
}
return;
- // Interrupt Priority Registers
} else if (GICD_IPRIORITYR.contains(addr)) {
+ // Interrupt Priority Registers
int first_intid = addr - GICD_IPRIORITYR.start();
if (isNotSPI(first_intid)) {
warn("Gicv3Distributor::write(): "
"GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
return;
- // Interrupt Configuration Registers
} else if (GICD_ICFGR.contains(addr)) {
- /* Here only the odd bits are used; even bits are RES0 */
+ // Interrupt Configuration Registers
+ // for x = 0 to 15:
+ // GICD_ICFGR[2x] = RES0
+ // GICD_ICFGR[2x + 1] =
+ // 0 level-sensitive
+ // 1 edge-triggered
int first_intid = (addr - GICD_ICFGR.start()) * 4;
if (isNotSPI(first_intid)) {
}
for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
- i = i + 2, int_id++) {
+ i = i + 2, int_id++) {
irqConfig[int_id] = data & (0x2 << i) ?
Gicv3::INT_EDGE_TRIGGERED :
Gicv3::INT_LEVEL_SENSITIVE;
}
for (int i = 0, int_id = first_intid;
- i < 8 * size && int_id < itLines; i++, int_id++) {
+ i < 8 * size && int_id < itLines; i++, int_id++) {
irqGrpmod[int_id] = data & (0x1 << i);
}
}
}
- // Non-secure Access Control Registers
} else if (GICD_NSACR.contains(addr)) {
+ // Non-secure Access Control Registers
// 2 bits per interrupt
int first_intid = (addr - GICD_NSACR.start()) * 4;
}
for (int i = 0, int_id = first_intid;
- i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
+ i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
}
}
void
-Gicv3Distributor::intDeasserted(uint32_t int_id)
+Gicv3Distributor::deassertSPI(uint32_t int_id)
{
panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
panic_if(int_id > itLines, "Invalid SPI!");
// Find the highest priority pending SPI
for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
- int_id++) {
+ int_id++) {
Gicv3::GroupId int_group = getIntGroup(int_id);
bool group_enabled = groupEnabled(int_group);
if (irqPending[int_id] && irqEnabled[int_id] &&
- !irqActive[int_id] && group_enabled) {
+ !irqActive[int_id] && group_enabled) {
IROUTER affinity_routing = irqAffinityRouting[int_id];
Gicv3Redistributor * target_redistributor = nullptr;
uint32_t target_cpu = target_redistributor->cpuId;
if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
- /*
- * Multiple pending ints with same priority.
- * Implementation choice which one to signal.
- * Our implementation selects the one with the lower id.
- */
- (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
- int_id < target_cpu_interface->hppi.intid)) {
+ /*
+ * Multiple pending ints with same priority.
+ * Implementation choice which one to signal.
+ * Our implementation selects the one with the lower id.
+ */
+ (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
+ int_id < target_cpu_interface->hppi.intid)) {
target_cpu_interface->hppi.intid = int_id;
target_cpu_interface->hppi.prio = irqPriority[int_id];
target_cpu_interface->hppi.group = int_group;
redistributor_i->getCPUInterface();
if (!new_hppi[i] && cpu_interface_i->hppi.prio != 0xff &&
- cpu_interface_i->hppi.intid >=
- (Gicv3::SGI_MAX + Gicv3::PPI_MAX) &&
- cpu_interface_i->hppi.intid < Gicv3::INTID_SECURE) {
+ cpu_interface_i->hppi.intid >= (Gicv3::SGI_MAX + Gicv3::PPI_MAX) &&
+ cpu_interface_i->hppi.intid < Gicv3::INTID_SECURE) {
fullUpdate();
}
}
}
Gicv3::IntStatus
-Gicv3Distributor::intStatus(uint32_t int_id)
+Gicv3Distributor::intStatus(uint32_t int_id) const
{
panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
panic_if(int_id > itLines, "Invalid SPI!");
}
Gicv3::GroupId
-Gicv3Distributor::getIntGroup(int int_id)
+Gicv3Distributor::getIntGroup(int int_id) const
{
panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
panic_if(int_id > itLines, "Invalid SPI!");
static const AddrRange GICD_IROUTER;
BitUnion64(IROUTER)
- Bitfield<63, 40> res0_1;
- Bitfield<39, 32> Aff3;
- Bitfield<31> IRM;
- Bitfield<30, 24> res0_2;
- Bitfield<23, 16> Aff2;
- Bitfield<15, 8> Aff1;
- Bitfield<7, 0> Aff0;
+ Bitfield<63, 40> res0_1;
+ Bitfield<39, 32> Aff3;
+ Bitfield<31> IRM;
+ Bitfield<30, 24> res0_2;
+ Bitfield<23, 16> Aff2;
+ Bitfield<15, 8> Aff1;
+ Bitfield<7, 0> Aff0;
EndBitUnion(IROUTER)
- static const uint32_t GICD_CTLR_ENABLEGRP0 = 1 << 0;
+ static const uint32_t GICD_CTLR_ENABLEGRP0 = 1 << 0;
+ static const uint32_t GICD_CTLR_ENABLEGRP1 = 1 << 0;
static const uint32_t GICD_CTLR_ENABLEGRP1NS = 1 << 1;
- static const uint32_t GICD_CTLR_ENABLEGRP1S = 1 << 2;
- static const uint32_t GICD_CTLR_ENABLEGRP1 = 1 << 0;
- static const uint32_t GICD_CTLR_ENABLEGRP1A = 1 << 1;
- static const uint32_t GICD_CTLR_DS = 1 << 6;
+ static const uint32_t GICD_CTLR_ENABLEGRP1A = 1 << 1;
+ static const uint32_t GICD_CTLR_ENABLEGRP1S = 1 << 2;
+ static const uint32_t GICD_CTLR_DS = 1 << 6;
bool ARE;
bool DS;
static const uint32_t ADDR_RANGE_SIZE = 0x10000;
- Gicv3Distributor(Gicv3 * gic, uint32_t it_lines);
- ~Gicv3Distributor();
- void init();
- void initState();
+ protected:
- uint64_t read(Addr addr, size_t size, bool is_secure_access);
- void write(Addr addr, uint64_t data, size_t size,
- bool is_secure_access);
- void serialize(CheckpointOut & cp) const override;
- void unserialize(CheckpointIn & cp) override;
+ void activateIRQ(uint32_t int_id);
+ void deactivateIRQ(uint32_t int_id);
+ void fullUpdate();
+ Gicv3::GroupId getIntGroup(int int_id) const;
- bool
- groupEnabled(Gicv3::GroupId group)
+ inline bool
+ groupEnabled(Gicv3::GroupId group) const
{
if (DS == 0) {
switch (group) {
}
}
- void sendInt(uint32_t int_id);
- void intDeasserted(uint32_t int_id);
- Gicv3::IntStatus intStatus(uint32_t int_id);
- void updateAndInformCPUInterfaces();
- void update();
- void fullUpdate();
- void activateIRQ(uint32_t int_id);
- void deactivateIRQ(uint32_t int_id);
+ Gicv3::IntStatus intStatus(uint32_t int_id) const;
- inline bool isNotSPI(uint8_t int_id)
+ inline bool isNotSPI(uint8_t int_id) const
{
if (int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX) || int_id >= itLines) {
return true;
}
}
- inline bool nsAccessToSecInt(uint8_t int_id, bool is_secure_access)
+ inline bool nsAccessToSecInt(uint8_t int_id, bool is_secure_access) const
{
return !DS && !is_secure_access && getIntGroup(int_id) != Gicv3::G1NS;
}
- protected:
-
void reset();
- Gicv3::GroupId getIntGroup(int int_id);
+ void serialize(CheckpointOut & cp) const override;
+ void unserialize(CheckpointIn & cp) override;
+ void update();
+ void updateAndInformCPUInterfaces();
+
+ public:
+
+ Gicv3Distributor(Gicv3 * gic, uint32_t it_lines);
+
+ void deassertSPI(uint32_t int_id);
+ void init();
+ void initState();
+ uint64_t read(Addr addr, size_t size, bool is_secure_access);
+ void sendInt(uint32_t int_id);
+ void write(Addr addr, uint64_t data, size_t size,
+ bool is_secure_access);
};
#endif //__DEV_ARM_GICV3_DISTRIBUTOR_H__
#include "mem/fs_translating_port_proxy.hh"
const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
- SGI_base + 0x041f);
+ SGI_base + 0x041f);
Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
: gic(gic),
{
}
-Gicv3Redistributor::~Gicv3Redistributor()
-{
-}
-
void
Gicv3Redistributor::init()
{
}
case GICR_PIDR0: { // Peripheral ID0 Register
- uint8_t part_0 = 0x92; // Part number, bits[7:0]
- return part_0;
+ return 0x92; // Part number, bits[7:0]
}
case GICR_PIDR1: { // Peripheral ID1 Register
uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
for (int i = 0, int_id = first_int_id; i < 32;
- i = i + 2, int_id++) {
+ i = i + 2, int_id++) {
if (!distributor->DS && !is_secure_access) {
// RAZ/WI for non-secure accesses for secure interrupts
if (getIntGroup(int_id) != Gicv3::G1NS) {
value = 0;
} else {
for (int i = 0, int_id = 0; i < 8 * size;
- i = i + 2, int_id++) {
+ i = i + 2, int_id++) {
value |= irqNsacr[int_id] << i;
}
}
}
if (not peInLowPowerState and
- (data & GICR_WAKER_ProcessorSleep)) {
+ (data & GICR_WAKER_ProcessorSleep)) {
DPRINTF(GIC, "Gicv3Redistributor::write(): "
"PE entering in low power state\n");
} else if (peInLowPowerState and
- not(data & GICR_WAKER_ProcessorSleep)) {
+ not(data & GICR_WAKER_ProcessorSleep)) {
DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
}
int first_intid = Gicv3::SGI_MAX;
for (int i = 0, int_id = first_intid; i < 8 * size;
- i = i + 2, int_id++) {
+ i = i + 2, int_id++) {
if (!distributor->DS && !is_secure_access) {
// RAZ/WI for non-secure accesses for secure interrupts
if (getIntGroup(int_id) != Gicv3::G1NS) {
}
}
- irqConfig[int_id] = data & (0x2 << i)
- ? Gicv3::INT_EDGE_TRIGGERED :
- Gicv3::INT_LEVEL_SENSITIVE;
+ irqConfig[int_id] = data & (0x2 << i) ?
+ Gicv3::INT_EDGE_TRIGGERED :
+ Gicv3::INT_LEVEL_SENSITIVE;
DPRINTF(GIC, "Gicv3Redistributor::write(): "
"int_id %d (PPI) config %d\n",
int_id, irqConfig[int_id]);
// RAZ/WI
} else {
for (int i = 0, int_id = 0; i < 8 * size;
- i = i + 2, int_id++) {
+ i = i + 2, int_id++) {
irqNsacr[int_id] = (data >> i) & 0x3;
}
}
int nsaccess = irqNsacr[int_id];
if ((int_group == Gicv3::G0S && nsaccess < 1) ||
- (int_group == Gicv3::G1S && nsaccess < 2)) {
+ (int_group == Gicv3::G1S && nsaccess < 2)) {
return;
}
}
}
Gicv3::IntStatus
-Gicv3Redistributor::intStatus(uint32_t int_id)
+Gicv3Redistributor::intStatus(uint32_t int_id) const
{
assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
if (irqPending[int_id] && irqEnabled[int_id] &&
!irqActive[int_id] && group_enabled) {
if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
- /*
- * Multiple pending ints with same priority.
- * Implementation choice which one to signal.
- * Our implementation selects the one with the lower id.
- */
- (irqPriority[int_id] == cpuInterface->hppi.prio &&
- int_id < cpuInterface->hppi.intid)) {
+ /*
+ * Multiple pending ints with same priority.
+ * Implementation choice which one to signal.
+ * Our implementation selects the one with the lower id.
+ */
+ (irqPriority[int_id] == cpuInterface->hppi.prio &&
+ int_id < cpuInterface->hppi.intid)) {
cpuInterface->hppi.intid = int_id;
cpuInterface->hppi.prio = irqPriority[int_id];
cpuInterface->hppi.group = int_group;
}
if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
- cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
+ cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
distributor->fullUpdate();
}
}
}
Gicv3::GroupId
-Gicv3Redistributor::getIntGroup(int int_id)
+Gicv3Redistributor::getIntGroup(int int_id) const
{
assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
}
uint32_t
-Gicv3Redistributor::getAffinity()
+Gicv3Redistributor::getAffinity() const
{
ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
}
bool
-Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group)
+Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
{
if (peInLowPowerState) {
return false;
#include "dev/arm/gic_v3.hh"
#include "sim/serialize.hh"
-class Gicv3Distributor;
class Gicv3CPUInterface;
+class Gicv3Distributor;
class Gicv3Redistributor : public Serializable
{
* GICv3 defines 2 contiguous 64KB frames for each redistributor.
* Order of frames must be RD_base, SGI_base.
*/
- static const uint32_t RD_base = 0x0;
+ static const uint32_t RD_base = 0x0;
static const uint32_t SGI_base = 0x10000;
enum {
// Control Register
GICR_CTLR = RD_base + 0x0000,
// Implementer Identification Register
- GICR_IIDR = RD_base + 0x0004,
+ GICR_IIDR = RD_base + 0x0004,
// Type Register
GICR_TYPER = RD_base + 0x0008,
// Wake Register
// Interrupt Clear-Enable Register 0
GICR_ICENABLER0 = SGI_base + 0x0180,
// Interrupt Set-Pending Register 0
- GICR_ISPENDR0 = SGI_base + 0x0200,
+ GICR_ISPENDR0 = SGI_base + 0x0200,
// Interrupt Clear-Pending Register 0
- GICR_ICPENDR0 = SGI_base + 0x0280,
+ GICR_ICPENDR0 = SGI_base + 0x0280,
// Interrupt Set-Active Register 0
GICR_ISACTIVER0 = SGI_base + 0x0300,
// Interrupt Clear-Active Register 0
GICR_ICACTIVER0 = SGI_base + 0x0380,
// SGI Configuration Register
- GICR_ICFGR0 = SGI_base + 0x0c00,
+ GICR_ICFGR0 = SGI_base + 0x0c00,
// PPI Configuration Register
- GICR_ICFGR1 = SGI_base + 0x0c04,
+ GICR_ICFGR1 = SGI_base + 0x0c04,
// Interrupt Group Modifier Register 0
- GICR_IGRPMODR0 = SGI_base + 0x0d00,
+ GICR_IGRPMODR0 = SGI_base + 0x0d00,
// Non-secure Access Control Register
- GICR_NSACR = SGI_base + 0x0e00,
+ GICR_NSACR = SGI_base + 0x0e00,
};
// Interrupt Priority Registers
std::vector<LPIConfigurationTableEntry> lpiConfigurationTable;
static const uint32_t GICR_CTLR_ENABLE_LPIS = 1 << 0;
- static const uint32_t GICR_CTLR_DPG0 = 1 << 24;
+ static const uint32_t GICR_CTLR_DPG0 = 1 << 24;
static const uint32_t GICR_CTLR_DPG1NS = 1 << 25;
- static const uint32_t GICR_CTLR_DPG1S = 1 << 26;
+ static const uint32_t GICR_CTLR_DPG1S = 1 << 26;
public:
static const uint32_t SMALLEST_LPI_ID = 8192;
- Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id);
- ~Gicv3Redistributor();
- void init();
- void initState();
- uint64_t read(Addr addr, size_t size, bool is_secure_access);
- void write(Addr addr, uint64_t data, size_t size,
- bool is_secure_access);
- void sendPPInt(uint32_t int_id);
- void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns);
- void serialize(CheckpointOut & cp) const override;
- void unserialize(CheckpointIn & cp) override;
- uint32_t getAffinity();
+ void activateIRQ(uint32_t int_id);
+ bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const;
+ void deactivateIRQ(uint32_t int_id);
- Gicv3CPUInterface *
+ inline Gicv3CPUInterface *
getCPUInterface() const
{
return cpuInterface;
}
- bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group);
+ Gicv3::GroupId getIntGroup(int int_id) const;
+ Gicv3::IntStatus intStatus(uint32_t int_id) const;
void setClrLPI(uint64_t data, bool set);
-
- protected:
-
void reset();
+ void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns);
+ void serialize(CheckpointOut & cp) const override;
+ void unserialize(CheckpointIn & cp) override;
void update();
void updateAndInformCPUInterface();
- Gicv3::IntStatus intStatus(uint32_t int_id);
- Gicv3::GroupId getIntGroup(int int_id);
- void activateIRQ(uint32_t int_id);
- void deactivateIRQ(uint32_t int_id);
+
+ public:
+
+ Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id);
void invalLpiConfig(uint32_t lpi_entry_index);
+ uint32_t getAffinity() const;
+ void init();
+ void initState();
+ uint64_t read(Addr addr, size_t size, bool is_secure_access);
+ void sendPPInt(uint32_t int_id);
+ void write(Addr addr, uint64_t data, size_t size, bool is_secure_access);
};
#endif //__DEV_ARM_GICV3_REDISTRIBUTOR_H__