diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index 582f397a61..63b7605fc6 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -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", ] diff --git a/src/arch/arm/pagetable.cc b/src/arch/arm/pagetable.cc index 542610d79c..e93e00e844 100644 --- a/src/arch/arm/pagetable.cc +++ b/src/arch/arm/pagetable.cc @@ -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); } } diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 463d0720f9..a4edcf586c 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -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; diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 81111cddd6..4357b0057c 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -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; diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index f391a4f1fd..8568be760f 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -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