arch-arm: Implement FEAT_TTST (#1323)
Implement small translation table extension. This feature relaxes the lower limit on the size of the translation tables, by increasing the maximum permitted values of the T1SZ and T0SZ field in: TCR_EL1, TCR_EL2, TCR_EL3,VTCR_EL2 and VSTCR_EL2 Change-Id: I4c2187815b2d7f14407edb38095c6bcc2004b62a Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
committed by
GitHub
parent
c9d9108978
commit
d825103df2
@@ -96,6 +96,7 @@ class ArmExtension(ScopedEnum):
|
||||
"FEAT_TLBIRANGE",
|
||||
"FEAT_FLAGM",
|
||||
"FEAT_IDST",
|
||||
"FEAT_TTST",
|
||||
# Armv8.5
|
||||
"FEAT_FLAGM2",
|
||||
"FEAT_RNG",
|
||||
@@ -204,6 +205,7 @@ class ArmDefaultRelease(Armv8):
|
||||
"FEAT_TLBIRANGE",
|
||||
"FEAT_FLAGM",
|
||||
"FEAT_IDST",
|
||||
"FEAT_TTST",
|
||||
# Armv8.5
|
||||
"FEAT_FLAGM2",
|
||||
"FEAT_EVT",
|
||||
@@ -252,6 +254,7 @@ class Armv84(Armv83):
|
||||
"FEAT_TLBIRANGE",
|
||||
"FEAT_FLAGM",
|
||||
"FEAT_IDST",
|
||||
"FEAT_TTST",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018-2019, 2021 Arm Limited
|
||||
* Copyright (c) 2013, 2018-2019, 2021, 2024 Arm Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -247,6 +247,7 @@ V8PageTableOps4k::firstS2Level(uint8_t sl0) const
|
||||
case 0: return LookupLevel::L2;
|
||||
case 1: return LookupLevel::L1;
|
||||
case 2: return LookupLevel::L0;
|
||||
case 3: return LookupLevel::L3; // Only when FEAT_TTST is implemented
|
||||
default: panic("Unsupported VTCR_EL2.SL0: %d", sl0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4976,6 +4976,7 @@ ISA::initializeMiscRegMetadata()
|
||||
AA64MMFR2 mmfr2_el1 = p.id_aa64mmfr2_el1;
|
||||
mmfr2_el1.uao = release->has(ArmExtension::FEAT_UAO) ? 0x1 : 0x0;
|
||||
mmfr2_el1.varange = release->has(ArmExtension::FEAT_LVA) ? 0x1 : 0x0;
|
||||
mmfr2_el1.st = release->has(ArmExtension::FEAT_TTST) ? 0x1 : 0x0;
|
||||
mmfr2_el1.ids = release->has(ArmExtension::FEAT_IDST) ? 0x1 : 0x0;
|
||||
mmfr2_el1.evt = release->has(ArmExtension::FEAT_EVT) ? 0x2 : 0x0;
|
||||
return mmfr2_el1;
|
||||
|
||||
@@ -857,22 +857,51 @@ TableWalker::processWalkLPAE()
|
||||
return currState->fault;
|
||||
}
|
||||
|
||||
bool
|
||||
TableWalker::checkVAddrSizeFaultAArch64(Addr addr, int top_bit,
|
||||
GrainSize tg, int tsz, bool low_range)
|
||||
Addr
|
||||
TableWalker::s1MinTxSz(GrainSize tg) const
|
||||
{
|
||||
// The effective maximum input size is 48 if ARMv8.2-LVA is not
|
||||
// supported or if the translation granule that is in use is 4KB or
|
||||
// 16KB in size. When ARMv8.2-LVA is supported, for the 64KB
|
||||
// translation granule size only, the effective minimum value of
|
||||
// 52.
|
||||
const bool have_lva = HaveExt(currState->tc, ArmExtension::FEAT_LVA);
|
||||
int in_max = (have_lva && tg == Grain64KB) ? 52 : 48;
|
||||
int in_min = 64 - (tg == Grain64KB ? 47 : 48);
|
||||
if (HaveExt(currState->tc, ArmExtension::FEAT_LVA) && tg == Grain64KB) {
|
||||
return 12;
|
||||
} else {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
return tsz > in_max || tsz < in_min || (low_range ?
|
||||
Addr
|
||||
TableWalker::maxTxSz(GrainSize tg) const
|
||||
{
|
||||
if (HaveExt(currState->tc, ArmExtension::FEAT_TTST)) {
|
||||
switch (tg) {
|
||||
case Grain4KB: return 48;
|
||||
case Grain16KB: return 48;
|
||||
case Grain64KB: return 47;
|
||||
default:
|
||||
panic("Invalid grain size\n");
|
||||
}
|
||||
}
|
||||
return 39;
|
||||
}
|
||||
|
||||
bool
|
||||
TableWalker::s1TxSzFault(GrainSize tg, int tsz) const
|
||||
{
|
||||
Addr min_txsz = s1MinTxSz(tg);
|
||||
Addr max_txsz = maxTxSz(tg);
|
||||
|
||||
return tsz > max_txsz || tsz < min_txsz;
|
||||
}
|
||||
|
||||
bool
|
||||
TableWalker::checkVAOutOfRange(Addr vaddr, int top_bit, int tsz, bool low_range)
|
||||
{
|
||||
return low_range ?
|
||||
bits(currState->vaddr, top_bit, tsz) != 0x0 :
|
||||
bits(currState->vaddr, top_bit, tsz) != mask(top_bit - tsz + 1));
|
||||
bits(currState->vaddr, top_bit, tsz) != mask(top_bit - tsz + 1);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -940,8 +969,8 @@ TableWalker::processWalkAArch64()
|
||||
currState->sh = currState->tcr.sh0;
|
||||
currState->irgn = currState->tcr.irgn0;
|
||||
currState->orgn = currState->tcr.orgn0;
|
||||
vaddr_fault = checkVAddrSizeFaultAArch64(currState->vaddr,
|
||||
top_bit, tg, tsz, true);
|
||||
vaddr_fault = s1TxSzFault(tg, currState->tcr.t0sz) ||
|
||||
checkVAOutOfRange(currState->vaddr, top_bit, tsz, true);
|
||||
|
||||
if (vaddr_fault || currState->tcr.epd0)
|
||||
fault = true;
|
||||
@@ -955,8 +984,8 @@ TableWalker::processWalkAArch64()
|
||||
currState->sh = currState->tcr.sh1;
|
||||
currState->irgn = currState->tcr.irgn1;
|
||||
currState->orgn = currState->tcr.orgn1;
|
||||
vaddr_fault = checkVAddrSizeFaultAArch64(currState->vaddr,
|
||||
top_bit, tg, tsz, false);
|
||||
vaddr_fault = s1TxSzFault(tg, currState->tcr.t1sz) ||
|
||||
checkVAOutOfRange(currState->vaddr, top_bit, tsz, false);
|
||||
|
||||
if (vaddr_fault || currState->tcr.epd1)
|
||||
fault = true;
|
||||
@@ -981,8 +1010,8 @@ TableWalker::processWalkAArch64()
|
||||
currState->sh = currState->tcr.sh0;
|
||||
currState->irgn = currState->tcr.irgn0;
|
||||
currState->orgn = currState->tcr.orgn0;
|
||||
vaddr_fault = checkVAddrSizeFaultAArch64(currState->vaddr,
|
||||
top_bit, tg, tsz, true);
|
||||
vaddr_fault = s1TxSzFault(tg, currState->tcr.t0sz) ||
|
||||
checkVAOutOfRange(currState->vaddr, top_bit, tsz, true);
|
||||
|
||||
if (vaddr_fault || (currState->hcr.e2h && currState->tcr.epd0))
|
||||
fault = true;
|
||||
@@ -997,8 +1026,8 @@ TableWalker::processWalkAArch64()
|
||||
currState->sh = currState->tcr.sh1;
|
||||
currState->irgn = currState->tcr.irgn1;
|
||||
currState->orgn = currState->tcr.orgn1;
|
||||
vaddr_fault = checkVAddrSizeFaultAArch64(currState->vaddr,
|
||||
top_bit, tg, tsz, false);
|
||||
vaddr_fault = s1TxSzFault(tg, currState->tcr.t1sz) ||
|
||||
checkVAOutOfRange(currState->vaddr, top_bit, tsz, false);
|
||||
|
||||
if (vaddr_fault || !currState->hcr.e2h || currState->tcr.epd1)
|
||||
fault = true;
|
||||
@@ -1021,8 +1050,8 @@ TableWalker::processWalkAArch64()
|
||||
currState->sh = currState->tcr.sh0;
|
||||
currState->irgn = currState->tcr.irgn0;
|
||||
currState->orgn = currState->tcr.orgn0;
|
||||
vaddr_fault = checkVAddrSizeFaultAArch64(currState->vaddr,
|
||||
top_bit, tg, tsz, true);
|
||||
vaddr_fault = s1TxSzFault(tg, currState->tcr.t0sz) ||
|
||||
checkVAOutOfRange(currState->vaddr, top_bit, tsz, true);
|
||||
|
||||
if (vaddr_fault)
|
||||
fault = true;
|
||||
|
||||
@@ -1216,8 +1216,11 @@ class TableWalker : public ClockedObject
|
||||
Fault processWalk();
|
||||
Fault processWalkLPAE();
|
||||
|
||||
bool checkVAddrSizeFaultAArch64(Addr addr, int top_bit,
|
||||
GrainSize granule, int tsz, bool low_range);
|
||||
Addr maxTxSz(GrainSize tg) const;
|
||||
Addr s1MinTxSz(GrainSize tg) const;
|
||||
bool s1TxSzFault(GrainSize tg, int tsz) const;
|
||||
bool checkVAOutOfRange(Addr addr, int top_bit,
|
||||
int tsz, bool low_range);
|
||||
|
||||
/// Returns true if the address exceeds the range permitted by the
|
||||
/// system-wide setting or by the TCR_ELx IPS/PS setting
|
||||
|
||||
Reference in New Issue
Block a user