summaryrefslogtreecommitdiff
path: root/src/dev/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev/arm')
-rw-r--r--src/dev/arm/gic_v3_cpu_interface.cc21
-rw-r--r--src/dev/arm/gic_v3_cpu_interface.hh1
-rw-r--r--src/dev/arm/gic_v3_distributor.cc118
-rw-r--r--src/dev/arm/gic_v3_distributor.hh3
-rw-r--r--src/dev/arm/gic_v3_its.cc2
-rw-r--r--src/dev/arm/gic_v3_redistributor.cc31
-rw-r--r--src/dev/arm/gic_v3_redistributor.hh2
7 files changed, 80 insertions, 98 deletions
diff --git a/src/dev/arm/gic_v3_cpu_interface.cc b/src/dev/arm/gic_v3_cpu_interface.cc
index 97d914568..b4c271d4a 100644
--- a/src/dev/arm/gic_v3_cpu_interface.cc
+++ b/src/dev/arm/gic_v3_cpu_interface.cc
@@ -1819,15 +1819,19 @@ Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
// SGI or PPI, redistributor
redistributor->activateIRQ(int_id);
- redistributor->updateAndInformCPUInterface();
} else if (int_id < Gicv3::INTID_SECURE) {
// SPI, distributor
distributor->activateIRQ(int_id);
- distributor->updateAndInformCPUInterfaces();
} else if (int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
// LPI, Redistributor
redistributor->setClrLPI(int_id, false);
}
+
+ // By setting the priority to 0xff we are effectively
+ // making the int_id not pending anymore at the cpu
+ // interface.
+ hppi.prio = 0xff;
+ updateDistributor();
}
void
@@ -1857,15 +1861,12 @@ Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group)
if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
// SGI or PPI, redistributor
redistributor->deactivateIRQ(int_id);
- redistributor->updateAndInformCPUInterface();
} else if (int_id < Gicv3::INTID_SECURE) {
// SPI, distributor
distributor->deactivateIRQ(int_id);
- distributor->updateAndInformCPUInterfaces();
- } else {
- // LPI, redistributor, shouldn't deactivate
- redistributor->updateAndInformCPUInterface();
}
+
+ updateDistributor();
}
void
@@ -1992,6 +1993,12 @@ Gicv3CPUInterface::highestActiveGroup() const
}
void
+Gicv3CPUInterface::updateDistributor()
+{
+ distributor->update();
+}
+
+void
Gicv3CPUInterface::update()
{
bool signal_IRQ = false;
diff --git a/src/dev/arm/gic_v3_cpu_interface.hh b/src/dev/arm/gic_v3_cpu_interface.hh
index 5c66fd75f..ed432bce5 100644
--- a/src/dev/arm/gic_v3_cpu_interface.hh
+++ b/src/dev/arm/gic_v3_cpu_interface.hh
@@ -326,6 +326,7 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable
void serialize(CheckpointOut & cp) const override;
void unserialize(CheckpointIn & cp) override;
void update();
+ void updateDistributor();
void virtualActivateIRQ(uint32_t lrIdx);
void virtualDeactivateIRQ(int lrIdx);
uint8_t virtualDropPriority();
diff --git a/src/dev/arm/gic_v3_distributor.cc b/src/dev/arm/gic_v3_distributor.cc
index f85474c9c..0211bec56 100644
--- a/src/dev/arm/gic_v3_distributor.cc
+++ b/src/dev/arm/gic_v3_distributor.cc
@@ -638,7 +638,7 @@ Gicv3Distributor::write(Addr addr, uint64_t data, size_t size,
}
}
- updateAndInformCPUInterfaces();
+ update();
return;
} else if (GICD_ICPENDR.contains(addr)) {
// Interrupt Clear-Pending Registers
@@ -663,10 +663,11 @@ Gicv3Distributor::write(Addr addr, uint64_t data, size_t size,
if (clear) {
irqPending[int_id] = false;
+ clearIrqCpuInterface(int_id);
}
}
- updateAndInformCPUInterfaces();
+ update();
return;
} else if (GICD_ISACTIVER.contains(addr)) {
// Interrupt Set-Active Registers
@@ -947,7 +948,7 @@ Gicv3Distributor::sendInt(uint32_t int_id)
irqPending[int_id] = true;
DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
"int_id %d (SPI) pending bit set\n", int_id);
- updateAndInformCPUInterfaces();
+ update();
}
void
@@ -956,40 +957,59 @@ 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!");
irqPending[int_id] = false;
- updateAndInformCPUInterfaces();
+ clearIrqCpuInterface(int_id);
+
+ update();
}
-void
-Gicv3Distributor::updateAndInformCPUInterfaces()
+Gicv3CPUInterface*
+Gicv3Distributor::route(uint32_t int_id)
{
- update();
+ IROUTER affinity_routing = irqAffinityRouting[int_id];
+ Gicv3Redistributor * target_redistributor = nullptr;
- for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
- gic->getCPUInterface(i)->update();
+ const Gicv3::GroupId int_group = getIntGroup(int_id);
+
+ if (affinity_routing.IRM) {
+ // Interrupts routed to any PE defined as a participating node
+ for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
+ Gicv3Redistributor * redistributor_i =
+ gic->getRedistributor(i);
+
+ if (redistributor_i->
+ canBeSelectedFor1toNInterrupt(int_group)) {
+ target_redistributor = redistributor_i;
+ break;
+ }
+ }
+ } else {
+ uint32_t affinity = (affinity_routing.Aff3 << 24) |
+ (affinity_routing.Aff2 << 16) |
+ (affinity_routing.Aff1 << 8) |
+ (affinity_routing.Aff0 << 0);
+ target_redistributor =
+ gic->getRedistributorByAffinity(affinity);
+ }
+
+ if (!target_redistributor) {
+ // Interrrupts targeting not present cpus must remain pending
+ return nullptr;
+ } else {
+ return target_redistributor->getCPUInterface();
}
}
void
-Gicv3Distributor::fullUpdate()
+Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id)
{
- for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
- Gicv3CPUInterface * cpu_interface_i = gic->getCPUInterface(i);
- cpu_interface_i->hppi.prio = 0xff;
- }
-
- update();
-
- for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
- Gicv3Redistributor * redistributor_i = gic->getRedistributor(i);
- redistributor_i->update();
- }
+ auto cpu_interface = route(int_id);
+ if (cpu_interface)
+ cpu_interface->hppi.prio = 0xff;
}
void
Gicv3Distributor::update()
{
- std::vector<bool> new_hppi(gic->getSystem()->numContexts(), false);
-
// Find the highest priority pending SPI
for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
int_id++) {
@@ -998,65 +1018,27 @@ Gicv3Distributor::update()
if (irqPending[int_id] && irqEnabled[int_id] &&
!irqActive[int_id] && group_enabled) {
- IROUTER affinity_routing = irqAffinityRouting[int_id];
- Gicv3Redistributor * target_redistributor = nullptr;
-
- if (affinity_routing.IRM) {
- // Interrupts routed to any PE defined as a participating node
- for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
- Gicv3Redistributor * redistributor_i =
- gic->getRedistributor(i);
-
- if (redistributor_i->
- canBeSelectedFor1toNInterrupt(int_group)) {
- target_redistributor = redistributor_i;
- break;
- }
- }
- } else {
- uint32_t affinity = (affinity_routing.Aff3 << 24) |
- (affinity_routing.Aff3 << 16) |
- (affinity_routing.Aff1 << 8) |
- (affinity_routing.Aff0 << 0);
- target_redistributor =
- gic->getRedistributorByAffinity(affinity);
- }
- if (!target_redistributor) {
- // Interrrupts targeting not present cpus must remain pending
- return;
- }
+ // Find the cpu interface where to route the interrupt
+ Gicv3CPUInterface *target_cpu_interface = route(int_id);
- Gicv3CPUInterface * target_cpu_interface =
- target_redistributor->getCPUInterface();
- uint32_t target_cpu = target_redistributor->cpuId;
+ // Invalid routing
+ if (!target_cpu_interface) continue;
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)) {
+
target_cpu_interface->hppi.intid = int_id;
target_cpu_interface->hppi.prio = irqPriority[int_id];
target_cpu_interface->hppi.group = int_group;
- new_hppi[target_cpu] = true;
}
}
}
+ // Update all redistributors
for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
- Gicv3Redistributor * redistributor_i = gic->getRedistributor(i);
- Gicv3CPUInterface * cpu_interface_i =
- 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) {
- fullUpdate();
- }
+ gic->getRedistributor(i)->update();
}
}
diff --git a/src/dev/arm/gic_v3_distributor.hh b/src/dev/arm/gic_v3_distributor.hh
index 0cf8d378c..76ab6dd02 100644
--- a/src/dev/arm/gic_v3_distributor.hh
+++ b/src/dev/arm/gic_v3_distributor.hh
@@ -222,13 +222,14 @@ class Gicv3Distributor : public Serializable
void serialize(CheckpointOut & cp) const override;
void unserialize(CheckpointIn & cp) override;
void update();
- void updateAndInformCPUInterfaces();
+ Gicv3CPUInterface* route(uint32_t int_id);
public:
Gicv3Distributor(Gicv3 * gic, uint32_t it_lines);
void deassertSPI(uint32_t int_id);
+ void clearIrqCpuInterface(uint32_t int_id);
void init();
void initState();
uint64_t read(Addr addr, size_t size, bool is_secure_access);
diff --git a/src/dev/arm/gic_v3_its.cc b/src/dev/arm/gic_v3_its.cc
index f822042ce..4108cc744 100644
--- a/src/dev/arm/gic_v3_its.cc
+++ b/src/dev/arm/gic_v3_its.cc
@@ -1271,7 +1271,7 @@ Gicv3Its::moveAllPendingState(
rd1->lpiPendingTablePtr,
0, sizeof(lpi_pending_table));
- rd2->updateAndInformCPUInterface();
+ rd2->updateDistributor();
}
Gicv3Its *
diff --git a/src/dev/arm/gic_v3_redistributor.cc b/src/dev/arm/gic_v3_redistributor.cc
index 71e74bfb8..e22ea7080 100644
--- a/src/dev/arm/gic_v3_redistributor.cc
+++ b/src/dev/arm/gic_v3_redistributor.cc
@@ -536,7 +536,7 @@ Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
}
}
- updateAndInformCPUInterface();
+ updateDistributor();
break;
case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
@@ -733,7 +733,7 @@ Gicv3Redistributor::sendPPInt(uint32_t int_id)
irqPending[int_id] = true;
DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
"int_id %d (PPI) pending bit set\n", int_id);
- updateAndInformCPUInterface();
+ updateDistributor();
}
void
@@ -770,7 +770,7 @@ Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
irqPending[int_id] = true;
DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
"int_id %d (SGI) pending bit set\n", int_id);
- updateAndInformCPUInterface();
+ updateDistributor();
}
Gicv3::IntStatus
@@ -791,6 +791,12 @@ Gicv3Redistributor::intStatus(uint32_t int_id) const
}
}
+void
+Gicv3Redistributor::updateDistributor()
+{
+ distributor->update();
+}
+
/*
* Recalculate the highest priority pending interrupt after a
* change to redistributor state.
@@ -798,8 +804,6 @@ Gicv3Redistributor::intStatus(uint32_t int_id) const
void
Gicv3Redistributor::update()
{
- bool new_hppi = false;
-
for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
Gicv3::GroupId int_group = getIntGroup(int_id);
bool group_enabled = distributor->groupEnabled(int_group);
@@ -817,7 +821,6 @@ Gicv3Redistributor::update()
cpuInterface->hppi.intid = int_id;
cpuInterface->hppi.prio = irqPriority[int_id];
cpuInterface->hppi.group = int_group;
- new_hppi = true;
}
}
}
@@ -866,17 +869,12 @@ Gicv3Redistributor::update()
cpuInterface->hppi.intid = lpi_id;
cpuInterface->hppi.prio = lpi_priority;
cpuInterface->hppi.group = lpi_group;
- new_hppi = true;
}
}
}
}
- if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
- (cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX ||
- cpuInterface->hppi.intid > SMALLEST_LPI_ID)) {
- distributor->fullUpdate();
- }
+ cpuInterface->update();
}
uint8_t
@@ -958,14 +956,7 @@ Gicv3Redistributor::setClrLPI(uint64_t data, bool set)
writeEntryLPI(lpi_id, lpi_pending_entry);
- updateAndInformCPUInterface();
-}
-
-void
-Gicv3Redistributor::updateAndInformCPUInterface()
-{
- update();
- cpuInterface->update();
+ updateDistributor();
}
Gicv3::GroupId
diff --git a/src/dev/arm/gic_v3_redistributor.hh b/src/dev/arm/gic_v3_redistributor.hh
index 29ff8672d..c59c3411f 100644
--- a/src/dev/arm/gic_v3_redistributor.hh
+++ b/src/dev/arm/gic_v3_redistributor.hh
@@ -210,7 +210,7 @@ class Gicv3Redistributor : public Serializable
void serialize(CheckpointOut & cp) const override;
void unserialize(CheckpointIn & cp) override;
void update();
- void updateAndInformCPUInterface();
+ void updateDistributor();
public: