summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2018-05-16 16:16:04 +0100
committerAndreas Sandberg <andreas.sandberg@arm.com>2018-06-06 13:56:18 +0000
commit072f325b2b5686d2a5b19f17f808810d5afd1944 (patch)
tree374458b24bbb997408a834828b5a92bc848a30f4
parent7f82aa3d60a1ca0f0b35435d42f875ff1f1bfe0b (diff)
downloadgem5-072f325b2b5686d2a5b19f17f808810d5afd1944.tar.xz
arch-arm: Respect EL from translation type
There are cases where instructions request translations in the context of a lower EL. This is currently not respected in the TLB and the page table walker. Fix that. Change-Id: Icd59657a1ecfd8bd75a001bb1a4e41a6f4808a36 Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/10506 Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
-rw-r--r--src/arch/arm/table_walker.cc22
-rw-r--r--src/arch/arm/tlb.cc59
-rw-r--r--src/arch/arm/tlb.hh8
3 files changed, 52 insertions, 37 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 26a07d70e..325a5128d 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -230,9 +230,15 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid,
// ARM DDI 0487A.f (ARMv8 ARM) pg J8-5672
// aarch32/translation/translation/AArch32.TranslateAddress dictates
// even AArch32 EL0 will use AArch64 translation if EL1 is in AArch64.
- currState->aarch64 = isStage2 || opModeIs64(currOpMode(_tc)) ||
- ((currEL(_tc) == EL0) && ELIs64(_tc, EL1));
- currState->el = currEL(_tc);
+ if (isStage2) {
+ currState->el = EL1;
+ currState->aarch64 = ELIs64(_tc, EL2);
+ } else {
+ currState->el =
+ TLB::tranTypeEL(_tc->readMiscReg(MISCREG_CPSR), tranType);
+ currState->aarch64 =
+ ELIs64(_tc, currState->el == EL0 ? EL1 : currState->el);
+ }
currState->transState = _trans;
currState->req = _req;
currState->fault = NoFault;
@@ -363,17 +369,11 @@ TableWalker::processWalkWrapper()
pendingChange();
currState = pendingQueue.front();
- ExceptionLevel target_el = EL0;
- if (currState->aarch64)
- target_el = currEL(currState->tc);
- else
- target_el = EL1;
-
// Check if a previous walk filled this request already
// @TODO Should this always be the TLB or should we look in the stage2 TLB?
TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
currState->vmid, currState->isHyp, currState->isSecure, true, false,
- target_el);
+ currState->el);
// Check if we still need to have a walk for this request. If the requesting
// instruction has been squashed, or a previous walk has filled the TLB with
@@ -439,7 +439,7 @@ TableWalker::processWalkWrapper()
currState = pendingQueue.front();
te = tlb->lookup(currState->vaddr, currState->asid,
currState->vmid, currState->isHyp, currState->isSecure, true,
- false, target_el);
+ false, currState->el);
} else {
// Terminate the loop, nothing more to do
currState = NULL;
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 5f104e96d..192f01bce 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -1268,35 +1268,13 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
isSecure = inSecureState(tc) &&
!(tranType & HypMode) && !(tranType & S1S2NsTran);
- const OperatingMode op_mode = (OperatingMode) (uint8_t)cpsr.mode;
- aarch64 = opModeIs64(op_mode) ||
- (opModeToEL(op_mode) == EL0 && ELIs64(tc, EL1));
+ aarch64EL = tranTypeEL(cpsr, tranType);
+ aarch64 = isStage2 ?
+ ELIs64(tc, EL2) :
+ ELIs64(tc, aarch64EL == EL0 ? EL1 : aarch64EL);
if (aarch64) { // AArch64
// 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:
@@ -1396,6 +1374,35 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
curTranType = tranType;
}
+ExceptionLevel
+TLB::tranTypeEL(CPSR cpsr, ArmTranslationType type)
+{
+ switch (type) {
+ case S1E0Tran:
+ case S12E0Tran:
+ return EL0;
+
+ case S1E1Tran:
+ case S12E1Tran:
+ return EL1;
+
+ case S1E2Tran:
+ return EL2;
+
+ case S1E3Tran:
+ return EL3;
+
+ case NormalTran:
+ case S1CTran:
+ case S1S2NsTran:
+ case HypMode:
+ return opModeToEL((OperatingMode)(uint8_t)cpsr.mode);
+
+ default:
+ panic("Unknown translation mode!\n");
+ }
+}
+
Fault
TLB::getTE(TlbEntry **te, RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool timing, bool functional,
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index b0e0d0d7f..b8ea99054 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -139,6 +139,14 @@ class TLB : public BaseTLB
S12E0Tran = 0x80,
S12E1Tran = 0x100
};
+
+ /**
+ * Determine the EL to use for the purpose of a translation given
+ * a specific translation type. If the translation type doesn't
+ * specify an EL, we use the current EL.
+ */
+ static ExceptionLevel tranTypeEL(CPSR cpsr, ArmTranslationType type);
+
protected:
TlbEntry* table; // the Page Table
int size; // TLB Size