arch-arm: Expose LookupLevel enum to the python world
Our goal is to make it a SimObject Param Change-Id: I90673fada66f59d4a90354660d2513a39c0ccba5 Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52007 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2009, 2013, 2015 ARM Limited
|
||||
# Copyright (c) 2009, 2013, 2015, 2021 Arm Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -40,6 +40,9 @@ from m5.params import *
|
||||
from m5.proxy import *
|
||||
from m5.objects.BaseTLB import BaseTLB
|
||||
|
||||
class ArmLookupLevel(Enum):
|
||||
vals = [ "L0", "L1", "L2", "L3" ]
|
||||
|
||||
class ArmTLB(BaseTLB):
|
||||
type = 'ArmTLB'
|
||||
cxx_class = 'gem5::ArmISA::TLB'
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
#include "arch/arm/tlb.hh"
|
||||
#include "arch/generic/mmu.hh"
|
||||
|
||||
#include "enums/ArmLookupLevel.hh"
|
||||
|
||||
#include "params/ArmMMU.hh"
|
||||
|
||||
namespace gem5
|
||||
@@ -57,6 +59,8 @@ class TableWalker;
|
||||
class MMU : public BaseMMU
|
||||
{
|
||||
protected:
|
||||
using LookupLevel = enums::ArmLookupLevel;
|
||||
|
||||
ArmISA::TLB *
|
||||
getDTBPtr() const
|
||||
{
|
||||
|
||||
@@ -130,16 +130,16 @@ V7LPageTableOps::walkMask(unsigned level) const
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V7LPageTableOps::LookupLevel
|
||||
V7LPageTableOps::firstLevel(uint8_t tsz) const
|
||||
{
|
||||
return L1;
|
||||
return LookupLevel::L1;
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V7LPageTableOps::LookupLevel
|
||||
V7LPageTableOps::lastLevel() const
|
||||
{
|
||||
return L3;
|
||||
return LookupLevel::L3;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -224,31 +224,31 @@ V8PageTableOps4k::walkMask(unsigned level) const
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps4k::LookupLevel
|
||||
V8PageTableOps4k::firstLevel(uint8_t tsz) const
|
||||
{
|
||||
if (tsz >= 16 && tsz <= 24) return L0;
|
||||
if (tsz >= 25 && tsz <= 33) return L1;
|
||||
if (tsz >= 34 && tsz <= 39) return L2;
|
||||
if (tsz >= 16 && tsz <= 24) return LookupLevel::L0;
|
||||
if (tsz >= 25 && tsz <= 33) return LookupLevel::L1;
|
||||
if (tsz >= 34 && tsz <= 39) return LookupLevel::L2;
|
||||
|
||||
panic("Unsupported TnSZ: %d\n", tsz);
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps4k::LookupLevel
|
||||
V8PageTableOps4k::firstS2Level(uint8_t sl0) const
|
||||
{
|
||||
switch (sl0) {
|
||||
case 0: return L2;
|
||||
case 1: return L1;
|
||||
case 2: return L0;
|
||||
case 0: return LookupLevel::L2;
|
||||
case 1: return LookupLevel::L1;
|
||||
case 2: return LookupLevel::L0;
|
||||
default: panic("Unsupported VTCR_EL2.SL0: %d", sl0);
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps4k::LookupLevel
|
||||
V8PageTableOps4k::lastLevel() const
|
||||
{
|
||||
return L3;
|
||||
return LookupLevel::L3;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -335,32 +335,32 @@ V8PageTableOps16k::walkMask(unsigned level) const
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps16k::LookupLevel
|
||||
V8PageTableOps16k::firstLevel(uint8_t tsz) const
|
||||
{
|
||||
if (tsz == 16) return L0;
|
||||
if (tsz >= 17 && tsz <= 27) return L1;
|
||||
if (tsz >= 28 && tsz <= 38) return L2;
|
||||
if (tsz == 39) return L3;
|
||||
if (tsz == 16) return LookupLevel::L0;
|
||||
if (tsz >= 17 && tsz <= 27) return LookupLevel::L1;
|
||||
if (tsz >= 28 && tsz <= 38) return LookupLevel::L2;
|
||||
if (tsz == 39) return LookupLevel::L3;
|
||||
|
||||
panic("Unsupported TnSZ: %d\n", tsz);
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps16k::LookupLevel
|
||||
V8PageTableOps16k::firstS2Level(uint8_t sl0) const
|
||||
{
|
||||
switch (sl0) {
|
||||
case 0: return L3;
|
||||
case 1: return L2;
|
||||
case 2: return L1;
|
||||
case 0: return LookupLevel::L3;
|
||||
case 1: return LookupLevel::L2;
|
||||
case 2: return LookupLevel::L1;
|
||||
default: panic("Unsupported VTCR_EL2.SL0: %d", sl0);
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps16k::LookupLevel
|
||||
V8PageTableOps16k::lastLevel() const
|
||||
{
|
||||
return L3;
|
||||
return LookupLevel::L3;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -439,31 +439,31 @@ V8PageTableOps64k::walkMask(unsigned level) const
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps64k::LookupLevel
|
||||
V8PageTableOps64k::firstLevel(uint8_t tsz) const
|
||||
{
|
||||
if (tsz >= 12 && tsz <= 21) return L1;
|
||||
if (tsz >= 22 && tsz <= 34) return L2;
|
||||
if (tsz >= 35 && tsz <= 39) return L3;
|
||||
if (tsz >= 12 && tsz <= 21) return LookupLevel::L1;
|
||||
if (tsz >= 22 && tsz <= 34) return LookupLevel::L2;
|
||||
if (tsz >= 35 && tsz <= 39) return LookupLevel::L3;
|
||||
|
||||
panic("Unsupported TnSZ: %d\n", tsz);
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps64k::LookupLevel
|
||||
V8PageTableOps64k::firstS2Level(uint8_t sl0) const
|
||||
{
|
||||
switch (sl0) {
|
||||
case 0: return L3;
|
||||
case 1: return L2;
|
||||
case 2: return L1;
|
||||
case 0: return LookupLevel::L3;
|
||||
case 1: return LookupLevel::L2;
|
||||
case 2: return LookupLevel::L1;
|
||||
default: panic("Unsupported VTCR_EL2.SL0: %d", sl0);
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
V8PageTableOps64k::LookupLevel
|
||||
V8PageTableOps64k::lastLevel() const
|
||||
{
|
||||
return L3;
|
||||
return LookupLevel::L3;
|
||||
}
|
||||
|
||||
const PageTableOps *
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "arch/arm/utility.hh"
|
||||
#include "arch/generic/mmu.hh"
|
||||
#include "enums/TypeTLB.hh"
|
||||
#include "enums/ArmLookupLevel.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
namespace gem5
|
||||
@@ -56,16 +57,6 @@ namespace gem5
|
||||
namespace ArmISA
|
||||
{
|
||||
|
||||
// Lookup level
|
||||
enum LookupLevel
|
||||
{
|
||||
L0 = 0, // AArch64 only
|
||||
L1,
|
||||
L2,
|
||||
L3,
|
||||
MAX_LOOKUP_LEVELS
|
||||
};
|
||||
|
||||
// Granule sizes
|
||||
enum GrainSize
|
||||
{
|
||||
@@ -98,6 +89,7 @@ struct PTE
|
||||
|
||||
struct PageTableOps
|
||||
{
|
||||
typedef enums::ArmLookupLevel LookupLevel;
|
||||
typedef int64_t pte_t;
|
||||
|
||||
virtual bool isValid(pte_t pte, unsigned level) const = 0;
|
||||
@@ -171,6 +163,8 @@ struct V8PageTableOps64k : public PageTableOps
|
||||
struct TlbEntry : public Serializable
|
||||
{
|
||||
public:
|
||||
typedef enums::ArmLookupLevel LookupLevel;
|
||||
|
||||
enum class MemoryType : std::uint8_t
|
||||
{
|
||||
StronglyOrdered,
|
||||
@@ -264,7 +258,8 @@ struct TlbEntry : public Serializable
|
||||
TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr,
|
||||
bool uncacheable, bool read_only) :
|
||||
pfn(_paddr >> PageShift), size(PageBytes - 1), vpn(_vaddr >> PageShift),
|
||||
attributes(0), lookupLevel(L1), asid(_asn), vmid(0), N(0),
|
||||
attributes(0), lookupLevel(LookupLevel::L1),
|
||||
asid(_asn), vmid(0), N(0),
|
||||
innerAttrs(0), outerAttrs(0), ap(read_only ? 0x3 : 0), hap(0x3),
|
||||
domain(DomainType::Client), mtype(MemoryType::StronglyOrdered),
|
||||
longDescFormat(false), isHyp(false), global(false), valid(true),
|
||||
@@ -280,8 +275,9 @@ struct TlbEntry : public Serializable
|
||||
}
|
||||
|
||||
TlbEntry() :
|
||||
pfn(0), size(0), vpn(0), attributes(0), lookupLevel(L1), asid(0),
|
||||
vmid(0), N(0), innerAttrs(0), outerAttrs(0), ap(0), hap(0x3),
|
||||
pfn(0), size(0), vpn(0), attributes(0), lookupLevel(LookupLevel::L1),
|
||||
asid(0), vmid(0), N(0),
|
||||
innerAttrs(0), outerAttrs(0), ap(0), hap(0x3),
|
||||
domain(DomainType::Client), mtype(MemoryType::StronglyOrdered),
|
||||
longDescFormat(false), isHyp(false), global(false), valid(false),
|
||||
ns(true), nstid(true), el(EL0), type(TypeTLB::unified),
|
||||
|
||||
@@ -239,8 +239,10 @@ void
|
||||
TableWalker::completeDrain()
|
||||
{
|
||||
if (drainState() == DrainState::Draining &&
|
||||
stateQueues[L0].empty() && stateQueues[L1].empty() &&
|
||||
stateQueues[L2].empty() && stateQueues[L3].empty() &&
|
||||
stateQueues[LookupLevel::L0].empty() &&
|
||||
stateQueues[LookupLevel::L1].empty() &&
|
||||
stateQueues[LookupLevel::L2].empty() &&
|
||||
stateQueues[LookupLevel::L3].empty() &&
|
||||
pendingQueue.empty()) {
|
||||
|
||||
DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
|
||||
@@ -253,7 +255,7 @@ TableWalker::drain()
|
||||
{
|
||||
bool state_queues_not_empty = false;
|
||||
|
||||
for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) {
|
||||
for (int i = 0; i < LookupLevel::Num_ArmLookupLevel; ++i) {
|
||||
if (!stateQueues[i].empty()) {
|
||||
state_queues_not_empty = true;
|
||||
break;
|
||||
@@ -592,7 +594,7 @@ TableWalker::processWalk()
|
||||
if (currState->isFetch)
|
||||
return std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
else
|
||||
@@ -600,7 +602,7 @@ TableWalker::processWalk()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L1, isStage2,
|
||||
ArmFault::TranslationLL + LookupLevel::L1, isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
}
|
||||
ttbr = currState->tc->readMiscReg(snsBankedIndex(
|
||||
@@ -612,7 +614,7 @@ TableWalker::processWalk()
|
||||
if (currState->isFetch)
|
||||
return std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
else
|
||||
@@ -620,7 +622,7 @@ TableWalker::processWalk()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L1, isStage2,
|
||||
ArmFault::TranslationLL + LookupLevel::L1, isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
}
|
||||
ttbr = ttbr1;
|
||||
@@ -635,7 +637,7 @@ TableWalker::processWalk()
|
||||
// Trickbox address check
|
||||
Fault f;
|
||||
f = testWalk(l1desc_addr, sizeof(uint32_t),
|
||||
TlbEntry::DomainType::NoAccess, L1, isStage2);
|
||||
TlbEntry::DomainType::NoAccess, LookupLevel::L1, isStage2);
|
||||
if (f) {
|
||||
DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
|
||||
if (currState->timing) {
|
||||
@@ -660,7 +662,8 @@ TableWalker::processWalk()
|
||||
|
||||
bool delayed;
|
||||
delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data,
|
||||
sizeof(uint32_t), flag, L1, &doL1DescEvent,
|
||||
sizeof(uint32_t), flag, LookupLevel::L1,
|
||||
&doL1DescEvent,
|
||||
&TableWalker::doL1Descriptor);
|
||||
if (!delayed) {
|
||||
f = currState->fault;
|
||||
@@ -674,7 +677,7 @@ TableWalker::processWalkLPAE()
|
||||
{
|
||||
Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
|
||||
int tsz, n;
|
||||
LookupLevel start_lookup_level = L1;
|
||||
LookupLevel start_lookup_level = LookupLevel::L1;
|
||||
|
||||
DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n",
|
||||
currState->vaddr_tainted, currState->ttbcr);
|
||||
@@ -691,7 +694,8 @@ TableWalker::processWalkLPAE()
|
||||
DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n");
|
||||
ttbr = currState->tc->readMiscReg(MISCREG_VTTBR);
|
||||
tsz = sext<4>(currState->vtcr.t0sz);
|
||||
start_lookup_level = currState->vtcr.sl0 ? L1 : L2;
|
||||
start_lookup_level = currState->vtcr.sl0 ?
|
||||
LookupLevel::L1 : LookupLevel::L2;
|
||||
currState->isUncacheable = currState->vtcr.irgn0 == 0;
|
||||
} else if (currState->isHyp) {
|
||||
DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n");
|
||||
@@ -727,7 +731,7 @@ TableWalker::processWalkLPAE()
|
||||
if (currState->isFetch)
|
||||
return std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::LpaeTran);
|
||||
else
|
||||
@@ -735,7 +739,7 @@ TableWalker::processWalkLPAE()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::LpaeTran);
|
||||
}
|
||||
@@ -744,7 +748,7 @@ TableWalker::processWalkLPAE()
|
||||
tsz = currState->ttbcr.t0sz;
|
||||
currState->isUncacheable = currState->ttbcr.irgn0 == 0;
|
||||
if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GiB
|
||||
start_lookup_level = L2;
|
||||
start_lookup_level = LookupLevel::L2;
|
||||
} else if (currState->vaddr >= ttbr1_min) {
|
||||
DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n");
|
||||
// Check if table walk is allowed
|
||||
@@ -752,7 +756,7 @@ TableWalker::processWalkLPAE()
|
||||
if (currState->isFetch)
|
||||
return std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::LpaeTran);
|
||||
else
|
||||
@@ -760,7 +764,7 @@ TableWalker::processWalkLPAE()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::LpaeTran);
|
||||
}
|
||||
@@ -770,13 +774,13 @@ TableWalker::processWalkLPAE()
|
||||
currState->isUncacheable = currState->ttbcr.irgn1 == 0;
|
||||
// Lower limit >= 3 GiB
|
||||
if (ttbr1_min >= (1ULL << 31) + (1ULL << 30))
|
||||
start_lookup_level = L2;
|
||||
start_lookup_level = LookupLevel::L2;
|
||||
} else {
|
||||
// Out of boundaries -> translation fault
|
||||
if (currState->isFetch)
|
||||
return std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::LpaeTran);
|
||||
else
|
||||
@@ -784,14 +788,14 @@ TableWalker::processWalkLPAE()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2, ArmFault::LpaeTran);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Perform lookup (ARM ARM issue C B3.6.6)
|
||||
if (start_lookup_level == L1) {
|
||||
if (start_lookup_level == LookupLevel::L1) {
|
||||
n = 5 - tsz;
|
||||
desc_addr = mbits(ttbr, 39, n) |
|
||||
(bits(currState->vaddr, n + 26, 30) << 3);
|
||||
@@ -888,7 +892,7 @@ TableWalker::processWalkAArch64()
|
||||
currState->tcr,
|
||||
currState->el);
|
||||
|
||||
LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS;
|
||||
LookupLevel start_lookup_level = LookupLevel::Num_ArmLookupLevel;
|
||||
bool vaddr_fault = false;
|
||||
switch (currState->el) {
|
||||
case EL0:
|
||||
@@ -953,7 +957,7 @@ TableWalker::processWalkAArch64()
|
||||
start_lookup_level = getPageTableOps(tg)->firstS2Level(
|
||||
currState->vtcr.sl0);
|
||||
|
||||
panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
|
||||
panic_if(start_lookup_level == LookupLevel::Num_ArmLookupLevel,
|
||||
"Cannot discern lookup level from vtcr.{sl0,tg0}");
|
||||
ps = currState->vtcr.ps;
|
||||
currState->isUncacheable = currState->vtcr.irgn0 == 0;
|
||||
@@ -1059,14 +1063,14 @@ TableWalker::processWalkAArch64()
|
||||
if (currState->isFetch)
|
||||
f = std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L0, isStage2,
|
||||
ArmFault::TranslationLL + LookupLevel::L0, isStage2,
|
||||
ArmFault::LpaeTran);
|
||||
else
|
||||
f = std::make_shared<DataAbort>(
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L0,
|
||||
ArmFault::TranslationLL + LookupLevel::L0,
|
||||
isStage2, ArmFault::LpaeTran);
|
||||
|
||||
if (currState->timing) {
|
||||
@@ -1088,11 +1092,11 @@ TableWalker::processWalkAArch64()
|
||||
}
|
||||
|
||||
// Determine starting lookup level
|
||||
if (start_lookup_level == MAX_LOOKUP_LEVELS) {
|
||||
if (start_lookup_level == LookupLevel::Num_ArmLookupLevel) {
|
||||
const auto* ptops = getPageTableOps(tg);
|
||||
|
||||
start_lookup_level = ptops->firstLevel(64 - tsz);
|
||||
panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
|
||||
panic_if(start_lookup_level == LookupLevel::Num_ArmLookupLevel,
|
||||
"Table walker couldn't find lookup level\n");
|
||||
}
|
||||
|
||||
@@ -1660,7 +1664,7 @@ TableWalker::doL1Descriptor()
|
||||
currState->fault =
|
||||
std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L1,
|
||||
ArmFault::TranslationLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
else
|
||||
@@ -1669,7 +1673,7 @@ TableWalker::doL1Descriptor()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L1, isStage2,
|
||||
ArmFault::TranslationLL + LookupLevel::L1, isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
return;
|
||||
case L1Descriptor::Section:
|
||||
@@ -1683,7 +1687,7 @@ TableWalker::doL1Descriptor()
|
||||
currState->vaddr_tainted,
|
||||
currState->l1Desc.domain(),
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::AccessFlagLL + L1,
|
||||
ArmFault::AccessFlagLL + LookupLevel::L1,
|
||||
isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
}
|
||||
@@ -1702,8 +1706,8 @@ TableWalker::doL1Descriptor()
|
||||
|
||||
// Trickbox address check
|
||||
currState->fault = testWalk(l2desc_addr, sizeof(uint32_t),
|
||||
currState->l1Desc.domain(), L2,
|
||||
isStage2);
|
||||
currState->l1Desc.domain(),
|
||||
LookupLevel::L2, isStage2);
|
||||
|
||||
if (currState->fault) {
|
||||
if (!currState->timing) {
|
||||
@@ -1893,10 +1897,10 @@ TableWalker::doLongDescriptor()
|
||||
(LookupLevel) (currState->longDesc.lookupLevel + 1);
|
||||
Event *event = NULL;
|
||||
switch (L) {
|
||||
case L1:
|
||||
case LookupLevel::L1:
|
||||
assert(currState->aarch64);
|
||||
case L2:
|
||||
case L3:
|
||||
case LookupLevel::L2:
|
||||
case LookupLevel::L3:
|
||||
event = LongDescEventByLevel[L];
|
||||
break;
|
||||
default:
|
||||
@@ -1943,14 +1947,14 @@ TableWalker::doL2Descriptor()
|
||||
if (currState->isFetch)
|
||||
currState->fault = std::make_shared<PrefetchAbort>(
|
||||
currState->vaddr_tainted,
|
||||
ArmFault::TranslationLL + L2,
|
||||
ArmFault::TranslationLL + LookupLevel::L2,
|
||||
isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
else
|
||||
currState->fault = std::make_shared<DataAbort>(
|
||||
currState->vaddr_tainted, currState->l1Desc.domain(),
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::TranslationLL + L2,
|
||||
ArmFault::TranslationLL + LookupLevel::L2,
|
||||
isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
return;
|
||||
@@ -1967,7 +1971,7 @@ TableWalker::doL2Descriptor()
|
||||
currState->vaddr_tainted,
|
||||
TlbEntry::DomainType::NoAccess,
|
||||
is_atomic ? false : currState->isWrite,
|
||||
ArmFault::AccessFlagLL + L2, isStage2,
|
||||
ArmFault::AccessFlagLL + LookupLevel::L2, isStage2,
|
||||
ArmFault::VmsaTran);
|
||||
}
|
||||
|
||||
@@ -1977,7 +1981,7 @@ TableWalker::doL2Descriptor()
|
||||
void
|
||||
TableWalker::doL1DescriptorWrapper()
|
||||
{
|
||||
currState = stateQueues[L1].front();
|
||||
currState = stateQueues[LookupLevel::L1].front();
|
||||
currState->delayed = false;
|
||||
// if there's a stage2 translation object we don't need it any more
|
||||
if (currState->stage2Tran) {
|
||||
@@ -1995,7 +1999,7 @@ TableWalker::doL1DescriptorWrapper()
|
||||
currState->vaddr_tainted);
|
||||
doL1Descriptor();
|
||||
|
||||
stateQueues[L1].pop_front();
|
||||
stateQueues[LookupLevel::L1].pop_front();
|
||||
// Check if fault was generated
|
||||
if (currState->fault != NoFault) {
|
||||
currState->transState->finish(currState->fault, currState->req,
|
||||
@@ -2031,7 +2035,7 @@ TableWalker::doL1DescriptorWrapper()
|
||||
delete currState;
|
||||
} else {
|
||||
// need to do L2 descriptor
|
||||
stateQueues[L2].push_back(currState);
|
||||
stateQueues[LookupLevel::L2].push_back(currState);
|
||||
}
|
||||
currState = NULL;
|
||||
}
|
||||
@@ -2039,7 +2043,7 @@ TableWalker::doL1DescriptorWrapper()
|
||||
void
|
||||
TableWalker::doL2DescriptorWrapper()
|
||||
{
|
||||
currState = stateQueues[L2].front();
|
||||
currState = stateQueues[LookupLevel::L2].front();
|
||||
assert(currState->delayed);
|
||||
// if there's a stage2 translation object we don't need it any more
|
||||
if (currState->stage2Tran) {
|
||||
@@ -2068,7 +2072,7 @@ TableWalker::doL2DescriptorWrapper()
|
||||
}
|
||||
|
||||
|
||||
stateQueues[L2].pop_front();
|
||||
stateQueues[LookupLevel::L2].pop_front();
|
||||
pending = false;
|
||||
nextWalk(currState->tc);
|
||||
|
||||
@@ -2083,25 +2087,25 @@ TableWalker::doL2DescriptorWrapper()
|
||||
void
|
||||
TableWalker::doL0LongDescriptorWrapper()
|
||||
{
|
||||
doLongDescriptorWrapper(L0);
|
||||
doLongDescriptorWrapper(LookupLevel::L0);
|
||||
}
|
||||
|
||||
void
|
||||
TableWalker::doL1LongDescriptorWrapper()
|
||||
{
|
||||
doLongDescriptorWrapper(L1);
|
||||
doLongDescriptorWrapper(LookupLevel::L1);
|
||||
}
|
||||
|
||||
void
|
||||
TableWalker::doL2LongDescriptorWrapper()
|
||||
{
|
||||
doLongDescriptorWrapper(L2);
|
||||
doLongDescriptorWrapper(LookupLevel::L2);
|
||||
}
|
||||
|
||||
void
|
||||
TableWalker::doL3LongDescriptorWrapper()
|
||||
{
|
||||
doLongDescriptorWrapper(L3);
|
||||
doLongDescriptorWrapper(LookupLevel::L3);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2154,7 +2158,7 @@ TableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level)
|
||||
currState->delayed = false;
|
||||
delete currState;
|
||||
} else {
|
||||
if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1)
|
||||
if (curr_lookup_level >= LookupLevel::Num_ArmLookupLevel - 1)
|
||||
panic("Max. number of lookups already reached in table walk\n");
|
||||
// Need to perform additional lookups
|
||||
stateQueues[currState->longDesc.lookupLevel].push_back(currState);
|
||||
@@ -2321,16 +2325,16 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool long_descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
LookupLevel
|
||||
TableWalker::LookupLevel
|
||||
TableWalker::toLookupLevel(uint8_t lookup_level_as_int)
|
||||
{
|
||||
switch (lookup_level_as_int) {
|
||||
case L1:
|
||||
return L1;
|
||||
case L2:
|
||||
return L2;
|
||||
case L3:
|
||||
return L3;
|
||||
case LookupLevel::L1:
|
||||
return LookupLevel::L1;
|
||||
case LookupLevel::L2:
|
||||
return LookupLevel::L2;
|
||||
case LookupLevel::L3:
|
||||
return LookupLevel::L3;
|
||||
default:
|
||||
panic("Invalid lookup level conversion");
|
||||
}
|
||||
|
||||
@@ -65,13 +65,15 @@ class TLB;
|
||||
|
||||
class TableWalker : public ClockedObject
|
||||
{
|
||||
using LookupLevel = enums::ArmLookupLevel;
|
||||
|
||||
public:
|
||||
class WalkerState;
|
||||
|
||||
class DescriptorBase
|
||||
{
|
||||
public:
|
||||
DescriptorBase() : lookupLevel(L0) {}
|
||||
DescriptorBase() : lookupLevel(LookupLevel::L0) {}
|
||||
|
||||
/** Current lookup level for this descriptor */
|
||||
LookupLevel lookupLevel;
|
||||
@@ -117,7 +119,7 @@ class TableWalker : public ClockedObject
|
||||
/** Default ctor */
|
||||
L1Descriptor() : data(0), _dirty(false)
|
||||
{
|
||||
lookupLevel = L1;
|
||||
lookupLevel = LookupLevel::L1;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@@ -280,13 +282,13 @@ class TableWalker : public ClockedObject
|
||||
/** Default ctor */
|
||||
L2Descriptor() : data(0), l1Parent(nullptr), _dirty(false)
|
||||
{
|
||||
lookupLevel = L2;
|
||||
lookupLevel = LookupLevel::L2;
|
||||
}
|
||||
|
||||
L2Descriptor(L1Descriptor &parent) : data(0), l1Parent(&parent),
|
||||
_dirty(false)
|
||||
{
|
||||
lookupLevel = L2;
|
||||
lookupLevel = LookupLevel::L2;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@@ -449,10 +451,10 @@ class TableWalker : public ClockedObject
|
||||
dbgHeader() const override
|
||||
{
|
||||
if (type() == LongDescriptor::Page) {
|
||||
assert(lookupLevel == L3);
|
||||
assert(lookupLevel == LookupLevel::L3);
|
||||
return "Inserting Page descriptor into TLB\n";
|
||||
} else {
|
||||
assert(lookupLevel < L3);
|
||||
assert(lookupLevel < LookupLevel::L3);
|
||||
return "Inserting Block descriptor into TLB\n";
|
||||
}
|
||||
}
|
||||
@@ -478,13 +480,14 @@ class TableWalker : public ClockedObject
|
||||
// 4 KiB granule and at L1 for 16/64 KiB granules
|
||||
switch (grainSize) {
|
||||
case Grain4KB:
|
||||
if (lookupLevel == L0 || lookupLevel == L3)
|
||||
if (lookupLevel == LookupLevel::L0 ||
|
||||
lookupLevel == LookupLevel::L3)
|
||||
return Invalid;
|
||||
else
|
||||
return Block;
|
||||
|
||||
case Grain16KB:
|
||||
if (lookupLevel == L2)
|
||||
if (lookupLevel == LookupLevel::L2)
|
||||
return Block;
|
||||
else
|
||||
return Invalid;
|
||||
@@ -492,8 +495,8 @@ class TableWalker : public ClockedObject
|
||||
case Grain64KB:
|
||||
// With Armv8.2-LPA (52bit PA) L1 Block descriptors
|
||||
// are allowed for 64KiB granule
|
||||
if ((lookupLevel == L1 && physAddrRange == 52) ||
|
||||
lookupLevel == L2)
|
||||
if ((lookupLevel == LookupLevel::L1 && physAddrRange == 52) ||
|
||||
lookupLevel == LookupLevel::L2)
|
||||
return Block;
|
||||
else
|
||||
return Invalid;
|
||||
@@ -502,7 +505,7 @@ class TableWalker : public ClockedObject
|
||||
return Invalid;
|
||||
}
|
||||
case 0x3:
|
||||
return lookupLevel == L3 ? Page : Table;
|
||||
return lookupLevel == LookupLevel::L3 ? Page : Table;
|
||||
default:
|
||||
return Invalid;
|
||||
}
|
||||
@@ -515,13 +518,13 @@ class TableWalker : public ClockedObject
|
||||
if (type() == Block) {
|
||||
switch (grainSize) {
|
||||
case Grain4KB:
|
||||
return lookupLevel == L1 ? 30 /* 1 GiB */
|
||||
: 21 /* 2 MiB */;
|
||||
return lookupLevel == LookupLevel::L1 ?
|
||||
30 /* 1 GiB */ : 21 /* 2 MiB */;
|
||||
case Grain16KB:
|
||||
return 25 /* 32 MiB */;
|
||||
case Grain64KB:
|
||||
return lookupLevel == L1 ? 42 /* 4 TiB */
|
||||
: 29 /* 512 MiB */;
|
||||
return lookupLevel == LookupLevel::L1 ?
|
||||
42 /* 4 TiB */ : 29 /* 512 MiB */;
|
||||
default:
|
||||
panic("Invalid AArch64 VM granule size\n");
|
||||
}
|
||||
@@ -592,7 +595,7 @@ class TableWalker : public ClockedObject
|
||||
int va_hi = va_lo + stride - 1;
|
||||
pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3);
|
||||
} else {
|
||||
if (lookupLevel == L1)
|
||||
if (lookupLevel == LookupLevel::L1)
|
||||
pa = nextTableAddr() | (bits(va, 29, 21) << 3);
|
||||
else // lookupLevel == L2
|
||||
pa = nextTableAddr() | (bits(va, 20, 12) << 3);
|
||||
@@ -1003,7 +1006,7 @@ class TableWalker : public ClockedObject
|
||||
protected:
|
||||
|
||||
/** Queues of requests for all the different lookup levels */
|
||||
std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
|
||||
std::list<WalkerState *> stateQueues[LookupLevel::Num_ArmLookupLevel];
|
||||
|
||||
/** Queue of requests that have passed are waiting because the walker is
|
||||
* currently busy. */
|
||||
|
||||
@@ -109,7 +109,7 @@ class TlbTestInterface
|
||||
virtual Fault walkCheck(Addr pa, Addr size, Addr va, bool is_secure,
|
||||
Addr is_priv, BaseMMU::Mode mode,
|
||||
TlbEntry::DomainType domain,
|
||||
LookupLevel lookup_level) = 0;
|
||||
enums::ArmLookupLevel lookup_level) = 0;
|
||||
};
|
||||
|
||||
class TLB : public BaseTLB
|
||||
@@ -158,6 +158,7 @@ class TLB : public BaseTLB
|
||||
public:
|
||||
using Params = ArmTLBParams;
|
||||
using Lookup = TlbEntry::Lookup;
|
||||
using LookupLevel = enums::ArmLookupLevel;
|
||||
|
||||
TLB(const Params &p);
|
||||
TLB(const Params &p, int _size, TableWalker *_walker);
|
||||
|
||||
Reference in New Issue
Block a user