arch-arm: Distinguish Instruction from Data TLB entries

As we are going to support I+D (shared) TLBs we need to tag a TLB entry
as a data or instruction entry, so that I-TLBI and D-TLBI do not
over-invalidate entries

(The patch is also fixing the coding style of the TLB insertion
methods in the Table Walker)

JIRA: https://gem5.atlassian.net/browse/GEM5-790

Change-Id: I3d5880175fe6eda1b2f0edcbd0ea6a146d3c7a39
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48147
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
Giacomo Travaglini
2021-07-08 10:39:37 +01:00
parent 242d0d467a
commit a23f39bc19
2 changed files with 30 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013 ARM Limited
* Copyright (c) 2010, 2012-2013, 2021 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -46,6 +46,7 @@
#include "arch/arm/page_size.hh"
#include "arch/arm/types.hh"
#include "arch/arm/utility.hh"
#include "enums/TypeTLB.hh"
#include "sim/serialize.hh"
namespace gem5
@@ -136,6 +137,9 @@ struct TlbEntry : public Serializable
bool nstid;
// Exception level on insert, AARCH64 EL0&1, AARCH32 -> el=1
ExceptionLevel el;
// This is used to distinguish between instruction and data entries
// in unified TLBs
TypeTLB type;
// Type of memory
bool nonCacheable; // Can we wrap this in mtype?
@@ -156,7 +160,8 @@ struct TlbEntry : public Serializable
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),
ns(true), nstid(true), el(EL0), nonCacheable(uncacheable),
ns(true), nstid(true), el(EL0), type(TypeTLB::unified),
nonCacheable(uncacheable),
shareable(false), outerShareable(false), xn(0), pxn(0)
{
// no restrictions by default, hap = 0x3
@@ -171,7 +176,8 @@ struct TlbEntry : public Serializable
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), nonCacheable(false),
ns(true), nstid(true), el(EL0), type(TypeTLB::unified),
nonCacheable(false),
shareable(false), outerShareable(false), xn(0), pxn(0)
{
// no restrictions by default, hap = 0x3
@@ -317,6 +323,7 @@ struct TlbEntry : public Serializable
SERIALIZE_SCALAR(valid);
SERIALIZE_SCALAR(ns);
SERIALIZE_SCALAR(nstid);
SERIALIZE_ENUM(type);
SERIALIZE_SCALAR(nonCacheable);
SERIALIZE_ENUM(lookupLevel);
SERIALIZE_ENUM(mtype);
@@ -347,6 +354,7 @@ struct TlbEntry : public Serializable
UNSERIALIZE_SCALAR(valid);
UNSERIALIZE_SCALAR(ns);
UNSERIALIZE_SCALAR(nstid);
UNSERIALIZE_ENUM(type);
UNSERIALIZE_SCALAR(nonCacheable);
UNSERIALIZE_ENUM(lookupLevel);
UNSERIALIZE_ENUM(mtype);

View File

@@ -1449,16 +1449,16 @@ TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
void
TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
LongDescriptor &lDescriptor)
LongDescriptor &l_descriptor)
{
assert(_haveLPAE);
uint8_t attr;
uint8_t sh = lDescriptor.sh();
uint8_t sh = l_descriptor.sh();
// Different format and source of attributes if this is a stage 2
// translation
if (isStage2) {
attr = lDescriptor.memAttr();
attr = l_descriptor.memAttr();
uint8_t attr_3_2 = (attr >> 2) & 0x3;
uint8_t attr_1_0 = attr & 0x3;
@@ -1479,7 +1479,7 @@ TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
}
} else {
uint8_t attrIndx = lDescriptor.attrIndx();
uint8_t attrIndx = l_descriptor.attrIndx();
// LPAE always uses remapping of memory attributes, irrespective of the
// value of SCTLR.TRE
@@ -1575,15 +1575,15 @@ TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
void
TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
LongDescriptor &lDescriptor)
LongDescriptor &l_descriptor)
{
uint8_t attr;
uint8_t attr_hi;
uint8_t attr_lo;
uint8_t sh = lDescriptor.sh();
uint8_t sh = l_descriptor.sh();
if (isStage2) {
attr = lDescriptor.memAttr();
attr = l_descriptor.memAttr();
uint8_t attr_hi = (attr >> 2) & 0x3;
uint8_t attr_lo = attr & 0x3;
@@ -1607,7 +1607,7 @@ TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
(attr_lo == 1) || (attr_lo == 2);
}
} else {
uint8_t attrIndx = lDescriptor.attrIndx();
uint8_t attrIndx = l_descriptor.attrIndx();
DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
ExceptionLevel regime = s1TranslationRegime(tc, currState->el);
@@ -2285,13 +2285,13 @@ TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
}
void
TableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
TableWalker::insertTableEntry(DescriptorBase &descriptor, bool long_descriptor)
{
TlbEntry te;
// Create and fill a new page table entry
te.valid = true;
te.longDescFormat = longDescriptor;
te.longDescFormat = long_descriptor;
te.isHyp = currState->isHyp;
te.asid = currState->asid;
te.vmid = currState->vmid;
@@ -2304,6 +2304,9 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
te.ns = !descriptor.secure(haveSecurity, currState) || isStage2;
te.nstid = !currState->isSecure;
te.xn = descriptor.xn();
te.type = currState->mode == BaseMMU::Execute ?
TypeTLB::instruction : TypeTLB::data;
if (currState->aarch64)
te.el = currState->el;
else
@@ -2315,24 +2318,24 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
// ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries
// as global
te.global = descriptor.global(currState) || isStage2;
if (longDescriptor) {
LongDescriptor lDescriptor =
if (long_descriptor) {
LongDescriptor l_descriptor =
dynamic_cast<LongDescriptor &>(descriptor);
te.xn |= currState->xnTable;
te.pxn = currState->pxnTable || lDescriptor.pxn();
te.pxn = currState->pxnTable || l_descriptor.pxn();
if (isStage2) {
// this is actually the HAP field, but its stored in the same bit
// possitions as the AP field in a stage 1 translation.
te.hap = lDescriptor.ap();
te.hap = l_descriptor.ap();
} else {
te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) |
(currState->userTable && (descriptor.ap() & 0x1));
}
if (currState->aarch64)
memAttrsAArch64(currState->tc, te, lDescriptor);
memAttrsAArch64(currState->tc, te, l_descriptor);
else
memAttrsLPAE(currState->tc, te, lDescriptor);
memAttrsLPAE(currState->tc, te, l_descriptor);
} else {
te.ap = descriptor.ap();
memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(),