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
This commit is contained in:
parent
2950a95672
commit
fc6879097b
3 changed files with 66 additions and 22 deletions
|
@ -1698,62 +1698,62 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
switch(misc_reg) {
|
switch(misc_reg) {
|
||||||
case MISCREG_AT_S1E1R_Xt:
|
case MISCREG_AT_S1E1R_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::S1CTran;
|
tranType = TLB::S1E1Tran;
|
||||||
mode = BaseTLB::Read;
|
mode = BaseTLB::Read;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E1W_Xt:
|
case MISCREG_AT_S1E1W_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::S1CTran;
|
tranType = TLB::S1E1Tran;
|
||||||
mode = BaseTLB::Write;
|
mode = BaseTLB::Write;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E0R_Xt:
|
case MISCREG_AT_S1E0R_Xt:
|
||||||
flags = TLB::MustBeOne | TLB::UserMode;
|
flags = TLB::MustBeOne | TLB::UserMode;
|
||||||
tranType = TLB::S1CTran;
|
tranType = TLB::S1E0Tran;
|
||||||
mode = BaseTLB::Read;
|
mode = BaseTLB::Read;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E0W_Xt:
|
case MISCREG_AT_S1E0W_Xt:
|
||||||
flags = TLB::MustBeOne | TLB::UserMode;
|
flags = TLB::MustBeOne | TLB::UserMode;
|
||||||
tranType = TLB::S1CTran;
|
tranType = TLB::S1E0Tran;
|
||||||
mode = BaseTLB::Write;
|
mode = BaseTLB::Write;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E2R_Xt:
|
case MISCREG_AT_S1E2R_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::HypMode;
|
tranType = TLB::S1E2Tran;
|
||||||
mode = BaseTLB::Read;
|
mode = BaseTLB::Read;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E2W_Xt:
|
case MISCREG_AT_S1E2W_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::HypMode;
|
tranType = TLB::S1E2Tran;
|
||||||
mode = BaseTLB::Write;
|
mode = BaseTLB::Write;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S12E0R_Xt:
|
case MISCREG_AT_S12E0R_Xt:
|
||||||
flags = TLB::MustBeOne | TLB::UserMode;
|
flags = TLB::MustBeOne | TLB::UserMode;
|
||||||
tranType = TLB::S1S2NsTran;
|
tranType = TLB::S12E0Tran;
|
||||||
mode = BaseTLB::Read;
|
mode = BaseTLB::Read;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S12E0W_Xt:
|
case MISCREG_AT_S12E0W_Xt:
|
||||||
flags = TLB::MustBeOne | TLB::UserMode;
|
flags = TLB::MustBeOne | TLB::UserMode;
|
||||||
tranType = TLB::S1S2NsTran;
|
tranType = TLB::S12E0Tran;
|
||||||
mode = BaseTLB::Write;
|
mode = BaseTLB::Write;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S12E1R_Xt:
|
case MISCREG_AT_S12E1R_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::S1S2NsTran;
|
tranType = TLB::S12E1Tran;
|
||||||
mode = BaseTLB::Read;
|
mode = BaseTLB::Read;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S12E1W_Xt:
|
case MISCREG_AT_S12E1W_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::S1S2NsTran;
|
tranType = TLB::S12E1Tran;
|
||||||
mode = BaseTLB::Write;
|
mode = BaseTLB::Write;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E3R_Xt:
|
case MISCREG_AT_S1E3R_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::HypMode; // There is no TZ mode defined.
|
tranType = TLB::S1E3Tran;
|
||||||
mode = BaseTLB::Read;
|
mode = BaseTLB::Read;
|
||||||
break;
|
break;
|
||||||
case MISCREG_AT_S1E3W_Xt:
|
case MISCREG_AT_S1E3W_Xt:
|
||||||
flags = TLB::MustBeOne;
|
flags = TLB::MustBeOne;
|
||||||
tranType = TLB::HypMode; // There is no TZ mode defined.
|
tranType = TLB::S1E3Tran;
|
||||||
mode = BaseTLB::Write;
|
mode = BaseTLB::Write;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1788,12 +1788,22 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
|
||||||
// Set fault bit and FSR
|
// Set fault bit and FSR
|
||||||
FSR fsr = armFault->getFsr(tc);
|
FSR fsr = armFault->getFsr(tc);
|
||||||
|
|
||||||
newVal = ((fsr >> 9) & 1) << 11;
|
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||||
// rearange fault status
|
if (cpsr.width) { // AArch32
|
||||||
newVal |= ((fsr >> 0) & 0x3f) << 1;
|
newVal = ((fsr >> 9) & 1) << 11;
|
||||||
newVal |= 0x1; // F bit
|
// rearrange fault status
|
||||||
newVal |= ((armFault->iss() >> 7) & 0x1) << 8;
|
newVal |= ((fsr >> 0) & 0x3f) << 1;
|
||||||
newVal |= armFault->isStage2() ? 0x200 : 0;
|
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,
|
DPRINTF(MiscRegs,
|
||||||
"MISCREG: Translated addr %#x fault fsr %#x: PAR: %#x\n",
|
"MISCREG: Translated addr %#x fault fsr %#x: PAR: %#x\n",
|
||||||
val, fsr, newVal);
|
val, fsr, newVal);
|
||||||
|
|
|
@ -1220,7 +1220,30 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||||
(opModeToEL(op_mode) == EL0 && ELIs64(tc, EL1));
|
(opModeToEL(op_mode) == EL0 && ELIs64(tc, EL1));
|
||||||
|
|
||||||
if (aarch64) { // AArch64
|
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) {
|
switch (aarch64EL) {
|
||||||
case EL0:
|
case EL0:
|
||||||
case EL1:
|
case EL1:
|
||||||
|
@ -1258,7 +1281,8 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||||
// compute it for every translation.
|
// compute it for every translation.
|
||||||
stage2Req = isStage2 ||
|
stage2Req = isStage2 ||
|
||||||
(hcr.vm && !isHyp && !isSecure &&
|
(hcr.vm && !isHyp && !isSecure &&
|
||||||
!(tranType & S1CTran) && (aarch64EL < EL2));
|
!(tranType & S1CTran) && (aarch64EL < EL2) &&
|
||||||
|
!(tranType & S1E1Tran)); // <--- FIX THIS HACK
|
||||||
directToStage2 = !isStage2 && stage2Req && !sctlr.m;
|
directToStage2 = !isStage2 && stage2Req && !sctlr.m;
|
||||||
} else {
|
} else {
|
||||||
vmid = 0;
|
vmid = 0;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2013 ARM Limited
|
* Copyright (c) 2010-2013, 2016 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -127,7 +127,17 @@ class TLB : public BaseTLB
|
||||||
HypMode = 0x2,
|
HypMode = 0x2,
|
||||||
// Secure code operating as if it wasn't (required by some Address
|
// Secure code operating as if it wasn't (required by some Address
|
||||||
// Translate operations)
|
// 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:
|
protected:
|
||||||
TlbEntry* table; // the Page Table
|
TlbEntry* table; // the Page Table
|
||||||
|
|
Loading…
Reference in a new issue