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:
Jairo Balart
2018-10-11 16:05:12 +02:00
committed by Giacomo Travaglini
parent 7d5696d1a9
commit 93c7fa5731
19 changed files with 6811 additions and 9 deletions

View File

@@ -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 *

View File

@@ -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:

View File

@@ -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)

View File

@@ -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",

View File

@@ -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",

View File

@@ -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; }

View File

@@ -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__

View File

@@ -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)")

View File

@@ -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')

View File

@@ -64,6 +64,13 @@ BaseGic::~BaseGic()
{
}
void
BaseGic::init()
{
PioDevice::init();
getSystem()->setGIC(this);
}
const BaseGic::Params *
BaseGic::params() const
{

View File

@@ -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
View 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
View 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__

File diff suppressed because it is too large Load Diff

View 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__

File diff suppressed because it is too large Load Diff

View 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__

View 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);
}

View 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__