From 072f325b2b5686d2a5b19f17f808810d5afd1944 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Wed, 16 May 2018 16:16:04 +0100 Subject: 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 Reviewed-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/10506 Maintainer: Giacomo Travaglini --- src/arch/arm/table_walker.cc | 22 ++++++++--------- src/arch/arm/tlb.cc | 59 +++++++++++++++++++++++++------------------- src/arch/arm/tlb.hh | 8 ++++++ 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 -- cgit v1.2.3