arch-arm: Explicitly implement I/DTLBI Ops in TLB
At the moment the ITLBI and DTLBI operations where implicitly implemented as generic TLBIs e.g: * DTLBIASID, ITLBIASID = TLBIASID This was possible as a single TLB was either an instruction TLB or a data TLB and no generic/shared TLB option was available. In other words, an ITLBI Op to an ITB was invalidating all entries as we were sure the ITB was not containing data entries. With shared TLBs, this doesn't hold true and we need to explicitly implement I/DTLBIs JIRA: https://gem5.atlassian.net/browse/GEM5-790 Change-Id: I39a4add7674f6008dacaedfd1fd90560d264048e Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48148 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:
@@ -228,6 +228,56 @@ TLB::flush(const TLBIALL& tlbi_op)
|
||||
stats.flushTlb++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const ITLBIALL& tlbi_op)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing all ITLB entries (%s lookup)\n",
|
||||
(tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
int x = 0;
|
||||
TlbEntry *te;
|
||||
while (x < size) {
|
||||
te = &table[x];
|
||||
const bool el_match = te->checkELMatch(
|
||||
tlbi_op.targetEL, tlbi_op.inHost);
|
||||
if (te->type & TypeTLB::instruction && te->valid &&
|
||||
tlbi_op.secureLookup == !te->nstid &&
|
||||
(te->vmid == vmid || tlbi_op.el2Enabled) && el_match) {
|
||||
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
te->valid = false;
|
||||
stats.flushedEntries++;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
|
||||
stats.flushTlb++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const DTLBIALL& tlbi_op)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing all DTLB entries (%s lookup)\n",
|
||||
(tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
int x = 0;
|
||||
TlbEntry *te;
|
||||
while (x < size) {
|
||||
te = &table[x];
|
||||
const bool el_match = te->checkELMatch(
|
||||
tlbi_op.targetEL, tlbi_op.inHost);
|
||||
if (te->type & TypeTLB::data && te->valid &&
|
||||
tlbi_op.secureLookup == !te->nstid &&
|
||||
(te->vmid == vmid || tlbi_op.el2Enabled) && el_match) {
|
||||
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
te->valid = false;
|
||||
stats.flushedEntries++;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
|
||||
stats.flushTlb++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const TLBIALLEL &tlbi_op)
|
||||
{
|
||||
@@ -307,7 +357,29 @@ TLB::flush(const TLBIMVA &tlbi_op)
|
||||
"(%s lookup)\n", tlbi_op.addr, tlbi_op.asid,
|
||||
(tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
_flushMva(tlbi_op.addr, tlbi_op.asid, tlbi_op.secureLookup, false,
|
||||
tlbi_op.targetEL, tlbi_op.inHost);
|
||||
tlbi_op.targetEL, tlbi_op.inHost, TypeTLB::unified);
|
||||
stats.flushTlbMvaAsid++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const ITLBIMVA &tlbi_op)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing ITLB entries with mva: %#x, asid: %#x "
|
||||
"(%s lookup)\n", tlbi_op.addr, tlbi_op.asid,
|
||||
(tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
_flushMva(tlbi_op.addr, tlbi_op.asid, tlbi_op.secureLookup, false,
|
||||
tlbi_op.targetEL, tlbi_op.inHost, TypeTLB::instruction);
|
||||
stats.flushTlbMvaAsid++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const DTLBIMVA &tlbi_op)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing DTLB entries with mva: %#x, asid: %#x "
|
||||
"(%s lookup)\n", tlbi_op.addr, tlbi_op.asid,
|
||||
(tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
_flushMva(tlbi_op.addr, tlbi_op.asid, tlbi_op.secureLookup, false,
|
||||
tlbi_op.targetEL, tlbi_op.inHost, TypeTLB::data);
|
||||
stats.flushTlbMvaAsid++;
|
||||
}
|
||||
|
||||
@@ -336,6 +408,58 @@ TLB::flush(const TLBIASID &tlbi_op)
|
||||
stats.flushTlbAsid++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const ITLBIASID &tlbi_op)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing ITLB entries with asid: %#x (%s lookup)\n",
|
||||
tlbi_op.asid, (tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
|
||||
int x = 0 ;
|
||||
TlbEntry *te;
|
||||
|
||||
while (x < size) {
|
||||
te = &table[x];
|
||||
if (te->type & TypeTLB::instruction &&
|
||||
te->valid && te->asid == tlbi_op.asid &&
|
||||
tlbi_op.secureLookup == !te->nstid &&
|
||||
(te->vmid == vmid || tlbi_op.el2Enabled) &&
|
||||
te->checkELMatch(tlbi_op.targetEL, tlbi_op.inHost)) {
|
||||
|
||||
te->valid = false;
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
stats.flushedEntries++;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
stats.flushTlbAsid++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const DTLBIASID &tlbi_op)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing DTLB entries with asid: %#x (%s lookup)\n",
|
||||
tlbi_op.asid, (tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
|
||||
int x = 0 ;
|
||||
TlbEntry *te;
|
||||
|
||||
while (x < size) {
|
||||
te = &table[x];
|
||||
if (te->type & TypeTLB::data &&
|
||||
te->valid && te->asid == tlbi_op.asid &&
|
||||
tlbi_op.secureLookup == !te->nstid &&
|
||||
(te->vmid == vmid || tlbi_op.el2Enabled) &&
|
||||
te->checkELMatch(tlbi_op.targetEL, tlbi_op.inHost)) {
|
||||
|
||||
te->valid = false;
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
stats.flushedEntries++;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
stats.flushTlbAsid++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flush(const TLBIMVAA &tlbi_op) {
|
||||
|
||||
@@ -343,13 +467,14 @@ TLB::flush(const TLBIMVAA &tlbi_op) {
|
||||
tlbi_op.addr,
|
||||
(tlbi_op.secureLookup ? "secure" : "non-secure"));
|
||||
_flushMva(tlbi_op.addr, 0xbeef, tlbi_op.secureLookup, true,
|
||||
tlbi_op.targetEL, tlbi_op.inHost);
|
||||
tlbi_op.targetEL, tlbi_op.inHost, TypeTLB::unified);
|
||||
stats.flushTlbMva++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
bool ignore_asn, ExceptionLevel target_el, bool in_host)
|
||||
bool ignore_asn, ExceptionLevel target_el, bool in_host,
|
||||
TypeTLB entry_type)
|
||||
{
|
||||
TlbEntry *te;
|
||||
// D5.7.2: Sign-extend address to 64 bits
|
||||
@@ -360,7 +485,8 @@ TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
te = lookup(mva, asn, vmid, hyp, secure_lookup, true, ignore_asn,
|
||||
target_el, in_host, BaseMMU::Read);
|
||||
while (te != NULL) {
|
||||
if (secure_lookup == !te->nstid) {
|
||||
bool matching_type = (te->type & entry_type);
|
||||
if (matching_type && secure_lookup == !te->nstid) {
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
te->valid = false;
|
||||
stats.flushedEntries++;
|
||||
|
||||
Reference in New Issue
Block a user