47#include "debug/GIC.hh"
78 irqGroup(it_lines, 0),
79 irqEnabled(it_lines, false),
80 irqPending(it_lines, false),
81 irqPendingIspendr(it_lines, false),
82 irqActive(it_lines, false),
83 irqPriority(it_lines, 0xAA),
84 irqConfig(it_lines,
Gicv3::INT_LEVEL_SENSITIVE),
85 irqGrpmod(it_lines, 0),
86 irqNsacr(it_lines, 0),
87 irqAffinityRouting(it_lines, 0),
91 gicdPidr2(
gic->params().gicv4 ? 0x4b : 0x3b),
122 int max_spi_int_id =
itLines - 1;
123 int it_lines_number =
divCeil(max_spi_int_id + 1, 32) - 1;
125 (1 << 17) | (1 << 16) |
126 ((have_security ? 1 : 0) << 10) |
127 (it_lines_number << 0);
147 if (!
DS && !is_secure_access) {
158 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
173 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
194 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
215 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
239 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
264 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
289 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
312 for (
int i = 0, int_id = first_intid;
i < size && int_id <
itLines;
317 if (!
DS && !is_secure_access) {
323 prio = (prio << 1) & 0xff;
327 val |= prio << (
i * 8);
334 warn(
"Gicv3Distributor::read(): "
335 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
347 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
348 i =
i + 2, int_id++) {
367 if (!is_secure_access) {
379 for (
int i = 0, int_id = first_intid;
380 i < 8 * size && int_id <
itLines;
i++, int_id++) {
396 if (
DS || (!
DS && !is_secure_access)) {
402 for (
int i = 0, int_id = first_intid;
403 i < 8 * size && int_id <
itLines;
i =
i + 2, int_id++) {
410 warn(
"Gicv3Distributor::read(): "
411 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
415 warn(
"Gicv3Distributor::read(): "
416 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
447 if (is_secure_access) {
469 return (
DS << 6) | (
ARE << 4) |
515 bool is_secure_access)
518 if (!
DS && !is_secure_access) {
529 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
532 DPRINTF(GIC,
"Gicv3Distributor::write(): int_id %d group %d\n",
545 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
557 DPRINTF(GIC,
"Gicv3Distributor::write(): "
558 "int_id %d enabled\n", int_id);
574 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
582 bool disable =
data & (1 <<
i) ? 1 : 0;
586 DPRINTF(GIC,
"Gicv3Distributor::write(): "
587 "int_id %d disabled\n", int_id);
603 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
614 bool pending =
data & (1 <<
i) ? 1 : 0;
617 DPRINTF(GIC,
"Gicv3Distributor::write() (GICD_ISPENDR): "
618 "int_id %d (SPI) pending bit set\n", int_id);
634 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
645 bool clear =
data & (1 <<
i) ? 1 : 0;
663 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
671 bool active =
data & (1 <<
i) ? 1 : 0;
687 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
695 bool clear =
data & (1 <<
i) ? 1 : 0;
699 DPRINTF(GIC,
"Gicv3Distributor::write(): "
700 "int_id %d active cleared\n", int_id);
716 for (
int i = 0, int_id = first_intid;
i < size && int_id <
itLines;
718 uint8_t prio =
bits(
data, (
i + 1) * 8 - 1, (
i * 8));
720 if (!
DS && !is_secure_access) {
725 prio = 0x80 | (prio >> 1);
730 DPRINTF(GIC,
"Gicv3Distributor::write(): int_id %d priority %d\n",
738 warn(
"Gicv3Distributor::write(): "
739 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
754 for (
int i = 0, int_id = first_intid;
i < 8 * size && int_id <
itLines;
755 i =
i + 2, int_id++) {
764 DPRINTF(GIC,
"Gicv3Distributor::write(): int_id %d config %d\n",
774 if (!is_secure_access) {
784 for (
int i = 0, int_id = first_intid;
785 i < 8 * size && int_id <
itLines;
i++, int_id++) {
802 if (
DS || (!
DS && !is_secure_access)) {
806 for (
int i = 0, int_id = first_intid;
807 i < 8 * size && int_id <
itLines;
i =
i + 2, int_id++) {
841 DPRINTF(GIC,
"Gicv3Distributor::write(): "
842 "int_id %d GICD_IROUTER %#llx\n",
859 if ((
data & (1 << 4)) == 0) {
860 warn(
"Gicv3Distributor::write(): "
861 "setting ARE to 0 is not supported!\n");
866 DPRINTF(GIC,
"Gicv3Distributor::write(): (DS 1)"
867 "EnableGrp1NS %d EnableGrp0 %d\n",
870 if (is_secure_access) {
883 if ((
data & (1 << 5)) == 0) {
884 warn(
"Gicv3Distributor::write(): "
885 "setting ARE_NS to 0 is not supported!\n");
888 if ((
data & (1 << 4)) == 0) {
889 warn(
"Gicv3Distributor::write(): "
890 "setting ARE_S to 0 is not supported!\n");
897 DPRINTF(GIC,
"Gicv3Distributor::write(): (DS 0 secure)"
899 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
912 if ((
data & (1 << 4)) == 0) {
913 warn(
"Gicv3Distributor::write(): "
914 "setting ARE_NS to 0 is not supported!\n");
918 DPRINTF(GIC,
"Gicv3Distributor::write(): (DS 0 non-secure)"
938 const uint32_t intid =
bits(
data, 9, 0);
957 const uint32_t intid =
bits(
data, 9, 0);
975 const uint32_t intid =
bits(
data, 9, 0);
991 const uint32_t intid =
bits(
data, 9, 0);
1002 gic->
reserved(
"Gicv3Distributor::write(): invalid offset %#x\n",
addr);
1014 DPRINTF(GIC,
"Gicv3Distributor::sendInt(): "
1015 "int_id %d (SPI) pending bit set\n", int_id);
1048 if (affinity_routing.IRM) {
1054 if (redistributor_i->
1055 canBeSelectedFor1toNInterrupt(int_group)) {
1056 target_redistributor = redistributor_i;
1061 uint32_t
affinity = (affinity_routing.Aff3 << 24) |
1062 (affinity_routing.Aff2 << 16) |
1063 (affinity_routing.Aff1 << 8) |
1064 (affinity_routing.Aff0 << 0);
1065 target_redistributor =
1069 if (!target_redistributor) {
1080 auto cpu_interface =
route(int_id);
1082 cpu_interface->resetHppi(int_id);
1104 if (!target_cpu_interface)
continue;
1108 int_id < target_cpu_interface->hppi.intid)) {
1110 target_cpu_interface->
hppi.
intid = int_id;
1112 target_cpu_interface->
hppi.
group = int_group;
1187 const size_t size =
itLines / 8;
bool has(ArmExtension ext) const
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
ArmSystem * getSystem() const
std::vector< uint8_t > irqPriority
std::vector< bool > irqActive
static const AddrRange GICD_IGROUPR
static const AddrRange GICD_ISPENDR
static const AddrRange GICD_ICFGR
static const AddrRange GICD_ICACTIVER
std::vector< uint8_t > irqGrpmod
void sendInt(uint32_t int_id)
std::vector< bool > irqPending
void unserialize(CheckpointIn &cp) override
Unserialize an object.
std::vector< bool > irqEnabled
static const AddrRange GICD_NSACR
bool groupEnabled(Gicv3::GroupId group) const
bool isNotSPI(uint32_t int_id) const
std::vector< uint8_t > irqNsacr
void clearInt(uint32_t int_id)
static const AddrRange GICD_IGRPMODR
std::vector< uint8_t > irqGroup
std::vector< IROUTER > irqAffinityRouting
static const uint32_t IDBITS
static const AddrRange GICD_ISENABLER
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...
Gicv3::IntStatus intStatus(uint32_t int_id) const
void copy(Gicv3Registers *from, Gicv3Registers *to)
static const uint32_t GICD_CTLR_ENABLEGRP1A
std::vector< Gicv3::IntTriggerType > irqConfig
static const AddrRange GICD_SPENDSGIR
void activateIRQ(uint32_t int_id)
Gicv3CPUInterface * route(uint32_t int_id)
static const AddrRange GICD_ICENABLER
static const AddrRange GICD_IROUTER
static const AddrRange GICD_ICPENDR
bool nsAccessToSecInt(uint32_t int_id, bool is_secure_access) const
std::vector< bool > irqPendingIspendr
bool isLevelSensitive(uint32_t int_id) const
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
static const AddrRange GICD_ITARGETSR
void deactivateIRQ(uint32_t int_id)
static const AddrRange GICD_IPRIORITYR
void deassertSPI(uint32_t int_id)
Gicv3::GroupId getIntGroup(int int_id) const
static const uint32_t GICD_CTLR_ENABLEGRP1NS
void clearIrqCpuInterface(uint32_t int_id)
Gicv3Distributor(Gicv3 *gic, uint32_t it_lines)
static const uint32_t GICD_CTLR_ENABLEGRP1S
uint64_t read(Addr addr, size_t size, bool is_secure_access)
static const AddrRange GICD_ISACTIVER
void serialize(CheckpointOut &cp) const override
Serialize an object.
static const uint32_t GICD_CTLR_DS
static const AddrRange GICD_CPENDSGIR
Gicv3CPUInterface * getCPUInterface() const
static void clearDistRange(Gicv3Registers *to, Addr daddr, size_t size)
static void copyDistRegister(Gicv3Registers *from, Gicv3Registers *to, Addr daddr)
static void copyDistRange(Gicv3Registers *from, Gicv3Registers *to, Addr daddr, size_t size)
Gicv3Redistributor * getRedistributor(ContextID context_id) const
void reserved(const char *fmt, Args... args) const
Gicv3Redistributor * getRedistributorByAffinity(const ArmISA::Affinity &aff) const
static const int INTID_SECURE
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr start() const
Get the start address of the range.
static constexpr T divCeil(const T &a, const U &b)
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 panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
Bitfield< 11, 0 > affinity
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)