dev-arm: Add a GICv3 model
Change-Id: Ib0067fc743f84ff7be9f12d2fc33ddf63736bdd1 Reviewed-on: https://gem5-review.googlesource.com/c/13436 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
committed by
Giacomo Travaglini
parent
7d5696d1a9
commit
93c7fa5731
@@ -48,6 +48,8 @@
|
||||
#include "debug/Arm.hh"
|
||||
#include "debug/MiscRegs.hh"
|
||||
#include "dev/arm/generic_timer.hh"
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
#include "dev/arm/gic_v3_cpu_interface.hh"
|
||||
#include "params/ArmISA.hh"
|
||||
#include "sim/faults.hh"
|
||||
#include "sim/stat_control.hh"
|
||||
@@ -94,6 +96,13 @@ ISA::ISA(Params *p)
|
||||
physAddrRange = 32; // dummy value
|
||||
}
|
||||
|
||||
// GICv3 CPU interface system registers are supported
|
||||
haveGICv3CPUInterface = false;
|
||||
|
||||
if (system && dynamic_cast<Gicv3 *>(system->getGIC())) {
|
||||
haveGICv3CPUInterface = true;
|
||||
}
|
||||
|
||||
initializeMiscRegMetadata();
|
||||
preUnflattenMiscReg();
|
||||
|
||||
@@ -372,6 +381,13 @@ ISA::startup(ThreadContext *tc)
|
||||
{
|
||||
pmu->setThreadContext(tc);
|
||||
|
||||
if (system) {
|
||||
Gicv3 *gicv3 = dynamic_cast<Gicv3 *>(system->getGIC());
|
||||
if (gicv3) {
|
||||
gicv3CpuInterface.reset(gicv3->getCPUInterface(tc->contextId()));
|
||||
gicv3CpuInterface->setISA(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -672,10 +688,11 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
|
||||
| (haveTimer ? 0x00010000 : 0x0);
|
||||
}
|
||||
case MISCREG_ID_AA64PFR0_EL1:
|
||||
return 0x0000000000000002 // AArch{64,32} supported at EL0
|
||||
| 0x0000000000000020 // EL1
|
||||
| (haveVirtualization ? 0x0000000000000200 : 0) // EL2
|
||||
| (haveSecurity ? 0x0000000000002000 : 0); // EL3
|
||||
return 0x0000000000000002 | // AArch{64,32} supported at EL0
|
||||
0x0000000000000020 | // EL1
|
||||
(haveVirtualization ? 0x0000000000000200 : 0) | // EL2
|
||||
(haveSecurity ? 0x0000000000002000 : 0) | // EL3
|
||||
(haveGICv3CPUInterface ? 0x0000000001000000 : 0);
|
||||
case MISCREG_ID_AA64PFR1_EL1:
|
||||
return 0; // bits [63:0] RES0 (reserved for future use)
|
||||
|
||||
@@ -689,6 +706,10 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
|
||||
case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
|
||||
return getGenericTimer(tc).readMiscReg(misc_reg);
|
||||
|
||||
case MISCREG_ICC_PMR_EL1 ... MISCREG_ICC_IGRPEN1_EL3:
|
||||
case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_LR15_EL2:
|
||||
return getGICv3CPUInterface(tc).readMiscReg(misc_reg);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1965,6 +1986,11 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||
case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
|
||||
getGenericTimer(tc).setMiscReg(misc_reg, newVal);
|
||||
break;
|
||||
|
||||
case MISCREG_ICC_PMR_EL1 ... MISCREG_ICC_IGRPEN1_EL3:
|
||||
case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_LR15_EL2:
|
||||
getGICv3CPUInterface(tc).setMiscReg(misc_reg, newVal);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setMiscRegNoEffect(misc_reg, newVal);
|
||||
@@ -1991,6 +2017,13 @@ ISA::getGenericTimer(ThreadContext *tc)
|
||||
return *timer.get();
|
||||
}
|
||||
|
||||
BaseISADevice &
|
||||
ISA::getGICv3CPUInterface(ThreadContext *tc)
|
||||
{
|
||||
panic_if(!gicv3CpuInterface, "GICV3 cpu interface is not registered!");
|
||||
return *gicv3CpuInterface.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ArmISA::ISA *
|
||||
|
||||
@@ -82,6 +82,9 @@ namespace ArmISA
|
||||
// Generic timer interface belonging to this ISA
|
||||
std::unique_ptr<BaseISADevice> timer;
|
||||
|
||||
// GICv3 CPU interface belonging to this ISA
|
||||
std::unique_ptr<BaseISADevice> gicv3CpuInterface;
|
||||
|
||||
// Cached copies of system-level properties
|
||||
bool highestELIs64;
|
||||
bool haveSecurity;
|
||||
@@ -89,6 +92,7 @@ namespace ArmISA
|
||||
bool haveVirtualization;
|
||||
bool haveCrypto;
|
||||
bool haveLargeAsid64;
|
||||
bool haveGICv3CPUInterface;
|
||||
uint8_t physAddrRange;
|
||||
|
||||
/**
|
||||
@@ -400,6 +404,7 @@ namespace ArmISA
|
||||
}
|
||||
|
||||
BaseISADevice &getGenericTimer(ThreadContext *tc);
|
||||
BaseISADevice &getGICv3CPUInterface(ThreadContext *tc);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -287,6 +287,11 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
|
||||
return MISCREG_DACR;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (opc1 == 0 && crm == 6 && opc2 == 0) {
|
||||
return MISCREG_ICC_PMR;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (opc1 == 0) {
|
||||
if (crm == 0) {
|
||||
@@ -668,10 +673,193 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
|
||||
if (opc2 == 0) {
|
||||
return MISCREG_ISR;
|
||||
}
|
||||
} else if (crm == 8) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_IAR0;
|
||||
case 1:
|
||||
return MISCREG_ICC_EOIR0;
|
||||
case 2:
|
||||
return MISCREG_ICC_HPPIR0;
|
||||
case 3:
|
||||
return MISCREG_ICC_BPR0;
|
||||
case 4:
|
||||
return MISCREG_ICC_AP0R0;
|
||||
case 5:
|
||||
return MISCREG_ICC_AP0R1;
|
||||
case 6:
|
||||
return MISCREG_ICC_AP0R2;
|
||||
case 7:
|
||||
return MISCREG_ICC_AP0R3;
|
||||
}
|
||||
} else if (crm == 9) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_AP1R0;
|
||||
case 1:
|
||||
return MISCREG_ICC_AP1R1;
|
||||
case 2:
|
||||
return MISCREG_ICC_AP1R2;
|
||||
case 3:
|
||||
return MISCREG_ICC_AP1R3;
|
||||
}
|
||||
} else if (crm == 11) {
|
||||
switch (opc2) {
|
||||
case 1:
|
||||
return MISCREG_ICC_DIR;
|
||||
case 3:
|
||||
return MISCREG_ICC_RPR;
|
||||
}
|
||||
} else if (crm == 12) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_IAR1;
|
||||
case 1:
|
||||
return MISCREG_ICC_EOIR1;
|
||||
case 2:
|
||||
return MISCREG_ICC_HPPIR1;
|
||||
case 3:
|
||||
return MISCREG_ICC_BPR1;
|
||||
case 4:
|
||||
return MISCREG_ICC_CTLR;
|
||||
case 5:
|
||||
return MISCREG_ICC_SRE;
|
||||
case 6:
|
||||
return MISCREG_ICC_IGRPEN0;
|
||||
case 7:
|
||||
return MISCREG_ICC_IGRPEN1;
|
||||
}
|
||||
}
|
||||
} else if (opc1 == 4) {
|
||||
if (crm == 0 && opc2 == 0)
|
||||
if (crm == 0 && opc2 == 0) {
|
||||
return MISCREG_HVBAR;
|
||||
} else if (crm == 8) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_AP0R0;
|
||||
case 1:
|
||||
return MISCREG_ICH_AP0R1;
|
||||
case 2:
|
||||
return MISCREG_ICH_AP0R2;
|
||||
case 3:
|
||||
return MISCREG_ICH_AP0R3;
|
||||
}
|
||||
} else if (crm == 9) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_AP1R0;
|
||||
case 1:
|
||||
return MISCREG_ICH_AP1R1;
|
||||
case 2:
|
||||
return MISCREG_ICH_AP1R2;
|
||||
case 3:
|
||||
return MISCREG_ICH_AP1R3;
|
||||
case 5:
|
||||
return MISCREG_ICC_HSRE;
|
||||
}
|
||||
} else if (crm == 11) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_HCR;
|
||||
case 1:
|
||||
return MISCREG_ICH_VTR;
|
||||
case 2:
|
||||
return MISCREG_ICH_MISR;
|
||||
case 3:
|
||||
return MISCREG_ICH_EISR;
|
||||
case 5:
|
||||
return MISCREG_ICH_ELRSR;
|
||||
case 7:
|
||||
return MISCREG_ICH_VMCR;
|
||||
}
|
||||
} else if (crm == 12) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_LR0;
|
||||
case 1:
|
||||
return MISCREG_ICH_LR1;
|
||||
case 2:
|
||||
return MISCREG_ICH_LR2;
|
||||
case 3:
|
||||
return MISCREG_ICH_LR3;
|
||||
case 4:
|
||||
return MISCREG_ICH_LR4;
|
||||
case 5:
|
||||
return MISCREG_ICH_LR5;
|
||||
case 6:
|
||||
return MISCREG_ICH_LR6;
|
||||
case 7:
|
||||
return MISCREG_ICH_LR7;
|
||||
}
|
||||
} else if (crm == 13) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_LR8;
|
||||
case 1:
|
||||
return MISCREG_ICH_LR9;
|
||||
case 2:
|
||||
return MISCREG_ICH_LR10;
|
||||
case 3:
|
||||
return MISCREG_ICH_LR11;
|
||||
case 4:
|
||||
return MISCREG_ICH_LR12;
|
||||
case 5:
|
||||
return MISCREG_ICH_LR13;
|
||||
case 6:
|
||||
return MISCREG_ICH_LR14;
|
||||
case 7:
|
||||
return MISCREG_ICH_LR15;
|
||||
}
|
||||
} else if (crm == 14) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_LRC0;
|
||||
case 1:
|
||||
return MISCREG_ICH_LRC1;
|
||||
case 2:
|
||||
return MISCREG_ICH_LRC2;
|
||||
case 3:
|
||||
return MISCREG_ICH_LRC3;
|
||||
case 4:
|
||||
return MISCREG_ICH_LRC4;
|
||||
case 5:
|
||||
return MISCREG_ICH_LRC5;
|
||||
case 6:
|
||||
return MISCREG_ICH_LRC6;
|
||||
case 7:
|
||||
return MISCREG_ICH_LRC7;
|
||||
}
|
||||
} else if (crm == 15) {
|
||||
switch (opc2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_LRC8;
|
||||
case 1:
|
||||
return MISCREG_ICH_LRC9;
|
||||
case 2:
|
||||
return MISCREG_ICH_LRC10;
|
||||
case 3:
|
||||
return MISCREG_ICH_LRC11;
|
||||
case 4:
|
||||
return MISCREG_ICH_LRC12;
|
||||
case 5:
|
||||
return MISCREG_ICH_LRC13;
|
||||
case 6:
|
||||
return MISCREG_ICH_LRC14;
|
||||
case 7:
|
||||
return MISCREG_ICH_LRC15;
|
||||
}
|
||||
}
|
||||
} else if (opc1 == 6) {
|
||||
if (crm == 12) {
|
||||
switch (opc2) {
|
||||
case 4:
|
||||
return MISCREG_ICC_MCTLR;
|
||||
case 5:
|
||||
return MISCREG_ICC_MSRE;
|
||||
case 7:
|
||||
return MISCREG_ICC_MGRPEN1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
@@ -1766,6 +1954,12 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_CURRENTEL;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_PMR_EL1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@@ -2145,6 +2339,72 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_DISR_EL1;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_IAR0_EL1;
|
||||
case 1:
|
||||
return MISCREG_ICC_EOIR0_EL1;
|
||||
case 2:
|
||||
return MISCREG_ICC_HPPIR0_EL1;
|
||||
case 3:
|
||||
return MISCREG_ICC_BPR0_EL1;
|
||||
case 4:
|
||||
return MISCREG_ICC_AP0R0_EL1;
|
||||
case 5:
|
||||
return MISCREG_ICC_AP0R1_EL1;
|
||||
case 6:
|
||||
return MISCREG_ICC_AP0R2_EL1;
|
||||
case 7:
|
||||
return MISCREG_ICC_AP0R3_EL1;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_AP1R0_EL1;
|
||||
case 1:
|
||||
return MISCREG_ICC_AP1R1_EL1;
|
||||
case 2:
|
||||
return MISCREG_ICC_AP1R2_EL1;
|
||||
case 3:
|
||||
return MISCREG_ICC_AP1R3_EL1;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
switch (op2) {
|
||||
case 1:
|
||||
return MISCREG_ICC_DIR_EL1;
|
||||
case 3:
|
||||
return MISCREG_ICC_RPR_EL1;
|
||||
case 5:
|
||||
return MISCREG_ICC_SGI1R_EL1;
|
||||
case 6:
|
||||
return MISCREG_ICC_ASGI1R_EL1;
|
||||
case 7:
|
||||
return MISCREG_ICC_SGI0R_EL1;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICC_IAR1_EL1;
|
||||
case 1:
|
||||
return MISCREG_ICC_EOIR1_EL1;
|
||||
case 2:
|
||||
return MISCREG_ICC_HPPIR1_EL1;
|
||||
case 3:
|
||||
return MISCREG_ICC_BPR1_EL1;
|
||||
case 4:
|
||||
return MISCREG_ICC_CTLR_EL1;
|
||||
case 5:
|
||||
return MISCREG_ICC_SRE_EL1;
|
||||
case 6:
|
||||
return MISCREG_ICC_IGRPEN0_EL1;
|
||||
case 7:
|
||||
return MISCREG_ICC_IGRPEN1_EL1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -2163,6 +2423,88 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_VDISR_EL2;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_AP0R0_EL2;
|
||||
case 1:
|
||||
return MISCREG_ICH_AP0R1_EL2;
|
||||
case 2:
|
||||
return MISCREG_ICH_AP0R2_EL2;
|
||||
case 3:
|
||||
return MISCREG_ICH_AP0R3_EL2;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_AP1R0_EL2;
|
||||
case 1:
|
||||
return MISCREG_ICH_AP1R1_EL2;
|
||||
case 2:
|
||||
return MISCREG_ICH_AP1R2_EL2;
|
||||
case 3:
|
||||
return MISCREG_ICH_AP1R3_EL2;
|
||||
case 5:
|
||||
return MISCREG_ICC_SRE_EL2;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_HCR_EL2;
|
||||
case 1:
|
||||
return MISCREG_ICH_VTR_EL2;
|
||||
case 2:
|
||||
return MISCREG_ICH_MISR_EL2;
|
||||
case 3:
|
||||
return MISCREG_ICH_EISR_EL2;
|
||||
case 5:
|
||||
return MISCREG_ICH_ELRSR_EL2;
|
||||
case 7:
|
||||
return MISCREG_ICH_VMCR_EL2;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_LR0_EL2;
|
||||
case 1:
|
||||
return MISCREG_ICH_LR1_EL2;
|
||||
case 2:
|
||||
return MISCREG_ICH_LR2_EL2;
|
||||
case 3:
|
||||
return MISCREG_ICH_LR3_EL2;
|
||||
case 4:
|
||||
return MISCREG_ICH_LR4_EL2;
|
||||
case 5:
|
||||
return MISCREG_ICH_LR5_EL2;
|
||||
case 6:
|
||||
return MISCREG_ICH_LR6_EL2;
|
||||
case 7:
|
||||
return MISCREG_ICH_LR7_EL2;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ICH_LR8_EL2;
|
||||
case 1:
|
||||
return MISCREG_ICH_LR9_EL2;
|
||||
case 2:
|
||||
return MISCREG_ICH_LR10_EL2;
|
||||
case 3:
|
||||
return MISCREG_ICH_LR11_EL2;
|
||||
case 4:
|
||||
return MISCREG_ICH_LR12_EL2;
|
||||
case 5:
|
||||
return MISCREG_ICH_LR13_EL2;
|
||||
case 6:
|
||||
return MISCREG_ICH_LR14_EL2;
|
||||
case 7:
|
||||
return MISCREG_ICH_LR15_EL2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -2177,6 +2519,16 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
return MISCREG_RMR_EL3;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
switch (op2) {
|
||||
case 4:
|
||||
return MISCREG_ICC_CTLR_EL3;
|
||||
case 5:
|
||||
return MISCREG_ICC_SRE_EL3;
|
||||
case 7:
|
||||
return MISCREG_ICC_IGRPEN1_EL3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4094,6 +4446,476 @@ ISA::initializeMiscRegMetadata()
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_CONTEXTIDR_EL2)
|
||||
.mon().hyp();
|
||||
|
||||
// GICv3 AArch64
|
||||
InitReg(MISCREG_ICC_PMR_EL1)
|
||||
.res0(0xffffff00) // [31:8]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_PMR);
|
||||
InitReg(MISCREG_ICC_IAR0_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0)
|
||||
.mapsTo(MISCREG_ICC_IAR0);
|
||||
InitReg(MISCREG_ICC_EOIR0_EL1)
|
||||
.allPrivileges().exceptUserMode().reads(0)
|
||||
.mapsTo(MISCREG_ICC_EOIR0);
|
||||
InitReg(MISCREG_ICC_HPPIR0_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0)
|
||||
.mapsTo(MISCREG_ICC_HPPIR0);
|
||||
InitReg(MISCREG_ICC_BPR0_EL1)
|
||||
.res0(0xfffffff8) // [31:3]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_BPR0);
|
||||
InitReg(MISCREG_ICC_AP0R0_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP0R0);
|
||||
InitReg(MISCREG_ICC_AP0R1_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP0R1);
|
||||
InitReg(MISCREG_ICC_AP0R2_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP0R2);
|
||||
InitReg(MISCREG_ICC_AP0R3_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP0R3);
|
||||
InitReg(MISCREG_ICC_AP1R0_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_AP1R0);
|
||||
InitReg(MISCREG_ICC_AP1R0_EL1_NS)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R0_NS);
|
||||
InitReg(MISCREG_ICC_AP1R0_EL1_S)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R0_S);
|
||||
InitReg(MISCREG_ICC_AP1R1_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_AP1R1);
|
||||
InitReg(MISCREG_ICC_AP1R1_EL1_NS)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R1_NS);
|
||||
InitReg(MISCREG_ICC_AP1R1_EL1_S)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R1_S);
|
||||
InitReg(MISCREG_ICC_AP1R2_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_AP1R2);
|
||||
InitReg(MISCREG_ICC_AP1R2_EL1_NS)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R2_NS);
|
||||
InitReg(MISCREG_ICC_AP1R2_EL1_S)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R2_S);
|
||||
InitReg(MISCREG_ICC_AP1R3_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_AP1R3);
|
||||
InitReg(MISCREG_ICC_AP1R3_EL1_NS)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R3_NS);
|
||||
InitReg(MISCREG_ICC_AP1R3_EL1_S)
|
||||
.bankedChild()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_AP1R3_S);
|
||||
InitReg(MISCREG_ICC_DIR_EL1)
|
||||
.res0(0xFF000000) // [31:24]
|
||||
.allPrivileges().exceptUserMode().reads(0)
|
||||
.mapsTo(MISCREG_ICC_DIR);
|
||||
InitReg(MISCREG_ICC_RPR_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0)
|
||||
.mapsTo(MISCREG_ICC_RPR);
|
||||
InitReg(MISCREG_ICC_SGI1R_EL1)
|
||||
.allPrivileges().exceptUserMode().reads(0)
|
||||
.mapsTo(MISCREG_ICC_SGI1R);
|
||||
InitReg(MISCREG_ICC_ASGI1R_EL1)
|
||||
.allPrivileges().exceptUserMode().reads(0)
|
||||
.mapsTo(MISCREG_ICC_ASGI1R);
|
||||
InitReg(MISCREG_ICC_SGI0R_EL1)
|
||||
.allPrivileges().exceptUserMode().reads(0)
|
||||
.mapsTo(MISCREG_ICC_SGI0R);
|
||||
InitReg(MISCREG_ICC_IAR1_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0)
|
||||
.mapsTo(MISCREG_ICC_IAR1);
|
||||
InitReg(MISCREG_ICC_EOIR1_EL1)
|
||||
.res0(0xFF000000) // [31:24]
|
||||
.allPrivileges().exceptUserMode().reads(0)
|
||||
.mapsTo(MISCREG_ICC_EOIR1);
|
||||
InitReg(MISCREG_ICC_HPPIR1_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0)
|
||||
.mapsTo(MISCREG_ICC_HPPIR1);
|
||||
InitReg(MISCREG_ICC_BPR1_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_BPR1);
|
||||
InitReg(MISCREG_ICC_BPR1_EL1_NS)
|
||||
.bankedChild()
|
||||
.res0(0xfffffff8) // [31:3]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_BPR1_NS);
|
||||
InitReg(MISCREG_ICC_BPR1_EL1_S)
|
||||
.bankedChild()
|
||||
.res0(0xfffffff8) // [31:3]
|
||||
.secure().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_BPR1_S);
|
||||
InitReg(MISCREG_ICC_CTLR_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_CTLR);
|
||||
InitReg(MISCREG_ICC_CTLR_EL1_NS)
|
||||
.bankedChild()
|
||||
.res0(0xFFFB00BC) // [31:19, 17:16, 7, 5:2]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_CTLR_NS);
|
||||
InitReg(MISCREG_ICC_CTLR_EL1_S)
|
||||
.bankedChild()
|
||||
.res0(0xFFFB00BC) // [31:19, 17:16, 7, 5:2]
|
||||
.secure().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_CTLR_S);
|
||||
InitReg(MISCREG_ICC_SRE_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_SRE);
|
||||
InitReg(MISCREG_ICC_SRE_EL1_NS)
|
||||
.bankedChild()
|
||||
.res0(0xFFFFFFF8) // [31:3]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_SRE_NS);
|
||||
InitReg(MISCREG_ICC_SRE_EL1_S)
|
||||
.bankedChild()
|
||||
.res0(0xFFFFFFF8) // [31:3]
|
||||
.secure().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_SRE_S);
|
||||
InitReg(MISCREG_ICC_IGRPEN0_EL1)
|
||||
.res0(0xFFFFFFFE) // [31:1]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_IGRPEN0);
|
||||
InitReg(MISCREG_ICC_IGRPEN1_EL1)
|
||||
.banked()
|
||||
.mapsTo(MISCREG_ICC_IGRPEN1);
|
||||
InitReg(MISCREG_ICC_IGRPEN1_EL1_NS)
|
||||
.bankedChild()
|
||||
.res0(0xFFFFFFFE) // [31:1]
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_IGRPEN1_NS);
|
||||
InitReg(MISCREG_ICC_IGRPEN1_EL1_S)
|
||||
.bankedChild()
|
||||
.res0(0xFFFFFFFE) // [31:1]
|
||||
.secure().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_IGRPEN1_S);
|
||||
InitReg(MISCREG_ICC_SRE_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_ICC_HSRE);
|
||||
InitReg(MISCREG_ICC_CTLR_EL3)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_MCTLR);
|
||||
InitReg(MISCREG_ICC_SRE_EL3)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_MSRE);
|
||||
InitReg(MISCREG_ICC_IGRPEN1_EL3)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ICC_MGRPEN1);
|
||||
|
||||
InitReg(MISCREG_ICH_AP0R0_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_ICH_AP0R0);
|
||||
InitReg(MISCREG_ICH_AP0R1_EL2)
|
||||
.hyp().mon()
|
||||
.unimplemented()
|
||||
.mapsTo(MISCREG_ICH_AP0R1);
|
||||
InitReg(MISCREG_ICH_AP0R2_EL2)
|
||||
.hyp().mon()
|
||||
.unimplemented()
|
||||
.mapsTo(MISCREG_ICH_AP0R2);
|
||||
InitReg(MISCREG_ICH_AP0R3_EL2)
|
||||
.hyp().mon()
|
||||
.unimplemented()
|
||||
.mapsTo(MISCREG_ICH_AP0R3);
|
||||
InitReg(MISCREG_ICH_AP1R0_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_ICH_AP1R0);
|
||||
InitReg(MISCREG_ICH_AP1R1_EL2)
|
||||
.hyp().mon()
|
||||
.unimplemented()
|
||||
.mapsTo(MISCREG_ICH_AP1R1);
|
||||
InitReg(MISCREG_ICH_AP1R2_EL2)
|
||||
.hyp().mon()
|
||||
.unimplemented()
|
||||
.mapsTo(MISCREG_ICH_AP1R2);
|
||||
InitReg(MISCREG_ICH_AP1R3_EL2)
|
||||
.hyp().mon()
|
||||
.unimplemented()
|
||||
.mapsTo(MISCREG_ICH_AP1R3);
|
||||
InitReg(MISCREG_ICH_HCR_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_ICH_HCR);
|
||||
InitReg(MISCREG_ICH_VTR_EL2)
|
||||
.hyp().mon().writes(0)
|
||||
.mapsTo(MISCREG_ICH_VTR);
|
||||
InitReg(MISCREG_ICH_MISR_EL2)
|
||||
.hyp().mon().writes(0)
|
||||
.mapsTo(MISCREG_ICH_MISR);
|
||||
InitReg(MISCREG_ICH_EISR_EL2)
|
||||
.hyp().mon().writes(0)
|
||||
.mapsTo(MISCREG_ICH_EISR);
|
||||
InitReg(MISCREG_ICH_ELRSR_EL2)
|
||||
.hyp().mon().writes(0)
|
||||
.mapsTo(MISCREG_ICH_ELRSR);
|
||||
InitReg(MISCREG_ICH_VMCR_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_ICH_VMCR);
|
||||
InitReg(MISCREG_ICH_LR0_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR1_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR2_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR3_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR4_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR5_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR6_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR7_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR8_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR9_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR10_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR11_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR12_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR13_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR14_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICH_LR15_EL2)
|
||||
.hyp().mon()
|
||||
.allPrivileges().exceptUserMode();
|
||||
|
||||
// GICv3 AArch32
|
||||
InitReg(MISCREG_ICC_AP0R0)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP0R1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP0R2)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP0R3)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R0)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R0_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R0_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R1_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R1_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R2)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R2_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R2_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R3)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R3_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_AP1R3_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_ASGI1R)
|
||||
.allPrivileges().exceptUserMode().reads(0);
|
||||
InitReg(MISCREG_ICC_BPR0)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_BPR1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_BPR1_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_BPR1_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_CTLR)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_CTLR_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_CTLR_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_DIR)
|
||||
.allPrivileges().exceptUserMode().reads(0);
|
||||
InitReg(MISCREG_ICC_EOIR0)
|
||||
.allPrivileges().exceptUserMode().reads(0);
|
||||
InitReg(MISCREG_ICC_EOIR1)
|
||||
.allPrivileges().exceptUserMode().reads(0);
|
||||
InitReg(MISCREG_ICC_HPPIR0)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ICC_HPPIR1)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ICC_HSRE)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_IAR0)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ICC_IAR1)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ICC_IGRPEN0)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_IGRPEN1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_IGRPEN1_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_IGRPEN1_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_MCTLR)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_MGRPEN1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_MSRE)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_PMR)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_RPR)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ICC_SGI0R)
|
||||
.allPrivileges().exceptUserMode().reads(0);
|
||||
InitReg(MISCREG_ICC_SGI1R)
|
||||
.allPrivileges().exceptUserMode().reads(0);
|
||||
InitReg(MISCREG_ICC_SRE)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_SRE_NS)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ICC_SRE_S)
|
||||
.allPrivileges().exceptUserMode();
|
||||
|
||||
InitReg(MISCREG_ICH_AP0R0)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP0R1)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP0R2)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP0R3)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP1R0)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP1R1)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP1R2)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_AP1R3)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_HCR)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_VTR)
|
||||
.hyp().mon().writes(0);
|
||||
InitReg(MISCREG_ICH_MISR)
|
||||
.hyp().mon().writes(0);
|
||||
InitReg(MISCREG_ICH_EISR)
|
||||
.hyp().mon().writes(0);
|
||||
InitReg(MISCREG_ICH_ELRSR)
|
||||
.hyp().mon().writes(0);
|
||||
InitReg(MISCREG_ICH_VMCR)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR0)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR1)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR2)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR3)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR4)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR5)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR6)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR7)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR8)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR9)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR10)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR11)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR12)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR13)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR14)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LR15)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC0)
|
||||
.mapsTo(MISCREG_ICH_LR0)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC1)
|
||||
.mapsTo(MISCREG_ICH_LR1)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC2)
|
||||
.mapsTo(MISCREG_ICH_LR2)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC3)
|
||||
.mapsTo(MISCREG_ICH_LR3)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC4)
|
||||
.mapsTo(MISCREG_ICH_LR4)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC5)
|
||||
.mapsTo(MISCREG_ICH_LR5)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC6)
|
||||
.mapsTo(MISCREG_ICH_LR6)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC7)
|
||||
.mapsTo(MISCREG_ICH_LR7)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC8)
|
||||
.mapsTo(MISCREG_ICH_LR8)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC9)
|
||||
.mapsTo(MISCREG_ICH_LR9)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC10)
|
||||
.mapsTo(MISCREG_ICH_LR10)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC11)
|
||||
.mapsTo(MISCREG_ICH_LR11)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC12)
|
||||
.mapsTo(MISCREG_ICH_LR12)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC13)
|
||||
.mapsTo(MISCREG_ICH_LR13)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC14)
|
||||
.mapsTo(MISCREG_ICH_LR14)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ICH_LRC15)
|
||||
.mapsTo(MISCREG_ICH_LR15)
|
||||
.hyp().mon();
|
||||
|
||||
InitReg(MISCREG_CNTHV_CTL_EL2)
|
||||
.mon().hyp();
|
||||
InitReg(MISCREG_CNTHV_CVAL_EL2)
|
||||
|
||||
@@ -673,6 +673,224 @@ namespace ArmISA
|
||||
MISCREG_CNTHV_TVAL_EL2,
|
||||
|
||||
MISCREG_ID_AA64MMFR2_EL1,
|
||||
|
||||
// GICv3, CPU interface
|
||||
MISCREG_ICC_PMR_EL1,
|
||||
MISCREG_ICC_IAR0_EL1,
|
||||
MISCREG_ICC_EOIR0_EL1,
|
||||
MISCREG_ICC_HPPIR0_EL1,
|
||||
MISCREG_ICC_BPR0_EL1,
|
||||
MISCREG_ICC_AP0R0_EL1,
|
||||
MISCREG_ICC_AP0R1_EL1,
|
||||
MISCREG_ICC_AP0R2_EL1,
|
||||
MISCREG_ICC_AP0R3_EL1,
|
||||
MISCREG_ICC_AP1R0_EL1,
|
||||
MISCREG_ICC_AP1R0_EL1_NS,
|
||||
MISCREG_ICC_AP1R0_EL1_S,
|
||||
MISCREG_ICC_AP1R1_EL1,
|
||||
MISCREG_ICC_AP1R1_EL1_NS,
|
||||
MISCREG_ICC_AP1R1_EL1_S,
|
||||
MISCREG_ICC_AP1R2_EL1,
|
||||
MISCREG_ICC_AP1R2_EL1_NS,
|
||||
MISCREG_ICC_AP1R2_EL1_S,
|
||||
MISCREG_ICC_AP1R3_EL1,
|
||||
MISCREG_ICC_AP1R3_EL1_NS,
|
||||
MISCREG_ICC_AP1R3_EL1_S,
|
||||
MISCREG_ICC_DIR_EL1,
|
||||
MISCREG_ICC_RPR_EL1,
|
||||
MISCREG_ICC_SGI1R_EL1,
|
||||
MISCREG_ICC_ASGI1R_EL1,
|
||||
MISCREG_ICC_SGI0R_EL1,
|
||||
MISCREG_ICC_IAR1_EL1,
|
||||
MISCREG_ICC_EOIR1_EL1,
|
||||
MISCREG_ICC_HPPIR1_EL1,
|
||||
MISCREG_ICC_BPR1_EL1,
|
||||
MISCREG_ICC_BPR1_EL1_NS,
|
||||
MISCREG_ICC_BPR1_EL1_S,
|
||||
MISCREG_ICC_CTLR_EL1,
|
||||
MISCREG_ICC_CTLR_EL1_NS,
|
||||
MISCREG_ICC_CTLR_EL1_S,
|
||||
MISCREG_ICC_SRE_EL1,
|
||||
MISCREG_ICC_SRE_EL1_NS,
|
||||
MISCREG_ICC_SRE_EL1_S,
|
||||
MISCREG_ICC_IGRPEN0_EL1,
|
||||
MISCREG_ICC_IGRPEN1_EL1,
|
||||
MISCREG_ICC_IGRPEN1_EL1_NS,
|
||||
MISCREG_ICC_IGRPEN1_EL1_S,
|
||||
MISCREG_ICC_SRE_EL2,
|
||||
MISCREG_ICC_CTLR_EL3,
|
||||
MISCREG_ICC_SRE_EL3,
|
||||
MISCREG_ICC_IGRPEN1_EL3,
|
||||
|
||||
// GICv3, CPU interface, virtualization
|
||||
MISCREG_ICH_AP0R0_EL2,
|
||||
MISCREG_ICH_AP0R1_EL2,
|
||||
MISCREG_ICH_AP0R2_EL2,
|
||||
MISCREG_ICH_AP0R3_EL2,
|
||||
MISCREG_ICH_AP1R0_EL2,
|
||||
MISCREG_ICH_AP1R1_EL2,
|
||||
MISCREG_ICH_AP1R2_EL2,
|
||||
MISCREG_ICH_AP1R3_EL2,
|
||||
MISCREG_ICH_HCR_EL2,
|
||||
MISCREG_ICH_VTR_EL2,
|
||||
MISCREG_ICH_MISR_EL2,
|
||||
MISCREG_ICH_EISR_EL2,
|
||||
MISCREG_ICH_ELRSR_EL2,
|
||||
MISCREG_ICH_VMCR_EL2,
|
||||
MISCREG_ICH_LR0_EL2,
|
||||
MISCREG_ICH_LR1_EL2,
|
||||
MISCREG_ICH_LR2_EL2,
|
||||
MISCREG_ICH_LR3_EL2,
|
||||
MISCREG_ICH_LR4_EL2,
|
||||
MISCREG_ICH_LR5_EL2,
|
||||
MISCREG_ICH_LR6_EL2,
|
||||
MISCREG_ICH_LR7_EL2,
|
||||
MISCREG_ICH_LR8_EL2,
|
||||
MISCREG_ICH_LR9_EL2,
|
||||
MISCREG_ICH_LR10_EL2,
|
||||
MISCREG_ICH_LR11_EL2,
|
||||
MISCREG_ICH_LR12_EL2,
|
||||
MISCREG_ICH_LR13_EL2,
|
||||
MISCREG_ICH_LR14_EL2,
|
||||
MISCREG_ICH_LR15_EL2,
|
||||
|
||||
MISCREG_ICV_PMR_EL1,
|
||||
MISCREG_ICV_IAR0_EL1,
|
||||
MISCREG_ICV_EOIR0_EL1,
|
||||
MISCREG_ICV_HPPIR0_EL1,
|
||||
MISCREG_ICV_BPR0_EL1,
|
||||
MISCREG_ICV_AP0R0_EL1,
|
||||
MISCREG_ICV_AP0R1_EL1,
|
||||
MISCREG_ICV_AP0R2_EL1,
|
||||
MISCREG_ICV_AP0R3_EL1,
|
||||
MISCREG_ICV_AP1R0_EL1,
|
||||
MISCREG_ICV_AP1R0_EL1_NS,
|
||||
MISCREG_ICV_AP1R0_EL1_S,
|
||||
MISCREG_ICV_AP1R1_EL1,
|
||||
MISCREG_ICV_AP1R1_EL1_NS,
|
||||
MISCREG_ICV_AP1R1_EL1_S,
|
||||
MISCREG_ICV_AP1R2_EL1,
|
||||
MISCREG_ICV_AP1R2_EL1_NS,
|
||||
MISCREG_ICV_AP1R2_EL1_S,
|
||||
MISCREG_ICV_AP1R3_EL1,
|
||||
MISCREG_ICV_AP1R3_EL1_NS,
|
||||
MISCREG_ICV_AP1R3_EL1_S,
|
||||
MISCREG_ICV_DIR_EL1,
|
||||
MISCREG_ICV_RPR_EL1,
|
||||
MISCREG_ICV_SGI1R_EL1,
|
||||
MISCREG_ICV_ASGI1R_EL1,
|
||||
MISCREG_ICV_SGI0R_EL1,
|
||||
MISCREG_ICV_IAR1_EL1,
|
||||
MISCREG_ICV_EOIR1_EL1,
|
||||
MISCREG_ICV_HPPIR1_EL1,
|
||||
MISCREG_ICV_BPR1_EL1,
|
||||
MISCREG_ICV_BPR1_EL1_NS,
|
||||
MISCREG_ICV_BPR1_EL1_S,
|
||||
MISCREG_ICV_CTLR_EL1,
|
||||
MISCREG_ICV_CTLR_EL1_NS,
|
||||
MISCREG_ICV_CTLR_EL1_S,
|
||||
MISCREG_ICV_SRE_EL1,
|
||||
MISCREG_ICV_SRE_EL1_NS,
|
||||
MISCREG_ICV_SRE_EL1_S,
|
||||
MISCREG_ICV_IGRPEN0_EL1,
|
||||
MISCREG_ICV_IGRPEN1_EL1,
|
||||
MISCREG_ICV_IGRPEN1_EL1_NS,
|
||||
MISCREG_ICV_IGRPEN1_EL1_S,
|
||||
|
||||
MISCREG_ICC_AP0R0,
|
||||
MISCREG_ICC_AP0R1,
|
||||
MISCREG_ICC_AP0R2,
|
||||
MISCREG_ICC_AP0R3,
|
||||
MISCREG_ICC_AP1R0,
|
||||
MISCREG_ICC_AP1R0_NS,
|
||||
MISCREG_ICC_AP1R0_S,
|
||||
MISCREG_ICC_AP1R1,
|
||||
MISCREG_ICC_AP1R1_NS,
|
||||
MISCREG_ICC_AP1R1_S,
|
||||
MISCREG_ICC_AP1R2,
|
||||
MISCREG_ICC_AP1R2_NS,
|
||||
MISCREG_ICC_AP1R2_S,
|
||||
MISCREG_ICC_AP1R3,
|
||||
MISCREG_ICC_AP1R3_NS,
|
||||
MISCREG_ICC_AP1R3_S,
|
||||
MISCREG_ICC_ASGI1R,
|
||||
MISCREG_ICC_BPR0,
|
||||
MISCREG_ICC_BPR1,
|
||||
MISCREG_ICC_BPR1_NS,
|
||||
MISCREG_ICC_BPR1_S,
|
||||
MISCREG_ICC_CTLR,
|
||||
MISCREG_ICC_CTLR_NS,
|
||||
MISCREG_ICC_CTLR_S,
|
||||
MISCREG_ICC_DIR,
|
||||
MISCREG_ICC_EOIR0,
|
||||
MISCREG_ICC_EOIR1,
|
||||
MISCREG_ICC_HPPIR0,
|
||||
MISCREG_ICC_HPPIR1,
|
||||
MISCREG_ICC_HSRE,
|
||||
MISCREG_ICC_IAR0,
|
||||
MISCREG_ICC_IAR1,
|
||||
MISCREG_ICC_IGRPEN0,
|
||||
MISCREG_ICC_IGRPEN1,
|
||||
MISCREG_ICC_IGRPEN1_NS,
|
||||
MISCREG_ICC_IGRPEN1_S,
|
||||
MISCREG_ICC_MCTLR,
|
||||
MISCREG_ICC_MGRPEN1,
|
||||
MISCREG_ICC_MSRE,
|
||||
MISCREG_ICC_PMR,
|
||||
MISCREG_ICC_RPR,
|
||||
MISCREG_ICC_SGI0R,
|
||||
MISCREG_ICC_SGI1R,
|
||||
MISCREG_ICC_SRE,
|
||||
MISCREG_ICC_SRE_NS,
|
||||
MISCREG_ICC_SRE_S,
|
||||
|
||||
MISCREG_ICH_AP0R0,
|
||||
MISCREG_ICH_AP0R1,
|
||||
MISCREG_ICH_AP0R2,
|
||||
MISCREG_ICH_AP0R3,
|
||||
MISCREG_ICH_AP1R0,
|
||||
MISCREG_ICH_AP1R1,
|
||||
MISCREG_ICH_AP1R2,
|
||||
MISCREG_ICH_AP1R3,
|
||||
MISCREG_ICH_HCR,
|
||||
MISCREG_ICH_VTR,
|
||||
MISCREG_ICH_MISR,
|
||||
MISCREG_ICH_EISR,
|
||||
MISCREG_ICH_ELRSR,
|
||||
MISCREG_ICH_VMCR,
|
||||
MISCREG_ICH_LR0,
|
||||
MISCREG_ICH_LR1,
|
||||
MISCREG_ICH_LR2,
|
||||
MISCREG_ICH_LR3,
|
||||
MISCREG_ICH_LR4,
|
||||
MISCREG_ICH_LR5,
|
||||
MISCREG_ICH_LR6,
|
||||
MISCREG_ICH_LR7,
|
||||
MISCREG_ICH_LR8,
|
||||
MISCREG_ICH_LR9,
|
||||
MISCREG_ICH_LR10,
|
||||
MISCREG_ICH_LR11,
|
||||
MISCREG_ICH_LR12,
|
||||
MISCREG_ICH_LR13,
|
||||
MISCREG_ICH_LR14,
|
||||
MISCREG_ICH_LR15,
|
||||
MISCREG_ICH_LRC0,
|
||||
MISCREG_ICH_LRC1,
|
||||
MISCREG_ICH_LRC2,
|
||||
MISCREG_ICH_LRC3,
|
||||
MISCREG_ICH_LRC4,
|
||||
MISCREG_ICH_LRC5,
|
||||
MISCREG_ICH_LRC6,
|
||||
MISCREG_ICH_LRC7,
|
||||
MISCREG_ICH_LRC8,
|
||||
MISCREG_ICH_LRC9,
|
||||
MISCREG_ICH_LRC10,
|
||||
MISCREG_ICH_LRC11,
|
||||
MISCREG_ICH_LRC12,
|
||||
MISCREG_ICH_LRC13,
|
||||
MISCREG_ICH_LRC14,
|
||||
MISCREG_ICH_LRC15,
|
||||
|
||||
// These MISCREG_FREESLOT are available Misc Register
|
||||
// slots for future registers to be implemented.
|
||||
MISCREG_FREESLOT_1,
|
||||
@@ -1389,6 +1607,224 @@ namespace ArmISA
|
||||
"cnthv_cval_el2",
|
||||
"cnthv_tval_el2",
|
||||
"id_aa64mmfr2_el1",
|
||||
|
||||
// GICv3, CPU interface
|
||||
"icc_pmr_el1",
|
||||
"icc_iar0_el1",
|
||||
"icc_eoir0_el1",
|
||||
"icc_hppir0_el1",
|
||||
"icc_bpr0_el1",
|
||||
"icc_ap0r0_el1",
|
||||
"icc_ap0r1_el1",
|
||||
"icc_ap0r2_el1",
|
||||
"icc_ap0r3_el1",
|
||||
"icc_ap1r0_el1",
|
||||
"icc_ap1r0_el1_ns",
|
||||
"icc_ap1r0_el1_s",
|
||||
"icc_ap1r1_el1",
|
||||
"icc_ap1r1_el1_ns",
|
||||
"icc_ap1r1_el1_s",
|
||||
"icc_ap1r2_el1",
|
||||
"icc_ap1r2_el1_ns",
|
||||
"icc_ap1r2_el1_s",
|
||||
"icc_ap1r3_el1",
|
||||
"icc_ap1r3_el1_ns",
|
||||
"icc_ap1r3_el1_s",
|
||||
"icc_dir_el1",
|
||||
"icc_rpr_el1",
|
||||
"icc_sgi1r_el1",
|
||||
"icc_asgi1r_el1",
|
||||
"icc_sgi0r_el1",
|
||||
"icc_iar1_el1",
|
||||
"icc_eoir1_el1",
|
||||
"icc_hppir1_el1",
|
||||
"icc_bpr1_el1",
|
||||
"icc_bpr1_el1_ns",
|
||||
"icc_bpr1_el1_s",
|
||||
"icc_ctlr_el1",
|
||||
"icc_ctlr_el1_ns",
|
||||
"icc_ctlr_el1_s",
|
||||
"icc_sre_el1",
|
||||
"icc_sre_el1_ns",
|
||||
"icc_sre_el1_s",
|
||||
"icc_igrpen0_el1",
|
||||
"icc_igrpen1_el1",
|
||||
"icc_igrpen1_el1_ns",
|
||||
"icc_igrpen1_el1_s",
|
||||
"icc_sre_el2",
|
||||
"icc_ctlr_el3",
|
||||
"icc_sre_el3",
|
||||
"icc_igrpen1_el3",
|
||||
|
||||
// GICv3, CPU interface, virtualization
|
||||
"ich_ap0r0_el2",
|
||||
"ich_ap0r1_el2",
|
||||
"ich_ap0r2_el2",
|
||||
"ich_ap0r3_el2",
|
||||
"ich_ap1r0_el2",
|
||||
"ich_ap1r1_el2",
|
||||
"ich_ap1r2_el2",
|
||||
"ich_ap1r3_el2",
|
||||
"ich_hcr_el2",
|
||||
"ich_vtr_el2",
|
||||
"ich_misr_el2",
|
||||
"ich_eisr_el2",
|
||||
"ich_elrsr_el2",
|
||||
"ich_vmcr_el2",
|
||||
"ich_lr0_el2",
|
||||
"ich_lr1_el2",
|
||||
"ich_lr2_el2",
|
||||
"ich_lr3_el2",
|
||||
"ich_lr4_el2",
|
||||
"ich_lr5_el2",
|
||||
"ich_lr6_el2",
|
||||
"ich_lr7_el2",
|
||||
"ich_lr8_el2",
|
||||
"ich_lr9_el2",
|
||||
"ich_lr10_el2",
|
||||
"ich_lr11_el2",
|
||||
"ich_lr12_el2",
|
||||
"ich_lr13_el2",
|
||||
"ich_lr14_el2",
|
||||
"ich_lr15_el2",
|
||||
|
||||
"icv_pmr_el1",
|
||||
"icv_iar0_el1",
|
||||
"icv_eoir0_el1",
|
||||
"icv_hppir0_el1",
|
||||
"icv_bpr0_el1",
|
||||
"icv_ap0r0_el1",
|
||||
"icv_ap0r1_el1",
|
||||
"icv_ap0r2_el1",
|
||||
"icv_ap0r3_el1",
|
||||
"icv_ap1r0_el1",
|
||||
"icv_ap1r0_el1_ns",
|
||||
"icv_ap1r0_el1_s",
|
||||
"icv_ap1r1_el1",
|
||||
"icv_ap1r1_el1_ns",
|
||||
"icv_ap1r1_el1_s",
|
||||
"icv_ap1r2_el1",
|
||||
"icv_ap1r2_el1_ns",
|
||||
"icv_ap1r2_el1_s",
|
||||
"icv_ap1r3_el1",
|
||||
"icv_ap1r3_el1_ns",
|
||||
"icv_ap1r3_el1_s",
|
||||
"icv_dir_el1",
|
||||
"icv_rpr_el1",
|
||||
"icv_sgi1r_el1",
|
||||
"icv_asgi1r_el1",
|
||||
"icv_sgi0r_el1",
|
||||
"icv_iar1_el1",
|
||||
"icv_eoir1_el1",
|
||||
"icv_hppir1_el1",
|
||||
"icv_bpr1_el1",
|
||||
"icv_bpr1_el1_ns",
|
||||
"icv_bpr1_el1_s",
|
||||
"icv_ctlr_el1",
|
||||
"icv_ctlr_el1_ns",
|
||||
"icv_ctlr_el1_s",
|
||||
"icv_sre_el1",
|
||||
"icv_sre_el1_ns",
|
||||
"icv_sre_el1_s",
|
||||
"icv_igrpen0_el1",
|
||||
"icv_igrpen1_el1",
|
||||
"icv_igrpen1_el1_ns",
|
||||
"icv_igrpen1_el1_s",
|
||||
|
||||
"icc_ap0r0",
|
||||
"icc_ap0r1",
|
||||
"icc_ap0r2",
|
||||
"icc_ap0r3",
|
||||
"icc_ap1r0",
|
||||
"icc_ap1r0_ns",
|
||||
"icc_ap1r0_s",
|
||||
"icc_ap1r1",
|
||||
"icc_ap1r1_ns",
|
||||
"icc_ap1r1_s",
|
||||
"icc_ap1r2",
|
||||
"icc_ap1r2_ns",
|
||||
"icc_ap1r2_s",
|
||||
"icc_ap1r3",
|
||||
"icc_ap1r3_ns",
|
||||
"icc_ap1r3_s",
|
||||
"icc_asgi1r",
|
||||
"icc_bpr0",
|
||||
"icc_bpr1",
|
||||
"icc_bpr1_ns",
|
||||
"icc_bpr1_s",
|
||||
"icc_ctlr",
|
||||
"icc_ctlr_ns",
|
||||
"icc_ctlr_s",
|
||||
"icc_dir",
|
||||
"icc_eoir0",
|
||||
"icc_eoir1",
|
||||
"icc_hppir0",
|
||||
"icc_hppir1",
|
||||
"icc_hsre",
|
||||
"icc_iar0",
|
||||
"icc_iar1",
|
||||
"icc_igrpen0",
|
||||
"icc_igrpen1",
|
||||
"icc_igrpen1_ns",
|
||||
"icc_igrpen1_s",
|
||||
"icc_mctlr",
|
||||
"icc_mgrpen1",
|
||||
"icc_msre",
|
||||
"icc_pmr",
|
||||
"icc_rpr",
|
||||
"icc_sgi0r",
|
||||
"icc_sgi1r",
|
||||
"icc_sre",
|
||||
"icc_sre_ns",
|
||||
"icc_sre_s",
|
||||
|
||||
"ich_ap0r0",
|
||||
"ich_ap0r1",
|
||||
"ich_ap0r2",
|
||||
"ich_ap0r3",
|
||||
"ich_ap1r0",
|
||||
"ich_ap1r1",
|
||||
"ich_ap1r2",
|
||||
"ich_ap1r3",
|
||||
"ich_hcr",
|
||||
"ich_vtr",
|
||||
"ich_misr",
|
||||
"ich_eisr",
|
||||
"ich_elrsr",
|
||||
"ich_vmcr",
|
||||
"ich_lr0",
|
||||
"ich_lr1",
|
||||
"ich_lr2",
|
||||
"ich_lr3",
|
||||
"ich_lr4",
|
||||
"ich_lr5",
|
||||
"ich_lr6",
|
||||
"ich_lr7",
|
||||
"ich_lr8",
|
||||
"ich_lr9",
|
||||
"ich_lr10",
|
||||
"ich_lr11",
|
||||
"ich_lr12",
|
||||
"ich_lr13",
|
||||
"ich_lr14",
|
||||
"ich_lr15",
|
||||
"ich_lrc0",
|
||||
"ich_lrc1",
|
||||
"ich_lrc2",
|
||||
"ich_lrc3",
|
||||
"ich_lrc4",
|
||||
"ich_lrc5",
|
||||
"ich_lrc6",
|
||||
"ich_lrc7",
|
||||
"ich_lrc8",
|
||||
"ich_lrc9",
|
||||
"ich_lrc10",
|
||||
"ich_lrc11",
|
||||
"ich_lrc12",
|
||||
"ich_lrc13",
|
||||
"ich_lrc14",
|
||||
"ich_lrc15",
|
||||
|
||||
"freeslot2",
|
||||
|
||||
"num_phys_regs",
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
#include "mem/fs_translating_port_proxy.hh"
|
||||
#include "mem/physical.hh"
|
||||
#include "sim/full_system.hh"
|
||||
@@ -63,6 +64,7 @@ ArmSystem::ArmSystem(Params *p)
|
||||
_haveVirtualization(p->have_virtualization),
|
||||
_haveCrypto(p->have_crypto),
|
||||
_genericTimer(nullptr),
|
||||
_gic(nullptr),
|
||||
_resetAddr(p->auto_reset_addr ?
|
||||
(kernelEntry & loadAddrMask) + loadAddrOffset :
|
||||
p->reset_addr),
|
||||
@@ -136,6 +138,7 @@ ArmSystem::initState()
|
||||
const Params* p = params();
|
||||
|
||||
if (bootldr) {
|
||||
bool isGICv3System = dynamic_cast<Gicv3 *>(getGIC()) != nullptr;
|
||||
bootldr->loadSections(physProxy);
|
||||
|
||||
inform("Using bootloader at address %#x\n", bootldr->entryPoint());
|
||||
@@ -143,15 +146,18 @@ ArmSystem::initState()
|
||||
// Put the address of the boot loader into r7 so we know
|
||||
// where to branch to after the reset fault
|
||||
// All other values needed by the boot loader to know what to do
|
||||
if (!p->gic_cpu_addr || !p->flags_addr)
|
||||
fatal("gic_cpu_addr && flags_addr must be set with bootloader\n");
|
||||
if (!p->flags_addr)
|
||||
fatal("flags_addr must be set with bootloader\n");
|
||||
|
||||
if (!p->gic_cpu_addr && !isGICv3System)
|
||||
fatal("gic_cpu_addr must be set with bootloader\n");
|
||||
|
||||
for (int i = 0; i < threadContexts.size(); i++) {
|
||||
if (!_highestELIs64)
|
||||
threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) +
|
||||
loadAddrOffset);
|
||||
|
||||
threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
|
||||
if (!isGICv3System)
|
||||
threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
|
||||
threadContexts[i]->setIntReg(5, params()->flags_addr);
|
||||
}
|
||||
inform("Using kernel entry physical address at %#x\n",
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "sim/system.hh"
|
||||
|
||||
class GenericTimer;
|
||||
class BaseGic;
|
||||
class ThreadContext;
|
||||
|
||||
class ArmSystem : public System
|
||||
@@ -97,6 +98,7 @@ class ArmSystem : public System
|
||||
* Pointer to the Generic Timer wrapper.
|
||||
*/
|
||||
GenericTimer *_genericTimer;
|
||||
BaseGic *_gic;
|
||||
|
||||
/**
|
||||
* Reset address (ARMv8)
|
||||
@@ -192,9 +194,18 @@ class ArmSystem : public System
|
||||
_genericTimer = generic_timer;
|
||||
}
|
||||
|
||||
/** Sets the pointer to the GIC. */
|
||||
void setGIC(BaseGic *gic)
|
||||
{
|
||||
_gic = gic;
|
||||
}
|
||||
|
||||
/** Get a pointer to the system's generic timer model */
|
||||
GenericTimer *getGenericTimer() const { return _genericTimer; }
|
||||
|
||||
/** Get a pointer to the system's GIC */
|
||||
BaseGic *getGIC() const { return _gic; }
|
||||
|
||||
/** Returns true if the register width of the highest implemented exception
|
||||
* level is 64 bits (ARMv8) */
|
||||
bool highestELIs64() const { return _highestELIs64; }
|
||||
|
||||
@@ -282,4 +282,15 @@ inline uint64_t alignToPowerOfTwo(uint64_t val)
|
||||
return val;
|
||||
};
|
||||
|
||||
/**
|
||||
* Count trailing zeros in a 32-bit value.
|
||||
*
|
||||
* Returns 32 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
inline int ctz32(uint32_t value)
|
||||
{
|
||||
return value ? __builtin_ctz(value) : 32;
|
||||
}
|
||||
|
||||
#endif // __BASE_BITFIELD_HH__
|
||||
|
||||
@@ -160,3 +160,15 @@ class VGic(PioDevice):
|
||||
node.appendPhandle(gic)
|
||||
|
||||
yield node
|
||||
|
||||
class Gicv3(BaseGic):
|
||||
type = 'Gicv3'
|
||||
cxx_header = "dev/arm/gic_v3.hh"
|
||||
|
||||
dist_addr = Param.Addr(0x2c000000, "Address for distributor")
|
||||
dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor")
|
||||
redist_addr = Param.Addr(0x2c010000, "Address for redistributors")
|
||||
redist_pio_delay = Param.Latency('10ns',
|
||||
"Delay for PIO r/w to redistributors")
|
||||
it_lines = Param.UInt32(1020,
|
||||
"Number of interrupt lines supported (max = 1020)")
|
||||
|
||||
@@ -57,6 +57,10 @@ if env['TARGET_ISA'] == 'arm':
|
||||
Source('generic_timer.cc')
|
||||
Source('gic_v2.cc')
|
||||
Source('gic_v2m.cc')
|
||||
Source('gic_v3.cc')
|
||||
Source('gic_v3_cpu_interface.cc')
|
||||
Source('gic_v3_distributor.cc')
|
||||
Source('gic_v3_redistributor.cc')
|
||||
Source('pl011.cc')
|
||||
Source('pl111.cc')
|
||||
Source('hdlcd.cc')
|
||||
|
||||
@@ -64,6 +64,13 @@ BaseGic::~BaseGic()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BaseGic::init()
|
||||
{
|
||||
PioDevice::init();
|
||||
getSystem()->setGIC(this);
|
||||
}
|
||||
|
||||
const BaseGic::Params *
|
||||
BaseGic::params() const
|
||||
{
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "arch/arm/system.hh"
|
||||
#include "dev/io_device.hh"
|
||||
|
||||
class Platform;
|
||||
@@ -67,6 +68,7 @@ class BaseGic : public PioDevice
|
||||
|
||||
BaseGic(const Params *p);
|
||||
virtual ~BaseGic();
|
||||
void init() override;
|
||||
|
||||
const Params * params() const;
|
||||
|
||||
@@ -99,6 +101,12 @@ class BaseGic : public PioDevice
|
||||
*/
|
||||
virtual void clearInt(uint32_t num) = 0;
|
||||
|
||||
ArmSystem *
|
||||
getSystem() const
|
||||
{
|
||||
return (ArmSystem *) sys;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Platform this GIC belongs to. */
|
||||
Platform *platform;
|
||||
|
||||
275
src/dev/arm/gic_v3.cc
Normal file
275
src/dev/arm/gic_v3.cc
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Metempsy Technology Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Jairo Balart
|
||||
*/
|
||||
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "debug/GIC.hh"
|
||||
#include "debug/Interrupt.hh"
|
||||
#include "dev/arm/gic_v3_cpu_interface.hh"
|
||||
#include "dev/arm/gic_v3_distributor.hh"
|
||||
#include "dev/arm/gic_v3_redistributor.hh"
|
||||
#include "dev/platform.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
Gicv3::Gicv3(const Params * p)
|
||||
: BaseGic(p)
|
||||
{
|
||||
}
|
||||
|
||||
Gicv3::~Gicv3()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::init()
|
||||
{
|
||||
distRange = RangeSize(params()->dist_addr,
|
||||
Gicv3Distributor::ADDR_RANGE_SIZE - 1);
|
||||
redistRange = RangeSize(params()->redist_addr,
|
||||
Gicv3Redistributor::ADDR_RANGE_SIZE * sys->numContexts() - 1);
|
||||
addrRanges = {distRange, redistRange};
|
||||
BaseGic::init();
|
||||
distributor = new Gicv3Distributor(this, params()->it_lines);
|
||||
redistributors.resize(sys->numContexts(), nullptr);
|
||||
cpuInterfaces.resize(sys->numContexts(), nullptr);
|
||||
|
||||
for (int i = 0; i < sys->numContexts(); i++) {
|
||||
redistributors[i] = new Gicv3Redistributor(this, i);
|
||||
cpuInterfaces[i] = new Gicv3CPUInterface(this, i);
|
||||
}
|
||||
|
||||
distributor->init();
|
||||
|
||||
for (int i = 0; i < sys->numContexts(); i++) {
|
||||
redistributors[i]->init();
|
||||
cpuInterfaces[i]->init();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::initState()
|
||||
{
|
||||
distributor->initState();
|
||||
|
||||
for (int i = 0; i < sys->numContexts(); i++) {
|
||||
redistributors[i]->initState();
|
||||
cpuInterfaces[i]->initState();
|
||||
}
|
||||
}
|
||||
|
||||
Tick
|
||||
Gicv3::read(PacketPtr pkt)
|
||||
{
|
||||
const Addr addr = pkt->getAddr();
|
||||
const size_t size = pkt->getSize();
|
||||
const ContextID context_id = pkt->req->contextId();
|
||||
bool is_secure_access = pkt->isSecure();
|
||||
uint64_t resp = 0;
|
||||
Tick delay = 0;
|
||||
|
||||
if (distRange.contains(addr)) {
|
||||
const Addr daddr = addr - distRange.start();
|
||||
panic_if(!distributor, "Distributor is null!");
|
||||
resp = distributor->read(daddr, size, is_secure_access);
|
||||
delay = params()->dist_pio_delay;
|
||||
DPRINTF(GIC, "Gicv3::read(): (distributor) context_id %d register %#x "
|
||||
"size %d is_secure_access %d (value %#x)\n",
|
||||
context_id, daddr, size, is_secure_access, resp);
|
||||
} else if (redistRange.contains(addr)) {
|
||||
Addr daddr = addr - redistRange.start();
|
||||
uint32_t redistributor_id =
|
||||
daddr / Gicv3Redistributor::ADDR_RANGE_SIZE;
|
||||
daddr = daddr % Gicv3Redistributor::ADDR_RANGE_SIZE;
|
||||
panic_if(redistributor_id >= redistributors.size(),
|
||||
"Invalid redistributor_id!");
|
||||
panic_if(!redistributors[redistributor_id], "Redistributor is null!");
|
||||
resp = redistributors[redistributor_id]->read(daddr, size,
|
||||
is_secure_access);
|
||||
delay = params()->redist_pio_delay;
|
||||
DPRINTF(GIC, "Gicv3::read(): (redistributor %d) context_id %d "
|
||||
"register %#x size %d is_secure_access %d (value %#x)\n",
|
||||
redistributor_id, context_id, daddr, size, is_secure_access,
|
||||
resp);
|
||||
} else {
|
||||
panic("Gicv3::read(): unknown address %#x\n", addr);
|
||||
}
|
||||
|
||||
pkt->setUintX(resp, LittleEndianByteOrder);
|
||||
pkt->makeAtomicResponse();
|
||||
return delay;
|
||||
}
|
||||
|
||||
Tick
|
||||
Gicv3::write(PacketPtr pkt)
|
||||
{
|
||||
const size_t size = pkt->getSize();
|
||||
uint64_t data = pkt->getUintX(LittleEndianByteOrder);
|
||||
const Addr addr = pkt->getAddr();
|
||||
const ContextID context_id = pkt->req->contextId();
|
||||
bool is_secure_access = pkt->isSecure();
|
||||
Tick delay = 0;
|
||||
|
||||
if (distRange.contains(addr)) {
|
||||
const Addr daddr = addr - distRange.start();
|
||||
panic_if(!distributor, "Distributor is null!");
|
||||
DPRINTF(GIC, "Gicv3::write(): (distributor) context_id %d "
|
||||
"register %#x size %d is_secure_access %d value %#x\n",
|
||||
context_id, daddr, size, is_secure_access, data);
|
||||
distributor->write(daddr, data, size, is_secure_access);
|
||||
delay = params()->dist_pio_delay;
|
||||
} else if (redistRange.contains(addr)) {
|
||||
Addr daddr = addr - redistRange.start();
|
||||
uint32_t redistributor_id =
|
||||
daddr / Gicv3Redistributor::ADDR_RANGE_SIZE;
|
||||
daddr = daddr % Gicv3Redistributor::ADDR_RANGE_SIZE;
|
||||
panic_if(redistributor_id >= redistributors.size(),
|
||||
"Invalid redistributor_id!");
|
||||
panic_if(!redistributors[redistributor_id], "Redistributor is null!");
|
||||
DPRINTF(GIC, "Gicv3::write(): (redistributor %d) context_id %d "
|
||||
"register %#x size %d is_secure_access %d value %#x\n",
|
||||
redistributor_id, context_id, daddr, size, is_secure_access,
|
||||
data);
|
||||
redistributors[redistributor_id]->write(daddr, data, size,
|
||||
is_secure_access);
|
||||
delay = params()->redist_pio_delay;
|
||||
} else {
|
||||
panic("Gicv3::write(): unknown address %#x\n", addr);
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return delay;
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::sendInt(uint32_t int_id)
|
||||
{
|
||||
panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
|
||||
panic_if(int_id >= Gicv3::INTID_SECURE, "Invalid SPI!");
|
||||
DPRINTF(Interrupt, "Gicv3::sendInt(): received SPI %d\n", int_id);
|
||||
distributor->sendInt(int_id);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::clearInt(uint32_t number)
|
||||
{
|
||||
distributor->intDeasserted(number);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::sendPPInt(uint32_t int_id, uint32_t cpu)
|
||||
{
|
||||
panic_if(cpu >= redistributors.size(), "Invalid cpuID sending PPI!");
|
||||
panic_if(int_id < Gicv3::SGI_MAX, "Invalid PPI!");
|
||||
panic_if(int_id >= Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid PPI!");
|
||||
DPRINTF(Interrupt, "Gicv3::sendPPInt(): received PPI %d cpuTarget %#x\n",
|
||||
int_id, cpu);
|
||||
redistributors[cpu]->sendPPInt(int_id);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::clearPPInt(uint32_t num, uint32_t cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::postInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
|
||||
{
|
||||
postDelayedInt(cpu, int_type);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::deassertInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
|
||||
{
|
||||
platform->intrctrl->clear(cpu, int_type, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::postDelayedInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
|
||||
{
|
||||
platform->intrctrl->post(cpu, int_type, 0);
|
||||
}
|
||||
|
||||
Gicv3Redistributor *
|
||||
Gicv3::getRedistributorByAffinity(uint32_t affinity)
|
||||
{
|
||||
for (auto & redistributor : redistributors) {
|
||||
if (redistributor->getAffinity() == affinity) {
|
||||
return redistributor;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::serialize(CheckpointOut & cp) const
|
||||
{
|
||||
distributor->serializeSection(cp, "distributor");
|
||||
|
||||
for (uint32_t redistributor_id = 0;
|
||||
redistributor_id < redistributors.size();
|
||||
redistributor_id++)
|
||||
redistributors[redistributor_id]->serializeSection(cp,
|
||||
csprintf("redistributors.%i", redistributor_id));
|
||||
|
||||
for (uint32_t cpu_interface_id = 0;
|
||||
cpu_interface_id < cpuInterfaces.size();
|
||||
cpu_interface_id++)
|
||||
cpuInterfaces[cpu_interface_id]->serializeSection(cp,
|
||||
csprintf("cpuInterface.%i", cpu_interface_id));
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3::unserialize(CheckpointIn & cp)
|
||||
{
|
||||
getSystem()->setGIC(this);
|
||||
|
||||
distributor->unserializeSection(cp, "distributor");
|
||||
|
||||
for (uint32_t redistributor_id = 0;
|
||||
redistributor_id < redistributors.size();
|
||||
redistributor_id++)
|
||||
redistributors[redistributor_id]->unserializeSection(cp,
|
||||
csprintf("redistributors.%i", redistributor_id));
|
||||
|
||||
for (uint32_t cpu_interface_id = 0;
|
||||
cpu_interface_id < cpuInterfaces.size();
|
||||
cpu_interface_id++)
|
||||
cpuInterfaces[cpu_interface_id]->unserializeSection(cp,
|
||||
csprintf("cpuInterface.%i", cpu_interface_id));
|
||||
}
|
||||
|
||||
Gicv3 *
|
||||
Gicv3Params::create()
|
||||
{
|
||||
return new Gicv3(this);
|
||||
}
|
||||
142
src/dev/arm/gic_v3.hh
Normal file
142
src/dev/arm/gic_v3.hh
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Metempsy Technology Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Jairo Balart
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_GICV3_H__
|
||||
#define __DEV_ARM_GICV3_H__
|
||||
|
||||
#include "dev/arm/base_gic.hh"
|
||||
#include "params/Gicv3.hh"
|
||||
|
||||
class Gicv3Distributor;
|
||||
class Gicv3Redistributor;
|
||||
class Gicv3CPUInterface;
|
||||
|
||||
class Gicv3 : public BaseGic
|
||||
{
|
||||
protected:
|
||||
|
||||
Gicv3Distributor * distributor;
|
||||
std::vector<Gicv3Redistributor *> redistributors;
|
||||
std::vector<Gicv3CPUInterface *> cpuInterfaces;
|
||||
AddrRange distRange;
|
||||
AddrRange redistRange;
|
||||
AddrRangeList addrRanges;
|
||||
|
||||
public:
|
||||
|
||||
// Special interrupt IDs
|
||||
static const int INTID_SECURE = 1020;
|
||||
static const int INTID_NONSECURE = 1021;
|
||||
static const int INTID_SPURIOUS = 1023;
|
||||
|
||||
// Number of Software Generated Interrupts
|
||||
static const int SGI_MAX = 16;
|
||||
// Number of Private Peripheral Interrupts
|
||||
static const int PPI_MAX = 16;
|
||||
|
||||
typedef enum {
|
||||
INT_INACTIVE,
|
||||
INT_PENDING,
|
||||
INT_ACTIVE,
|
||||
INT_ACTIVE_PENDING,
|
||||
} IntStatus;
|
||||
|
||||
typedef enum {
|
||||
G0S,
|
||||
G1S,
|
||||
G1NS,
|
||||
} GroupId;
|
||||
|
||||
typedef enum {
|
||||
INT_LEVEL_SENSITIVE,
|
||||
INT_EDGE_TRIGGERED,
|
||||
} IntTriggerType;
|
||||
|
||||
typedef Gicv3Params Params;
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
Gicv3(const Params * p);
|
||||
~Gicv3();
|
||||
void init() override;
|
||||
void initState() override;
|
||||
|
||||
AddrRangeList
|
||||
getAddrRanges() const override
|
||||
{
|
||||
return addrRanges;
|
||||
}
|
||||
|
||||
Tick read(PacketPtr pkt) override;
|
||||
Tick write(PacketPtr pkt) override;
|
||||
void sendInt(uint32_t int_id) override;
|
||||
void clearInt(uint32_t int_id) override;
|
||||
void sendPPInt(uint32_t int_id, uint32_t cpu) override;
|
||||
void clearPPInt(uint32_t int_id, uint32_t cpu) override;
|
||||
|
||||
void serialize(CheckpointOut & cp) const override;
|
||||
void unserialize(CheckpointIn & cp) override;
|
||||
|
||||
Gicv3Distributor *
|
||||
getDistributor() const
|
||||
{
|
||||
return distributor;
|
||||
}
|
||||
|
||||
Gicv3CPUInterface *
|
||||
getCPUInterface(int cpu_id) const
|
||||
{
|
||||
assert(cpu_id < cpuInterfaces.size() and cpuInterfaces[cpu_id]);
|
||||
return cpuInterfaces[cpu_id];
|
||||
}
|
||||
|
||||
Gicv3Redistributor *
|
||||
getRedistributor(ContextID context_id) const
|
||||
{
|
||||
assert(context_id < redistributors.size() and
|
||||
redistributors[context_id]);
|
||||
return redistributors[context_id];
|
||||
}
|
||||
|
||||
Gicv3Redistributor * getRedistributorByAffinity(uint32_t affinity);
|
||||
void postInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
|
||||
void postDelayedInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
|
||||
void deassertInt(uint32_t cpu, ArmISA::InterruptTypes int_type);
|
||||
|
||||
protected:
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_GICV3_H__
|
||||
2362
src/dev/arm/gic_v3_cpu_interface.cc
Normal file
2362
src/dev/arm/gic_v3_cpu_interface.cc
Normal file
File diff suppressed because it is too large
Load Diff
301
src/dev/arm/gic_v3_cpu_interface.hh
Normal file
301
src/dev/arm/gic_v3_cpu_interface.hh
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Metempsy Technology Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Jairo Balart
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_GICV3_CPU_INTERFACE_H__
|
||||
#define __DEV_ARM_GICV3_CPU_INTERFACE_H__
|
||||
|
||||
#include "arch/arm/isa_device.hh"
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
|
||||
class Gicv3Redistributor;
|
||||
class Gicv3Distributor;
|
||||
|
||||
class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable
|
||||
{
|
||||
private:
|
||||
|
||||
friend class Gicv3Redistributor;
|
||||
friend class Gicv3Distributor;
|
||||
|
||||
protected:
|
||||
|
||||
Gicv3 * gic;
|
||||
Gicv3Redistributor * redistributor;
|
||||
Gicv3Distributor * distributor;
|
||||
uint32_t cpuId;
|
||||
|
||||
static const uint32_t ICC_SRE_EL1_SRE = 1 << 0;
|
||||
static const uint32_t ICC_SRE_EL1_DFB = 1 << 1;
|
||||
static const uint32_t ICC_SRE_EL1_DIB = 1 << 2;
|
||||
|
||||
static const uint32_t ICC_SRE_EL2_SRE = 1 << 0;
|
||||
static const uint32_t ICC_SRE_EL2_DFB = 1 << 1;
|
||||
static const uint32_t ICC_SRE_EL2_DIB = 1 << 2;
|
||||
static const uint32_t ICC_SRE_EL2_ENABLE = 1 << 3;
|
||||
|
||||
static const uint32_t ICC_SRE_EL3_SRE = 1 << 0;
|
||||
static const uint32_t ICC_SRE_EL3_DFB = 1 << 1;
|
||||
static const uint32_t ICC_SRE_EL3_DIB = 1 << 2;
|
||||
static const uint32_t ICC_SRE_EL3_ENABLE = 1 << 3;
|
||||
|
||||
static const uint32_t ICC_CTLR_EL3_CBPR_EL1S = 1 << 0;
|
||||
static const uint32_t ICC_CTLR_EL3_CBPR_EL1NS = 1 << 1;
|
||||
static const uint32_t ICC_CTLR_EL3_EOIMODE_EL3 = 1 << 2;
|
||||
static const uint32_t ICC_CTLR_EL3_EOIMODE_EL1S = 1 << 3;
|
||||
static const uint32_t ICC_CTLR_EL3_EOIMODE_EL1NS = 1 << 4;
|
||||
static const uint32_t ICC_CTLR_EL3_RM = 1 << 5;
|
||||
static const uint32_t ICC_CTLR_EL3_PMHE = 1 << 6;
|
||||
static const uint32_t ICC_CTLR_EL3_PRIBITS_SHIFT = 8;
|
||||
static const uint32_t ICC_CTLR_EL3_IDBITS_SHIFT = 11;
|
||||
static const uint32_t ICC_CTLR_EL3_SEIS = 1 << 14;
|
||||
static const uint32_t ICC_CTLR_EL3_A3V = 1 << 15;
|
||||
static const uint32_t ICC_CTLR_EL3_nDS = 1 << 17;
|
||||
static const uint32_t ICC_CTLR_EL3_RSS = 1 << 18;
|
||||
|
||||
static const uint32_t ICC_CTLR_EL1_CBPR = 1 << 0;
|
||||
static const uint32_t ICC_CTLR_EL1_EOIMODE = 1 << 1;
|
||||
static const uint32_t ICC_CTLR_EL1_PMHE = 1 << 6;
|
||||
static const uint32_t ICC_CTLR_EL1_SEIS = 1 << 14;
|
||||
static const uint32_t ICC_CTLR_EL1_A3V = 1 << 15;
|
||||
static const uint32_t ICC_CTLR_EL1_RSS = 1 << 18;
|
||||
static const uint32_t ICC_CTLR_EL1_PRIBITS_SHIFT = 8;
|
||||
static const uint32_t ICC_CTLR_EL1_PRIBITS_MASK =
|
||||
7U << ICC_CTLR_EL1_PRIBITS_SHIFT;
|
||||
static const uint32_t ICC_CTLR_EL1_IDBITS_SHIFT = 11;
|
||||
|
||||
static const uint32_t ICC_IGRPEN0_EL1_ENABLE = 1 << 0;
|
||||
static const uint32_t ICC_IGRPEN1_EL1_ENABLE = 1 << 0;
|
||||
|
||||
static const uint32_t ICC_IGRPEN1_EL3_ENABLEGRP1NS = 1 << 0;
|
||||
static const uint32_t ICC_IGRPEN1_EL3_ENABLEGRP1S = 1 << 1;
|
||||
|
||||
static const uint8_t PRIORITY_BITS = 5;
|
||||
|
||||
/* Minimum BPR for Secure, or when security not enabled */
|
||||
static const uint8_t GIC_MIN_BPR = 2;
|
||||
/* Minimum BPR for Nonsecure when security is enabled */
|
||||
static const uint8_t GIC_MIN_BPR_NS = GIC_MIN_BPR + 1;
|
||||
|
||||
static const uint8_t VIRTUAL_PRIORITY_BITS = 5;
|
||||
static const uint8_t VIRTUAL_PREEMPTION_BITS = 5;
|
||||
static const uint8_t VIRTUAL_NUM_LIST_REGS = 16;
|
||||
|
||||
static const uint8_t GIC_MIN_VBPR = 7 - VIRTUAL_PREEMPTION_BITS;
|
||||
|
||||
typedef struct {
|
||||
uint32_t intid;
|
||||
uint8_t prio;
|
||||
Gicv3::GroupId group;
|
||||
} hppi_t;
|
||||
|
||||
hppi_t hppi;
|
||||
|
||||
// GIC CPU interface memory mapped control registers (legacy)
|
||||
enum {
|
||||
GICC_CTLR = 0x0000,
|
||||
GICC_PMR = 0x0004,
|
||||
GICC_BPR = 0x0008,
|
||||
GICC_IAR = 0x000C,
|
||||
GICC_EOIR = 0x0010,
|
||||
GICC_RPR = 0x0014,
|
||||
GICC_HPPI = 0x0018,
|
||||
GICC_ABPR = 0x001C,
|
||||
GICC_AIAR = 0x0020,
|
||||
GICC_AEOIR = 0x0024,
|
||||
GICC_AHPPIR = 0x0028,
|
||||
GICC_STATUSR = 0x002C,
|
||||
GICC_IIDR = 0x00FC,
|
||||
};
|
||||
|
||||
static const AddrRange GICC_APR;
|
||||
static const AddrRange GICC_NSAPR;
|
||||
|
||||
// GIC CPU virtual interface memory mapped control registers (legacy)
|
||||
enum {
|
||||
GICH_HCR = 0x0000,
|
||||
GICH_VTR = 0x0004,
|
||||
GICH_VMCR = 0x0008,
|
||||
GICH_MISR = 0x0010,
|
||||
GICH_EISR = 0x0020,
|
||||
GICH_ELRSR = 0x0030,
|
||||
};
|
||||
|
||||
static const AddrRange GICH_APR;
|
||||
static const AddrRange GICH_LR;
|
||||
|
||||
static const uint32_t ICH_HCR_EL2_EN = 1 << 0;
|
||||
static const uint32_t ICH_HCR_EL2_UIE = 1 << 1;
|
||||
static const uint32_t ICH_HCR_EL2_LRENPIE = 1 << 2;
|
||||
static const uint32_t ICH_HCR_EL2_NPIE = 1 << 3;
|
||||
static const uint32_t ICH_HCR_EL2_VGRP0EIE = 1 << 4;
|
||||
static const uint32_t ICH_HCR_EL2_VGRP0DIE = 1 << 5;
|
||||
static const uint32_t ICH_HCR_EL2_VGRP1EIE = 1 << 6;
|
||||
static const uint32_t ICH_HCR_EL2_VGRP1DIE = 1 << 7;
|
||||
static const uint32_t ICH_HCR_EL2_TC = 1 << 10;
|
||||
static const uint32_t ICH_HCR_EL2_TALL0 = 1 << 11;
|
||||
static const uint32_t ICH_HCR_EL2_TALL1 = 1 << 12;
|
||||
static const uint32_t ICH_HCR_EL2_TSEI = 1 << 13;
|
||||
static const uint32_t ICH_HCR_EL2_TDIR = 1 << 14;
|
||||
static const uint32_t ICH_HCR_EL2_EOICOUNT_MASK = 0x1fU << 27;
|
||||
|
||||
static const uint64_t ICH_LR_EL2_VINTID_SHIFT = 0;
|
||||
static const uint64_t ICH_LR_EL2_VINTID_LENGTH = 32;
|
||||
static const uint64_t ICH_LR_EL2_VINTID_MASK =
|
||||
(0xffffffffULL << ICH_LR_EL2_VINTID_SHIFT);
|
||||
static const uint64_t ICH_LR_EL2_PINTID_SHIFT = 32;
|
||||
static const uint64_t ICH_LR_EL2_PINTID_LENGTH = 10;
|
||||
static const uint64_t ICH_LR_EL2_PINTID_MASK =
|
||||
(0x3ffULL << ICH_LR_EL2_PINTID_SHIFT);
|
||||
/* Note that EOI shares with the top bit of the pINTID field */
|
||||
static const uint64_t ICH_LR_EL2_EOI = (1ULL << 41);
|
||||
static const uint64_t ICH_LR_EL2_PRIORITY_SHIFT = 48;
|
||||
static const uint64_t ICH_LR_EL2_PRIORITY_LENGTH = 8;
|
||||
static const uint64_t ICH_LR_EL2_PRIORITY_MASK =
|
||||
(0xffULL << ICH_LR_EL2_PRIORITY_SHIFT);
|
||||
static const uint64_t ICH_LR_EL2_GROUP = (1ULL << 60);
|
||||
static const uint64_t ICH_LR_EL2_HW = (1ULL << 61);
|
||||
static const uint64_t ICH_LR_EL2_STATE_SHIFT = 62;
|
||||
static const uint64_t ICH_LR_EL2_STATE_LENGTH = 2;
|
||||
static const uint64_t ICH_LR_EL2_STATE_MASK =
|
||||
(3ULL << ICH_LR_EL2_STATE_SHIFT);
|
||||
/* values for the state field: */
|
||||
static const uint64_t ICH_LR_EL2_STATE_INVALID = 0;
|
||||
static const uint64_t ICH_LR_EL2_STATE_PENDING = 1;
|
||||
static const uint64_t ICH_LR_EL2_STATE_ACTIVE = 2;
|
||||
static const uint64_t ICH_LR_EL2_STATE_ACTIVE_PENDING = 3;
|
||||
static const uint64_t ICH_LR_EL2_STATE_PENDING_BIT =
|
||||
(1ULL << ICH_LR_EL2_STATE_SHIFT);
|
||||
static const uint64_t ICH_LR_EL2_STATE_ACTIVE_BIT =
|
||||
(2ULL << ICH_LR_EL2_STATE_SHIFT);
|
||||
|
||||
static const uint64_t ICH_LRC_PRIORITY_SHIFT =
|
||||
ICH_LR_EL2_PRIORITY_SHIFT - 32;
|
||||
static const uint64_t ICH_LRC_PRIORITY_LENGTH =
|
||||
ICH_LR_EL2_PRIORITY_LENGTH;
|
||||
|
||||
static const uint32_t ICH_MISR_EL2_EOI = (1 << 0);
|
||||
static const uint32_t ICH_MISR_EL2_U = (1 << 1);
|
||||
static const uint32_t ICH_MISR_EL2_LRENP = (1 << 2);
|
||||
static const uint32_t ICH_MISR_EL2_NP = (1 << 3);
|
||||
static const uint32_t ICH_MISR_EL2_VGRP0E = (1 << 4);
|
||||
static const uint32_t ICH_MISR_EL2_VGRP0D = (1 << 5);
|
||||
static const uint32_t ICH_MISR_EL2_VGRP1E = (1 << 6);
|
||||
static const uint32_t ICH_MISR_EL2_VGRP1D = (1 << 7);
|
||||
|
||||
static const uint32_t ICH_VMCR_EL2_VENG0_SHIFT = 0;
|
||||
static const uint32_t ICH_VMCR_EL2_VENG0 =
|
||||
(1 << ICH_VMCR_EL2_VENG0_SHIFT);
|
||||
static const uint32_t ICH_VMCR_EL2_VENG1_SHIFT = 1;
|
||||
static const uint32_t ICH_VMCR_EL2_VENG1 =
|
||||
(1 << ICH_VMCR_EL2_VENG1_SHIFT);
|
||||
static const uint32_t ICH_VMCR_EL2_VACKCTL = (1 << 2);
|
||||
static const uint32_t ICH_VMCR_EL2_VFIQEN = (1 << 3);
|
||||
static const uint32_t ICH_VMCR_EL2_VCBPR_SHIFT = 4;
|
||||
static const uint32_t ICH_VMCR_EL2_VCBPR =
|
||||
(1 << ICH_VMCR_EL2_VCBPR_SHIFT);
|
||||
static const uint32_t ICH_VMCR_EL2_VEOIM_SHIFT = 9;
|
||||
static const uint32_t ICH_VMCR_EL2_VEOIM =
|
||||
(1 << ICH_VMCR_EL2_VEOIM_SHIFT);
|
||||
static const uint32_t ICH_VMCR_EL2_VBPR1_SHIFT = 18;
|
||||
static const uint32_t ICH_VMCR_EL2_VBPR1_LENGTH = 3;
|
||||
static const uint32_t ICH_VMCR_EL2_VBPR1_MASK =
|
||||
(0x7U << ICH_VMCR_EL2_VBPR1_SHIFT);
|
||||
static const uint32_t ICH_VMCR_EL2_VBPR0_SHIFT = 21;
|
||||
static const uint32_t ICH_VMCR_EL2_VBPR0_LENGTH = 3;
|
||||
static const uint32_t ICH_VMCR_EL2_VBPR0_MASK =
|
||||
(0x7U << ICH_VMCR_EL2_VBPR0_SHIFT);
|
||||
static const uint32_t ICH_VMCR_EL2_VPMR_SHIFT = 24;
|
||||
static const uint32_t ICH_VMCR_EL2_VPMR_LENGTH = 8;
|
||||
static const uint32_t ICH_VMCR_EL2_VPMR_MASK =
|
||||
(0xffU << ICH_VMCR_EL2_VPMR_SHIFT);
|
||||
|
||||
static const uint32_t ICH_VTR_EL2_LISTREGS_SHIFT = 0;
|
||||
static const uint32_t ICH_VTR_EL2_TDS = 1 << 19;
|
||||
static const uint32_t ICH_VTR_EL2_NV4 = 1 << 20;
|
||||
static const uint32_t ICH_VTR_EL2_A3V = 1 << 21;
|
||||
static const uint32_t ICH_VTR_EL2_SEIS = 1 << 22;
|
||||
static const uint32_t ICH_VTR_EL2_IDBITS_SHIFT = 23;
|
||||
static const uint32_t ICH_VTR_EL2_PREBITS_SHIFT = 26;
|
||||
static const uint32_t ICH_VTR_EL2_PRIBITS_SHIFT = 29;
|
||||
|
||||
public:
|
||||
|
||||
Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id);
|
||||
~Gicv3CPUInterface();
|
||||
void init();
|
||||
void initState();
|
||||
|
||||
ArmISA::MiscReg readMiscReg(int misc_reg) override;
|
||||
void setMiscReg(int misc_reg, ArmISA::MiscReg val) override;
|
||||
void update();
|
||||
void virtualUpdate();
|
||||
|
||||
void serialize(CheckpointOut & cp) const override;
|
||||
void unserialize(CheckpointIn & cp) override;
|
||||
|
||||
protected:
|
||||
|
||||
void reset();
|
||||
bool hppiCanPreempt();
|
||||
bool hppviCanPreempt(int lrIdx);
|
||||
bool groupEnabled(Gicv3::GroupId group);
|
||||
uint8_t highestActivePriority();
|
||||
uint8_t virtualHighestActivePriority();
|
||||
bool inSecureState();
|
||||
int currEL();
|
||||
bool haveEL(ArmISA::ExceptionLevel el);
|
||||
void activateIRQ(uint32_t intid, Gicv3::GroupId group);
|
||||
void virtualActivateIRQ(uint32_t lrIdx);
|
||||
void deactivateIRQ(uint32_t intid, Gicv3::GroupId group);
|
||||
void virtualDeactivateIRQ(int lrIdx);
|
||||
uint32_t groupPriorityMask(Gicv3::GroupId group);
|
||||
uint32_t virtualGroupPriorityMask(Gicv3::GroupId group);
|
||||
void dropPriority(Gicv3::GroupId group);
|
||||
uint8_t virtualDropPriority();
|
||||
ArmISA::InterruptTypes intSignalType(Gicv3::GroupId group);
|
||||
bool isEOISplitMode();
|
||||
bool virtualIsEOISplitMode();
|
||||
bool isSecureBelowEL3();
|
||||
bool inSecureState2();
|
||||
uint32_t eoiMaintenanceInterruptStatus(uint32_t * misr);
|
||||
uint32_t maintenanceInterruptStatus();
|
||||
int highestActiveGroup();
|
||||
bool getHCREL2FMO();
|
||||
bool getHCREL2IMO();
|
||||
uint32_t getHPPIR1();
|
||||
uint32_t getHPPIR0();
|
||||
int getHPPVILR();
|
||||
int virtualFindActive(uint32_t intid);
|
||||
void virtualIncrementEOICount();
|
||||
bool isEL3OrMon();
|
||||
bool isAA64();
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_GICV3_CPU_INTERFACE_H__
|
||||
1132
src/dev/arm/gic_v3_distributor.cc
Normal file
1132
src/dev/arm/gic_v3_distributor.cc
Normal file
File diff suppressed because it is too large
Load Diff
218
src/dev/arm/gic_v3_distributor.hh
Normal file
218
src/dev/arm/gic_v3_distributor.hh
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Metempsy Technology Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Jairo Balart
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_GICV3_DISTRIBUTOR_H__
|
||||
#define __DEV_ARM_GICV3_DISTRIBUTOR_H__
|
||||
|
||||
#include "base/addr_range.hh"
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
class Gicv3Distributor : public Serializable
|
||||
{
|
||||
private:
|
||||
|
||||
friend class Gicv3Redistributor;
|
||||
friend class Gicv3CPUInterface;
|
||||
|
||||
protected:
|
||||
|
||||
Gicv3 * gic;
|
||||
const uint32_t itLines;
|
||||
|
||||
enum {
|
||||
// Control Register
|
||||
GICD_CTLR = 0x0000,
|
||||
// Interrupt Controller Type Register
|
||||
GICD_TYPER = 0x0004,
|
||||
// Implementer Identification Register
|
||||
GICD_IIDR = 0x0008,
|
||||
// Error Reporting Status Register
|
||||
GICD_STATUSR = 0x0010,
|
||||
// Peripheral ID0 Register
|
||||
GICD_PIDR0 = 0xffe0,
|
||||
// Peripheral ID1 Register
|
||||
GICD_PIDR1 = 0xffe4,
|
||||
// Peripheral ID2 Register
|
||||
GICD_PIDR2 = 0xffe8,
|
||||
// Peripheral ID3 Register
|
||||
GICD_PIDR3 = 0xffec,
|
||||
// Peripheral ID4 Register
|
||||
GICD_PIDR4 = 0xffd0,
|
||||
// Peripheral ID5 Register
|
||||
GICD_PIDR5 = 0xffd4,
|
||||
// Peripheral ID6 Register
|
||||
GICD_PIDR6 = 0xffd8,
|
||||
// Peripheral ID7 Register
|
||||
GICD_PIDR7 = 0xffdc,
|
||||
};
|
||||
|
||||
// Interrupt Group Registers
|
||||
static const AddrRange GICD_IGROUPR;
|
||||
// Interrupt Set-Enable Registers
|
||||
static const AddrRange GICD_ISENABLER;
|
||||
// Interrupt Clear-Enable Registers
|
||||
static const AddrRange GICD_ICENABLER;
|
||||
// Interrupt Set-Pending Registers
|
||||
static const AddrRange GICD_ISPENDR;
|
||||
// Interrupt Clear-Pending Registers
|
||||
static const AddrRange GICD_ICPENDR;
|
||||
// Interrupt Set-Active Registers
|
||||
static const AddrRange GICD_ISACTIVER;
|
||||
// Interrupt Clear-Active Registers
|
||||
static const AddrRange GICD_ICACTIVER;
|
||||
// Interrupt Priority Registers
|
||||
static const AddrRange GICD_IPRIORITYR;
|
||||
// Interrupt Processor Targets Registers
|
||||
static const AddrRange GICD_ITARGETSR; // GICv2 legacy
|
||||
// Interrupt Configuration Registers
|
||||
static const AddrRange GICD_ICFGR;
|
||||
// Interrupt Group Modifier Registers
|
||||
static const AddrRange GICD_IGRPMODR;
|
||||
// Non-secure Access Control Registers
|
||||
static const AddrRange GICD_NSACR;
|
||||
// SGI Clear-Pending Registers
|
||||
static const AddrRange GICD_CPENDSGIR; // GICv2 legacy
|
||||
// SGI Set-Pending Registers
|
||||
static const AddrRange GICD_SPENDSGIR; // GICv2 legacy
|
||||
// Interrupt Routing Registers
|
||||
static const AddrRange GICD_IROUTER;
|
||||
|
||||
BitUnion64(IROUTER)
|
||||
Bitfield<63, 40> res0_1;
|
||||
Bitfield<39, 32> Aff3;
|
||||
Bitfield<31> IRM;
|
||||
Bitfield<30, 24> res0_2;
|
||||
Bitfield<23, 16> Aff2;
|
||||
Bitfield<15, 8> Aff1;
|
||||
Bitfield<7, 0> Aff0;
|
||||
EndBitUnion(IROUTER)
|
||||
|
||||
static const uint32_t GICD_CTLR_ENABLEGRP0 = 1 << 0;
|
||||
static const uint32_t GICD_CTLR_ENABLEGRP1NS = 1 << 1;
|
||||
static const uint32_t GICD_CTLR_ENABLEGRP1S = 1 << 2;
|
||||
static const uint32_t GICD_CTLR_ENABLEGRP1 = 1 << 0;
|
||||
static const uint32_t GICD_CTLR_ENABLEGRP1A = 1 << 1;
|
||||
static const uint32_t GICD_CTLR_DS = 1 << 6;
|
||||
|
||||
bool ARE;
|
||||
bool DS;
|
||||
bool EnableGrp1S;
|
||||
bool EnableGrp1NS;
|
||||
bool EnableGrp0;
|
||||
std::vector <uint8_t> irqGroup;
|
||||
std::vector <bool> irqEnabled;
|
||||
std::vector <bool> irqPending;
|
||||
std::vector <bool> irqActive;
|
||||
std::vector <uint8_t> irqPriority;
|
||||
std::vector <Gicv3::IntTriggerType> irqConfig;
|
||||
std::vector <uint8_t> irqGrpmod;
|
||||
std::vector <uint8_t> irqNsacr;
|
||||
std::vector <IROUTER> irqAffinityRouting;
|
||||
|
||||
public:
|
||||
|
||||
static const uint32_t ADDR_RANGE_SIZE = 0x10000;
|
||||
|
||||
Gicv3Distributor(Gicv3 * gic, uint32_t it_lines);
|
||||
~Gicv3Distributor();
|
||||
void init();
|
||||
void initState();
|
||||
|
||||
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 serialize(CheckpointOut & cp) const override;
|
||||
void unserialize(CheckpointIn & cp) override;
|
||||
|
||||
bool
|
||||
groupEnabled(Gicv3::GroupId group)
|
||||
{
|
||||
if (DS == 0) {
|
||||
switch (group) {
|
||||
case Gicv3::G0S:
|
||||
return EnableGrp0;
|
||||
|
||||
case Gicv3::G1S:
|
||||
return EnableGrp1S;
|
||||
|
||||
case Gicv3::G1NS:
|
||||
return EnableGrp1NS;
|
||||
|
||||
default:
|
||||
panic("Gicv3Distributor::groupEnabled(): "
|
||||
"invalid group!\n");
|
||||
}
|
||||
} else {
|
||||
switch (group) {
|
||||
case Gicv3::G0S:
|
||||
return EnableGrp0;
|
||||
|
||||
case Gicv3::G1S:
|
||||
case Gicv3::G1NS:
|
||||
return EnableGrp1NS;
|
||||
|
||||
default:
|
||||
panic("Gicv3Distributor::groupEnabled(): "
|
||||
"invalid group!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendInt(uint32_t int_id);
|
||||
void intDeasserted(uint32_t int_id);
|
||||
Gicv3::IntStatus intStatus(uint32_t int_id);
|
||||
void updateAndInformCPUInterfaces();
|
||||
void update();
|
||||
void fullUpdate();
|
||||
void activateIRQ(uint32_t int_id);
|
||||
void deactivateIRQ(uint32_t int_id);
|
||||
|
||||
inline bool isNotSPI(uint8_t int_id)
|
||||
{
|
||||
if (int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX) || int_id >= itLines) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool nsAccessToSecInt(uint8_t int_id, bool is_secure_access)
|
||||
{
|
||||
return !DS && !is_secure_access && getIntGroup(int_id) != Gicv3::G1NS;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void reset();
|
||||
Gicv3::GroupId getIntGroup(int int_id);
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_GICV3_DISTRIBUTOR_H__
|
||||
834
src/dev/arm/gic_v3_redistributor.cc
Normal file
834
src/dev/arm/gic_v3_redistributor.cc
Normal file
@@ -0,0 +1,834 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Metempsy Technology Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Jairo Balart
|
||||
*/
|
||||
|
||||
#include "dev/arm/gic_v3_redistributor.hh"
|
||||
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "debug/GIC.hh"
|
||||
#include "dev/arm/gic_v3_cpu_interface.hh"
|
||||
#include "dev/arm/gic_v3_distributor.hh"
|
||||
|
||||
const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
|
||||
SGI_base + 0x041f);
|
||||
|
||||
Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
|
||||
: gic(gic),
|
||||
distributor(nullptr),
|
||||
cpuInterface(nullptr),
|
||||
cpuId(cpu_id),
|
||||
irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
|
||||
irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
Gicv3Redistributor::~Gicv3Redistributor()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::init()
|
||||
{
|
||||
distributor = gic->getDistributor();
|
||||
cpuInterface = gic->getCPUInterface(cpuId);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::initState()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::reset()
|
||||
{
|
||||
peInLowPowerState = true;
|
||||
std::fill(irqGroup.begin(), irqGroup.end(), 0);
|
||||
std::fill(irqEnabled.begin(), irqEnabled.end(), false);
|
||||
std::fill(irqPending.begin(), irqPending.end(), false);
|
||||
std::fill(irqActive.begin(), irqActive.end(), false);
|
||||
std::fill(irqPriority.begin(), irqPriority.end(), 0);
|
||||
|
||||
// SGIs have edge-triggered behavior
|
||||
for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
|
||||
irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
|
||||
}
|
||||
|
||||
std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
|
||||
std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
|
||||
DPG1S = false;
|
||||
DPG1NS = false;
|
||||
DPG0 = false;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
|
||||
{
|
||||
if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
|
||||
uint64_t value = 0;
|
||||
int first_intid = addr - GICR_IPRIORITYR.start();
|
||||
|
||||
for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
|
||||
uint8_t prio = irqPriority[int_id];
|
||||
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
continue;
|
||||
} else {
|
||||
// NS view
|
||||
prio = (prio << 1) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
value |= prio << (i * 8);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
switch (addr) {
|
||||
case GICR_CTLR: { // Control Register
|
||||
uint64_t value = 0;
|
||||
|
||||
if (DPG1S) {
|
||||
value |= GICR_CTLR_DPG1S;
|
||||
}
|
||||
|
||||
if (DPG1NS) {
|
||||
value |= GICR_CTLR_DPG1NS;
|
||||
}
|
||||
|
||||
if (DPG0) {
|
||||
value |= GICR_CTLR_DPG0;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_IIDR: // Implementer Identification Register
|
||||
//return 0x43b; // r0p0 GIC-500
|
||||
return 0;
|
||||
|
||||
case GICR_TYPER: { // Type Register
|
||||
/*
|
||||
* Affinity_Value [63:32] == X
|
||||
* (The identity of the PE associated with this Redistributor)
|
||||
* CommonLPIAff [25:24] == 01
|
||||
* (All Redistributors with the same Aff3 value must share an
|
||||
* LPI Configuration table)
|
||||
* Processor_Number [23:8] == X
|
||||
* (A unique identifier for the PE)
|
||||
* DPGS [5] == 1
|
||||
* (GICR_CTLR.DPG* bits are supported)
|
||||
* Last [4] == X
|
||||
* (This Redistributor is the highest-numbered Redistributor in
|
||||
* a series of contiguous Redistributor pages)
|
||||
* DirectLPI [3] == 0
|
||||
* (direct injection of LPIs not supported)
|
||||
* VLPIS [1] == 0
|
||||
* (virtual LPIs not supported)
|
||||
* PLPIS [0] == 0
|
||||
* (physical LPIs not supported)
|
||||
*/
|
||||
uint64_t affinity = getAffinity();
|
||||
int last = cpuId == (gic->getSystem()->numContexts() - 1);
|
||||
return (affinity << 32) | (1 << 24) | (cpuId << 8) |
|
||||
(1 << 5) | (last << 4);
|
||||
}
|
||||
|
||||
case GICR_WAKER: // Wake Register
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peInLowPowerState) {
|
||||
return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case GICR_PIDR0: { // Peripheral ID0 Register
|
||||
uint8_t part_0 = 0x92; // Part number, bits[7:0]
|
||||
return part_0;
|
||||
}
|
||||
|
||||
case GICR_PIDR1: { // Peripheral ID1 Register
|
||||
uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
|
||||
uint8_t part_1 = 0x4; // Part number, bits[11:8]
|
||||
return (des_0 << 4) | (part_1 << 0);
|
||||
}
|
||||
|
||||
case GICR_PIDR2: { // Peripheral ID2 Register
|
||||
uint8_t arch_rev = 0x3; // 0x3 GICv3
|
||||
uint8_t jedec = 0x1; // JEP code
|
||||
uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
|
||||
return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
|
||||
}
|
||||
|
||||
case GICR_PIDR3: // Peripheral ID3 Register
|
||||
return 0x0; // Implementation defined
|
||||
|
||||
case GICR_PIDR4: { // Peripheral ID4 Register
|
||||
uint8_t size = 0x4; // 64 KB software visible page
|
||||
uint8_t des_2 = 0x4; // ARM implementation
|
||||
return (size << 4) | (des_2 << 0);
|
||||
}
|
||||
|
||||
case GICR_PIDR5: // Peripheral ID5 Register
|
||||
case GICR_PIDR6: // Peripheral ID6 Register
|
||||
case GICR_PIDR7: // Peripheral ID7 Register
|
||||
return 0; // RES0
|
||||
|
||||
case GICR_IGROUPR0: { // Interrupt Group Register 0
|
||||
uint64_t value = 0;
|
||||
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
value |= (irqGroup[int_id] << int_id);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
|
||||
case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
|
||||
uint64_t value = 0;
|
||||
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (irqEnabled[int_id]) {
|
||||
value |= (1 << int_id);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
|
||||
case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
|
||||
uint64_t value = 0;
|
||||
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
value |= (irqPending[int_id] << int_id);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
|
||||
case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
|
||||
uint64_t value = 0;
|
||||
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
value |= irqActive[int_id] << int_id;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_ICFGR0: // SGI Configuration Register
|
||||
case GICR_ICFGR1: { // PPI Configuration Register
|
||||
uint64_t value = 0;
|
||||
uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
|
||||
|
||||
for (int i = 0, int_id = first_int_id; i < 32;
|
||||
i = i + 2, int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
|
||||
value |= (0x2) << i;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
|
||||
uint64_t value = 0;
|
||||
|
||||
if (distributor->DS) {
|
||||
value = 0;
|
||||
} else {
|
||||
if (!is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses
|
||||
value = 0;
|
||||
} else {
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
value |= irqGrpmod[int_id] << int_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case GICR_NSACR: { // Non-secure Access Control Register
|
||||
uint64_t value = 0;
|
||||
|
||||
if (distributor->DS) {
|
||||
// RAZ/WI
|
||||
value = 0;
|
||||
} else {
|
||||
if (!is_secure_access) {
|
||||
// RAZ/WI
|
||||
value = 0;
|
||||
} else {
|
||||
for (int i = 0, int_id = 0; i < 8 * size;
|
||||
i = i + 2, int_id++) {
|
||||
value |= irqNsacr[int_id] << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
|
||||
bool is_secure_access)
|
||||
{
|
||||
if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
|
||||
int first_intid = addr - GICR_IPRIORITYR.start();
|
||||
|
||||
for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
|
||||
uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
|
||||
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
continue;
|
||||
} else {
|
||||
// NS view
|
||||
prio = 0x80 | (prio >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
irqPriority[int_id] = prio;
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d priority %d\n", int_id, irqPriority[int_id]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (addr) {
|
||||
case GICR_CTLR: {
|
||||
// GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
|
||||
DPG1S = data & GICR_CTLR_DPG1S;
|
||||
DPG1NS = data & GICR_CTLR_DPG1NS;
|
||||
DPG0 = data & GICR_CTLR_DPG0;
|
||||
break;
|
||||
}
|
||||
|
||||
case GICR_WAKER: // Wake Register
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses
|
||||
return;
|
||||
}
|
||||
|
||||
if (not peInLowPowerState and
|
||||
(data & GICR_WAKER_ProcessorSleep)) {
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"PE entering in low power state\n");
|
||||
} else if (peInLowPowerState and
|
||||
not(data & GICR_WAKER_ProcessorSleep)) {
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
|
||||
}
|
||||
|
||||
peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
|
||||
break;
|
||||
|
||||
case GICR_IGROUPR0: // Interrupt Group Register 0
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses
|
||||
return;
|
||||
}
|
||||
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d group %d\n", int_id, irqGroup[int_id]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool enable = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (enable) {
|
||||
irqEnabled[int_id] = true;
|
||||
}
|
||||
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d enable %i\n", int_id, irqEnabled[int_id]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool disable = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (disable) {
|
||||
irqEnabled[int_id] = false;
|
||||
}
|
||||
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d enable %i\n", int_id, irqEnabled[int_id]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool pending = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (pending) {
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write() "
|
||||
"(GICR_ISPENDR0): int_id %d (PPI) "
|
||||
"pending bit set\n", int_id);
|
||||
irqPending[int_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
updateAndInformCPUInterface();
|
||||
break;
|
||||
|
||||
case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool clear = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (clear) {
|
||||
irqPending[int_id] = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool activate = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (activate) {
|
||||
if (!irqActive[int_id]) {
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d active set\n", int_id);
|
||||
}
|
||||
|
||||
irqActive[int_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool clear = data & (1 << int_id) ? 1 : 0;
|
||||
|
||||
if (clear) {
|
||||
if (irqActive[int_id]) {
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d active cleared\n", int_id);
|
||||
}
|
||||
|
||||
irqActive[int_id] = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GICR_ICFGR1: { // PPI Configuration Register
|
||||
int first_intid = Gicv3::SGI_MAX;
|
||||
|
||||
for (int i = 0, int_id = first_intid; i < 8 * size;
|
||||
i = i + 2, int_id++) {
|
||||
if (!distributor->DS && !is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses for secure interrupts
|
||||
if (getIntGroup(int_id) != Gicv3::G1NS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
irqConfig[int_id] = data & (0x2 << i)
|
||||
? Gicv3::INT_EDGE_TRIGGERED :
|
||||
Gicv3::INT_LEVEL_SENSITIVE;
|
||||
DPRINTF(GIC, "Gicv3Redistributor::write(): "
|
||||
"int_id %d (PPI) config %d\n",
|
||||
int_id, irqConfig[int_id]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
|
||||
if (distributor->DS) {
|
||||
// RAZ/WI if secutiry disabled
|
||||
} else {
|
||||
for (int int_id = 0; int_id < 8 * size; int_id++) {
|
||||
if (!is_secure_access) {
|
||||
// RAZ/WI for non-secure accesses
|
||||
continue;
|
||||
}
|
||||
|
||||
irqGrpmod[int_id] = data & (1 << int_id);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GICR_NSACR: { // Non-secure Access Control Register
|
||||
if (distributor->DS) {
|
||||
// RAZ/WI
|
||||
} else {
|
||||
if (!is_secure_access) {
|
||||
// RAZ/WI
|
||||
} else {
|
||||
for (int i = 0, int_id = 0; i < 8 * size;
|
||||
i = i + 2, int_id++) {
|
||||
irqNsacr[int_id] = (data >> i) & 0x3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::sendPPInt(uint32_t int_id)
|
||||
{
|
||||
assert((int_id >= Gicv3::SGI_MAX) &&
|
||||
(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
|
||||
irqPending[int_id] = true;
|
||||
DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
|
||||
"int_id %d (PPI) pending bit set\n", int_id);
|
||||
updateAndInformCPUInterface();
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
|
||||
{
|
||||
assert(int_id < Gicv3::SGI_MAX);
|
||||
Gicv3::GroupId int_group = getIntGroup(int_id);
|
||||
|
||||
// asked for secure group 1
|
||||
// configured as group 0
|
||||
// send group 0
|
||||
if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
|
||||
group = Gicv3::G0S;
|
||||
}
|
||||
|
||||
if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ns && distributor->DS == 0) {
|
||||
int nsaccess = irqNsacr[int_id];
|
||||
|
||||
if ((int_group == Gicv3::G0S && nsaccess < 1) ||
|
||||
(int_group == Gicv3::G1S && nsaccess < 2)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
irqPending[int_id] = true;
|
||||
DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
|
||||
"int_id %d (SGI) pending bit set\n", int_id);
|
||||
updateAndInformCPUInterface();
|
||||
}
|
||||
|
||||
Gicv3::IntStatus
|
||||
Gicv3Redistributor::intStatus(uint32_t int_id)
|
||||
{
|
||||
assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
|
||||
|
||||
if (irqPending[int_id]) {
|
||||
if (irqActive[int_id]) {
|
||||
return Gicv3::INT_ACTIVE_PENDING;
|
||||
}
|
||||
|
||||
return Gicv3::INT_PENDING;
|
||||
} else if (irqActive[int_id]) {
|
||||
return Gicv3::INT_ACTIVE;
|
||||
} else {
|
||||
return Gicv3::INT_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Recalculate the highest priority pending interrupt after a
|
||||
* change to redistributor state.
|
||||
*/
|
||||
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);
|
||||
|
||||
if (irqPending[int_id] && irqEnabled[int_id] &&
|
||||
!irqActive[int_id] && group_enabled) {
|
||||
if ((irqPriority[int_id] < cpuInterface->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] == cpuInterface->hppi.prio &&
|
||||
int_id < cpuInterface->hppi.intid)) {
|
||||
cpuInterface->hppi.intid = int_id;
|
||||
cpuInterface->hppi.prio = irqPriority[int_id];
|
||||
cpuInterface->hppi.group = int_group;
|
||||
new_hppi = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
|
||||
cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
|
||||
distributor->fullUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::updateAndInformCPUInterface()
|
||||
{
|
||||
update();
|
||||
cpuInterface->update();
|
||||
}
|
||||
|
||||
Gicv3::GroupId
|
||||
Gicv3Redistributor::getIntGroup(int int_id)
|
||||
{
|
||||
assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
|
||||
|
||||
if (distributor->DS) {
|
||||
if (irqGroup[int_id] == 0) {
|
||||
return Gicv3::G0S;
|
||||
} else {
|
||||
return Gicv3::G1NS;
|
||||
}
|
||||
} else {
|
||||
if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
|
||||
return Gicv3::G0S;
|
||||
} else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
|
||||
return Gicv3::G1NS;
|
||||
} else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
|
||||
return Gicv3::G1S;
|
||||
} else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
|
||||
return Gicv3::G1NS;
|
||||
}
|
||||
}
|
||||
|
||||
M5_UNREACHABLE;
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::activateIRQ(uint32_t int_id)
|
||||
{
|
||||
irqPending[int_id] = false;
|
||||
irqActive[int_id] = true;
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
|
||||
{
|
||||
irqActive[int_id] = false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Gicv3Redistributor::getAffinity()
|
||||
{
|
||||
ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
|
||||
uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
|
||||
/*
|
||||
* Aff3 = MPIDR[39:32]
|
||||
* (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
|
||||
* Aff2 = MPIDR[23:16]
|
||||
* Aff1 = MPIDR[15:8]
|
||||
* Aff0 = MPIDR[7:0]
|
||||
* affinity = Aff3.Aff2.Aff1.Aff0
|
||||
*/
|
||||
uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
|
||||
return affinity;
|
||||
}
|
||||
|
||||
bool
|
||||
Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group)
|
||||
{
|
||||
if (peInLowPowerState) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!distributor->groupEnabled(group)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((group == Gicv3::G1S) && DPG1S) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((group == Gicv3::G1NS) && DPG1NS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((group == Gicv3::G0S) && DPG0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::serialize(CheckpointOut & cp) const
|
||||
{
|
||||
SERIALIZE_SCALAR(peInLowPowerState);
|
||||
SERIALIZE_CONTAINER(irqGroup);
|
||||
SERIALIZE_CONTAINER(irqEnabled);
|
||||
SERIALIZE_CONTAINER(irqPending);
|
||||
SERIALIZE_CONTAINER(irqActive);
|
||||
SERIALIZE_CONTAINER(irqPriority);
|
||||
SERIALIZE_CONTAINER(irqConfig);
|
||||
SERIALIZE_CONTAINER(irqGrpmod);
|
||||
SERIALIZE_CONTAINER(irqNsacr);
|
||||
SERIALIZE_SCALAR(DPG1S);
|
||||
SERIALIZE_SCALAR(DPG1NS);
|
||||
SERIALIZE_SCALAR(DPG0);
|
||||
}
|
||||
|
||||
void
|
||||
Gicv3Redistributor::unserialize(CheckpointIn & cp)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(peInLowPowerState);
|
||||
UNSERIALIZE_CONTAINER(irqGroup);
|
||||
UNSERIALIZE_CONTAINER(irqEnabled);
|
||||
UNSERIALIZE_CONTAINER(irqPending);
|
||||
UNSERIALIZE_CONTAINER(irqActive);
|
||||
UNSERIALIZE_CONTAINER(irqPriority);
|
||||
UNSERIALIZE_CONTAINER(irqConfig);
|
||||
UNSERIALIZE_CONTAINER(irqGrpmod);
|
||||
UNSERIALIZE_CONTAINER(irqNsacr);
|
||||
UNSERIALIZE_SCALAR(DPG1S);
|
||||
UNSERIALIZE_SCALAR(DPG1NS);
|
||||
UNSERIALIZE_SCALAR(DPG0);
|
||||
}
|
||||
183
src/dev/arm/gic_v3_redistributor.hh
Normal file
183
src/dev/arm/gic_v3_redistributor.hh
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Metempsy Technology Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Jairo Balart
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_GICV3_REDISTRIBUTOR_H__
|
||||
#define __DEV_ARM_GICV3_REDISTRIBUTOR_H__
|
||||
|
||||
#include "base/addr_range.hh"
|
||||
#include "dev/arm/gic_v3.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
class Gicv3Distributor;
|
||||
class Gicv3CPUInterface;
|
||||
|
||||
class Gicv3Redistributor : public Serializable
|
||||
{
|
||||
private:
|
||||
|
||||
friend class Gicv3CPUInterface;
|
||||
friend class Gicv3Distributor;
|
||||
|
||||
protected:
|
||||
|
||||
Gicv3 * gic;
|
||||
Gicv3Distributor * distributor;
|
||||
Gicv3CPUInterface * cpuInterface;
|
||||
uint32_t cpuId;
|
||||
|
||||
/*
|
||||
* GICv3 defines 2 contiguous 64KB frames for each redistributor.
|
||||
* Order of frames must be RD_base, SGI_base.
|
||||
*/
|
||||
static const uint32_t RD_base = 0x0;
|
||||
static const uint32_t SGI_base = 0x10000;
|
||||
|
||||
enum {
|
||||
// Control Register
|
||||
GICR_CTLR = RD_base + 0x0000,
|
||||
// Implementer Identification Register
|
||||
GICR_IIDR = RD_base + 0x0004,
|
||||
// Type Register
|
||||
GICR_TYPER = RD_base + 0x0008,
|
||||
// Wake Register
|
||||
GICR_WAKER = RD_base + 0x0014,
|
||||
// Peripheral ID0 Register
|
||||
GICR_PIDR0 = RD_base + 0xffe0,
|
||||
// Peripheral ID1 Register
|
||||
GICR_PIDR1 = RD_base + 0xffe4,
|
||||
// Peripheral ID2 Register
|
||||
GICR_PIDR2 = RD_base + 0xffe8,
|
||||
// Peripheral ID3 Register
|
||||
GICR_PIDR3 = RD_base + 0xffec,
|
||||
// Peripheral ID4 Register
|
||||
GICR_PIDR4 = RD_base + 0xffd0,
|
||||
// Peripheral ID5 Register
|
||||
GICR_PIDR5 = RD_base + 0xffd4,
|
||||
// Peripheral ID6 Register
|
||||
GICR_PIDR6 = RD_base + 0xffd8,
|
||||
// Peripheral ID7 Register
|
||||
GICR_PIDR7 = RD_base + 0xffdc,
|
||||
};
|
||||
|
||||
static const uint32_t GICR_WAKER_ProcessorSleep = 1 << 1;
|
||||
static const uint32_t GICR_WAKER_ChildrenAsleep = 1 << 2;
|
||||
|
||||
bool peInLowPowerState;
|
||||
|
||||
enum {
|
||||
// Interrupt Group Register 0
|
||||
GICR_IGROUPR0 = SGI_base + 0x0080,
|
||||
// Interrupt Set-Enable Register 0
|
||||
GICR_ISENABLER0 = SGI_base + 0x0100,
|
||||
// Interrupt Clear-Enable Register 0
|
||||
GICR_ICENABLER0 = SGI_base + 0x0180,
|
||||
// Interrupt Set-Pending Register 0
|
||||
GICR_ISPENDR0 = SGI_base + 0x0200,
|
||||
// Interrupt Clear-Pending Register 0
|
||||
GICR_ICPENDR0 = SGI_base + 0x0280,
|
||||
// Interrupt Set-Active Register 0
|
||||
GICR_ISACTIVER0 = SGI_base + 0x0300,
|
||||
// Interrupt Clear-Active Register 0
|
||||
GICR_ICACTIVER0 = SGI_base + 0x0380,
|
||||
// SGI Configuration Register
|
||||
GICR_ICFGR0 = SGI_base + 0x0c00,
|
||||
// PPI Configuration Register
|
||||
GICR_ICFGR1 = SGI_base + 0x0c04,
|
||||
// Interrupt Group Modifier Register 0
|
||||
GICR_IGRPMODR0 = SGI_base + 0x0d00,
|
||||
// Non-secure Access Control Register
|
||||
GICR_NSACR = SGI_base + 0x0e00,
|
||||
};
|
||||
|
||||
// Interrupt Priority Registers
|
||||
static const AddrRange GICR_IPRIORITYR;
|
||||
|
||||
std::vector <uint8_t> irqGroup;
|
||||
std::vector <bool> irqEnabled;
|
||||
std::vector <bool> irqPending;
|
||||
std::vector <bool> irqActive;
|
||||
std::vector <uint8_t> irqPriority;
|
||||
std::vector <Gicv3::IntTriggerType> irqConfig;
|
||||
std::vector <uint8_t> irqGrpmod;
|
||||
std::vector <uint8_t> irqNsacr;
|
||||
|
||||
bool DPG1S;
|
||||
bool DPG1NS;
|
||||
bool DPG0;
|
||||
|
||||
static const uint32_t GICR_CTLR_DPG0 = 1 << 24;
|
||||
static const uint32_t GICR_CTLR_DPG1NS = 1 << 25;
|
||||
static const uint32_t GICR_CTLR_DPG1S = 1 << 26;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* GICv3 defines only 2 64K consecutive frames for the redistributor
|
||||
* (RD_base and SGI_base) but we are using 2 extra 64K stride frames
|
||||
* to match GICv4 that defines 4 64K consecutive frames for them.
|
||||
* Note this must match with DTB/DTS GIC node definition and boot
|
||||
* loader code.
|
||||
*/
|
||||
static const uint32_t ADDR_RANGE_SIZE = 0x40000;
|
||||
|
||||
Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id);
|
||||
~Gicv3Redistributor();
|
||||
void init();
|
||||
void initState();
|
||||
|
||||
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 sendPPInt(uint32_t int_id);
|
||||
void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns);
|
||||
void serialize(CheckpointOut & cp) const override;
|
||||
void unserialize(CheckpointIn & cp) override;
|
||||
uint32_t getAffinity();
|
||||
|
||||
Gicv3CPUInterface *
|
||||
getCPUInterface() const
|
||||
{
|
||||
return cpuInterface;
|
||||
}
|
||||
|
||||
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group);
|
||||
|
||||
protected:
|
||||
|
||||
void reset();
|
||||
void update();
|
||||
void updateAndInformCPUInterface();
|
||||
Gicv3::IntStatus intStatus(uint32_t int_id);
|
||||
Gicv3::GroupId getIntGroup(int int_id);
|
||||
void activateIRQ(uint32_t int_id);
|
||||
void deactivateIRQ(uint32_t int_id);
|
||||
};
|
||||
|
||||
#endif //__DEV_ARM_GICV3_REDISTRIBUTOR_H__
|
||||
Reference in New Issue
Block a user