45#include "debug/GIC.hh"
100 for (
int i = 0, int_id = first_intid;
i < size;
i++, int_id++) {
109 prio = (prio << 1) & 0xff;
113 value |= prio << (
i * 8);
136 value |= GICR_CTLR_ENABLE_LPIS;
168 int last =
cpuId == (
gic->getSystem()->threads.size() - 1);
170 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
191 uint8_t part_1 = 0x4;
192 return (des_0 << 4) | (part_1 << 0);
196 return gic->getDistributor()->gicdPidr2;
205 return (size << 4) | (des_2 << 0);
221 for (
int int_id = 0; int_id < 8 * size; int_id++) {
222 value |= (
irqGroup[int_id] << int_id);
232 for (
int int_id = 0; int_id < 8 * size; int_id++) {
241 value |= (1 << int_id);
252 for (
int int_id = 0; int_id < 8 * size; int_id++) {
270 for (
int int_id = 0; int_id < 8 * size; int_id++) {
289 for (
int i = 0, int_id = first_int_id;
i < 32;
290 i =
i + 2, int_id++) {
312 if (!is_secure_access) {
316 for (
int int_id = 0; int_id < 8 * size; int_id++) {
332 if (!is_secure_access) {
336 for (
int i = 0, int_id = 0;
i < 8 * size;
337 i =
i + 2, int_id++) {
380 gic->reserved(
"Gicv3Redistributor::read(): invalid offset %#x\n",
addr);
387 bool is_secure_access)
392 for (
int i = 0, int_id = first_intid;
i < size;
i++, int_id++) {
393 uint8_t prio =
bits(
data, (
i + 1) * 8 - 1, (
i * 8));
401 prio = 0x80 | (prio >> 1);
406 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
407 "int_id %d priority %d\n", int_id,
irqPriority[int_id]);
433 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
434 "PE entering in low power state\n");
437 DPRINTF(GIC,
"Gicv3Redistributor::write(): powering up PE\n");
450 for (
int int_id = 0; int_id < 8 * size; int_id++) {
452 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
453 "int_id %d group %d\n", int_id,
irqGroup[int_id]);
459 for (
int int_id = 0; int_id < 8 * size; int_id++) {
473 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
474 "int_id %d enable %i\n", int_id,
irqEnabled[int_id]);
480 for (
int int_id = 0; int_id < 8 * size; int_id++) {
488 bool disable =
data & (1 << int_id) ? 1 : 0;
494 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
495 "int_id %d enable %i\n", int_id,
irqEnabled[int_id]);
501 for (
int int_id = 0; int_id < 8 * size; int_id++) {
509 bool pending =
data & (1 << int_id) ? 1 : 0;
512 DPRINTF(GIC,
"Gicv3Redistributor::write() "
513 "(GICR_ISPENDR0): int_id %d (PPI) "
514 "pending bit set\n", int_id);
524 for (
int int_id = 0; int_id < 8 * size; int_id++) {
532 bool clear =
data & (1 << int_id) ? 1 : 0;
542 for (
int int_id = 0; int_id < 8 * size; int_id++) {
554 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
555 "int_id %d active set\n", int_id);
565 for (
int int_id = 0; int_id < 8 * size; int_id++) {
573 bool clear =
data & (1 << int_id) ? 1 : 0;
577 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
578 "int_id %d active cleared\n", int_id);
593 for (
int i = 0, int_id = first_intid;
i < 8 * size;
594 i =
i + 2, int_id++) {
605 DPRINTF(GIC,
"Gicv3Redistributor::write(): "
606 "int_id %d (PPI) config %d\n",
617 for (
int int_id = 0; int_id < 8 * size; int_id++) {
618 if (!is_secure_access) {
634 if (!is_secure_access) {
637 for (
int i = 0, int_id = 0;
i < 8 * size;
638 i =
i + 2, int_id++) {
707 gic->reserved(
"Gicv3Redistributor::write(): invalid offset %#x\n",
addr);
719 DPRINTF(GIC,
"Gicv3Redistributor::sendPPInt(): "
720 "int_id %d (PPI) pending bit set\n", int_id);
741 bool forward =
false;
759 forward = (group == int_group) ||
764 if (!forward)
return;
768 DPRINTF(GIC,
"Gicv3ReDistributor::sendSGI(): "
769 "int_id %d (SGI) pending bit set\n", int_id);
804 if (
gic->blockIntUpdate())
809 bool group_enabled =
distributor->groupEnabled(int_group);
820 int_id < cpuInterface->hppi.intid)) {
831 const uint32_t largest_lpi_id = 1 << (
lpiIDBits + 1);
833 const size_t table_size = largest_lpi_id / 8;
834 auto lpi_pending_table = std::make_unique<uint8_t[]>(table_size);
835 auto lpi_config_table = std::make_unique<uint8_t[]>(number_lpis);
838 lpi_pending_table.get(),
842 lpi_config_table.get(),
847 uint32_t lpi_pending_entry_byte = lpi_id / 8;
848 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
849 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
850 1 << lpi_pending_entry_bit_position;
853 LPIConfigurationTableEntry config_entry =
854 lpi_config_table[lpi_configuration_entry_index];
856 bool lpi_is_enable = config_entry.enable;
861 bool group_enabled =
distributor->groupEnabled(lpi_group);
863 if (lpi_is_pending && lpi_is_enable && group_enabled) {
864 uint8_t lpi_priority = config_entry.priority << 2;
866 if ((lpi_priority < cpuInterface->hppi.prio) ||
868 lpi_id < cpuInterface->hppi.intid)) {
892 uint8_t lpi_pending_entry;
893 memProxy->readBlob(lpi_pending_entry_ptr,
895 sizeof(lpi_pending_entry));
897 return lpi_pending_entry;
905 memProxy->writeBlob(lpi_pending_entry_ptr,
907 sizeof(lpi_pending_entry));
916 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
917 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
931 uint32_t lpi_id =
data & 0xffffffff;
932 uint32_t largest_lpi_id = 1 << (
lpiIDBits + 1);
934 if (lpi_id > largest_lpi_id) {
943 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
944 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
953 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
961 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
uint8_t readEntryLPI(uint32_t intid)
static const uint32_t GICR_WAKER_ProcessorSleep
void clearPPInt(uint32_t int_id)
bool isPendingLPI(uint32_t intid)
static const uint32_t GICR_CTLR_DPG1S
std::vector< uint8_t > irqGroup
Gicv3Distributor * distributor
std::vector< uint8_t > irqPriority
uint32_t getAffinity() const
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
void activateIRQ(uint32_t int_id)
std::vector< bool > irqActive
Gicv3Redistributor(Gicv3 *gic, uint32_t cpu_id)
static const uint32_t GICR_WAKER_ChildrenAsleep
std::vector< bool > irqPending
std::vector< uint8_t > irqNsacr
void writeEntryLPI(uint32_t intid, uint8_t lpi_entry)
void sendPPInt(uint32_t int_id)
bool isLevelSensitive(uint32_t int_id) const
Gicv3::GroupId getIntGroup(int int_id) const
void serialize(CheckpointOut &cp) const override
Serialize an object.
void copy(Gicv3Registers *from, Gicv3Registers *to)
void deactivateIRQ(uint32_t int_id)
std::vector< bool > irqEnabled
std::vector< Gicv3::IntTriggerType > irqConfig
static const uint32_t SMALLEST_LPI_ID
static const uint32_t GICR_CTLR_DPG1NS
static const uint32_t GICR_CTLR_DPG0
void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
bool treatAsEdgeTriggered(uint32_t int_id) const
This helper is used to check if an interrupt should be treated as edge triggered in the following sce...
Addr lpiConfigurationTablePtr
static const AddrRange GICR_IPRIORITYR
Gicv3::IntStatus intStatus(uint32_t int_id) const
const uint32_t addrRangeSize
std::vector< uint8_t > irqGrpmod
Gicv3CPUInterface * cpuInterface
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 unserialize(CheckpointIn &cp) override
Unserialize an object.
void setClrLPI(uint64_t data, bool set)
std::vector< bool > irqPendingIspendr
ThreadContext is the external interface to all thread state for anything outside of the CPU.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
Affinity getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Bitfield< 11, 0 > affinity
Copyright (c) 2024 Arm Limited All rights reserved.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
static void activate(const char *expr)
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)