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:
Giacomo Travaglini
2021-10-19 14:18:14 +01:00
parent d860e0bd2d
commit 1268c6ec3c
7 changed files with 132 additions and 121 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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. */

View File

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