"True if LSE is implemented (ARMv8.1)")
have_pan = Param.Bool(True,
"True if Priviledge Access Never is implemented (ARMv8.1)")
+ have_secel2 = Param.Bool(True,
+ "True if Secure EL2 is implemented (ARMv8)")
semihosting = Param.ArmSemihosting(NULL,
"Enable support for the Arm semihosting by settings this parameter")
break;
}
- Iris::CanonicalMsn out_msn = inSecureState(this) ?
+ Iris::CanonicalMsn out_msn = isSecure(this) ?
Iris::PhysicalMemorySecureMsn : Iris::PhysicalMemoryNonSecureMsn;
// Figure out what memory spaces match the canonical numbers we need.
} else {
bool lower_32 = false;
if (toEL == EL3) {
- if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
+ if (EL2Enabled(tc))
lower_32 = ELIs32(tc, EL2);
else
lower_32 = ELIs32(tc, EL1);
+ } else if (ELIsInHost(tc, fromEL) && fromEL == EL0 && toEL == EL2) {
+ lower_32 = ELIs32(tc, EL0);
} else {
lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
}
HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
toHyp = fromEL == EL2;
- toHyp |= ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
+ toHyp |= ArmSystem::haveEL(tc, EL2) && !isSecure(tc) &&
currEL(tc) <= EL1 && (hcr.tge || stage2 ||
(source == DebugEvent && hdcr.tde));
return toHyp;
const auto tc = xc->tcBase();
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
- if ((ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
- !ELIs32(tc, EL2) && (hcr.tge == 1 || mdcr.tde == 1)) ||
- !ELIs32(tc, EL1)) {
+ if ((EL2Enabled(tc) && !ELIs32(tc, EL2) &&
+ (hcr.tge || mdcr.tde)) || !ELIs32(tc, EL1)) {
// Route to AArch64 Software Breakpoint
return std::make_shared<SoftwareBreakpoint>(machInst, imm);
} else {
{
const bool have_virtualization = ArmSystem::haveVirtualization(tc);
const bool have_security = ArmSystem::haveSecurity(tc);
- const bool is_secure = inSecureState(tc);
+ const bool is_secure = isSecure(tc);
const ExceptionLevel cur_el = currEL(tc);
if (cur_el == EL0 && ELIs64(tc, EL1))
fault = checkForWFxTrap32(tc, EL1, isWfe);
}
- if ((fault == NoFault) &&
- ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) &&
+ if ((fault == NoFault) && EL2Enabled(tc) &&
((curr_el == EL0) || (curr_el == EL1))) {
fault = checkForWFxTrap32(tc, EL2, isWfe);
// Get the index of the banked version of SCTLR:
// SCTLR_s or SCTLR_ns.
auto banked_sctlr = snsBankedIndex(
- MISCREG_SCTLR, tc, !inSecureState(tc));
+ MISCREG_SCTLR, tc, !isSecure(tc));
// SCTLR.SED bit is enabling/disabling the ue of SETEND instruction.
setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed;
if (unknownMode(mode))
return true;
- const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
- const ExceptionLevel target_el = opModeToEL(mode);
+ SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
+ HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
- HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
- SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3));
-
- if (target_el > opModeToEL(cur_mode))
- return true;
-
- if (!ArmSystem::haveEL(tc, target_el))
- return true;
-
- if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge)
+ //ELFromSPSR
+ bool valid;
+ ExceptionLevel target_el = opModeToEL(mode);
+ if (!spsr.width) {
+ if (!ArmSystem::highestELIs64(tc)) {
+ valid = false;
+ } else if (!ArmSystem::haveEL(tc, target_el)) {
+ valid = false;
+ } else if (spsr & 0x2) {
+ valid = false;
+ } else if (target_el == EL0 && spsr.sp) {
+ valid = false;
+ } else if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) &&
+ !scr.ns && !IsSecureEL2Enabled(tc)) {
+ valid = false;
+ } else {
+ valid = true;
+ }
+ } else {
+ valid = !unknownMode32(mode);
+ }
+ if (!valid)
return true;
- if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) && !scr.ns)
+ if (target_el > currEL(tc))
return true;
bool spsr_mode_is_aarch32 = (spsr.width == 1);
if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32))
return true;
- if (!spsr.width) {
- // aarch64
- if (!ArmSystem::highestELIs64(tc))
- return true;
- if (spsr & 0x2)
- return true;
- if (target_el == EL0 && spsr.sp)
- return true;
- } else {
- // aarch32
- return unknownMode32(mode);
+ if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && hcr.tge &&
+ (IsSecureEL2Enabled(tc) || !isSecureBelowEL3(tc))) {
+ return true;
}
return false;
// AArch64 or TGE is in force and EL2 is using AArch64.
HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
return (pstateEL == EL0 && !ELIs32(tc, EL1)) ||
- (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
+ (ArmSystem::haveEL(tc, EL2) && !isSecure(tc) &&
!ELIs32(tc, EL2) && hcr.tge);
}
{
bool privileged = (cpsr.mode != MODE_USER);
bool haveVirt = ArmSystem::haveVirtualization(tc);
- bool haveSecurity = ArmSystem::haveSecurity(tc);
- bool isSecure = inSecureState(scr, cpsr) || !haveSecurity;
+ bool isSecure = ArmISA::isSecure(tc);
uint32_t bitMask = 0;
else
scr = tc->readMiscReg(MISCREG_SCR_EL3);
- bool is_secure = inSecureState(tc);
+ bool is_secure = isSecure(tc);
switch(int_type) {
case INT_FIQ:
}
bool isHypMode = currEL(tc) == EL2;
- bool isSecure = inSecureState(tc);
+ bool isSecure = ArmISA::isSecure(tc);
bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode;
bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode;
bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
virtWake = (hcr.vi || interrupts[INT_VIRT_IRQ]) && hcr.imo;
virtWake |= (hcr.vf || interrupts[INT_VIRT_FIQ]) && hcr.fmo;
virtWake |= hcr.va && hcr.amo;
- virtWake &= (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr);
+ virtWake &= (cpsr.mode != MODE_HYP) && !isSecure(tc);
return maskedIntStatus || virtWake;
}
bool useHcrMux;
CPSR isr = 0; // ARM ARM states ISR reg uses same bit possitions as CPSR
- useHcrMux = (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr);
+ useHcrMux = (cpsr.mode != MODE_HYP) && !isSecure(tc);
isr.i = (useHcrMux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi)
: interrupts[INT_IRQ];
isr.f = (useHcrMux & hcr.fmo) ? (interrupts[INT_VIRT_FIQ] || hcr.vf)
// virtual interrupt, and if its allowed to happen
// ARM ARM Issue C section B1.9.9, B1.9.11, and B1.9.13
bool isHypMode = currEL(tc) == EL2;
- bool isSecure = inSecureState(tc);
+ bool isSecure = ArmISA::isSecure(tc);
bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode;
bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode;
bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
physAddrRange = system->physAddrRange();
haveSVE = system->haveSVE();
havePAN = system->havePAN();
+ haveSecEL2 = system->haveSecEL2();
sveVL = system->sveVL();
haveLSE = system->haveLSE();
} else {
physAddrRange = 32; // dummy value
haveSVE = true;
havePAN = false;
+ haveSecEL2 = true;
sveVL = p->sve_vl_se;
haveLSE = true;
}
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,
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);
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;
(haveVirtualization ? 0x0000000000000200 : 0) | // EL2
(haveSecurity ? 0x0000000000002000 : 0) | // EL3
(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)
{
// 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 =
if (el == EL2 || (el == EL0 && ELIsInHost(tc, el))) {
len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL2]).len;
- } else if (haveVirtualization && !inSecureState(tc) &&
+ } else if (haveVirtualization && !isSecure(tc) &&
(el == EL0 || el == EL1)) {
len = std::min(
len,
bool haveSVE;
bool haveLSE;
bool havePAN;
+ bool haveSecEL2;
/** SVE vector length in quadwords */
unsigned sveVL;
if (hcr.e2h == 0x0 || currEL(tc) != EL2)
return misc_reg;
SCR scr = readMiscRegNoEffect(MISCREG_SCR_EL3);
- bool sec_el2 = scr.eel2 && false;
+ bool sec_el2 = scr.eel2 && haveSecEL2;
switch(misc_reg) {
case MISCREG_SPSR_EL1:
return MISCREG_SPSR_EL2;
bxjcode = '''
HSTR hstr = Hstr;
CPSR cpsr = Cpsr;
- SCR scr = Scr;
if (ArmSystem::haveVirtualization(xc->tcBase()) && hstr.tjdbx &&
- !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
- fault = std::make_shared<HypervisorTrap>(machInst, op1, EC_TRAPPED_BXJ);
+ !isSecure(xc->tcBase()) && (cpsr.mode != MODE_HYP)) {
+ fault = std::make_shared<HypervisorTrap>(machInst, op1, EC_TRAPPED_BXJ);
}
IWNPC = Op1;
'''
vmrsCode = vmrsEnabledCheckCode + '''
CPSR cpsr = Cpsr;
- SCR scr = Scr;
- if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
+ if (!isSecure(xc->tcBase()) && (cpsr.mode != MODE_HYP)) {
HCR hcr = Hcr;
bool hypTrap = false;
switch(xc->tcBase()->flattenRegId(RegId(MiscRegClass, op1)).index()) {
SCR scr = Scr;
if ((cpsr.mode != MODE_USER) && FullSystem) {
- if (ArmSystem::haveVirtualization(xc->tcBase()) &&
- !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP) && hcr.tsc) {
+ if (EL2Enabled(xc->tcBase()) && (cpsr.mode != MODE_HYP) && hcr.tsc) {
fault = std::make_shared<HypervisorTrap>(machInst, 0,
EC_SMC_TO_HYP);
} else {
hvcCode = '''
CPSR cpsr = Cpsr;
- SCR scr = Scr;
// Filter out the various cases where this instruction isn't defined
if (!FullSystem || !ArmSystem::haveVirtualization(xc->tcBase()) ||
(cpsr.mode == MODE_USER) ||
- (ArmSystem::haveSecurity(xc->tcBase()) && (!scr.ns || !scr.hce))) {
+ (isSecure(xc->tcBase()) && !IsSecureEL2Enabled(xc->tcBase()))) {
fault = disabledFault();
} else {
fault = std::make_shared<HypervisorCall>(machInst, imm);
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
- !inSecureState(Scr, Cpsr)))) {
+ !isSecure(xc->tcBase())))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
- !inSecureState(Scr, Cpsr)))) {
+ !isSecure(xc->tcBase())))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
- !inSecureState(Scr, Cpsr)))) {
+ !isSecure(xc->tcBase())))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
- !inSecureState(Scr, Cpsr)))) {
+ !isSecure(xc->tcBase())))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
// of whether the register is accessible, in other modes we
// trap if only if the register IS accessible.
if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) &
- !inSecureState(Scr, Cpsr)))) {
+ !isSecure(xc->tcBase())))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
ExceptionLevel pstate_EL = (ExceptionLevel)(uint8_t)(cpsr.el);
bool unalloc_encod = !ArmSystem::haveEL(tc, EL2) || pstate_EL == EL0 ||
- (pstate_EL == EL1 && inSecureState(tc));
+ (pstate_EL == EL1 && (!IsSecureEL2Enabled(tc) &&
+ isSecure(tc)));
bool hvc_enable = ArmSystem::haveEL(tc, EL3) ?
scr.hce : !hcr.hcd;
return MISCREG_VTCR_EL2;
}
break;
+ case 6:
+ switch (op2) {
+ case 0:
+ return MISCREG_VSTTBR_EL2;
+ case 2:
+ return MISCREG_VSTCR_EL2;
+ }
+ break;
}
break;
case 5:
InitReg(MISCREG_VTCR_EL2)
.hyp().mon()
.mapsTo(MISCREG_VTCR);
+ InitReg(MISCREG_VSTTBR_EL2)
+ .hyp().mon();
+ InitReg(MISCREG_VSTCR_EL2)
+ .hyp().mon();
InitReg(MISCREG_TTBR0_EL3)
.mon();
InitReg(MISCREG_TCR_EL3)
MISCREG_TCR_EL2,
MISCREG_VTTBR_EL2,
MISCREG_VTCR_EL2,
+ MISCREG_VSTTBR_EL2,
+ MISCREG_VSTCR_EL2,
MISCREG_TTBR0_EL3,
MISCREG_TCR_EL3,
MISCREG_DACR32_EL2,
"tcr_el2",
"vttbr_el2",
"vtcr_el2",
+ "vsttbr_el2",
+ "vstcr_el2",
"ttbr0_el3",
"tcr_el3",
"dacr32_el2",
bool secure, bool mask)
{
bool route_to_el2 = ArmSystem::haveEL(tc, EL2) &&
- !secure && enableTdeTge;
+ (!secure || HaveSecureEL2Ext(tc)) && enableTdeTge;
ExceptionLevel target_el = route_to_el2 ? EL2 : EL1;
if (oslk || (bSDD && secure && ArmSystem::haveEL(tc, EL3))) {
break;
case 0x8:
- if (ArmSystem::haveEL(tc, EL2) && !ELIsInHost(tc, el)) {
+ if (EL2Enabled(tc) && !ELIsInHost(tc, el)) {
v = testVMIDMatch(tc);
}
break;
case 0x9:
- if (from_link && ArmSystem::haveEL(tc, EL2) &&
- !ELIsInHost(tc, el)) {
+ if (from_link && EL2Enabled(tc) && !ELIsInHost(tc, el)) {
v = testVMIDMatch(tc);
}
break;
case 0xa:
- if (ArmSystem::haveEL(tc, EL2) && !ELIsInHost(tc, el)) {
+ if (EL2Enabled(tc) && !ELIsInHost(tc, el)) {
v = testContextMatch(tc, true);
if (v && !from_link)
v = v && testVMIDMatch(tc);
}
break;
case 0xb:
- if (from_link && ArmSystem::haveEL(tc, EL2) &&
- !ELIsInHost(tc, el)) {
+ if (from_link && EL2Enabled(tc) && !ELIsInHost(tc, el)) {
v = testContextMatch(tc, true);
v = v && testVMIDMatch(tc);
}
break;
case 0xc:
- if (HaveVirtHostExt(tc) && !inSecureState(tc))
+ if (HaveVirtHostExt(tc) && (!isSecure(tc)|| HaveSecureEL2Ext(tc)))
v = testContextMatch(tc, false);
break;
case 0xd:
- if (HaveVirtHostExt(tc) && from_link && !inSecureState(tc))
- v = testContextMatch(tc, false);
+ if (HaveVirtHostExt(tc) && from_link &&
+ (!isSecure(tc)|| HaveSecureEL2Ext(tc))) {
+ v = testContextMatch(tc, false);
+ }
break;
case 0xe:
- if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el)
- && !inSecureState(tc) ) {
+ if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) &&
+ (!isSecure(tc)|| HaveSecureEL2Ext(tc))) {
v = testContextMatch(tc, true); // CONTEXTIDR_EL1
v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
}
break;
case 0xf:
- if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) && from_link
- && !inSecureState(tc) ) {
+ if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) && from_link &&
+ (!isSecure(tc)|| HaveSecureEL2Ext(tc))) {
v = testContextMatch(tc, true); // CONTEXTIDR_EL1
v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
}
bool enabled_dst = false;
bool secure = isSecureBelowEL3(tc) || dest == EL3;
- CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
- if (cpsr.width) {
+// CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+// if (cpsr.width) {
+ if (ELIs32(tc, dest)) {
enabled_dst = conf->isDebugEnabledForEL32(tc, dest, secure,
spsr.d == 1);
} else {
Addr vaddress = addr & ~ 0x1f;
Addr low_addr = bits(addr, 5, 2);
if (vaddress == vbase) {
- if (ArmSystem::haveEL(tc, EL3) && !inSecureState(tc)) {
+ if (ArmSystem::haveEL(tc, EL3) && !isSecure(tc)) {
uint32_t bmask = 1UL << (low_addr + 24);
match_word = match_word | (DBGVCR) bmask;
// Non-secure vectors
}
uint32_t mvbase = getVectorBase(tc, true);
if (ArmSystem::haveEL(tc, EL3) && ELIs32(tc, EL3) &&
- inSecureState(tc) && (vaddress == mvbase)) {
+ isSecure(tc) && (vaddress == mvbase)) {
uint32_t bmask = 1UL << (low_addr + 8);
match_word = match_word | (DBGVCR) bmask;
// Monitor vectors
enabled = match_word != 0x0;
// Check for UNPREDICTABLE case - match on Prefetch Abort and
// Data Abort vectors
- ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
+ ExceptionLevel ELd = debugTargetFrom(tc, isSecure(tc));
if (((match_word & 0x18001818) != 0x0) && ELd == el) {
enabled = false;
}
} else if (ELIs32(tc, EL3) && fault->getToMode() == MODE_MON) {
mask = (DBGVCR) 0x0000DE00;
} else {
- if (inSecureState(tc))
+ if (isSecure(tc))
mask = (DBGVCR) 0x000000DE;
else
mask = (DBGVCR) 0xDE000000;
{
switch (ssc) {
case 0x0: return true;
- case 0x1: return !inSecureState(tc);
- case 0x2: return inSecureState(tc);
+ case 0x1: return !isSecure(tc);
+ case 0x2: return isSecure(tc);
case 0x3:
{
- bool b = hmc? true: inSecureState(tc);
+ bool b = hmc? true: isSecure(tc);
return b;
}
default: panic("Unreachable value");
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
ExceptionLevel el = (ExceptionLevel) currEL(tc);
if (aarch32) {
- return isDebugEnabledForEL32(tc, el, inSecureState(tc),
+ return isDebugEnabledForEL32(tc, el, isSecure(tc),
(bool)cpsr.d == 1);
} else {
- return isDebugEnabledForEL64(tc, el, inSecureState(tc),
+ return isDebugEnabledForEL64(tc, el, isSecure(tc),
(bool)cpsr.d == 1 );
}
}
bool
targetAArch32(ThreadContext *tc)
{
- ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
+ ExceptionLevel ELd = debugTargetFrom(tc, isSecure(tc));
return ELIs32(tc, ELd) && aarch32;
}
static std::unique_ptr<PortProxy> port_proxy_s;
static System *secure_sys = nullptr;
- if (ArmISA::inSecureState(tc)) {
+ if (ArmISA::isSecure(tc)) {
System *sys = tc->getSystemPtr();
if (sys != secure_sys) {
if (FullSystem) {
{
fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this, timing,
- functional, false, tranType);
+ functional, secure, tranType);
// Call finish if we're done already
if ((fault != NoFault) || (stage2Te != NULL)) {
// Since we directly requested the table entry (which we need later on
// if we haven't got the table entry get it now
if ((fault == NoFault) && (stage2Te == NULL)) {
fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this,
- timing, functional, false, tranType);
+ timing, functional, secure, tranType);
}
// Now we have the stage 2 table entry we need to merge it with the stage
Fault fault;
bool complete;
bool selfDelete;
+ bool secure;
public:
Stage2LookUp(TLB *s1Tlb, TLB *s2Tlb, TlbEntry s1Te, const RequestPtr &_req,
TLB::Translation *_transState, BaseTLB::Mode _mode, bool _timing,
- bool _functional, TLB::ArmTranslationType _tranType) :
+ bool _functional, bool _secure, TLB::ArmTranslationType _tranType) :
stage1Tlb(s1Tlb), stage2Tlb(s2Tlb), stage1Te(s1Te), s1Req(_req),
transState(_transState), mode(_mode), timing(_timing),
functional(_functional), tranType(_tranType), stage2Te(nullptr),
- fault(NoFault), complete(false), selfDelete(false)
+ fault(NoFault), complete(false), selfDelete(false), secure(_secure)
{
req = std::make_shared<Request>();
req->setVirt(s1Te.pAddr(s1Req->getVaddr()), s1Req->getSize(),
_sveVL(p->sve_vl),
_haveLSE(p->have_lse),
_havePAN(p->have_pan),
+ _haveSecEL2(p->have_secel2),
semihosting(p->semihosting),
multiProc(p->multi_proc)
{
/** True if Priviledge Access Never is implemented */
const unsigned _havePAN;
+ /** True if Secure EL2 is implemented */
+ const unsigned _haveSecEL2;
+
/**
* True if the Semihosting interface is enabled.
*/
/** Returns true if Priviledge Access Never is implemented */
bool havePAN() const { return _havePAN; }
+ /** Returns true if Priviledge Access Never is implemented */
+ bool haveSecEL2() const { return _haveSecEL2; }
+
/** Returns the supported physical address range in bits if the highest
* implemented exception level is 64 bits (ARMv8) */
uint8_t physAddrRange64() const { return _physAddrRange64; }
currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2);
if (isStage2) {
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
- currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR_EL2);
+ if (currState->secureLookup) {
+ currState->vtcr =
+ currState->tc->readMiscReg(MISCREG_VSTCR_EL2);
+ } else {
+ currState->vtcr =
+ currState->tc->readMiscReg(MISCREG_VTCR_EL2);
+ }
} else switch (currState->el) {
case EL0:
if (HaveVirtHostExt(currState->tc) &&
break;
case EL1:
if (isStage2) {
- DPRINTF(TLB, " - Selecting VTTBR0 (AArch64 stage 2)\n");
- ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
+ if (currState->secureLookup) {
+ DPRINTF(TLB, " - Selecting VSTTBR_EL2 (AArch64 stage 2)\n");
+ ttbr = currState->tc->readMiscReg(MISCREG_VSTTBR_EL2);
+ } else {
+ DPRINTF(TLB, " - Selecting VTTBR_EL2 (AArch64 stage 2)\n");
+ ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
+ }
tsz = 64 - currState->vtcr.t0sz64;
tg = GrainMap_tg0[currState->vtcr.tg0];
// ARM DDI 0487A.f D7-2148
bool w = is_write;
bool x = is_fetch;
+ xn = ArmSystem::haveEL(tc, EL3) && isSecure && te->ns && scr.sif;
+
// grant_read is used for faults from an atomic instruction that
// both reads and writes from a memory location. From a ISS point
// of view they count as read if a read to that address would have
cpsr = tc->readMiscReg(MISCREG_CPSR);
// Dependencies: SCR/SCR_EL3, CPSR
- isSecure = inSecureState(tc) &&
+ isSecure = ArmISA::isSecure(tc) &&
!(tranType & HypMode) && !(tranType & S1S2NsTran);
aarch64EL = tranTypeEL(cpsr, tranType);
scr = tc->readMiscReg(MISCREG_SCR_EL3);
isPriv = aarch64EL != EL0;
if (haveVirtualization) {
- vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 55, 48);
+ uint64_t vttbr = isSecure? tc->readMiscReg(MISCREG_VSTTBR_EL2):
+ tc->readMiscReg(MISCREG_VTTBR_EL2);
+ vmid = bits(vttbr, 55, 48);
isHyp = aarch64EL == EL2;
isHyp |= tranType & HypMode;
isHyp &= (tranType & S1S2NsTran) == 0;
isHyp &= (tranType & S1CTran) == 0;
+ bool vm = hcr.vm;
+ if (HaveVirtHostExt(tc) && hcr.e2h == 1 && hcr.tge ==1) {
+ vm = 0;
+ }
if (hcr.e2h == 1 && (aarch64EL == EL2
|| (hcr.tge ==1 && aarch64EL == EL0))) {
// Work out if we should skip the first stage of translation and go
// directly to stage 2. This value is cached so we don't have to
// compute it for every translation.
- bool vm = hcr.vm;
- if (HaveVirtHostExt(tc) && hcr.e2h == 1 && hcr.tge == 1) {
- vm = 0;
- }
-
+ bool sec = !isSecure || (isSecure && IsSecureEL2Enabled(tc));
stage2Req = isStage2 ||
- (vm && !isHyp && !isSecure &&
+ (vm && !isHyp && sec &&
!(tranType & S1CTran) && (aarch64EL < EL2) &&
!(tranType & S1E1Tran)); // <--- FIX THIS HACK
- stage2DescReq = isStage2 || (vm && !isHyp && !isSecure &&
+ stage2DescReq = isStage2 || (vm && !isHyp && sec &&
(aarch64EL < EL2));
directToStage2 = !isStage2 && stage2Req && !sctlr.m;
}
// Work out if we should skip the first stage of translation and go
// directly to stage 2. This value is cached so we don't have to
// compute it for every translation.
- stage2Req = hcr.vm && !isStage2 && !isHyp && !isSecure &&
+ bool sec = !isSecure || (isSecure && IsSecureEL2Enabled(tc));
+ stage2Req = hcr.vm && !isStage2 && !isHyp && sec &&
!(tranType & S1CTran);
- stage2DescReq = hcr.vm && !isStage2 && !isHyp && !isSecure;
+ stage2DescReq = hcr.vm && !isStage2 && !isHyp && sec;
directToStage2 = stage2Req && !sctlr.m;
} else {
vmid = 0;
fault = checkPermissions(s1Te, req, mode);
if (stage2Req & (fault == NoFault)) {
Stage2LookUp *s2Lookup = new Stage2LookUp(this, stage2Tlb, *s1Te,
- req, translation, mode, timing, functional, curTranType);
+ req, translation, mode, timing, functional, !(s1Te->ns),
+ curTranType);
fault = s2Lookup->getTe(tc, mergeTe);
if (s2Lookup->isComplete()) {
*te = mergeTe;
bool predicate)
: InstEntry(tarmCtx.thread, tarmCtx.pc, tarmCtx.staticInst, predicate)
{
- secureMode = inSecureState(tarmCtx.thread);
+ secureMode = isSecure(tarmCtx.thread);
auto arm_inst = static_cast<const ArmStaticInst*>(
tarmCtx.staticInst.get()
}
bool
-inSecureState(ThreadContext *tc)
+isSecure(ThreadContext *tc)
{
- SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
- tc->readMiscReg(MISCREG_SCR);
- return ArmSystem::haveSecurity(tc) && inSecureState(
- scr, tc->readMiscReg(MISCREG_CPSR));
+ CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+ if (ArmSystem::haveEL(tc, EL3) && !cpsr.width && currEL(tc) == EL3)
+ return true;
+ if (ArmSystem::haveEL(tc, EL3) && cpsr.width && cpsr.mode == MODE_MON)
+ return true;
+ else
+ return isSecureBelowEL3(tc);
}
bool
debugTargetFrom(ThreadContext *tc, bool secure)
{
bool route_to_el2;
- if (ArmSystem::haveEL(tc, EL2) && !secure){
- if (ELIs32(tc, EL2)){
+ if (ArmSystem::haveEL(tc, EL2) && (!secure || HaveSecureEL2Ext(tc))) {
+ if (ELIs32(tc, EL2)) {
const HCR hcr = tc->readMiscReg(MISCREG_HCR);
- const HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
+ const HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
route_to_el2 = (hdcr.tde == 1 || hcr.tge == 1);
- }else{
+ } else {
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
- const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
+ const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
route_to_el2 = (mdcr.tde == 1 || hcr.tge == 1);
}
}else{
ExceptionLevel target;
if (route_to_el2) {
target = EL2;
- }else if (ArmSystem::haveEL(tc, EL3) && !ArmSystem::highestELIs64(tc)
- && secure){
+ } else if (ArmSystem::haveEL(tc, EL3) && !ArmSystem::highestELIs64(tc)
+ && secure) {
target = EL3;
- }else{
+ } else {
target = EL1;
}
return target;
IsSecureEL2Enabled(ThreadContext *tc)
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
- if (ArmSystem::haveEL(tc, EL2) && HaveSecureEL2Ext(tc)) {
+ if (ArmSystem::haveEL(tc, EL2) && HaveSecureEL2Ext(tc) &&
+ !ELIs32(tc, EL2)) {
if (ArmSystem::haveEL(tc, EL3))
return !ELIs32(tc, EL3) && scr.eel2;
else
- return inSecureState(tc);
+ return isSecure(tc);
}
return false;
}
return ELStateUsingAArch32K(tc, el, secure);
}
+bool
+haveAArch32EL(ThreadContext *tc, ExceptionLevel el)
+{
+ if (!ArmSystem::haveEL(tc, el))
+ return false;
+ else if (!ArmSystem::highestELIs64(tc))
+ return true;
+ else if (ArmSystem::highestEL(tc) == el)
+ return false;
+ else if (el == EL0)
+ return true;
+ return true;
+}
+
std::pair<bool, bool>
ELStateUsingAArch32K(ThreadContext *tc, ExceptionLevel el, bool secure)
{
bool known, aarch32;
known = aarch32 = false;
- if (ArmSystem::highestELIs64(tc) && ArmSystem::highestEL(tc) == el) {
+ if (!haveAArch32EL(tc, el)) {
// Target EL is the highest one in a system where
// the highest is using AArch64.
known = true; aarch32 = false;
+ } else if (secure && el == EL2) {
+ known = true; aarch32 = false;
} else if (!ArmSystem::highestELIs64(tc)) {
// All ELs are using AArch32:
known = true; aarch32 = true;
+ } else if (ArmSystem::highestEL(tc) == el) {
+ known = true; aarch32 = false;
} else {
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
- bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
+ bool aarch32_below_el3 = have_el3 && scr.rw == 0 &&
+ (!secure || !HaveSecureEL2Ext(tc) || !scr.eel2);
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
- bool secEL2 = false;
- bool aarch32_at_el1 = (aarch32_below_el3
- || (have_el2
- && (secEL2 || !isSecureBelowEL3(tc))
- && hcr.rw == 0 && !(hcr.e2h && hcr.tge
- && HaveVirtHostExt(tc))));
+ bool sec_el2 = HaveSecureEL2Ext(tc) && scr.eel2;
+ bool aarch32_at_el1 = (aarch32_below_el3 ||
+ (have_el2 && (sec_el2 || !secure) &&
+ hcr.rw == 0 && !(hcr.e2h && hcr.tge &&
+ HaveVirtHostExt(tc))));
// Only know if EL0 using AArch32 from PSTATE
if (el == EL0 && !aarch32_at_el1) {
// EL0 controlled by PSTATE
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
-
known = (currEL(tc) == EL0);
aarch32 = (cpsr.width == 1);
} else {
return !inUserMode(tc);
}
+bool isSecure(ThreadContext *tc);
+
bool inAArch64(ThreadContext *tc);
static inline OperatingMode
}
}
-bool inSecureState(ThreadContext *tc);
-
bool isSecureBelowEL3(ThreadContext *tc);
bool longDescFormatInUse(ThreadContext *tc);