44 #include "debug/GIC.hh" 54 cpuInterface(nullptr),
57 peInLowPowerState(true),
59 irqEnabled(
Gicv3::SGI_MAX +
Gicv3::PPI_MAX, false),
60 irqPending(
Gicv3::SGI_MAX +
Gicv3::PPI_MAX, false),
61 irqActive(
Gicv3::SGI_MAX +
Gicv3::PPI_MAX, false),
62 irqPriority(
Gicv3::SGI_MAX +
Gicv3::PPI_MAX, 0),
70 lpiConfigurationTablePtr(0),
72 lpiPendingTablePtr(0),
73 addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
93 for (
int i = 0, int_id = first_intid;
i < size;
i++, int_id++) {
102 prio = (prio << 1) & 0xff;
106 value |= prio << (
i * 8);
129 value |= GICR_CTLR_ENABLE_LPIS;
162 return (affinity << 32) | (1 << 24) | (
cpuId << 8) |
163 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
184 uint8_t part_1 = 0x4;
185 return (des_0 << 4) | (part_1 << 0);
189 uint8_t arch_rev = 0x3;
192 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
201 return (size << 4) | (des_2 << 0);
217 for (
int int_id = 0; int_id < 8 * size; int_id++) {
218 value |= (
irqGroup[int_id] << int_id);
228 for (
int int_id = 0; int_id < 8 * size; int_id++) {
237 value |= (1 << int_id);
248 for (
int int_id = 0; int_id < 8 * size; int_id++) {
266 for (
int int_id = 0; int_id < 8 * size; int_id++) {
285 for (
int i = 0, int_id = first_int_id;
i < 32;
286 i =
i + 2, int_id++) {
308 if (!is_secure_access) {
312 for (
int int_id = 0; int_id < 8 * size; int_id++) {
328 if (!is_secure_access) {
332 for (
int i = 0, int_id = 0;
i < 8 * size;
333 i =
i + 2, int_id++) {
376 panic(
"Gicv3Redistributor::read(): invalid offset %#x\n", addr);
383 bool is_secure_access)
388 for (
int i = 0, int_id = first_intid;
i < size;
i++, int_id++) {
389 uint8_t prio =
bits(data, (
i + 1) * 8 - 1, (
i * 8));
397 prio = 0x80 | (prio >> 1);
402 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 403 "int_id %d priority %d\n", int_id,
irqPriority[int_id]);
429 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 430 "PE entering in low power state\n");
433 DPRINTF(GIC,
"Gicv3Redistributor::write(): powering up PE\n");
446 for (
int int_id = 0; int_id < 8 * size; int_id++) {
447 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
448 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 449 "int_id %d group %d\n", int_id,
irqGroup[int_id]);
455 for (
int int_id = 0; int_id < 8 * size; int_id++) {
463 bool enable = data & (1 << int_id) ? 1 : 0;
469 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 470 "int_id %d enable %i\n", int_id,
irqEnabled[int_id]);
476 for (
int int_id = 0; int_id < 8 * size; int_id++) {
484 bool disable = data & (1 << int_id) ? 1 : 0;
490 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 491 "int_id %d enable %i\n", int_id,
irqEnabled[int_id]);
497 for (
int int_id = 0; int_id < 8 * size; int_id++) {
505 bool pending = data & (1 << int_id) ? 1 : 0;
508 DPRINTF(GIC,
"Gicv3Redistributor::write() " 509 "(GICR_ISPENDR0): int_id %d (PPI) " 510 "pending bit set\n", int_id);
519 for (
int int_id = 0; int_id < 8 * size; int_id++) {
527 bool clear = data & (1 << int_id) ? 1 : 0;
537 for (
int int_id = 0; int_id < 8 * size; int_id++) {
545 bool activate = data & (1 << int_id) ? 1 : 0;
549 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 550 "int_id %d active set\n", int_id);
560 for (
int int_id = 0; int_id < 8 * size; int_id++) {
568 bool clear = data & (1 << int_id) ? 1 : 0;
572 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 573 "int_id %d active cleared\n", int_id);
588 for (
int i = 0, int_id = first_intid;
i < 8 * size;
589 i =
i + 2, int_id++) {
600 DPRINTF(GIC,
"Gicv3Redistributor::write(): " 601 "int_id %d (PPI) config %d\n",
612 for (
int int_id = 0; int_id < 8 * size; int_id++) {
613 if (!is_secure_access) {
618 irqGrpmod[int_id] = data & (1 << int_id);
629 if (!is_secure_access) {
632 for (
int i = 0, int_id = 0;
i < 8 * size;
633 i =
i + 2, int_id++) {
702 panic(
"Gicv3Redistributor::write(): invalid offset %#x\n", addr);
713 DPRINTF(GIC,
"Gicv3Redistributor::sendPPInt(): " 714 "int_id %d (PPI) pending bit set\n", int_id);
724 bool forward =
false;
742 forward = (group == int_group) ||
747 if (!forward)
return;
750 DPRINTF(GIC,
"Gicv3ReDistributor::sendSGI(): " 751 "int_id %d (SGI) pending bit set\n", int_id);
799 int_id < cpuInterface->hppi.intid)) {
810 const uint32_t largest_lpi_id = 1 << (
lpiIDBits + 1);
813 uint8_t lpi_pending_table[largest_lpi_id / 8];
814 uint8_t lpi_config_table[number_lpis];
818 sizeof(lpi_pending_table));
822 sizeof(lpi_config_table));
824 for (
int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
826 uint32_t lpi_pending_entry_byte = lpi_id / 8;
827 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
828 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
829 1 << lpi_pending_entry_bit_position;
832 LPIConfigurationTableEntry config_entry =
833 lpi_config_table[lpi_configuration_entry_index];
835 bool lpi_is_enable = config_entry.enable;
842 if (lpi_is_pending && lpi_is_enable && group_enabled) {
843 uint8_t lpi_priority = config_entry.priority << 2;
845 if ((lpi_priority < cpuInterface->hppi.prio) ||
847 lpi_id < cpuInterface->hppi.intid)) {
871 uint8_t lpi_pending_entry;
874 sizeof(lpi_pending_entry));
876 return lpi_pending_entry;
886 sizeof(lpi_pending_entry));
895 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
896 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
910 uint32_t lpi_id = data & 0xffffffff;
911 uint32_t largest_lpi_id = 1 << (
lpiIDBits + 1);
913 if (lpi_id > largest_lpi_id) {
922 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
923 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
932 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
940 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
1003 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
uint8_t readEntryLPI(uint32_t intid)
#define panic(...)
This implements a cprintf based panic() function.
void deactivateIRQ(uint32_t int_id)
static const uint32_t GICR_CTLR_DPG0
#define UNSERIALIZE_CONTAINER(member)
bool isPendingLPI(uint32_t intid)
static const AddrRange GICR_IPRIORITYR
bool contains(const Addr &a) const
Determine if the range contains an address.
Gicv3CPUInterface * cpuInterface
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::vector< Gicv3::IntTriggerType > irqConfig
std::vector< uint8_t > irqPriority
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
void resetHppi(uint32_t intid)
std::vector< bool > irqEnabled
ThreadContext is the external interface to all thread state for anything outside of the CPU...
RegVal getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
This helper function is returning the value of MPIDR_EL1.
ThreadContext * getThreadContext(ContextID tid) const
std::vector< bool > irqPending
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
#define UNSERIALIZE_SCALAR(scalar)
void sendPPInt(uint32_t int_id)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void writeEntryLPI(uint32_t intid, uint8_t lpi_entry)
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
void assertWakeRequest(void)
std::vector< bool > irqActive
std::vector< uint8_t > irqGroup
void activateIRQ(uint32_t int_id)
static const uint32_t GICR_WAKER_ChildrenAsleep
void setClrLPI(uint64_t data, bool set)
unsigned numContexts() const
Gicv3::IntStatus intStatus(uint32_t int_id) const
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Gicv3CPUInterface * getCPUInterface(int cpu_id) const
Gicv3Distributor * distributor
std::vector< uint8_t > irqGrpmod
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
#define SERIALIZE_SCALAR(scalar)
void deassertWakeRequest(void)
static const uint32_t SMALLEST_LPI_ID
void clearPendingInterrupts(void)
static const uint32_t GICR_CTLR_DPG1S
#define SERIALIZE_CONTAINER(member)
std::ostream CheckpointOut
std::vector< uint8_t > irqNsacr
bool groupEnabled(Gicv3::GroupId group) const
Addr start() const
Get the start address of the range.
bool havePendingInterrupts(void) const
static const uint32_t GICR_WAKER_ProcessorSleep
uint32_t getAffinity() const
Gicv3::GroupId getIntGroup(int int_id) const
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
static const uint32_t GICR_CTLR_DPG1NS
ArmSystem * getSystem() const
Addr lpiConfigurationTablePtr
void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
uint64_t read(Addr addr, size_t size, bool is_secure_access)
Gicv3Redistributor(Gicv3 *gic, uint32_t cpu_id)
Gicv3Distributor * getDistributor() const