arch-arm: Implement FEAT_TLBIRANGE extension (#414)

This commit is contained in:
Andreas Sandberg
2023-10-09 17:09:31 +01:00
committed by GitHub
10 changed files with 758 additions and 27 deletions

View File

@@ -89,6 +89,7 @@ class ArmExtension(ScopedEnum):
# Armv8.4
"FEAT_SEL2",
"FEAT_TLBIOS",
"FEAT_TLBIRANGE",
"FEAT_FLAGM",
"FEAT_IDST",
# Armv8.5
@@ -183,6 +184,7 @@ class ArmDefaultRelease(Armv8):
# Armv8.4
"FEAT_SEL2",
"FEAT_TLBIOS",
"FEAT_TLBIRANGE",
"FEAT_FLAGM",
"FEAT_IDST",
# Armv8.5
@@ -229,6 +231,7 @@ class Armv84(Armv83):
extensions = Armv83.extensions + [
"FEAT_SEL2",
"FEAT_TLBIOS",
"FEAT_TLBIRANGE",
"FEAT_FLAGM",
"FEAT_IDST",
]

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2013,2017-2022 Arm Limited
* Copyright (c) 2011-2013,2017-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -852,6 +852,354 @@ TlbiOp64::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) cons
}
return;
}
case MISCREG_TLBI_RVAE1_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVA tlbiOp(target_el, secure, value, asid, false);
if (tlbiOp.valid())
tlbiOp(tc);
return;
}
case MISCREG_TLBI_RVAE1IS_Xt:
case MISCREG_TLBI_RVAE1OS_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVA tlbiOp(target_el, secure, value, asid, false);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
return;
}
case MISCREG_TLBI_RVAAE1_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVAA tlbiOp(target_el, secure, value, false);
if (tlbiOp.valid())
tlbiOp(tc);
return;
}
case MISCREG_TLBI_RVAAE1IS_Xt:
case MISCREG_TLBI_RVAAE1OS_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVAA tlbiOp(target_el, secure, value, false);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
return;
}
case MISCREG_TLBI_RVALE1_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVA tlbiOp(target_el, secure, value, asid, true);
if (tlbiOp.valid())
tlbiOp(tc);
return;
}
case MISCREG_TLBI_RVALE1IS_Xt:
case MISCREG_TLBI_RVALE1OS_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVA tlbiOp(target_el, secure, value, asid, true);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
return;
}
case MISCREG_TLBI_RVAALE1_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVAA tlbiOp(target_el, secure, value, true);
if (tlbiOp.valid())
tlbiOp(tc);
return;
}
case MISCREG_TLBI_RVAALE1IS_Xt:
case MISCREG_TLBI_RVAALE1OS_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
ExceptionLevel target_el = EL1;
if (EL2Enabled(tc)) {
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
if (hcr.tge && hcr.e2h) {
target_el = EL2;
}
}
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
TLBIRMVAA tlbiOp(target_el, secure, value, true);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
return;
}
case MISCREG_TLBI_RIPAS2E1_Xt:
{
if (EL2Enabled(tc)) {
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) &&
!scr.ns && !bits(value, 63);
TLBIRIPA tlbiOp(EL1, secure, value, false);
tlbiOp(tc);
}
return;
}
case MISCREG_TLBI_RIPAS2E1IS_Xt:
{
if (EL2Enabled(tc)) {
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) &&
!scr.ns && !bits(value, 63);
TLBIRIPA tlbiOp(EL1, secure, value, false);
tlbiOp.broadcast(tc);
}
return;
}
case MISCREG_TLBI_RIPAS2LE1_Xt:
{
if (EL2Enabled(tc)) {
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) &&
!scr.ns && !bits(value, 63);
TLBIRIPA tlbiOp(EL1, secure, value, true);
tlbiOp(tc);
}
return;
}
case MISCREG_TLBI_RIPAS2LE1IS_Xt:
{
if (EL2Enabled(tc)) {
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
bool secure = release->has(ArmExtension::SECURITY) &&
!scr.ns && !bits(value, 63);
TLBIRIPA tlbiOp(EL1, secure, value, true);
tlbiOp.broadcast(tc);
}
return;
}
case MISCREG_TLBI_RVAE2_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
if (hcr.e2h) {
// The asid will only be used when e2h == 1
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
TLBIRMVA tlbiOp(EL2, secure, value, asid, false);
if (tlbiOp.valid())
tlbiOp(tc);
} else {
TLBIRMVAA tlbiOp(EL2, secure, value, false);
if (tlbiOp.valid())
tlbiOp(tc);
}
return;
}
case MISCREG_TLBI_RVAE2IS_Xt:
case MISCREG_TLBI_RVAE2OS_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
if (hcr.e2h) {
// The asid will only be used when e2h == 1
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
TLBIRMVA tlbiOp(EL2, secure, value, asid, false);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
} else {
TLBIRMVAA tlbiOp(EL2, secure, value, false);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
}
return;
}
case MISCREG_TLBI_RVALE2_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
if (hcr.e2h) {
// The asid will only be used when e2h == 1
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
TLBIRMVA tlbiOp(EL2, secure, value, asid, true);
if (tlbiOp.valid())
tlbiOp(tc);
} else {
TLBIRMVAA tlbiOp(EL2, secure, value, true);
if (tlbiOp.valid())
tlbiOp(tc);
}
return;
}
case MISCREG_TLBI_RVALE2IS_Xt:
case MISCREG_TLBI_RVALE2OS_Xt:
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
bool secure = release->has(ArmExtension::SECURITY) && !scr.ns;
if (hcr.e2h) {
// The asid will only be used when e2h == 1
auto asid = asid_16bits ? bits(value, 63, 48) :
bits(value, 55, 48);
TLBIRMVA tlbiOp(EL2, secure, value, asid, true);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
} else {
TLBIRMVAA tlbiOp(EL2, secure, value, true);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
}
return;
}
case MISCREG_TLBI_RVAE3_Xt:
{
TLBIRMVAA tlbiOp(EL3, true, value, false);
if (tlbiOp.valid())
tlbiOp(tc);
return;
}
case MISCREG_TLBI_RVAE3IS_Xt:
case MISCREG_TLBI_RVAE3OS_Xt:
{
TLBIRMVAA tlbiOp(EL3, true, value, false);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
return;
}
case MISCREG_TLBI_RVALE3_Xt:
{
TLBIRMVAA tlbiOp(EL3, true, value, true);
if (tlbiOp.valid())
tlbiOp(tc);
return;
}
case MISCREG_TLBI_RVALE3IS_Xt:
case MISCREG_TLBI_RVALE3OS_Xt:
{
TLBIRMVAA tlbiOp(EL3, true, value, true);
if (tlbiOp.valid())
tlbiOp.broadcast(tc);
return;
}
default:
panic("Invalid TLBI\n");
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2011-2022 Arm Limited
// Copyright (c) 2011-2023 Arm Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -542,6 +542,16 @@ namespace Aarch64
case MISCREG_TLBI_VAALE1_Xt:
case MISCREG_TLBI_IPAS2E1_Xt:
case MISCREG_TLBI_IPAS2LE1_Xt:
case MISCREG_TLBI_RVAE1_Xt:
case MISCREG_TLBI_RVAAE1_Xt:
case MISCREG_TLBI_RVALE1_Xt:
case MISCREG_TLBI_RVAALE1_Xt:
case MISCREG_TLBI_RIPAS2E1_Xt:
case MISCREG_TLBI_RIPAS2LE1_Xt:
case MISCREG_TLBI_RVAE2_Xt:
case MISCREG_TLBI_RVALE2_Xt:
case MISCREG_TLBI_RVAE3_Xt:
case MISCREG_TLBI_RVALE3_Xt:
return new Tlbi64LocalHub(
machInst, miscReg, rt);
case MISCREG_TLBI_ALLE3IS:
@@ -576,6 +586,26 @@ namespace Aarch64
case MISCREG_TLBI_IPAS2E1OS_Xt:
case MISCREG_TLBI_IPAS2LE1IS_Xt:
case MISCREG_TLBI_IPAS2LE1OS_Xt:
case MISCREG_TLBI_RVAE1IS_Xt:
case MISCREG_TLBI_RVAE1OS_Xt:
case MISCREG_TLBI_RVAAE1IS_Xt:
case MISCREG_TLBI_RVAAE1OS_Xt:
case MISCREG_TLBI_RVALE1IS_Xt:
case MISCREG_TLBI_RVALE1OS_Xt:
case MISCREG_TLBI_RVAALE1IS_Xt:
case MISCREG_TLBI_RVAALE1OS_Xt:
case MISCREG_TLBI_RIPAS2E1IS_Xt:
case MISCREG_TLBI_RIPAS2E1OS_Xt:
case MISCREG_TLBI_RIPAS2LE1IS_Xt:
case MISCREG_TLBI_RIPAS2LE1OS_Xt:
case MISCREG_TLBI_RVAE2IS_Xt:
case MISCREG_TLBI_RVAE2OS_Xt:
case MISCREG_TLBI_RVALE2IS_Xt:
case MISCREG_TLBI_RVALE2OS_Xt:
case MISCREG_TLBI_RVAE3IS_Xt:
case MISCREG_TLBI_RVAE3OS_Xt:
case MISCREG_TLBI_RVALE3IS_Xt:
case MISCREG_TLBI_RVALE3OS_Xt:
return new Tlbi64ShareableHub(
machInst, miscReg, rt, dec.dvmEnabled);
default:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013, 2021 Arm Limited
* Copyright (c) 2010, 2012-2013, 2021, 2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -186,6 +186,12 @@ struct TlbEntry : public Serializable
{
// virtual address
Addr va = 0;
// lookup size:
// * != 0 -> this is a range based lookup.
// end_address = va + size
// * == 0 -> This is a normal lookup. size should
// be ignored
Addr size = 0;
// context id/address space id to use
uint16_t asn = 0;
// if on lookup asn should be ignored
@@ -219,6 +225,7 @@ struct TlbEntry : public Serializable
uint16_t asid; // Address Space Identifier
vmid_t vmid; // Virtual machine Identifier
GrainSize tg; // Translation Granule Size
uint8_t N; // Number of bits in pagesize
uint8_t innerAttrs;
uint8_t outerAttrs;
@@ -263,7 +270,7 @@ struct TlbEntry : public Serializable
bool uncacheable, bool read_only) :
pfn(_paddr >> PageShift), size(PageBytes - 1), vpn(_vaddr >> PageShift),
attributes(0), lookupLevel(LookupLevel::L1),
asid(_asn), vmid(0), N(0),
asid(_asn), vmid(0), tg(Grain4KB), 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),
@@ -281,7 +288,7 @@ struct TlbEntry : public Serializable
TlbEntry() :
pfn(0), size(0), vpn(0), attributes(0), lookupLevel(LookupLevel::L1),
asid(0), vmid(0), N(0),
asid(0), vmid(0), tg(ReservedGrain), N(0),
innerAttrs(0), outerAttrs(0), ap(0), hap(0x3),
domain(DomainType::Client), mtype(MemoryType::StronglyOrdered),
longDescFormat(false), isHyp(false), global(false), valid(false),
@@ -306,12 +313,25 @@ struct TlbEntry : public Serializable
return pfn << PageShift;
}
bool
matchAddress(const Lookup &lookup) const
{
Addr page_addr = vpn << N;
if (lookup.size) {
// This is a range based loookup
return lookup.va <= page_addr + size &&
lookup.va + lookup.size > page_addr;
} else {
// This is a normal lookup
return lookup.va >= page_addr && lookup.va <= page_addr + size;
}
}
bool
match(const Lookup &lookup) const
{
bool match = false;
Addr v = vpn << N;
if (valid && lookup.va >= v && lookup.va <= v + size &&
if (valid && matchAddress(lookup) &&
(lookup.secure == !nstid) && (lookup.hyp == isHyp))
{
match = checkELMatch(lookup.targetEL, lookup.inHost);
@@ -319,8 +339,8 @@ struct TlbEntry : public Serializable
if (match && !lookup.ignoreAsn) {
match = global || (lookup.asn == asid);
}
if (match && nstid) {
match = isHyp || (lookup.vmid == vmid);
if (match && useVMID(lookup.targetEL, lookup.inHost)) {
match = lookup.vmid == vmid;
}
}
return match;

View File

@@ -759,12 +759,24 @@ std::unordered_map<MiscRegNum64, MiscRegIndex> miscRegNumToIdx{
{ MiscRegNum64(1, 0, 8, 1, 3), MISCREG_TLBI_VAAE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 1, 5), MISCREG_TLBI_VALE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 1, 7), MISCREG_TLBI_VAALE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 2, 1), MISCREG_TLBI_RVAE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 2, 3), MISCREG_TLBI_RVAAE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 2, 5), MISCREG_TLBI_RVALE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 2, 7), MISCREG_TLBI_RVAALE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 3, 0), MISCREG_TLBI_VMALLE1IS },
{ MiscRegNum64(1, 0, 8, 3, 1), MISCREG_TLBI_VAE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 3, 2), MISCREG_TLBI_ASIDE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 3, 3), MISCREG_TLBI_VAAE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 3, 5), MISCREG_TLBI_VALE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 3, 7), MISCREG_TLBI_VAALE1IS_Xt },
{ MiscRegNum64(1, 0, 8, 5, 1), MISCREG_TLBI_RVAE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 5, 3), MISCREG_TLBI_RVAAE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 5, 5), MISCREG_TLBI_RVALE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 5, 7), MISCREG_TLBI_RVAALE1OS_Xt },
{ MiscRegNum64(1, 0, 8, 6, 1), MISCREG_TLBI_RVAE1_Xt },
{ MiscRegNum64(1, 0, 8, 6, 3), MISCREG_TLBI_RVAAE1_Xt },
{ MiscRegNum64(1, 0, 8, 6, 5), MISCREG_TLBI_RVALE1_Xt },
{ MiscRegNum64(1, 0, 8, 6, 7), MISCREG_TLBI_RVAALE1_Xt },
{ MiscRegNum64(1, 0, 8, 7, 0), MISCREG_TLBI_VMALLE1 },
{ MiscRegNum64(1, 0, 8, 7, 1), MISCREG_TLBI_VAE1_Xt },
{ MiscRegNum64(1, 0, 8, 7, 2), MISCREG_TLBI_ASIDE1_Xt },
@@ -783,12 +795,16 @@ std::unordered_map<MiscRegNum64, MiscRegIndex> miscRegNumToIdx{
{ MiscRegNum64(1, 4, 7, 8, 6), MISCREG_AT_S12E0R_Xt },
{ MiscRegNum64(1, 4, 7, 8, 7), MISCREG_AT_S12E0W_Xt },
{ MiscRegNum64(1, 4, 8, 0, 1), MISCREG_TLBI_IPAS2E1IS_Xt },
{ MiscRegNum64(1, 4, 8, 0, 2), MISCREG_TLBI_RIPAS2E1IS_Xt },
{ MiscRegNum64(1, 4, 8, 0, 5), MISCREG_TLBI_IPAS2LE1IS_Xt },
{ MiscRegNum64(1, 4, 8, 1, 0), MISCREG_TLBI_ALLE2OS },
{ MiscRegNum64(1, 4, 8, 1, 1), MISCREG_TLBI_VAE2OS_Xt },
{ MiscRegNum64(1, 4, 8, 1, 4), MISCREG_TLBI_ALLE1OS },
{ MiscRegNum64(1, 4, 8, 1, 5), MISCREG_TLBI_VALE2OS_Xt },
{ MiscRegNum64(1, 4, 8, 1, 6), MISCREG_TLBI_VMALLS12E1OS },
{ MiscRegNum64(1, 4, 8, 0, 6), MISCREG_TLBI_RIPAS2LE1IS_Xt },
{ MiscRegNum64(1, 4, 8, 2, 1), MISCREG_TLBI_RVAE2IS_Xt },
{ MiscRegNum64(1, 4, 8, 2, 5), MISCREG_TLBI_RVALE2IS_Xt },
{ MiscRegNum64(1, 4, 8, 3, 0), MISCREG_TLBI_ALLE2IS },
{ MiscRegNum64(1, 4, 8, 3, 1), MISCREG_TLBI_VAE2IS_Xt },
{ MiscRegNum64(1, 4, 8, 3, 4), MISCREG_TLBI_ALLE1IS },
@@ -796,8 +812,16 @@ std::unordered_map<MiscRegNum64, MiscRegIndex> miscRegNumToIdx{
{ MiscRegNum64(1, 4, 8, 3, 6), MISCREG_TLBI_VMALLS12E1IS },
{ MiscRegNum64(1, 4, 8, 4, 0), MISCREG_TLBI_IPAS2E1OS_Xt },
{ MiscRegNum64(1, 4, 8, 4, 1), MISCREG_TLBI_IPAS2E1_Xt },
{ MiscRegNum64(1, 4, 8, 4, 2), MISCREG_TLBI_RIPAS2E1_Xt },
{ MiscRegNum64(1, 4, 8, 4, 3), MISCREG_TLBI_RIPAS2E1OS_Xt },
{ MiscRegNum64(1, 4, 8, 4, 4), MISCREG_TLBI_IPAS2LE1OS_Xt },
{ MiscRegNum64(1, 4, 8, 4, 5), MISCREG_TLBI_IPAS2LE1_Xt },
{ MiscRegNum64(1, 4, 8, 4, 6), MISCREG_TLBI_RIPAS2LE1_Xt },
{ MiscRegNum64(1, 4, 8, 4, 7), MISCREG_TLBI_RIPAS2LE1OS_Xt },
{ MiscRegNum64(1, 4, 8, 5, 1), MISCREG_TLBI_RVAE2OS_Xt },
{ MiscRegNum64(1, 4, 8, 5, 5), MISCREG_TLBI_RVALE2OS_Xt },
{ MiscRegNum64(1, 4, 8, 6, 1), MISCREG_TLBI_RVAE2_Xt },
{ MiscRegNum64(1, 4, 8, 6, 5), MISCREG_TLBI_RVALE2_Xt },
{ MiscRegNum64(1, 4, 8, 7, 0), MISCREG_TLBI_ALLE2 },
{ MiscRegNum64(1, 4, 8, 7, 1), MISCREG_TLBI_VAE2_Xt },
{ MiscRegNum64(1, 4, 8, 7, 4), MISCREG_TLBI_ALLE1 },
@@ -808,9 +832,15 @@ std::unordered_map<MiscRegNum64, MiscRegIndex> miscRegNumToIdx{
{ MiscRegNum64(1, 6, 8, 1, 0), MISCREG_TLBI_ALLE3OS },
{ MiscRegNum64(1, 6, 8, 1, 1), MISCREG_TLBI_VAE3OS_Xt },
{ MiscRegNum64(1, 6, 8, 1, 5), MISCREG_TLBI_VALE3OS_Xt },
{ MiscRegNum64(1, 6, 8, 2, 1), MISCREG_TLBI_RVAE3IS_Xt },
{ MiscRegNum64(1, 6, 8, 2, 5), MISCREG_TLBI_RVALE3IS_Xt },
{ MiscRegNum64(1, 6, 8, 3, 0), MISCREG_TLBI_ALLE3IS },
{ MiscRegNum64(1, 6, 8, 3, 1), MISCREG_TLBI_VAE3IS_Xt },
{ MiscRegNum64(1, 6, 8, 3, 5), MISCREG_TLBI_VALE3IS_Xt },
{ MiscRegNum64(1, 6, 8, 5, 1), MISCREG_TLBI_RVAE3OS_Xt },
{ MiscRegNum64(1, 6, 8, 5, 5), MISCREG_TLBI_RVALE3OS_Xt },
{ MiscRegNum64(1, 6, 8, 6, 1), MISCREG_TLBI_RVAE3_Xt },
{ MiscRegNum64(1, 6, 8, 6, 5), MISCREG_TLBI_RVALE3_Xt },
{ MiscRegNum64(1, 6, 8, 7, 0), MISCREG_TLBI_ALLE3 },
{ MiscRegNum64(1, 6, 8, 7, 1), MISCREG_TLBI_VAE3_Xt },
{ MiscRegNum64(1, 6, 8, 7, 5), MISCREG_TLBI_VALE3_Xt },
@@ -4276,7 +4306,9 @@ ISA::initializeMiscRegMetadata()
isar0_el1.atomic = release->has(ArmExtension::FEAT_LSE) ? 0x2 : 0x0;
isar0_el1.rdm = release->has(ArmExtension::FEAT_RDM) ? 0x1 : 0x0;
isar0_el1.tme = release->has(ArmExtension::TME) ? 0x1 : 0x0;
isar0_el1.tlb = release->has(ArmExtension::FEAT_TLBIOS) ? 0x1 : 0x0;
isar0_el1.tlb = release->has(ArmExtension::FEAT_TLBIRANGE) ?
0x2 : release->has(ArmExtension::FEAT_TLBIOS) ?
0x1 : 0x0;
isar0_el1.ts = release->has(ArmExtension::FEAT_FLAGM2) ?
0x2 : release->has(ArmExtension::FEAT_FLAGM) ?
0x1 : 0x0;
@@ -4889,6 +4921,79 @@ ISA::initializeMiscRegMetadata()
.monSecureWrite().monNonSecureWrite();
InitReg(MISCREG_TLBI_VALE3_Xt)
.monSecureWrite().monNonSecureWrite();
InitReg(MISCREG_TLBI_RVAE1_Xt)
.faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvae1>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVAAE1_Xt)
.faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvaae1>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVALE1_Xt)
.faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvale1>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVAALE1_Xt)
.faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvaale1>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RIPAS2E1_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RIPAS2LE1_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVAE2_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVALE2_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVAE3_Xt)
.monWrite();
InitReg(MISCREG_TLBI_RVALE3_Xt)
.monWrite();
InitReg(MISCREG_TLBI_RVAE1IS_Xt)
.faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvae1is>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVAAE1IS_Xt)
.faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvaae1is>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVALE1IS_Xt)
.faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvale1is>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVAALE1IS_Xt)
.faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvaale1is>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RIPAS2E1IS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RIPAS2LE1IS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVAE2IS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVALE2IS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVAE3IS_Xt)
.monWrite();
InitReg(MISCREG_TLBI_RVALE3IS_Xt)
.monWrite();
InitReg(MISCREG_TLBI_RVAE1OS_Xt)
.faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvae1os>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVAAE1OS_Xt)
.faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvaae1os>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVALE1OS_Xt)
.faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvale1os>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RVAALE1OS_Xt)
.faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvaale1os>)
.writes(1).exceptUserMode();
InitReg(MISCREG_TLBI_RIPAS2E1OS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RIPAS2LE1OS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVAE2OS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVALE2OS_Xt)
.hypWrite().monWrite();
InitReg(MISCREG_TLBI_RVAE3OS_Xt)
.monWrite();
InitReg(MISCREG_TLBI_RVALE3OS_Xt)
.monWrite();
InitReg(MISCREG_PMINTENSET_EL1)
.allPrivileges().exceptUserMode()
.mapsTo(MISCREG_PMINTENSET);

View File

@@ -729,6 +729,36 @@ namespace ArmISA
MISCREG_TLBI_ALLE3,
MISCREG_TLBI_VAE3_Xt,
MISCREG_TLBI_VALE3_Xt,
MISCREG_TLBI_RVAE1_Xt,
MISCREG_TLBI_RVAAE1_Xt,
MISCREG_TLBI_RVALE1_Xt,
MISCREG_TLBI_RVAALE1_Xt,
MISCREG_TLBI_RIPAS2E1_Xt,
MISCREG_TLBI_RIPAS2LE1_Xt,
MISCREG_TLBI_RVAE2_Xt,
MISCREG_TLBI_RVALE2_Xt,
MISCREG_TLBI_RVAE3_Xt,
MISCREG_TLBI_RVALE3_Xt,
MISCREG_TLBI_RVAE1IS_Xt,
MISCREG_TLBI_RVAAE1IS_Xt,
MISCREG_TLBI_RVALE1IS_Xt,
MISCREG_TLBI_RVAALE1IS_Xt,
MISCREG_TLBI_RIPAS2E1IS_Xt,
MISCREG_TLBI_RIPAS2LE1IS_Xt,
MISCREG_TLBI_RVAE2IS_Xt,
MISCREG_TLBI_RVALE2IS_Xt,
MISCREG_TLBI_RVAE3IS_Xt,
MISCREG_TLBI_RVALE3IS_Xt,
MISCREG_TLBI_RVAE1OS_Xt,
MISCREG_TLBI_RVAAE1OS_Xt,
MISCREG_TLBI_RVALE1OS_Xt,
MISCREG_TLBI_RVAALE1OS_Xt,
MISCREG_TLBI_RIPAS2E1OS_Xt,
MISCREG_TLBI_RIPAS2LE1OS_Xt,
MISCREG_TLBI_RVAE2OS_Xt,
MISCREG_TLBI_RVALE2OS_Xt,
MISCREG_TLBI_RVAE3OS_Xt,
MISCREG_TLBI_RVALE3OS_Xt,
MISCREG_PMINTENSET_EL1,
MISCREG_PMINTENCLR_EL1,
MISCREG_PMCR_EL0,
@@ -1503,6 +1533,13 @@ namespace ArmISA
return *this;
}
chain
monWrite(bool v = true) const
{
monSecureWrite(v);
monNonSecureWrite(v);
return *this;
}
chain
monSecure(bool v = true) const
{
monSecureRead(v);
@@ -2411,6 +2448,36 @@ namespace ArmISA
"tlbi_alle3",
"tlbi_vae3_xt",
"tlbi_vale3_xt",
"tlbi_rvae1_xt",
"tlbi_rvaae1_xt",
"tlbi_rvale1_xt",
"tlbi_rvaale1_xt",
"tlbi_ripas2e1_xt",
"tlbi_ripas2le1_xt",
"tlbi_rvae2_xt",
"tlbi_rvale2_xt",
"tlbi_rvae3_xt",
"tlbi_rvale3_xt",
"tlbi_rvae1is_xt",
"tlbi_rvaae1is_xt",
"tlbi_rvale1is_xt",
"tlbi_rvaale1is_xt",
"tlbi_ripas2e1is_xt",
"tlbi_ripas2le1is_xt",
"tlbi_rvae2is_xt",
"tlbi_rvale2is_xt",
"tlbi_rvae3is_xt",
"tlbi_rvale3is_xt",
"tlbi_rvae1os_xt",
"tlbi_rvaae1os_xt",
"tlbi_rvale1os_xt",
"tlbi_rvaale1os_xt",
"tlbi_ripas2e1os_xt",
"tlbi_ripas2le1os_xt",
"tlbi_rvae2os_xt",
"tlbi_rvale2os_xt",
"tlbi_rvae3os_xt",
"tlbi_rvale3os_xt",
"pmintenset_el1",
"pmintenclr_el1",
"pmcr_el0",

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2019, 2021-2022 Arm Limited
* Copyright (c) 2010, 2012-2019, 2021-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -2305,6 +2305,7 @@ TableWalker::insertPartialTableEntry(LongDescriptor &descriptor)
te.asid = currState->asid;
te.vmid = currState->vmid;
te.N = descriptor.offsetBits();
te.tg = descriptor.grainSize;
te.vpn = currState->vaddr >> te.N;
te.size = (1ULL << te.N) - 1;
te.pfn = descriptor.nextTableAddr();
@@ -2378,6 +2379,7 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool long_descriptor)
LongDescriptor l_descriptor =
dynamic_cast<LongDescriptor &>(descriptor);
te.tg = l_descriptor.grainSize;
te.xn |= currState->xnTable;
te.pxn = currState->pxnTable || l_descriptor.pxn();
if (isStage2) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2022 Arm Limited
* Copyright (c) 2018-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -209,6 +209,22 @@ TLBIALLN::match(TlbEntry* te, vmid_t vmid) const
te->checkELMatch(targetEL, false);
}
TlbEntry::Lookup
TLBIMVAA::lookupGen(vmid_t vmid) const
{
TlbEntry::Lookup lookup_data;
lookup_data.va = sext<56>(addr);
lookup_data.ignoreAsn = true;
lookup_data.vmid = vmid;
lookup_data.hyp = targetEL == EL2;
lookup_data.secure = secureLookup;
lookup_data.functional = true;
lookup_data.targetEL = targetEL;
lookup_data.inHost = inHost;
lookup_data.mode = BaseMMU::Read;
return lookup_data;
}
void
TLBIMVAA::operator()(ThreadContext* tc)
{
@@ -224,10 +240,19 @@ TLBIMVAA::operator()(ThreadContext* tc)
bool
TLBIMVAA::match(TlbEntry* te, vmid_t vmid) const
{
TlbEntry::Lookup lookup_data = lookupGen(vmid);
return te->match(lookup_data) && (!lastLevel || !te->partial);
}
TlbEntry::Lookup
TLBIMVA::lookupGen(vmid_t vmid) const
{
TlbEntry::Lookup lookup_data;
lookup_data.va = sext<56>(addr);
lookup_data.ignoreAsn = true;
lookup_data.asn = asid;
lookup_data.ignoreAsn = false;
lookup_data.vmid = vmid;
lookup_data.hyp = targetEL == EL2;
lookup_data.secure = secureLookup;
@@ -236,7 +261,7 @@ TLBIMVAA::match(TlbEntry* te, vmid_t vmid) const
lookup_data.inHost = inHost;
lookup_data.mode = BaseMMU::Read;
return te->match(lookup_data) && (!lastLevel || !te->partial);
return lookup_data;
}
void
@@ -255,17 +280,7 @@ TLBIMVA::operator()(ThreadContext* tc)
bool
TLBIMVA::match(TlbEntry* te, vmid_t vmid) const
{
TlbEntry::Lookup lookup_data;
lookup_data.va = sext<56>(addr);
lookup_data.asn = asid;
lookup_data.ignoreAsn = false;
lookup_data.vmid = vmid;
lookup_data.hyp = targetEL == EL2;
lookup_data.secure = secureLookup;
lookup_data.functional = true;
lookup_data.targetEL = targetEL;
lookup_data.inHost = inHost;
lookup_data.mode = BaseMMU::Read;
TlbEntry::Lookup lookup_data = lookupGen(vmid);
return te->match(lookup_data) && (!lastLevel || !te->partial);
}
@@ -305,5 +320,37 @@ TLBIIPA::operator()(ThreadContext* tc)
}
}
bool
TLBIRMVA::match(TlbEntry* te, vmid_t vmid) const
{
TlbEntry::Lookup lookup_data = lookupGen(vmid);
lookup_data.size = rangeSize();
auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial);
if (addr_match) {
return tgMap[rangeData.tg] == te->tg &&
(resTLBIttl(rangeData.tg, rangeData.ttl) ||
rangeData.ttl == te->lookupLevel);
} else {
return false;
}
}
bool
TLBIRMVAA::match(TlbEntry* te, vmid_t vmid) const
{
TlbEntry::Lookup lookup_data = lookupGen(vmid);
lookup_data.size = rangeSize();
auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial);
if (addr_match) {
return tgMap[rangeData.tg] == te->tg &&
(resTLBIttl(rangeData.tg, rangeData.ttl) ||
rangeData.ttl == te->lookupLevel);
} else {
return false;
}
}
} // namespace ArmISA
} // namespace gem5

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, 2022 Arm Limited
* Copyright (c) 2018-2020, 2022-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -300,6 +300,8 @@ class TLBIALLN : public TLBIOp
/** TLB Invalidate by VA, All ASID */
class TLBIMVAA : public TLBIOp
{
protected:
TlbEntry::Lookup lookupGen(vmid_t vmid) const;
public:
TLBIMVAA(ExceptionLevel _targetEL, bool _secure,
Addr _addr, bool last_level)
@@ -319,6 +321,9 @@ class TLBIMVAA : public TLBIOp
/** TLB Invalidate by VA */
class TLBIMVA : public TLBIOp
{
protected:
TlbEntry::Lookup lookupGen(vmid_t vmid) const;
public:
TLBIMVA(ExceptionLevel _targetEL, bool _secure,
Addr _addr, uint16_t _asid, bool last_level)
@@ -368,6 +373,61 @@ class DTLBIMVA : public TLBIMVA
bool match(TlbEntry *entry, vmid_t curr_vmid) const override;
};
class TLBIRange
{
public:
/**
* Is the range valid? This mainly depends on the specified
* translation granule.
*/
bool valid() const { return granule != ReservedGrain; }
protected:
BitUnion64(RangeData)
Bitfield<47, 46> tg;
Bitfield<45, 44> scale;
Bitfield<43, 39> num;
Bitfield<38, 37> ttl;
Bitfield<36, 0> baseAddr;
EndBitUnion(RangeData)
static constexpr std::array<GrainSize, 4> tgMap = {
ReservedGrain,
Grain4KB,
Grain16KB,
Grain64KB
};
TLBIRange(RegVal val)
: rangeData(val), granule(tgMap[rangeData.tg])
{}
Addr
startAddress() const
{
return sext<37>(rangeData.baseAddr) << granule;
}
Addr
rangeSize() const
{
return (rangeData.num + 1) << (5 * rangeData.scale + 1 + granule);
}
bool
resTLBIttl(uint8_t tg, uint8_t ttl) const
{
switch (ttl) {
case 0: return true;
case 1: return tgMap[tg] == Grain16KB;
default: return false;
}
}
RangeData rangeData;
GrainSize granule;
};
/** TLB Invalidate by Intermediate Physical Address */
class TLBIIPA : public TLBIOp
{
@@ -392,7 +452,7 @@ class TLBIIPA : public TLBIOp
}
/** TLBIIPA is basically a TLBIMVAA for stage2 TLBs */
TLBIMVAA
virtual TLBIMVAA
makeStage2() const
{
return TLBIMVAA(EL1, secureLookup, addr, lastLevel);
@@ -402,6 +462,49 @@ class TLBIIPA : public TLBIOp
bool lastLevel;
};
/** TLB Range Invalidate by VA */
class TLBIRMVA : public TLBIRange, public TLBIMVA
{
public:
TLBIRMVA(ExceptionLevel _targetEL, bool _secure,
RegVal val, uint16_t _asid, bool last_level)
: TLBIRange(val),
TLBIMVA(_targetEL, _secure, startAddress(), _asid, last_level)
{}
bool match(TlbEntry *entry, vmid_t curr_vmid) const override;
};
/** TLB Range Invalidate by VA, All ASIDs */
class TLBIRMVAA : public TLBIRange, public TLBIMVAA
{
public:
TLBIRMVAA(ExceptionLevel _targetEL, bool _secure,
RegVal val, bool last_level)
: TLBIRange(val),
TLBIMVAA(_targetEL, _secure, startAddress(), last_level)
{}
bool match(TlbEntry *entry, vmid_t curr_vmid) const override;
};
/** TLB Range Invalidate by VA, All ASIDs */
class TLBIRIPA : public TLBIRange, public TLBIIPA
{
public:
TLBIRIPA(ExceptionLevel _targetEL, bool _secure,
RegVal val, bool last_level)
: TLBIRange(val),
TLBIIPA(_targetEL, _secure, startAddress(), last_level)
{}
virtual TLBIMVAA
makeStage2() const
{
return TLBIRMVAA(EL1, secureLookup, rangeData, lastLevel);
}
};
} // namespace ArmISA
} // namespace gem5

View File

@@ -366,6 +366,12 @@ void syncVecElemsToRegs(ThreadContext *tc);
bool fgtEnabled(ThreadContext *tc);
static inline bool
useVMID(ExceptionLevel el, bool in_host)
{
return el == EL1 || (el == EL0 && !in_host);
}
} // namespace ArmISA
} // namespace gem5