/*
- * Copyright (c) 2010-2018 ARM Limited
+ * Copyright (c) 2010-2021 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* 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: Gabe Black
- * Ali Saidi
*/
#include "arch/arm/isa.hh"
+
+#include "arch/arm/faults.hh"
+#include "arch/arm/htm.hh"
+#include "arch/arm/interrupts.hh"
+#include "arch/arm/mmu.hh"
#include "arch/arm/pmu.hh"
+#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
-#include "arch/arm/tlb.hh"
#include "arch/arm/tlbi_op.hh"
#include "cpu/base.hh"
#include "cpu/checker/cpu.hh"
namespace ArmISA
{
-ISA::ISA(Params *p)
- : SimObject(p),
- system(NULL),
- _decoderFlavour(p->decoderFlavour),
- _vecRegRenameMode(Enums::Full),
- pmu(p->pmu),
- impdefAsNop(p->impdef_nop)
+ISA::ISA(const Params &p) : BaseISA(p), system(NULL),
+ _decoderFlavor(p.decoderFlavor), _vecRegRenameMode(Enums::Full),
+ pmu(p.pmu), impdefAsNop(p.impdef_nop),
+ afterStartup(false)
{
miscRegs[MISCREG_SCTLR_RST] = 0;
// Give all ISA devices a pointer to this ISA
pmu->setISA(this);
- system = dynamic_cast<ArmSystem *>(p->system);
+ system = dynamic_cast<ArmSystem *>(p.system);
// Cache system-level properties
if (FullSystem && system) {
haveVirtualization = system->haveVirtualization();
haveLargeAsid64 = system->haveLargeAsid64();
physAddrRange = system->physAddrRange();
+ haveSVE = system->haveSVE();
+ haveVHE = system->haveVHE();
+ havePAN = system->havePAN();
+ haveSecEL2 = system->haveSecEL2();
+ sveVL = system->sveVL();
+ haveLSE = system->haveLSE();
+ haveTME = system->haveTME();
} else {
highestELIs64 = true; // ArmSystem::highestELIs64 does the same
haveSecurity = haveLPAE = haveVirtualization = false;
haveCrypto = true;
haveLargeAsid64 = false;
physAddrRange = 32; // dummy value
- }
-
- // GICv3 CPU interface system registers are supported
- haveGICv3CPUInterface = false;
-
- if (system && dynamic_cast<Gicv3 *>(system->getGIC())) {
- haveGICv3CPUInterface = true;
+ haveSVE = true;
+ haveVHE = false;
+ havePAN = false;
+ haveSecEL2 = true;
+ sveVL = p.sve_vl_se;
+ haveLSE = true;
+ haveTME = true;
}
// Initial rename mode depends on highestEL
const_cast<Enums::VecRegRenameMode&>(_vecRegRenameMode) =
highestELIs64 ? Enums::Full : Enums::Elem;
+ selfDebug = new SelfDebug();
initializeMiscRegMetadata();
preUnflattenMiscReg();
std::vector<struct ISA::MiscRegLUTEntry> ISA::lookUpMiscReg(NUM_MISCREGS);
-const ArmISAParams *
+const ArmISAParams &
ISA::params() const
{
- return dynamic_cast<const Params *>(_params);
+ return dynamic_cast<const Params &>(_params);
}
void
ISA::clear()
{
- const Params *p(params());
+ const Params &p(params());
+
+ // Invalidate cached copies of miscregs in the TLBs
+ if (tc) {
+ getMMUPtr(tc)->invalidateMiscReg();
+ }
SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST];
memset(miscRegs, 0, sizeof(miscRegs));
}
void
-ISA::clear32(const ArmISAParams *p, const SCTLR &sctlr_rst)
+ISA::clear32(const ArmISAParams &p, const SCTLR &sctlr_rst)
{
CPSR cpsr = 0;
cpsr.mode = MODE_USER;
miscRegs[MISCREG_CPACR] = 0;
- miscRegs[MISCREG_FPSID] = p->fpsid;
+ miscRegs[MISCREG_FPSID] = p.fpsid;
if (haveLPAE) {
TTBCR ttbcr = miscRegs[MISCREG_TTBCR_NS];
}
void
-ISA::clear64(const ArmISAParams *p)
+ISA::clear64(const ArmISAParams &p)
{
CPSR cpsr = 0;
Addr rvbar = system->resetAddr();
}
void
-ISA::initID32(const ArmISAParams *p)
+ISA::initID32(const ArmISAParams &p)
{
// Initialize configurable default values
- miscRegs[MISCREG_MIDR] = p->midr;
- miscRegs[MISCREG_MIDR_EL1] = p->midr;
- miscRegs[MISCREG_VPIDR] = p->midr;
-
- miscRegs[MISCREG_ID_ISAR0] = p->id_isar0;
- miscRegs[MISCREG_ID_ISAR1] = p->id_isar1;
- miscRegs[MISCREG_ID_ISAR2] = p->id_isar2;
- miscRegs[MISCREG_ID_ISAR3] = p->id_isar3;
- miscRegs[MISCREG_ID_ISAR4] = p->id_isar4;
- miscRegs[MISCREG_ID_ISAR5] = p->id_isar5;
-
- miscRegs[MISCREG_ID_MMFR0] = p->id_mmfr0;
- miscRegs[MISCREG_ID_MMFR1] = p->id_mmfr1;
- miscRegs[MISCREG_ID_MMFR2] = p->id_mmfr2;
- miscRegs[MISCREG_ID_MMFR3] = p->id_mmfr3;
+
+ uint32_t midr;
+ if (p.midr != 0x0)
+ midr = p.midr;
+ else if (highestELIs64)
+ // Cortex-A57 TRM r0p0 MIDR
+ midr = 0x410fd070;
+ else
+ // Cortex-A15 TRM r0p0 MIDR
+ midr = 0x410fc0f0;
+
+ miscRegs[MISCREG_MIDR] = midr;
+ miscRegs[MISCREG_MIDR_EL1] = midr;
+ miscRegs[MISCREG_VPIDR] = midr;
+
+ miscRegs[MISCREG_ID_ISAR0] = p.id_isar0;
+ miscRegs[MISCREG_ID_ISAR1] = p.id_isar1;
+ miscRegs[MISCREG_ID_ISAR2] = p.id_isar2;
+ miscRegs[MISCREG_ID_ISAR3] = p.id_isar3;
+ miscRegs[MISCREG_ID_ISAR4] = p.id_isar4;
+ miscRegs[MISCREG_ID_ISAR5] = p.id_isar5;
+ miscRegs[MISCREG_ID_ISAR6] = p.id_isar6;
+
+ miscRegs[MISCREG_ID_MMFR0] = p.id_mmfr0;
+ miscRegs[MISCREG_ID_MMFR1] = p.id_mmfr1;
+ miscRegs[MISCREG_ID_MMFR2] = p.id_mmfr2;
+ miscRegs[MISCREG_ID_MMFR3] = p.id_mmfr3;
+ miscRegs[MISCREG_ID_MMFR4] = p.id_mmfr4;
miscRegs[MISCREG_ID_ISAR5] = insertBits(
miscRegs[MISCREG_ID_ISAR5], 19, 4,
}
void
-ISA::initID64(const ArmISAParams *p)
+ISA::initID64(const ArmISAParams &p)
{
// Initialize configurable id registers
- miscRegs[MISCREG_ID_AA64AFR0_EL1] = p->id_aa64afr0_el1;
- miscRegs[MISCREG_ID_AA64AFR1_EL1] = p->id_aa64afr1_el1;
+ miscRegs[MISCREG_ID_AA64AFR0_EL1] = p.id_aa64afr0_el1;
+ miscRegs[MISCREG_ID_AA64AFR1_EL1] = p.id_aa64afr1_el1;
miscRegs[MISCREG_ID_AA64DFR0_EL1] =
- (p->id_aa64dfr0_el1 & 0xfffffffffffff0ffULL) |
- (p->pmu ? 0x0000000000000100ULL : 0); // Enable PMUv3
+ (p.id_aa64dfr0_el1 & 0xfffffffffffff0ffULL) |
+ (p.pmu ? 0x0000000000000100ULL : 0); // Enable PMUv3
- miscRegs[MISCREG_ID_AA64DFR1_EL1] = p->id_aa64dfr1_el1;
- miscRegs[MISCREG_ID_AA64ISAR0_EL1] = p->id_aa64isar0_el1;
- miscRegs[MISCREG_ID_AA64ISAR1_EL1] = p->id_aa64isar1_el1;
- miscRegs[MISCREG_ID_AA64MMFR0_EL1] = p->id_aa64mmfr0_el1;
- miscRegs[MISCREG_ID_AA64MMFR1_EL1] = p->id_aa64mmfr1_el1;
- miscRegs[MISCREG_ID_AA64MMFR2_EL1] = p->id_aa64mmfr2_el1;
+ miscRegs[MISCREG_ID_AA64DFR1_EL1] = p.id_aa64dfr1_el1;
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1] = p.id_aa64isar0_el1;
+ miscRegs[MISCREG_ID_AA64ISAR1_EL1] = p.id_aa64isar1_el1;
+ miscRegs[MISCREG_ID_AA64MMFR0_EL1] = p.id_aa64mmfr0_el1;
+ miscRegs[MISCREG_ID_AA64MMFR1_EL1] = p.id_aa64mmfr1_el1;
+ miscRegs[MISCREG_ID_AA64MMFR2_EL1] = p.id_aa64mmfr2_el1;
miscRegs[MISCREG_ID_DFR0_EL1] =
- (p->pmu ? 0x03000000ULL : 0); // Enable PMUv3
+ (p.pmu ? 0x03000000ULL : 0); // Enable PMUv3
miscRegs[MISCREG_ID_DFR0] = miscRegs[MISCREG_ID_DFR0_EL1];
+ // SVE
+ miscRegs[MISCREG_ID_AA64ZFR0_EL1] = 0; // SVEver 0
+ if (haveSecurity) {
+ miscRegs[MISCREG_ZCR_EL3] = sveVL - 1;
+ } else if (haveVirtualization) {
+ miscRegs[MISCREG_ZCR_EL2] = sveVL - 1;
+ } else {
+ miscRegs[MISCREG_ZCR_EL1] = sveVL - 1;
+ }
+
// Enforce consistency with system-level settings...
// EL3
miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
miscRegs[MISCREG_ID_AA64PFR0_EL1], 11, 8,
haveVirtualization ? 0x2 : 0x0);
+ // SVE
+ miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64PFR0_EL1], 35, 32,
+ haveSVE ? 0x1 : 0x0);
+ // SecEL2
+ miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64PFR0_EL1], 39, 36,
+ haveSecEL2 ? 0x1 : 0x0);
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1], 39, 36,
+ haveSecEL2 ? 0x1 : 0x0);
// Large ASID support
miscRegs[MISCREG_ID_AA64MMFR0_EL1] = insertBits(
miscRegs[MISCREG_ID_AA64MMFR0_EL1], 7, 4,
miscRegs[MISCREG_ID_AA64ISAR0_EL1] = insertBits(
miscRegs[MISCREG_ID_AA64ISAR0_EL1], 19, 4,
haveCrypto ? 0x1112 : 0x0);
+ // LSE
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1], 23, 20,
+ haveLSE ? 0x2 : 0x0);
+ // VHE
+ miscRegs[MISCREG_ID_AA64MMFR1_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64MMFR1_EL1], 11, 8,
+ haveVHE ? 0x1 : 0x0);
+ // PAN
+ miscRegs[MISCREG_ID_AA64MMFR1_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64MMFR1_EL1], 23, 20,
+ havePAN ? 0x1 : 0x0);
+ // TME
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1] = insertBits(
+ miscRegs[MISCREG_ID_AA64ISAR0_EL1], 27, 24,
+ haveTME ? 0x1 : 0x0);
}
void
-ISA::startup(ThreadContext *tc)
+ISA::startup()
{
- pmu->setThreadContext(tc);
+ BaseISA::startup();
- if (system) {
- Gicv3 *gicv3 = dynamic_cast<Gicv3 *>(system->getGIC());
- if (gicv3) {
- gicv3CpuInterface.reset(gicv3->getCPUInterface(tc->contextId()));
- gicv3CpuInterface->setISA(this);
+ if (tc) {
+ setupThreadContext();
+
+ if (haveTME) {
+ std::unique_ptr<BaseHTMCheckpoint> cpt(new HTMCheckpoint());
+ tc->setHtmCheckpointPtr(std::move(cpt));
}
}
+
+ afterStartup = true;
}
+void
+ISA::setupThreadContext()
+{
+ pmu->setThreadContext(tc);
+
+ if (!system)
+ return;
+
+ selfDebug->init(tc);
+
+ Gicv3 *gicv3 = dynamic_cast<Gicv3 *>(system->getGIC());
+ if (!gicv3)
+ return;
+
+ if (!gicv3CpuInterface)
+ gicv3CpuInterface.reset(gicv3->getCPUInterface(tc->contextId()));
+
+ gicv3CpuInterface->setISA(this);
+ gicv3CpuInterface->setThreadContext(tc);
+}
+
+void
+ISA::takeOverFrom(ThreadContext *new_tc, ThreadContext *old_tc)
+{
+ tc = new_tc;
+ setupThreadContext();
+}
RegVal
ISA::readMiscRegNoEffect(int misc_reg) const
RegVal
-ISA::readMiscReg(int misc_reg, ThreadContext *tc)
+ISA::readMiscReg(int misc_reg)
{
CPSR cpsr = 0;
PCState pc = 0;
miscRegName[misc_reg]);
}
#endif
+ misc_reg = redirectRegVHE(tc, misc_reg);
switch (unflattenMiscReg(misc_reg)) {
case MISCREG_HCR:
- {
+ case MISCREG_HCR2:
if (!haveVirtualization)
return 0;
- else
- return readMiscRegNoEffect(MISCREG_HCR);
- }
+ break;
case MISCREG_CPACR:
{
const uint32_t ones = (uint32_t)(-1);
case MISCREG_MIDR:
cpsr = readMiscRegNoEffect(MISCREG_CPSR);
scr = readMiscRegNoEffect(MISCREG_SCR);
- if ((cpsr.mode == MODE_HYP) || inSecureState(scr, cpsr)) {
+ if ((cpsr.mode == MODE_HYP) || isSecure(tc)) {
return readMiscRegNoEffect(misc_reg);
} else {
return readMiscRegNoEffect(MISCREG_VPIDR);
const uint32_t ones = (uint32_t)(-1);
FPSCR fpscrMask = 0;
fpscrMask.len = ones;
+ fpscrMask.fz16 = ones;
fpscrMask.stride = ones;
fpscrMask.rMode = ones;
fpscrMask.fz = ones;
{
return miscRegs[MISCREG_CPSR] & 0xc;
}
+ case MISCREG_PAN:
+ {
+ return miscRegs[MISCREG_CPSR] & 0x400000;
+ }
case MISCREG_L2CTLR:
{
// mostly unimplemented, just set NumCPUs field from sim and return
L2CTLR l2ctlr = 0;
// b00:1CPU to b11:4CPUs
- l2ctlr.numCPUs = tc->getSystemPtr()->numContexts() - 1;
+ l2ctlr.numCPUs = tc->getSystemPtr()->threads.size() - 1;
return l2ctlr;
}
case MISCREG_DBGDIDR:
*/
return 0x5 << 16;
case MISCREG_DBGDSCRint:
- return 0;
+ return readMiscRegNoEffect(MISCREG_DBGDSCRint);
case MISCREG_ISR:
- return tc->getCpuPtr()->getInterruptController(tc->threadId())->getISR(
- readMiscRegNoEffect(MISCREG_HCR),
- readMiscRegNoEffect(MISCREG_CPSR),
- readMiscRegNoEffect(MISCREG_SCR));
+ {
+ auto ic = dynamic_cast<ArmISA::Interrupts *>(
+ tc->getCpuPtr()->getInterruptController(tc->threadId()));
+ return ic->getISR(
+ readMiscRegNoEffect(MISCREG_HCR),
+ readMiscRegNoEffect(MISCREG_CPSR),
+ readMiscRegNoEffect(MISCREG_SCR));
+ }
case MISCREG_ISR_EL1:
- return tc->getCpuPtr()->getInterruptController(tc->threadId())->getISR(
- readMiscRegNoEffect(MISCREG_HCR_EL2),
- readMiscRegNoEffect(MISCREG_CPSR),
- readMiscRegNoEffect(MISCREG_SCR_EL3));
+ {
+ auto ic = dynamic_cast<ArmISA::Interrupts *>(
+ tc->getCpuPtr()->getInterruptController(tc->threadId()));
+ return ic->getISR(
+ readMiscRegNoEffect(MISCREG_HCR_EL2),
+ readMiscRegNoEffect(MISCREG_CPSR),
+ readMiscRegNoEffect(MISCREG_SCR_EL3));
+ }
case MISCREG_DCZID_EL0:
return 0x04; // DC ZVA clear 64-byte chunks
case MISCREG_HCPTR:
val &= ~(1 << 14);
// If a CP bit in NSACR is 0 then the corresponding bit in
// HCPTR is RAO/WI
- bool secure_lookup = haveSecurity &&
- inSecureState(readMiscRegNoEffect(MISCREG_SCR),
- readMiscRegNoEffect(MISCREG_CPSR));
+ bool secure_lookup = haveSecurity && isSecure(tc);
if (!secure_lookup) {
RegVal mask = readMiscRegNoEffect(MISCREG_NSACR);
val |= (mask ^ 0x7FFF) & 0xBFFF;
0x0000000000000020 | // EL1
(haveVirtualization ? 0x0000000000000200 : 0) | // EL2
(haveSecurity ? 0x0000000000002000 : 0) | // EL3
- (haveGICv3CPUInterface ? 0x0000000001000000 : 0);
+ (haveSVE ? 0x0000000100000000 : 0) | // SVE
+ (haveSecEL2 ? 0x0000001000000000 : 0) | // SecEL2
+ (gicv3CpuInterface ? 0x0000000001000000 : 0);
case MISCREG_ID_AA64PFR1_EL1:
return 0; // bits [63:0] RES0 (reserved for future use)
// Generic Timer registers
- case MISCREG_CNTHV_CTL_EL2:
- case MISCREG_CNTHV_CVAL_EL2:
- case MISCREG_CNTHV_TVAL_EL2:
- case MISCREG_CNTFRQ ... MISCREG_CNTHP_CTL:
- case MISCREG_CNTPCT ... MISCREG_CNTHP_CVAL:
- case MISCREG_CNTKCTL_EL1 ... MISCREG_CNTV_CVAL_EL0:
- case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
- return getGenericTimer(tc).readMiscReg(misc_reg);
+ case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+ case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
+ return getGenericTimer().readMiscReg(misc_reg);
+ case MISCREG_ICC_AP0R0 ... MISCREG_ICH_LRC15:
case MISCREG_ICC_PMR_EL1 ... MISCREG_ICC_IGRPEN1_EL3:
case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_LR15_EL2:
- return getGICv3CPUInterface(tc).readMiscReg(misc_reg);
+ return getGICv3CPUInterface().readMiscReg(misc_reg);
default:
break;
if (upper > 0) {
miscRegs[lower] = bits(v, 31, 0);
miscRegs[upper] = bits(v, 63, 32);
- DPRINTF(MiscRegs, "Writing to misc reg %d (%d:%d) : %#x\n",
- misc_reg, lower, upper, v);
+ DPRINTF(MiscRegs, "Writing MiscReg %s (%d %d:%d) : %#x\n",
+ miscRegName[misc_reg], misc_reg, lower, upper, v);
} else {
miscRegs[lower] = v;
- DPRINTF(MiscRegs, "Writing to misc reg %d (%d) : %#x\n",
- misc_reg, lower, v);
+ DPRINTF(MiscRegs, "Writing MiscReg %s (%d %d) : %#x\n",
+ miscRegName[misc_reg], misc_reg, lower, v);
}
}
void
-ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
+ISA::setMiscReg(int misc_reg, RegVal val)
{
RegVal newVal = val;
int old_mode = old_cpsr.mode;
CPSR cpsr = val;
if (old_mode != cpsr.mode || cpsr.il != old_cpsr.il) {
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
+ }
+
+ if (cpsr.pan != old_cpsr.pan) {
+ getMMUPtr(tc)->invalidateMiscReg(MMU::D_TLBS);
}
DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n",
pc.nextThumb(cpsr.t);
pc.nextJazelle(cpsr.j);
pc.illegalExec(cpsr.il == 1);
+ selfDebug->setDebugMask(cpsr.d == 1);
+
+ tc->getDecoderPtr()->setSveLen((getCurSveVecLenInBits() >> 7) - 1);
// Follow slightly different semantics if a CheckerCPU object
// is connected
miscRegName[misc_reg], val);
}
#endif
+ misc_reg = redirectRegVHE(tc, misc_reg);
+
switch (unflattenMiscReg(misc_reg)) {
case MISCREG_CPACR:
{
miscRegName[misc_reg], newVal);
}
break;
+ case MISCREG_CPACR_EL1:
+ {
+ const uint32_t ones = (uint32_t)(-1);
+ CPACR cpacrMask = 0;
+ cpacrMask.tta = ones;
+ cpacrMask.fpen = ones;
+ if (haveSVE) {
+ cpacrMask.zen = ones;
+ }
+ newVal &= cpacrMask;
+ DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n",
+ miscRegName[misc_reg], newVal);
+ }
+ break;
case MISCREG_CPTR_EL2:
{
const uint32_t ones = (uint32_t)(-1);
cptrMask.tcpac = ones;
cptrMask.tta = ones;
cptrMask.tfp = ones;
+ if (haveSVE) {
+ cptrMask.tz = ones;
+ }
newVal &= cptrMask;
cptrMask = 0;
cptrMask.res1_13_12_el2 = ones;
- cptrMask.res1_9_0_el2 = ones;
+ cptrMask.res1_7_0_el2 = ones;
+ if (!haveSVE) {
+ cptrMask.res1_8_el2 = ones;
+ }
+ cptrMask.res1_9_el2 = ones;
newVal |= cptrMask;
DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n",
miscRegName[misc_reg], newVal);
cptrMask.tcpac = ones;
cptrMask.tta = ones;
cptrMask.tfp = ones;
+ if (haveSVE) {
+ cptrMask.ez = ones;
+ }
newVal &= cptrMask;
DPRINTF(MiscRegs, "Writing misc reg %s: %#x\n",
miscRegName[misc_reg], newVal);
fpscrMask.ixe = ones;
fpscrMask.ide = ones;
fpscrMask.len = ones;
+ fpscrMask.fz16 = ones;
fpscrMask.stride = ones;
fpscrMask.rMode = ones;
fpscrMask.fz = ones;
const uint32_t ones = (uint32_t)(-1);
FPSCR fpscrMask = 0;
fpscrMask.len = ones;
+ fpscrMask.fz16 = ones;
fpscrMask.stride = ones;
fpscrMask.rMode = ones;
fpscrMask.fz = ones;
(readMiscRegNoEffect(MISCREG_FPEXC) & ~fpexcMask);
}
break;
+ case MISCREG_HCR2:
+ if (!haveVirtualization)
+ return;
+ break;
case MISCREG_HCR:
{
+ const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
+ selfDebug->setenableTDETGE((HCR)val, mdcr);
if (!haveVirtualization)
return;
}
break;
+
+ case MISCREG_HDCR:
+ {
+ const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+ selfDebug->setenableTDETGE(hcr, (HDCR)val);
+ }
+ break;
+ case MISCREG_DBGOSLAR:
+ {
+ OSL r = tc->readMiscReg(MISCREG_DBGOSLSR);
+ const uint32_t temp = (val == 0xC5ACCE55)? 0x1 : 0x0;
+ selfDebug->updateOSLock((RegVal) temp);
+ r.oslk = bits(temp,0);
+ tc->setMiscReg(MISCREG_DBGOSLSR, r);
+ }
+ break;
+ case MISCREG_DBGBCR0:
+ selfDebug->updateDBGBCR(0, val);
+ break;
+ case MISCREG_DBGBCR1:
+ selfDebug->updateDBGBCR(1, val);
+ break;
+ case MISCREG_DBGBCR2:
+ selfDebug->updateDBGBCR(2, val);
+ break;
+ case MISCREG_DBGBCR3:
+ selfDebug->updateDBGBCR(3, val);
+ break;
+ case MISCREG_DBGBCR4:
+ selfDebug->updateDBGBCR(4, val);
+ break;
+ case MISCREG_DBGBCR5:
+ selfDebug->updateDBGBCR(5, val);
+ break;
+ case MISCREG_DBGBCR6:
+ selfDebug->updateDBGBCR(6, val);
+ break;
+ case MISCREG_DBGBCR7:
+ selfDebug->updateDBGBCR(7, val);
+ break;
+ case MISCREG_DBGBCR8:
+ selfDebug->updateDBGBCR(8, val);
+ break;
+ case MISCREG_DBGBCR9:
+ selfDebug->updateDBGBCR(9, val);
+ break;
+ case MISCREG_DBGBCR10:
+ selfDebug->updateDBGBCR(10, val);
+ break;
+ case MISCREG_DBGBCR11:
+ selfDebug->updateDBGBCR(11, val);
+ break;
+ case MISCREG_DBGBCR12:
+ selfDebug->updateDBGBCR(12, val);
+ break;
+ case MISCREG_DBGBCR13:
+ selfDebug->updateDBGBCR(13, val);
+ break;
+ case MISCREG_DBGBCR14:
+ selfDebug->updateDBGBCR(14, val);
+ break;
+ case MISCREG_DBGBCR15:
+ selfDebug->updateDBGBCR(15, val);
+ break;
+ case MISCREG_DBGWCR0:
+ selfDebug->updateDBGWCR(0, val);
+ break;
+ case MISCREG_DBGWCR1:
+ selfDebug->updateDBGWCR(1, val);
+ break;
+ case MISCREG_DBGWCR2:
+ selfDebug->updateDBGWCR(2, val);
+ break;
+ case MISCREG_DBGWCR3:
+ selfDebug->updateDBGWCR(3, val);
+ break;
+ case MISCREG_DBGWCR4:
+ selfDebug->updateDBGWCR(4, val);
+ break;
+ case MISCREG_DBGWCR5:
+ selfDebug->updateDBGWCR(5, val);
+ break;
+ case MISCREG_DBGWCR6:
+ selfDebug->updateDBGWCR(6, val);
+ break;
+ case MISCREG_DBGWCR7:
+ selfDebug->updateDBGWCR(7, val);
+ break;
+ case MISCREG_DBGWCR8:
+ selfDebug->updateDBGWCR(8, val);
+ break;
+ case MISCREG_DBGWCR9:
+ selfDebug->updateDBGWCR(9, val);
+ break;
+ case MISCREG_DBGWCR10:
+ selfDebug->updateDBGWCR(10, val);
+ break;
+ case MISCREG_DBGWCR11:
+ selfDebug->updateDBGWCR(11, val);
+ break;
+ case MISCREG_DBGWCR12:
+ selfDebug->updateDBGWCR(12, val);
+ break;
+ case MISCREG_DBGWCR13:
+ selfDebug->updateDBGWCR(13, val);
+ break;
+ case MISCREG_DBGWCR14:
+ selfDebug->updateDBGWCR(14, val);
+ break;
+ case MISCREG_DBGWCR15:
+ selfDebug->updateDBGWCR(15, val);
+ break;
+
+ case MISCREG_MDCR_EL2:
+ {
+ const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+ selfDebug->setenableTDETGE(hcr, (HDCR)val);
+ }
+ break;
+ case MISCREG_SDCR:
+ case MISCREG_MDCR_EL3:
+ {
+ selfDebug->setbSDD(val);
+ }
+ break;
+ case MISCREG_DBGDSCRext:
+ {
+ selfDebug->setMDBGen(val);
+ DBGDS32 r = tc->readMiscReg(MISCREG_DBGDSCRint);
+ DBGDS32 v = val;
+ r.moe = v.moe;
+ r.udccdis = v.udccdis;
+ r.mdbgen = v.mdbgen;
+ tc->setMiscReg(MISCREG_DBGDSCRint, r);
+ r = tc->readMiscReg(MISCREG_DBGDSCRint);
+ }
+
+ break;
+ case MISCREG_MDSCR_EL1:
+ {
+ selfDebug->setMDSCRvals(val);
+ }
+ break;
+
+ case MISCREG_OSLAR_EL1:
+ {
+ selfDebug->updateOSLock(val);
+ OSL r = tc->readMiscReg(MISCREG_OSLSR_EL1);
+ r.oslk = bits(val, 0);
+ r.oslm_3 = 1;
+ tc->setMiscReg(MISCREG_OSLSR_EL1, r);
+ }
+ break;
+
+ case MISCREG_DBGBCR0_EL1:
+ selfDebug->updateDBGBCR(0, val);
+ break;
+ case MISCREG_DBGBCR1_EL1:
+ selfDebug->updateDBGBCR(1, val);
+ break;
+ case MISCREG_DBGBCR2_EL1:
+ selfDebug->updateDBGBCR(2, val);
+ break;
+ case MISCREG_DBGBCR3_EL1:
+ selfDebug->updateDBGBCR(3, val);
+ break;
+ case MISCREG_DBGBCR4_EL1:
+ selfDebug->updateDBGBCR(4, val);
+ break;
+ case MISCREG_DBGBCR5_EL1:
+ selfDebug->updateDBGBCR(5, val);
+ break;
+ case MISCREG_DBGBCR6_EL1:
+ selfDebug->updateDBGBCR(6, val);
+ break;
+ case MISCREG_DBGBCR7_EL1:
+ selfDebug->updateDBGBCR(7, val);
+ break;
+ case MISCREG_DBGBCR8_EL1:
+ selfDebug->updateDBGBCR(8, val);
+ break;
+ case MISCREG_DBGBCR9_EL1:
+ selfDebug->updateDBGBCR(9, val);
+ break;
+ case MISCREG_DBGBCR10_EL1:
+ selfDebug->updateDBGBCR(10, val);
+ break;
+ case MISCREG_DBGBCR11_EL1:
+ selfDebug->updateDBGBCR(11, val);
+ break;
+ case MISCREG_DBGBCR12_EL1:
+ selfDebug->updateDBGBCR(12, val);
+ break;
+ case MISCREG_DBGBCR13_EL1:
+ selfDebug->updateDBGBCR(13, val);
+ break;
+ case MISCREG_DBGBCR14_EL1:
+ selfDebug->updateDBGBCR(14, val);
+ break;
+ case MISCREG_DBGBCR15_EL1:
+ selfDebug->updateDBGBCR(15, val);
+ break;
+ case MISCREG_DBGWCR0_EL1:
+ selfDebug->updateDBGWCR(0, val);
+ break;
+ case MISCREG_DBGWCR1_EL1:
+ selfDebug->updateDBGWCR(1, val);
+ break;
+ case MISCREG_DBGWCR2_EL1:
+ selfDebug->updateDBGWCR(2, val);
+ break;
+ case MISCREG_DBGWCR3_EL1:
+ selfDebug->updateDBGWCR(3, val);
+ break;
+ case MISCREG_DBGWCR4_EL1:
+ selfDebug->updateDBGWCR(4, val);
+ break;
+ case MISCREG_DBGWCR5_EL1:
+ selfDebug->updateDBGWCR(5, val);
+ break;
+ case MISCREG_DBGWCR6_EL1:
+ selfDebug->updateDBGWCR(6, val);
+ break;
+ case MISCREG_DBGWCR7_EL1:
+ selfDebug->updateDBGWCR(7, val);
+ break;
+ case MISCREG_DBGWCR8_EL1:
+ selfDebug->updateDBGWCR(8, val);
+ break;
+ case MISCREG_DBGWCR9_EL1:
+ selfDebug->updateDBGWCR(9, val);
+ break;
+ case MISCREG_DBGWCR10_EL1:
+ selfDebug->updateDBGWCR(10, val);
+ break;
+ case MISCREG_DBGWCR11_EL1:
+ selfDebug->updateDBGWCR(11, val);
+ break;
+ case MISCREG_DBGWCR12_EL1:
+ selfDebug->updateDBGWCR(12, val);
+ break;
+ case MISCREG_DBGWCR13_EL1:
+ selfDebug->updateDBGWCR(13, val);
+ break;
+ case MISCREG_DBGWCR14_EL1:
+ selfDebug->updateDBGWCR(14, val);
+ break;
+ case MISCREG_DBGWCR15_EL1:
+ selfDebug->updateDBGWCR(15, val);
+ break;
case MISCREG_IFSR:
{
// ARM ARM (ARM DDI 0406C.b) B4.1.96
}
break;
case MISCREG_SCR:
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
case MISCREG_SCTLR:
{
SCTLR new_sctlr = newVal;
new_sctlr.nmfi = ((bool)sctlr.nmfi) && !haveVirtualization;
miscRegs[sctlr_idx] = (RegVal)new_sctlr;
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
}
case MISCREG_MIDR:
case MISCREG_ID_PFR0:
case MISCREG_ID_MMFR1:
case MISCREG_ID_MMFR2:
case MISCREG_ID_MMFR3:
+ case MISCREG_ID_MMFR4:
case MISCREG_ID_ISAR0:
case MISCREG_ID_ISAR1:
case MISCREG_ID_ISAR2:
// TLB Invalidate All
case MISCREG_TLBIALL: // TLBI all entries, EL0&1,
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
tlbiOp(tc);
// TLB Invalidate All, Inner Shareable
case MISCREG_TLBIALLIS:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
tlbiOp.broadcast(tc);
// Instruction TLB Invalidate All
case MISCREG_ITLBIALL:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
ITLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
tlbiOp(tc);
// Data TLB Invalidate All
case MISCREG_DTLBIALL:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
DTLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
tlbiOp(tc);
case MISCREG_TLBIMVA:
case MISCREG_TLBIMVAL:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIMVA tlbiOp(EL1,
haveSecurity && !scr.ns,
case MISCREG_TLBIMVAIS:
case MISCREG_TLBIMVALIS:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIMVA tlbiOp(EL1,
haveSecurity && !scr.ns,
// TLB Invalidate by ASID match
case MISCREG_TLBIASID:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIASID tlbiOp(EL1,
haveSecurity && !scr.ns,
// TLB Invalidate by ASID match, Inner Shareable
case MISCREG_TLBIASIDIS:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIASID tlbiOp(EL1,
haveSecurity && !scr.ns,
case MISCREG_TLBIMVAA:
case MISCREG_TLBIMVAAL:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
- mbits(newVal, 31,12), false);
+ mbits(newVal, 31,12));
tlbiOp(tc);
return;
case MISCREG_TLBIMVAAIS:
case MISCREG_TLBIMVAALIS:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
- mbits(newVal, 31,12), false);
+ mbits(newVal, 31,12));
tlbiOp.broadcast(tc);
return;
case MISCREG_TLBIMVAH:
case MISCREG_TLBIMVALH:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
- mbits(newVal, 31,12), true);
+ TLBIMVAA tlbiOp(EL2, haveSecurity && !scr.ns,
+ mbits(newVal, 31,12));
tlbiOp(tc);
return;
case MISCREG_TLBIMVAHIS:
case MISCREG_TLBIMVALHIS:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
- mbits(newVal, 31,12), true);
+ TLBIMVAA tlbiOp(EL2, haveSecurity && !scr.ns,
+ mbits(newVal, 31,12));
tlbiOp.broadcast(tc);
return;
case MISCREG_TLBIIPAS2:
case MISCREG_TLBIIPAS2L:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIIPA tlbiOp(EL1,
haveSecurity && !scr.ns,
case MISCREG_TLBIIPAS2IS:
case MISCREG_TLBIIPAS2LIS:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
TLBIIPA tlbiOp(EL1,
haveSecurity && !scr.ns,
// Instruction TLB Invalidate by VA
case MISCREG_ITLBIMVA:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
ITLBIMVA tlbiOp(EL1,
haveSecurity && !scr.ns,
// Data TLB Invalidate by VA
case MISCREG_DTLBIMVA:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
DTLBIMVA tlbiOp(EL1,
haveSecurity && !scr.ns,
// Instruction TLB Invalidate by ASID match
case MISCREG_ITLBIASID:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
ITLBIASID tlbiOp(EL1,
haveSecurity && !scr.ns,
// Data TLB Invalidate by ASID match
case MISCREG_DTLBIASID:
{
- assert32(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert32();
+ scr = readMiscReg(MISCREG_SCR);
DTLBIASID tlbiOp(EL1,
haveSecurity && !scr.ns,
// TLB Invalidate All, Non-Secure Non-Hyp
case MISCREG_TLBIALLNSNH:
{
- assert32(tc);
+ assert32();
- TLBIALLN tlbiOp(EL1, false);
+ TLBIALLN tlbiOp(EL1);
tlbiOp(tc);
return;
}
// TLB Invalidate All, Non-Secure Non-Hyp, Inner Shareable
case MISCREG_TLBIALLNSNHIS:
{
- assert32(tc);
+ assert32();
- TLBIALLN tlbiOp(EL1, false);
+ TLBIALLN tlbiOp(EL1);
tlbiOp.broadcast(tc);
return;
}
// TLB Invalidate All, Hyp mode
case MISCREG_TLBIALLH:
{
- assert32(tc);
+ assert32();
- TLBIALLN tlbiOp(EL1, true);
+ TLBIALLN tlbiOp(EL2);
tlbiOp(tc);
return;
}
// TLB Invalidate All, Hyp mode, Inner Shareable
case MISCREG_TLBIALLHIS:
{
- assert32(tc);
+ assert32();
- TLBIALLN tlbiOp(EL1, true);
+ TLBIALLN tlbiOp(EL2);
tlbiOp.broadcast(tc);
return;
}
// AArch64 TLB Invalidate All, EL3
case MISCREG_TLBI_ALLE3:
{
- assert64(tc);
+ assert64();
- TLBIALL tlbiOp(EL3, true);
+ TLBIALLEL tlbiOp(EL3, true);
tlbiOp(tc);
return;
}
// AArch64 TLB Invalidate All, EL3, Inner Shareable
case MISCREG_TLBI_ALLE3IS:
{
- assert64(tc);
+ assert64();
- TLBIALL tlbiOp(EL3, true);
+ TLBIALLEL tlbiOp(EL3, true);
tlbiOp.broadcast(tc);
return;
}
- // AArch64 TLB Invalidate All, EL2, Inner Shareable
+ // AArch64 TLB Invalidate All, EL2
case MISCREG_TLBI_ALLE2:
- case MISCREG_TLBI_ALLE2IS:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIALL tlbiOp(EL2, haveSecurity && !scr.ns);
+ TLBIALLEL tlbiOp(EL2, haveSecurity && !scr.ns);
tlbiOp(tc);
return;
}
+ // AArch64 TLB Invalidate All, EL2, Inner Shareable
+ case MISCREG_TLBI_ALLE2IS:
+ {
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
+
+ TLBIALLEL tlbiOp(EL2, haveSecurity && !scr.ns);
+ tlbiOp.broadcast(tc);
+ return;
+ }
// AArch64 TLB Invalidate All, EL1
case MISCREG_TLBI_ALLE1:
- case MISCREG_TLBI_VMALLE1:
- case MISCREG_TLBI_VMALLS12E1:
- // @todo: handle VMID and stage 2 to enable Virtualization
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
+ TLBIALLEL tlbiOp(EL1, haveSecurity && !scr.ns);
tlbiOp(tc);
return;
}
// AArch64 TLB Invalidate All, EL1, Inner Shareable
case MISCREG_TLBI_ALLE1IS:
- case MISCREG_TLBI_VMALLE1IS:
+ {
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
+
+ TLBIALLEL tlbiOp(EL1, haveSecurity && !scr.ns);
+ tlbiOp.broadcast(tc);
+ return;
+ }
+ case MISCREG_TLBI_VMALLS12E1:
+ {
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
+
+ TLBIVMALL tlbiOp(EL1, haveSecurity && !scr.ns, true);
+ tlbiOp(tc);
+ return;
+ }
+ case MISCREG_TLBI_VMALLE1:
+ {
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
+
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIVMALL tlbiOp(target_el, haveSecurity && !scr.ns, false);
+ tlbiOp(tc);
+ return;
+ }
case MISCREG_TLBI_VMALLS12E1IS:
- // @todo: handle VMID and stage 2 to enable Virtualization
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIALL tlbiOp(EL1, haveSecurity && !scr.ns);
+ TLBIVMALL tlbiOp(EL1, haveSecurity && !scr.ns, true);
+ tlbiOp.broadcast(tc);
+ return;
+ }
+ case MISCREG_TLBI_VMALLE1IS:
+ {
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
+
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIVMALL tlbiOp(target_el, haveSecurity && !scr.ns, false);
tlbiOp.broadcast(tc);
return;
}
// VAEx(IS) and VALEx(IS) are the same because TLBs
// only store entries
// from the last level of translation table walks
- // @todo: handle VMID to enable Virtualization
// AArch64 TLB Invalidate by VA, EL3
case MISCREG_TLBI_VAE3_Xt:
case MISCREG_TLBI_VALE3_Xt:
{
- assert64(tc);
+ assert64();
TLBIMVA tlbiOp(EL3, true,
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
case MISCREG_TLBI_VAE3IS_Xt:
case MISCREG_TLBI_VALE3IS_Xt:
{
- assert64(tc);
+ assert64();
TLBIMVA tlbiOp(EL3, true,
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
case MISCREG_TLBI_VAE2_Xt:
case MISCREG_TLBI_VALE2_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
TLBIMVA tlbiOp(EL2, haveSecurity && !scr.ns,
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
case MISCREG_TLBI_VAE2IS_Xt:
case MISCREG_TLBI_VALE2IS_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
TLBIMVA tlbiOp(EL2, haveSecurity && !scr.ns,
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
case MISCREG_TLBI_VAE1_Xt:
case MISCREG_TLBI_VALE1_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
bits(newVal, 55, 48);
- TLBIMVA tlbiOp(EL1, haveSecurity && !scr.ns,
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIMVA tlbiOp(target_el, haveSecurity && !scr.ns,
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
asid);
case MISCREG_TLBI_VAE1IS_Xt:
case MISCREG_TLBI_VALE1IS_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
bits(newVal, 55, 48);
- TLBIMVA tlbiOp(EL1, haveSecurity && !scr.ns,
- static_cast<Addr>(bits(newVal, 43, 0)) << 12,
- asid);
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIMVA tlbiOp(target_el, haveSecurity && !scr.ns,
+ static_cast<Addr>(bits(newVal, 43, 0)) << 12,
+ asid);
tlbiOp.broadcast(tc);
return;
}
// AArch64 TLB Invalidate by ASID, EL1
- // @todo: handle VMID to enable Virtualization
case MISCREG_TLBI_ASIDE1_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
bits(newVal, 55, 48);
- TLBIASID tlbiOp(EL1, haveSecurity && !scr.ns, asid);
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIASID tlbiOp(target_el, haveSecurity && !scr.ns, asid);
tlbiOp(tc);
return;
}
// AArch64 TLB Invalidate by ASID, EL1, Inner Shareable
case MISCREG_TLBI_ASIDE1IS_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
bits(newVal, 55, 48);
- TLBIASID tlbiOp(EL1, haveSecurity && !scr.ns, asid);
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIASID tlbiOp(target_el, haveSecurity && !scr.ns, asid);
tlbiOp.broadcast(tc);
return;
}
case MISCREG_TLBI_VAAE1_Xt:
case MISCREG_TLBI_VAALE1_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
- static_cast<Addr>(bits(newVal, 43, 0)) << 12, false);
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIMVAA tlbiOp(target_el, haveSecurity && !scr.ns,
+ static_cast<Addr>(bits(newVal, 43, 0)) << 12);
tlbiOp(tc);
return;
case MISCREG_TLBI_VAAE1IS_Xt:
case MISCREG_TLBI_VAALE1IS_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
- TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
- static_cast<Addr>(bits(newVal, 43, 0)) << 12, false);
+ HCR hcr = readMiscReg(MISCREG_HCR_EL2);
+ bool is_host = (hcr.tge && hcr.e2h);
+ ExceptionLevel target_el = is_host ? EL2 : EL1;
+ TLBIMVAA tlbiOp(target_el, haveSecurity && !scr.ns,
+ static_cast<Addr>(bits(newVal, 43, 0)) << 12);
tlbiOp.broadcast(tc);
return;
case MISCREG_TLBI_IPAS2E1_Xt:
case MISCREG_TLBI_IPAS2LE1_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
TLBIIPA tlbiOp(EL1, haveSecurity && !scr.ns,
static_cast<Addr>(bits(newVal, 35, 0)) << 12);
case MISCREG_TLBI_IPAS2E1IS_Xt:
case MISCREG_TLBI_IPAS2LE1IS_Xt:
{
- assert64(tc);
- scr = readMiscReg(MISCREG_SCR, tc);
+ assert64();
+ scr = readMiscReg(MISCREG_SCR);
TLBIIPA tlbiOp(EL1, haveSecurity && !scr.ns,
static_cast<Addr>(bits(newVal, 35, 0)) << 12);
{
// If a CP bit in NSACR is 0 then the corresponding bit in
// HCPTR is RAO/WI. Same applies to NSASEDIS
- secure_lookup = haveSecurity &&
- inSecureState(readMiscRegNoEffect(MISCREG_SCR),
- readMiscRegNoEffect(MISCREG_CPSR));
+ secure_lookup = haveSecurity && isSecure(tc);
if (!secure_lookup) {
RegVal oldValue = readMiscRegNoEffect(MISCREG_HCPTR);
RegVal mask =
misc_reg = MISCREG_IFAR_S;
break;
case MISCREG_ATS1CPR:
+ addressTranslation(TLB::S1CTran, BaseTLB::Read, 0, val);
+ return;
case MISCREG_ATS1CPW:
+ addressTranslation(TLB::S1CTran, BaseTLB::Write, 0, val);
+ return;
case MISCREG_ATS1CUR:
+ addressTranslation(TLB::S1CTran, BaseTLB::Read,
+ TLB::UserMode, val);
+ return;
case MISCREG_ATS1CUW:
+ addressTranslation(TLB::S1CTran, BaseTLB::Write,
+ TLB::UserMode, val);
+ return;
case MISCREG_ATS12NSOPR:
+ if (!haveSecurity)
+ panic("Security Extensions required for ATS12NSOPR");
+ addressTranslation(TLB::S1S2NsTran, BaseTLB::Read, 0, val);
+ return;
case MISCREG_ATS12NSOPW:
+ if (!haveSecurity)
+ panic("Security Extensions required for ATS12NSOPW");
+ addressTranslation(TLB::S1S2NsTran, BaseTLB::Write, 0, val);
+ return;
case MISCREG_ATS12NSOUR:
+ if (!haveSecurity)
+ panic("Security Extensions required for ATS12NSOUR");
+ addressTranslation(TLB::S1S2NsTran, BaseTLB::Read,
+ TLB::UserMode, val);
+ return;
case MISCREG_ATS12NSOUW:
+ if (!haveSecurity)
+ panic("Security Extensions required for ATS12NSOUW");
+ addressTranslation(TLB::S1S2NsTran, BaseTLB::Write,
+ TLB::UserMode, val);
+ return;
case MISCREG_ATS1HR:
+ addressTranslation(TLB::HypMode, BaseTLB::Read, 0, val);
+ return;
case MISCREG_ATS1HW:
- {
- Request::Flags flags = 0;
- BaseTLB::Mode mode = BaseTLB::Read;
- TLB::ArmTranslationType tranType = TLB::NormalTran;
- Fault fault;
- switch(misc_reg) {
- case MISCREG_ATS1CPR:
- flags = TLB::MustBeOne;
- tranType = TLB::S1CTran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_ATS1CPW:
- flags = TLB::MustBeOne;
- tranType = TLB::S1CTran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_ATS1CUR:
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1CTran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_ATS1CUW:
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1CTran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_ATS12NSOPR:
- if (!haveSecurity)
- panic("Security Extensions required for ATS12NSOPR");
- flags = TLB::MustBeOne;
- tranType = TLB::S1S2NsTran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_ATS12NSOPW:
- if (!haveSecurity)
- panic("Security Extensions required for ATS12NSOPW");
- flags = TLB::MustBeOne;
- tranType = TLB::S1S2NsTran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_ATS12NSOUR:
- if (!haveSecurity)
- panic("Security Extensions required for ATS12NSOUR");
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1S2NsTran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_ATS12NSOUW:
- if (!haveSecurity)
- panic("Security Extensions required for ATS12NSOUW");
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1S2NsTran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_ATS1HR: // only really useful from secure mode.
- flags = TLB::MustBeOne;
- tranType = TLB::HypMode;
- mode = BaseTLB::Read;
- break;
- case MISCREG_ATS1HW:
- flags = TLB::MustBeOne;
- tranType = TLB::HypMode;
- mode = BaseTLB::Write;
- break;
- }
- // If we're in timing mode then doing the translation in
- // functional mode then we're slightly distorting performance
- // results obtained from simulations. The translation should be
- // done in the same mode the core is running in. NOTE: This
- // can't be an atomic translation because that causes problems
- // with unexpected atomic snoop requests.
- warn("Translating via %s in functional mode! Fix Me!\n",
- miscRegName[misc_reg]);
-
- auto req = std::make_shared<Request>(
- 0, val, 0, flags, Request::funcMasterId,
- tc->pcState().pc(), tc->contextId());
-
- fault = getDTBPtr(tc)->translateFunctional(
- req, tc, mode, tranType);
-
- TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
- HCR hcr = readMiscRegNoEffect(MISCREG_HCR);
-
- RegVal newVal;
- if (fault == NoFault) {
- Addr paddr = req->getPaddr();
- if (haveLPAE && (ttbcr.eae || tranType & TLB::HypMode ||
- ((tranType & TLB::S1S2NsTran) && hcr.vm) )) {
- newVal = (paddr & mask(39, 12)) |
- (getDTBPtr(tc)->getAttr());
- } else {
- newVal = (paddr & 0xfffff000) |
- (getDTBPtr(tc)->getAttr());
- }
- DPRINTF(MiscRegs,
- "MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n",
- val, newVal);
- } else {
- ArmFault *armFault = static_cast<ArmFault *>(fault.get());
- armFault->update(tc);
- // Set fault bit and FSR
- FSR fsr = armFault->getFsr(tc);
-
- newVal = ((fsr >> 9) & 1) << 11;
- if (newVal) {
- // LPAE - rearange fault status
- newVal |= ((fsr >> 0) & 0x3f) << 1;
- } else {
- // VMSA - rearange fault status
- newVal |= ((fsr >> 0) & 0xf) << 1;
- newVal |= ((fsr >> 10) & 0x1) << 5;
- newVal |= ((fsr >> 12) & 0x1) << 6;
- }
- newVal |= 0x1; // F bit
- newVal |= ((armFault->iss() >> 7) & 0x1) << 8;
- newVal |= armFault->isStage2() ? 0x200 : 0;
- DPRINTF(MiscRegs,
- "MISCREG: Translated addr 0x%08x fault fsr %#x: PAR: 0x%08x\n",
- val, fsr, newVal);
- }
- setMiscRegNoEffect(MISCREG_PAR, newVal);
- return;
- }
+ addressTranslation(TLB::HypMode, BaseTLB::Write, 0, val);
+ return;
case MISCREG_TTBCR:
{
TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
newVal = (newVal & ttbcrMask) | (ttbcr & (~ttbcrMask));
}
// Invalidate TLB MiscReg
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
}
case MISCREG_TTBR0:
}
}
// Invalidate TLB MiscReg
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
break;
}
case MISCREG_SCTLR_EL1:
case MISCREG_DACR:
case MISCREG_VTTBR:
case MISCREG_SCR_EL3:
- case MISCREG_HCR_EL2:
case MISCREG_TCR_EL1:
case MISCREG_TCR_EL2:
case MISCREG_TCR_EL3:
case MISCREG_TTBR0_EL2:
case MISCREG_TTBR1_EL2:
case MISCREG_TTBR0_EL3:
- getITBPtr(tc)->invalidateMiscReg();
- getDTBPtr(tc)->invalidateMiscReg();
+ getMMUPtr(tc)->invalidateMiscReg();
+ break;
+ case MISCREG_HCR_EL2:
+ {
+ const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
+ selfDebug->setenableTDETGE((HCR)val, mdcr);
+ getMMUPtr(tc)->invalidateMiscReg();
+ }
break;
case MISCREG_NZCV:
{
misc_reg = MISCREG_CPSR;
}
break;
+ case MISCREG_PAN:
+ {
+ // PAN is affecting data accesses
+ getMMUPtr(tc)->invalidateMiscReg(MMU::D_TLBS);
+
+ CPSR cpsr = miscRegs[MISCREG_CPSR];
+ cpsr.pan = (uint8_t) ((CPSR) newVal).pan;
+ newVal = cpsr;
+ misc_reg = MISCREG_CPSR;
+ }
+ break;
case MISCREG_AT_S1E1R_Xt:
+ addressTranslation64(TLB::S1E1Tran, BaseTLB::Read, 0, val);
+ return;
case MISCREG_AT_S1E1W_Xt:
+ addressTranslation64(TLB::S1E1Tran, BaseTLB::Write, 0, val);
+ return;
case MISCREG_AT_S1E0R_Xt:
+ addressTranslation64(TLB::S1E0Tran, BaseTLB::Read,
+ TLB::UserMode, val);
+ return;
case MISCREG_AT_S1E0W_Xt:
+ addressTranslation64(TLB::S1E0Tran, BaseTLB::Write,
+ TLB::UserMode, val);
+ return;
case MISCREG_AT_S1E2R_Xt:
+ addressTranslation64(TLB::S1E2Tran, BaseTLB::Read, 0, val);
+ return;
case MISCREG_AT_S1E2W_Xt:
+ addressTranslation64(TLB::S1E2Tran, BaseTLB::Write, 0, val);
+ return;
case MISCREG_AT_S12E1R_Xt:
+ addressTranslation64(TLB::S12E1Tran, BaseTLB::Read, 0, val);
+ return;
case MISCREG_AT_S12E1W_Xt:
+ addressTranslation64(TLB::S12E1Tran, BaseTLB::Write, 0, val);
+ return;
case MISCREG_AT_S12E0R_Xt:
+ addressTranslation64(TLB::S12E0Tran, BaseTLB::Read,
+ TLB::UserMode, val);
+ return;
case MISCREG_AT_S12E0W_Xt:
+ addressTranslation64(TLB::S12E0Tran, BaseTLB::Write,
+ TLB::UserMode, val);
+ return;
case MISCREG_AT_S1E3R_Xt:
+ addressTranslation64(TLB::S1E3Tran, BaseTLB::Read, 0, val);
+ return;
case MISCREG_AT_S1E3W_Xt:
- {
- RequestPtr req = std::make_shared<Request>();
- Request::Flags flags = 0;
- BaseTLB::Mode mode = BaseTLB::Read;
- TLB::ArmTranslationType tranType = TLB::NormalTran;
- Fault fault;
- switch(misc_reg) {
- case MISCREG_AT_S1E1R_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S1E1Tran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_AT_S1E1W_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S1E1Tran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_AT_S1E0R_Xt:
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1E0Tran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_AT_S1E0W_Xt:
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1E0Tran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_AT_S1E2R_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S1E2Tran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_AT_S1E2W_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S1E2Tran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_AT_S12E0R_Xt:
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S12E0Tran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_AT_S12E0W_Xt:
- flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S12E0Tran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_AT_S12E1R_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S12E1Tran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_AT_S12E1W_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S12E1Tran;
- mode = BaseTLB::Write;
- break;
- case MISCREG_AT_S1E3R_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S1E3Tran;
- mode = BaseTLB::Read;
- break;
- case MISCREG_AT_S1E3W_Xt:
- flags = TLB::MustBeOne;
- tranType = TLB::S1E3Tran;
- mode = BaseTLB::Write;
- break;
- }
- // If we're in timing mode then doing the translation in
- // functional mode then we're slightly distorting performance
- // results obtained from simulations. The translation should be
- // done in the same mode the core is running in. NOTE: This
- // can't be an atomic translation because that causes problems
- // with unexpected atomic snoop requests.
- warn("Translating via %s in functional mode! Fix Me!\n",
- miscRegName[misc_reg]);
-
- req->setVirt(0, val, 0, flags, Request::funcMasterId,
- tc->pcState().pc());
- req->setContext(tc->contextId());
- fault = getDTBPtr(tc)->translateFunctional(req, tc, mode,
- tranType);
-
- RegVal newVal;
- if (fault == NoFault) {
- Addr paddr = req->getPaddr();
- uint64_t attr = getDTBPtr(tc)->getAttr();
- uint64_t attr1 = attr >> 56;
- if (!attr1 || attr1 ==0x44) {
- attr |= 0x100;
- attr &= ~ uint64_t(0x80);
- }
- newVal = (paddr & mask(47, 12)) | attr;
- DPRINTF(MiscRegs,
- "MISCREG: Translated addr %#x: PAR_EL1: %#xx\n",
- val, newVal);
- } else {
- ArmFault *armFault = static_cast<ArmFault *>(fault.get());
- armFault->update(tc);
- // Set fault bit and FSR
- FSR fsr = armFault->getFsr(tc);
-
- CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
- if (cpsr.width) { // AArch32
- newVal = ((fsr >> 9) & 1) << 11;
- // rearrange fault status
- newVal |= ((fsr >> 0) & 0x3f) << 1;
- newVal |= 0x1; // F bit
- newVal |= ((armFault->iss() >> 7) & 0x1) << 8;
- newVal |= armFault->isStage2() ? 0x200 : 0;
- } else { // AArch64
- newVal = 1; // F bit
- newVal |= fsr << 1; // FST
- // TODO: DDI 0487A.f D7-2083, AbortFault's s1ptw bit.
- newVal |= armFault->isStage2() ? 1 << 8 : 0; // PTW
- newVal |= armFault->isStage2() ? 1 << 9 : 0; // S
- newVal |= 1 << 11; // RES1
- }
- DPRINTF(MiscRegs,
- "MISCREG: Translated addr %#x fault fsr %#x: PAR: %#x\n",
- val, fsr, newVal);
- }
- setMiscRegNoEffect(MISCREG_PAR_EL1, newVal);
- return;
- }
+ addressTranslation64(TLB::S1E3Tran, BaseTLB::Write, 0, val);
+ return;
case MISCREG_SPSR_EL3:
case MISCREG_SPSR_EL2:
case MISCREG_SPSR_EL1:
- // Force bits 23:21 to 0
- newVal = val & ~(0x7 << 21);
- break;
+ {
+ RegVal spsr_mask = havePAN ?
+ ~(0x2 << 22) : ~(0x3 << 22);
+
+ newVal = val & spsr_mask;
+ break;
+ }
case MISCREG_L2CTLR:
warn("miscreg L2CTLR (%s) written with %#x. ignored...\n",
miscRegName[misc_reg], uint32_t(val));
break;
// Generic Timer registers
- case MISCREG_CNTHV_CTL_EL2:
- case MISCREG_CNTHV_CVAL_EL2:
- case MISCREG_CNTHV_TVAL_EL2:
- case MISCREG_CNTFRQ ... MISCREG_CNTHP_CTL:
- case MISCREG_CNTPCT ... MISCREG_CNTHP_CVAL:
- case MISCREG_CNTKCTL_EL1 ... MISCREG_CNTV_CVAL_EL0:
- case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
- getGenericTimer(tc).setMiscReg(misc_reg, newVal);
+ case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+ case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
+ getGenericTimer().setMiscReg(misc_reg, newVal);
break;
-
+ case MISCREG_ICC_AP0R0 ... MISCREG_ICH_LRC15:
case MISCREG_ICC_PMR_EL1 ... MISCREG_ICC_IGRPEN1_EL3:
case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_LR15_EL2:
- getGICv3CPUInterface(tc).setMiscReg(misc_reg, newVal);
+ getGICv3CPUInterface().setMiscReg(misc_reg, newVal);
return;
+ case MISCREG_ZCR_EL3:
+ case MISCREG_ZCR_EL2:
+ case MISCREG_ZCR_EL1:
+ tc->getDecoderPtr()->setSveLen((getCurSveVecLenInBits() >> 7) - 1);
+ break;
}
}
setMiscRegNoEffect(misc_reg, newVal);
}
BaseISADevice &
-ISA::getGenericTimer(ThreadContext *tc)
+ISA::getGenericTimer()
{
// We only need to create an ISA interface the first time we try
// to access the timer.
}
BaseISADevice &
-ISA::getGICv3CPUInterface(ThreadContext *tc)
+ISA::getGICv3CPUInterface()
{
panic_if(!gicv3CpuInterface, "GICV3 cpu interface is not registered!");
return *gicv3CpuInterface.get();
}
+unsigned
+ISA::getCurSveVecLenInBits() const
+{
+ if (!FullSystem) {
+ return sveVL * 128;
+ }
+
+ panic_if(!tc,
+ "A ThreadContext is needed to determine the SVE vector length "
+ "in full-system mode");
+
+ CPSR cpsr = miscRegs[MISCREG_CPSR];
+ ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
+
+ unsigned len = 0;
+
+ if (el == EL1 || (el == EL0 && !ELIsInHost(tc, el))) {
+ len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL1]).len;
+ }
+
+ if (el == EL2 || (el == EL0 && ELIsInHost(tc, el))) {
+ len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL2]).len;
+ } else if (haveVirtualization && !isSecure(tc) &&
+ (el == EL0 || el == EL1)) {
+ len = std::min(
+ len,
+ static_cast<unsigned>(
+ static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL2]).len));
+ }
+
+ if (el == EL3) {
+ len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL3]).len;
+ } else if (haveSecurity) {
+ len = std::min(
+ len,
+ static_cast<unsigned>(
+ static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL3]).len));
+ }
+
+ len = std::min(len, sveVL - 1);
+
+ return (len + 1) * 128;
+}
+
+void
+ISA::zeroSveVecRegUpperPart(VecRegContainer &vc, unsigned eCount)
+{
+ auto vv = vc.as<uint64_t>();
+ for (int i = 2; i < eCount; ++i) {
+ vv[i] = 0;
+ }
}
-ArmISA::ISA *
-ArmISAParams::create()
+void
+ISA::serialize(CheckpointOut &cp) const
{
- return new ArmISA::ISA(this);
+ DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
+ SERIALIZE_MAPPING(miscRegs, miscRegName, NUM_PHYS_MISCREGS);
}
+
+void
+ISA::unserialize(CheckpointIn &cp)
+{
+ DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
+ UNSERIALIZE_MAPPING(miscRegs, miscRegName, NUM_PHYS_MISCREGS);
+ CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
+ updateRegMap(tmp_cpsr);
+}
+
+void
+ISA::addressTranslation64(TLB::ArmTranslationType tran_type,
+ BaseTLB::Mode mode, Request::Flags flags, RegVal val)
+{
+ // If we're in timing mode then doing the translation in
+ // functional mode then we're slightly distorting performance
+ // results obtained from simulations. The translation should be
+ // done in the same mode the core is running in. NOTE: This
+ // can't be an atomic translation because that causes problems
+ // with unexpected atomic snoop requests.
+ warn_once("Doing AT (address translation) in functional mode! Fix Me!\n");
+
+ auto req = std::make_shared<Request>(
+ val, 0, flags, Request::funcRequestorId,
+ tc->pcState().pc(), tc->contextId());
+
+ Fault fault = getMMUPtr(tc)->translateFunctional(
+ req, tc, mode, tran_type);
+
+ PAR par = 0;
+ if (fault == NoFault) {
+ Addr paddr = req->getPaddr();
+ uint64_t attr = getMMUPtr(tc)->getAttr();
+ uint64_t attr1 = attr >> 56;
+ if (!attr1 || attr1 ==0x44) {
+ attr |= 0x100;
+ attr &= ~ uint64_t(0x80);
+ }
+ par = (paddr & mask(47, 12)) | attr;
+ DPRINTF(MiscRegs,
+ "MISCREG: Translated addr %#x: PAR_EL1: %#xx\n",
+ val, par);
+ } else {
+ ArmFault *arm_fault = static_cast<ArmFault *>(fault.get());
+ arm_fault->update(tc);
+ // Set fault bit and FSR
+ FSR fsr = arm_fault->getFsr(tc);
+
+ par.f = 1; // F bit
+ par.fst = fsr.status; // FST
+ par.ptw = (arm_fault->iss() >> 7) & 0x1; // S1PTW
+ par.s = arm_fault->isStage2() ? 1 : 0; // S
+
+ DPRINTF(MiscRegs,
+ "MISCREG: Translated addr %#x fault fsr %#x: PAR: %#x\n",
+ val, fsr, par);
+ }
+ setMiscRegNoEffect(MISCREG_PAR_EL1, par);
+ return;
+}
+
+void
+ISA::addressTranslation(TLB::ArmTranslationType tran_type,
+ BaseTLB::Mode mode, Request::Flags flags, RegVal val)
+{
+ // If we're in timing mode then doing the translation in
+ // functional mode then we're slightly distorting performance
+ // results obtained from simulations. The translation should be
+ // done in the same mode the core is running in. NOTE: This
+ // can't be an atomic translation because that causes problems
+ // with unexpected atomic snoop requests.
+ warn_once("Doing AT (address translation) in functional mode! Fix Me!\n");
+
+ auto req = std::make_shared<Request>(
+ val, 0, flags, Request::funcRequestorId,
+ tc->pcState().pc(), tc->contextId());
+
+ Fault fault = getMMUPtr(tc)->translateFunctional(
+ req, tc, mode, tran_type);
+
+ PAR par = 0;
+ if (fault == NoFault) {
+ Addr paddr = req->getPaddr();
+ TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
+ HCR hcr = readMiscRegNoEffect(MISCREG_HCR);
+
+ uint8_t max_paddr_bit = 0;
+ if (haveLPAE && (ttbcr.eae || tran_type & TLB::HypMode ||
+ ((tran_type & TLB::S1S2NsTran) && hcr.vm) )) {
+
+ max_paddr_bit = 39;
+ } else {
+ max_paddr_bit = 31;
+ }
+
+ par = (paddr & mask(max_paddr_bit, 12)) |
+ (getMMUPtr(tc)->getAttr());
+
+ DPRINTF(MiscRegs,
+ "MISCREG: Translated addr 0x%08x: PAR: 0x%08x\n",
+ val, par);
+ } else {
+ ArmFault *arm_fault = static_cast<ArmFault *>(fault.get());
+ arm_fault->update(tc);
+ // Set fault bit and FSR
+ FSR fsr = arm_fault->getFsr(tc);
+
+ par.f = 0x1; // F bit
+ par.lpae = fsr.lpae;
+ par.ptw = (arm_fault->iss() >> 7) & 0x1;
+ par.s = arm_fault->isStage2() ? 1 : 0;
+
+ if (par.lpae) {
+ // LPAE - rearange fault status
+ par.fst = fsr.status;
+ } else {
+ // VMSA - rearange fault status
+ par.fs4_0 = fsr.fsLow | (fsr.fsHigh << 5);
+ par.fs5 = fsr.ext;
+ }
+ DPRINTF(MiscRegs,
+ "MISCREG: Translated addr 0x%08x fault fsr %#x: PAR: 0x%08x\n",
+ val, fsr, par);
+ }
+ setMiscRegNoEffect(MISCREG_PAR, par);
+ return;
+}
+
+ISA::MiscRegLUTEntryInitializer::chain
+ISA::MiscRegLUTEntryInitializer::highest(ArmSystem *const sys) const
+{
+ switch (FullSystem ? sys->highestEL() : EL1) {
+ case EL0:
+ case EL1: priv(); break;
+ case EL2: hyp(); break;
+ case EL3: mon(); break;
+ }
+ return *this;
+}
+
+} // namespace ArmISA