dev-arm: Implement LevelSensitive PPIs in GICv3
Change-Id: I7f28408eff7d502427c4486518c83506893f4a7a Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31516 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -193,8 +193,12 @@ Gicv3::sendPPInt(uint32_t int_id, uint32_t cpu)
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::clearPPInt(uint32_t num, uint32_t cpu)
|
||||
Gicv3::clearPPInt(uint32_t int_id, uint32_t cpu)
|
||||
{
|
||||
panic_if(cpu >= redistributors.size(), "Invalid cpuID clearing PPI!");
|
||||
DPRINTF(Interrupt, "Gicv3::clearPPInt(): received PPI %d cpuTarget %#x\n",
|
||||
int_id, cpu);
|
||||
redistributors[cpu]->clearPPInt(int_id);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* Copyright (c) 2019-2020 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -58,6 +58,7 @@ Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
|
||||
irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
|
||||
irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
|
||||
irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
|
||||
irqPendingIspendr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
|
||||
irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
|
||||
irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
|
||||
irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX, Gicv3::INT_EDGE_TRIGGERED),
|
||||
@@ -509,6 +510,7 @@ Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
|
||||
"(GICR_ISPENDR0): int_id %d (PPI) "
|
||||
"pending bit set\n", int_id);
|
||||
irqPending[int_id] = true;
|
||||
irqPendingIspendr[int_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +528,7 @@ Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
|
||||
|
||||
bool clear = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (clear) {
|
||||
if (clear && treatAsEdgeTriggered(int_id)) {
|
||||
irqPending[int_id] = false;
|
||||
}
|
||||
}
|
||||
@@ -710,11 +712,23 @@ Gicv3Redistributor::sendPPInt(uint32_t int_id)
|
||||
assert((int_id >= Gicv3::SGI_MAX) &&
|
||||
(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
|
||||
irqPending[int_id] = true;
|
||||
irqPendingIspendr[int_id] = false;
|
||||
DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
|
||||
"int_id %d (PPI) pending bit set\n", int_id);
|
||||
updateDistributor();
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::clearPPInt(uint32_t int_id)
|
||||
{
|
||||
assert((int_id >= Gicv3::SGI_MAX) &&
|
||||
(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
|
||||
|
||||
if (isLevelSensitive(int_id)) {
|
||||
irqPending[int_id] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
|
||||
{
|
||||
@@ -747,6 +761,7 @@ Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
|
||||
if (!forward) return;
|
||||
|
||||
irqPending[int_id] = true;
|
||||
irqPendingIspendr[int_id] = false;
|
||||
DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
|
||||
"int_id %d (SGI) pending bit set\n", int_id);
|
||||
updateDistributor();
|
||||
@@ -977,7 +992,9 @@ Gicv3Redistributor::getIntGroup(int int_id) const
|
||||
void
|
||||
Gicv3Redistributor::activateIRQ(uint32_t int_id)
|
||||
{
|
||||
irqPending[int_id] = false;
|
||||
if (treatAsEdgeTriggered(int_id)) {
|
||||
irqPending[int_id] = false;
|
||||
}
|
||||
irqActive[int_id] = true;
|
||||
}
|
||||
|
||||
@@ -1037,6 +1054,7 @@ Gicv3Redistributor::serialize(CheckpointOut & cp) const
|
||||
SERIALIZE_CONTAINER(irqGroup);
|
||||
SERIALIZE_CONTAINER(irqEnabled);
|
||||
SERIALIZE_CONTAINER(irqPending);
|
||||
SERIALIZE_CONTAINER(irqPendingIspendr);
|
||||
SERIALIZE_CONTAINER(irqActive);
|
||||
SERIALIZE_CONTAINER(irqPriority);
|
||||
SERIALIZE_CONTAINER(irqConfig);
|
||||
@@ -1058,6 +1076,7 @@ Gicv3Redistributor::unserialize(CheckpointIn & cp)
|
||||
UNSERIALIZE_CONTAINER(irqGroup);
|
||||
UNSERIALIZE_CONTAINER(irqEnabled);
|
||||
UNSERIALIZE_CONTAINER(irqPending);
|
||||
UNSERIALIZE_CONTAINER(irqPendingIspendr);
|
||||
UNSERIALIZE_CONTAINER(irqActive);
|
||||
UNSERIALIZE_CONTAINER(irqPriority);
|
||||
UNSERIALIZE_CONTAINER(irqConfig);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* Copyright (c) 2019-2020 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -153,6 +153,7 @@ class Gicv3Redistributor : public Serializable
|
||||
std::vector <uint8_t> irqGroup;
|
||||
std::vector <bool> irqEnabled;
|
||||
std::vector <bool> irqPending;
|
||||
std::vector <bool> irqPendingIspendr;
|
||||
std::vector <bool> irqActive;
|
||||
std::vector <uint8_t> irqPriority;
|
||||
std::vector <Gicv3::IntTriggerType> irqConfig;
|
||||
@@ -221,6 +222,29 @@ class Gicv3Redistributor : public Serializable
|
||||
void update();
|
||||
void updateDistributor();
|
||||
|
||||
protected:
|
||||
|
||||
bool isLevelSensitive(uint32_t int_id) const
|
||||
{
|
||||
return irqConfig[int_id] == Gicv3::INT_LEVEL_SENSITIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper is used to check if an interrupt should be treated as
|
||||
* edge triggered in the following scenarios:
|
||||
*
|
||||
* a) While activating the interrupt
|
||||
* b) While clearing an interrupt via ICPENDR
|
||||
*
|
||||
* In fact, in these two situations, a level sensitive interrupt
|
||||
* which had been made pending via a write to ISPENDR, will be
|
||||
* treated as it if was edge triggered.
|
||||
*/
|
||||
bool treatAsEdgeTriggered(uint32_t int_id) const
|
||||
{
|
||||
return !isLevelSensitive(int_id) || irqPendingIspendr[int_id];
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id);
|
||||
@@ -228,6 +252,7 @@ class Gicv3Redistributor : public Serializable
|
||||
void init();
|
||||
uint64_t read(Addr addr, size_t size, bool is_secure_access);
|
||||
void sendPPInt(uint32_t int_id);
|
||||
void clearPPInt(uint32_t int_id);
|
||||
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user