arch-arm: Implementing SecureEL2 feature for Armv8
This patch adds Secure EL2 feature. This allows stage1
EL2/EL&0 and stage2 secure translation.
The changes are organized as follow:
+ insts/static_inst.cc: Modify checks for illegalInstruction on eret
+ isa.cc/hh: Enabling contorl bits
+ isa/insts/misc.hh/64.hh: Smc fault trigger.
+ miscregs.cc/hh: Declaration and initialization of new registers
+ self_debug.cc/hh: Add secureEL2 types for breakpoints
+ stage2_lookup.cc/hh: Allow stage2 in secure state.
+ tlb.cc/table_walker.cc: Allow secure state for stage2 and stage 1 EL2&0
translation regime
+ utility.cc/hh: New function InSecure and refactor of other helpers
to enable secure state
JIRA: https://gem5.atlassian.net/browse/GEM5-686
Change-Id: Ie59438b1828508e944334420da1d8f4745649056
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31394
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -75,6 +75,8 @@ class ArmSystem(System):
|
||||
"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")
|
||||
|
||||
@@ -59,7 +59,7 @@ CortexA76TC::translateAddress(Addr &paddr, Addr vaddr)
|
||||
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.
|
||||
|
||||
@@ -977,10 +977,12 @@ ArmFaultVals<T>::offset64(ThreadContext *tc)
|
||||
} 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));
|
||||
}
|
||||
@@ -1310,7 +1312,7 @@ PrefetchAbort::routeToHyp(ThreadContext *tc) const
|
||||
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;
|
||||
|
||||
@@ -634,9 +634,8 @@ ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const
|
||||
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 {
|
||||
@@ -728,7 +727,7 @@ ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
|
||||
{
|
||||
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))
|
||||
@@ -908,8 +907,7 @@ ArmStaticInst::trapWFx(ThreadContext *tc,
|
||||
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);
|
||||
@@ -945,7 +943,7 @@ ArmStaticInst::checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const
|
||||
// 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;
|
||||
@@ -1097,22 +1095,34 @@ illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
|
||||
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))
|
||||
//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 (!ArmSystem::haveEL(tc, target_el))
|
||||
return true;
|
||||
|
||||
if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge)
|
||||
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);
|
||||
@@ -1123,17 +1133,9 @@ illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
|
||||
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;
|
||||
@@ -1206,7 +1208,7 @@ ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc,
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -214,8 +214,7 @@ class ArmStaticInst : public StaticInst
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ ArmISA::Interrupts::takeInt(InterruptTypes int_type) const
|
||||
else
|
||||
scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
||||
|
||||
bool is_secure = inSecureState(tc);
|
||||
bool is_secure = isSecure(tc);
|
||||
|
||||
switch(int_type) {
|
||||
case INT_FIQ:
|
||||
|
||||
@@ -145,7 +145,7 @@ class Interrupts : public BaseInterrupts
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -185,7 +185,7 @@ class Interrupts : public BaseInterrupts
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ class Interrupts : public BaseInterrupts
|
||||
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)
|
||||
@@ -247,7 +247,7 @@ class Interrupts : public BaseInterrupts
|
||||
// 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;
|
||||
|
||||
@@ -88,6 +88,7 @@ ISA::ISA(Params *p) : BaseISA(p), system(NULL),
|
||||
physAddrRange = system->physAddrRange();
|
||||
haveSVE = system->haveSVE();
|
||||
havePAN = system->havePAN();
|
||||
haveSecEL2 = system->haveSecEL2();
|
||||
sveVL = system->sveVL();
|
||||
haveLSE = system->haveLSE();
|
||||
} else {
|
||||
@@ -98,6 +99,7 @@ ISA::ISA(Params *p) : BaseISA(p), system(NULL),
|
||||
physAddrRange = 32; // dummy value
|
||||
haveSVE = true;
|
||||
havePAN = false;
|
||||
haveSecEL2 = true;
|
||||
sveVL = p->sve_vl_se;
|
||||
haveLSE = true;
|
||||
}
|
||||
@@ -397,6 +399,13 @@ ISA::initID64(const ArmISAParams *p)
|
||||
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,
|
||||
@@ -554,7 +563,7 @@ ISA::readMiscReg(int misc_reg)
|
||||
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);
|
||||
@@ -731,9 +740,7 @@ ISA::readMiscReg(int misc_reg)
|
||||
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;
|
||||
@@ -764,6 +771,7 @@ ISA::readMiscReg(int misc_reg)
|
||||
(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)
|
||||
@@ -1968,9 +1976,7 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
{
|
||||
// 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 =
|
||||
@@ -2464,7 +2470,7 @@ ISA::getCurSveVecLenInBits() const
|
||||
|
||||
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,
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace ArmISA
|
||||
bool haveSVE;
|
||||
bool haveLSE;
|
||||
bool havePAN;
|
||||
bool haveSecEL2;
|
||||
|
||||
/** SVE vector length in quadwords */
|
||||
unsigned sveVL;
|
||||
@@ -695,7 +696,7 @@ namespace ArmISA
|
||||
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;
|
||||
|
||||
@@ -151,11 +151,10 @@ let {{
|
||||
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;
|
||||
'''
|
||||
|
||||
@@ -210,8 +210,7 @@ let {{
|
||||
|
||||
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()) {
|
||||
|
||||
@@ -95,8 +95,7 @@ let {{
|
||||
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 {
|
||||
@@ -121,12 +120,11 @@ let {{
|
||||
|
||||
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);
|
||||
@@ -936,7 +934,7 @@ let {{
|
||||
// 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);
|
||||
}
|
||||
@@ -970,7 +968,7 @@ let {{
|
||||
// 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);
|
||||
}
|
||||
@@ -1003,7 +1001,7 @@ let {{
|
||||
// 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);
|
||||
}
|
||||
@@ -1037,7 +1035,7 @@ let {{
|
||||
// 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);
|
||||
}
|
||||
@@ -1115,7 +1113,7 @@ let {{
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ let {{
|
||||
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;
|
||||
|
||||
@@ -2356,6 +2356,14 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
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:
|
||||
@@ -4880,6 +4888,10 @@ ISA::initializeMiscRegMetadata()
|
||||
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)
|
||||
|
||||
@@ -596,6 +596,8 @@ namespace ArmISA
|
||||
MISCREG_TCR_EL2,
|
||||
MISCREG_VTTBR_EL2,
|
||||
MISCREG_VTCR_EL2,
|
||||
MISCREG_VSTTBR_EL2,
|
||||
MISCREG_VSTCR_EL2,
|
||||
MISCREG_TTBR0_EL3,
|
||||
MISCREG_TCR_EL3,
|
||||
MISCREG_DACR32_EL2,
|
||||
@@ -1695,6 +1697,8 @@ namespace ArmISA
|
||||
"tcr_el2",
|
||||
"vttbr_el2",
|
||||
"vtcr_el2",
|
||||
"vsttbr_el2",
|
||||
"vstcr_el2",
|
||||
"ttbr0_el3",
|
||||
"tcr_el3",
|
||||
"dacr32_el2",
|
||||
|
||||
@@ -165,7 +165,7 @@ SelfDebug::isDebugEnabledForEL64(ThreadContext *tc, ExceptionLevel el,
|
||||
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))) {
|
||||
@@ -269,53 +269,53 @@ BrkPoint::test(ThreadContext *tc, Addr pc, ExceptionLevel el, DBGBCR ctr,
|
||||
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
|
||||
}
|
||||
@@ -652,8 +652,9 @@ SoftwareStep::debugExceptionReturnSS(ThreadContext *tc, CPSR spsr,
|
||||
|
||||
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 {
|
||||
@@ -760,7 +761,7 @@ VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el)
|
||||
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
|
||||
@@ -772,7 +773,7 @@ VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el)
|
||||
}
|
||||
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
|
||||
@@ -793,7 +794,7 @@ VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el)
|
||||
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;
|
||||
}
|
||||
@@ -818,7 +819,7 @@ VectorCatch::exceptionTrapping(ThreadContext *tc, ExceptionLevel el,
|
||||
} 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;
|
||||
|
||||
@@ -341,11 +341,11 @@ class SelfDebug
|
||||
{
|
||||
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");
|
||||
@@ -372,10 +372,10 @@ class SelfDebug
|
||||
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 );
|
||||
}
|
||||
}
|
||||
@@ -464,7 +464,7 @@ class SelfDebug
|
||||
bool
|
||||
targetAArch32(ThreadContext *tc)
|
||||
{
|
||||
ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
|
||||
ExceptionLevel ELd = debugTargetFrom(tc, isSecure(tc));
|
||||
return ELIs32(tc, ELd) && aarch32;
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ ArmSemihosting::portProxy(ThreadContext *tc)
|
||||
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) {
|
||||
|
||||
@@ -55,7 +55,7 @@ Stage2LookUp::getTe(ThreadContext *tc, TlbEntry *destTe)
|
||||
|
||||
{
|
||||
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
|
||||
@@ -180,7 +180,7 @@ Stage2LookUp::finish(const Fault &_fault, const RequestPtr &req,
|
||||
// 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
|
||||
|
||||
@@ -69,15 +69,16 @@ class Stage2LookUp : public BaseTLB::Translation
|
||||
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(),
|
||||
|
||||
@@ -70,6 +70,7 @@ ArmSystem::ArmSystem(Params *p)
|
||||
_sveVL(p->sve_vl),
|
||||
_haveLSE(p->have_lse),
|
||||
_havePAN(p->have_pan),
|
||||
_haveSecEL2(p->have_secel2),
|
||||
semihosting(p->semihosting),
|
||||
multiProc(p->multi_proc)
|
||||
{
|
||||
|
||||
@@ -128,6 +128,9 @@ class ArmSystem : public System
|
||||
/** 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.
|
||||
*/
|
||||
@@ -223,6 +226,9 @@ class ArmSystem : public System
|
||||
/** 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; }
|
||||
|
||||
@@ -267,7 +267,13 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
|
||||
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) &&
|
||||
@@ -825,8 +831,13 @@ TableWalker::processWalkAArch64()
|
||||
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
|
||||
|
||||
@@ -833,6 +833,8 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
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
|
||||
@@ -1351,7 +1353,7 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||
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);
|
||||
@@ -1420,11 +1422,17 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType 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))) {
|
||||
@@ -1436,16 +1444,12 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||
// 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;
|
||||
}
|
||||
@@ -1494,9 +1498,10 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||
// 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;
|
||||
@@ -1652,7 +1657,8 @@ TLB::getResultTe(TlbEntry **te, const RequestPtr &req,
|
||||
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;
|
||||
|
||||
@@ -118,7 +118,7 @@ TarmacTracerRecord::TraceInstEntry::TraceInstEntry(
|
||||
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()
|
||||
|
||||
@@ -171,12 +171,15 @@ sendEvent(ThreadContext *tc)
|
||||
}
|
||||
|
||||
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
|
||||
@@ -190,14 +193,14 @@ ExceptionLevel
|
||||
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{
|
||||
@@ -206,10 +209,10 @@ debugTargetFrom(ThreadContext *tc, bool secure)
|
||||
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;
|
||||
@@ -344,11 +347,12 @@ bool
|
||||
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;
|
||||
}
|
||||
@@ -393,6 +397,20 @@ ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
|
||||
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)
|
||||
{
|
||||
@@ -405,30 +423,33 @@ 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 {
|
||||
|
||||
@@ -128,6 +128,8 @@ inPrivilegedMode(ThreadContext *tc)
|
||||
return !inUserMode(tc);
|
||||
}
|
||||
|
||||
bool isSecure(ThreadContext *tc);
|
||||
|
||||
bool inAArch64(ThreadContext *tc);
|
||||
|
||||
static inline OperatingMode
|
||||
@@ -256,8 +258,6 @@ inSecureState(SCR scr, CPSR cpsr)
|
||||
}
|
||||
}
|
||||
|
||||
bool inSecureState(ThreadContext *tc);
|
||||
|
||||
bool isSecureBelowEL3(ThreadContext *tc);
|
||||
|
||||
bool longDescFormatInUse(ThreadContext *tc);
|
||||
|
||||
Reference in New Issue
Block a user