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>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user