summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Johnson <Dylan.Johnson@ARM.com>2016-08-02 10:38:02 +0100
committerDylan Johnson <Dylan.Johnson@ARM.com>2016-08-02 10:38:02 +0100
commitfc6879097b04643f6345adad39e54f44afb85d2f (patch)
tree046cd5dd4701d0098160f9d46c9b158cc9548fe0
parent2950a95672599a9baf9007c18faf210ff9c3e392 (diff)
downloadgem5-fc6879097b04643f6345adad39e54f44afb85d2f.tar.xz
arm: Fix EL perceived at TLB for address translation instructions
During address translation instructions (such as AT S1E1R_Xt) the exception level can be different than the current exception level. This patch fixes how the TLB determines what EL to use during these instructions. Change-Id: Ia9ce229404de9e284bc1f7479fd2c580efd55f8f
-rw-r--r--src/arch/arm/isa.cc46
-rw-r--r--src/arch/arm/tlb.cc28
-rw-r--r--src/arch/arm/tlb.hh14
3 files changed, 66 insertions, 22 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index 2300b925e..016e1eca0 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -1698,62 +1698,62 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
switch(misc_reg) {
case MISCREG_AT_S1E1R_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::S1CTran;
+ tranType = TLB::S1E1Tran;
mode = BaseTLB::Read;
break;
case MISCREG_AT_S1E1W_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::S1CTran;
+ tranType = TLB::S1E1Tran;
mode = BaseTLB::Write;
break;
case MISCREG_AT_S1E0R_Xt:
flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1CTran;
+ tranType = TLB::S1E0Tran;
mode = BaseTLB::Read;
break;
case MISCREG_AT_S1E0W_Xt:
flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1CTran;
+ tranType = TLB::S1E0Tran;
mode = BaseTLB::Write;
break;
case MISCREG_AT_S1E2R_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::HypMode;
+ tranType = TLB::S1E2Tran;
mode = BaseTLB::Read;
break;
case MISCREG_AT_S1E2W_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::HypMode;
+ tranType = TLB::S1E2Tran;
mode = BaseTLB::Write;
break;
case MISCREG_AT_S12E0R_Xt:
flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1S2NsTran;
+ tranType = TLB::S12E0Tran;
mode = BaseTLB::Read;
break;
case MISCREG_AT_S12E0W_Xt:
flags = TLB::MustBeOne | TLB::UserMode;
- tranType = TLB::S1S2NsTran;
+ tranType = TLB::S12E0Tran;
mode = BaseTLB::Write;
break;
case MISCREG_AT_S12E1R_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::S1S2NsTran;
+ tranType = TLB::S12E1Tran;
mode = BaseTLB::Read;
break;
case MISCREG_AT_S12E1W_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::S1S2NsTran;
+ tranType = TLB::S12E1Tran;
mode = BaseTLB::Write;
break;
case MISCREG_AT_S1E3R_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::HypMode; // There is no TZ mode defined.
+ tranType = TLB::S1E3Tran;
mode = BaseTLB::Read;
break;
case MISCREG_AT_S1E3W_Xt:
flags = TLB::MustBeOne;
- tranType = TLB::HypMode; // There is no TZ mode defined.
+ tranType = TLB::S1E3Tran;
mode = BaseTLB::Write;
break;
}
@@ -1788,12 +1788,22 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
// Set fault bit and FSR
FSR fsr = armFault->getFsr(tc);
- newVal = ((fsr >> 9) & 1) << 11;
- // rearange fault status
- newVal |= ((fsr >> 0) & 0x3f) << 1;
- newVal |= 0x1; // F bit
- newVal |= ((armFault->iss() >> 7) & 0x1) << 8;
- newVal |= armFault->isStage2() ? 0x200 : 0;
+ 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);
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 864f0c28c..536fa51cd 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -1220,7 +1220,30 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
(opModeToEL(op_mode) == EL0 && ELIs64(tc, EL1));
if (aarch64) { // AArch64
- aarch64EL = (ExceptionLevel) (uint8_t) cpsr.el;
+ // determine EL we need to translate in
+ switch (tranType) {
+ case S1E0Tran:
+ case S12E0Tran:
+ aarch64EL = EL0;
+ break;
+ case S1E1Tran:
+ case S12E1Tran:
+ aarch64EL = EL1;
+ break;
+ case S1E2Tran:
+ aarch64EL = EL2;
+ break;
+ case S1E3Tran:
+ aarch64EL = EL3;
+ break;
+ case NormalTran:
+ case S1CTran:
+ case S1S2NsTran:
+ case HypMode:
+ aarch64EL = (ExceptionLevel) (uint8_t) cpsr.el;
+ break;
+ }
+
switch (aarch64EL) {
case EL0:
case EL1:
@@ -1258,7 +1281,8 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
// compute it for every translation.
stage2Req = isStage2 ||
(hcr.vm && !isHyp && !isSecure &&
- !(tranType & S1CTran) && (aarch64EL < EL2));
+ !(tranType & S1CTran) && (aarch64EL < EL2) &&
+ !(tranType & S1E1Tran)); // <--- FIX THIS HACK
directToStage2 = !isStage2 && stage2Req && !sctlr.m;
} else {
vmid = 0;
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 298c603b9..ef05bb421 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2013 ARM Limited
+ * Copyright (c) 2010-2013, 2016 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -127,7 +127,17 @@ class TLB : public BaseTLB
HypMode = 0x2,
// Secure code operating as if it wasn't (required by some Address
// Translate operations)
- S1S2NsTran = 0x4
+ S1S2NsTran = 0x4,
+ // Address translation instructions (eg AT S1E0R_Xt) need to be handled
+ // in special ways during translation because they could need to act
+ // like a different EL than the current EL. The following flags are
+ // for these instructions
+ S1E0Tran = 0x8,
+ S1E1Tran = 0x10,
+ S1E2Tran = 0x20,
+ S1E3Tran = 0x40,
+ S12E0Tran = 0x80,
+ S12E1Tran = 0x100
};
protected:
TlbEntry* table; // the Page Table