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:
Giacomo Travaglini
2024-07-04 09:37:41 +01:00
committed by GitHub
parent c9d9108978
commit d825103df2
5 changed files with 58 additions and 21 deletions

View File

@@ -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",
]

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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