diff options
Diffstat (limited to 'src/dev')
-rw-r--r-- | src/dev/arm/gic_v3_cpu_interface.cc | 21 | ||||
-rw-r--r-- | src/dev/arm/gic_v3_cpu_interface.hh | 1 | ||||
-rw-r--r-- | src/dev/arm/gic_v3_distributor.cc | 118 | ||||
-rw-r--r-- | src/dev/arm/gic_v3_distributor.hh | 3 | ||||
-rw-r--r-- | src/dev/arm/gic_v3_its.cc | 2 | ||||
-rw-r--r-- | src/dev/arm/gic_v3_redistributor.cc | 31 | ||||
-rw-r--r-- | src/dev/arm/gic_v3_redistributor.hh | 2 |
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: |