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:
Giacomo Travaglini
2021-07-08 14:33:58 +01:00
parent a23f39bc19
commit 395c6d4fa3
2 changed files with 145 additions and 5 deletions

View File

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

View File

@@ -47,6 +47,7 @@
#include "arch/arm/utility.hh"
#include "arch/generic/tlb.hh"
#include "base/statistics.hh"
#include "enums/TypeTLB.hh"
#include "mem/request.hh"
#include "params/ArmTLB.hh"
#include "sim/probe/pmu.hh"
@@ -62,11 +63,17 @@ class TableWalker;
class TLB;
class TLBIALL;
class ITLBIALL;
class DTLBIALL;
class TLBIALLEL;
class TLBIVMALL;
class TLBIALLN;
class TLBIMVA;
class ITLBIMVA;
class DTLBIMVA;
class TLBIASID;
class ITLBIASID;
class DTLBIASID;
class TLBIMVAA;
class TlbTestInterface
@@ -191,6 +198,8 @@ class TLB : public BaseTLB
/** Reset the entire TLB
*/
void flush(const TLBIALL &tlbi_op);
void flush(const ITLBIALL &tlbi_op);
void flush(const DTLBIALL &tlbi_op);
/** Implementaton of AArch64 TLBI ALLE1(IS), ALLE2(IS), ALLE3(IS)
* instructions
@@ -210,10 +219,14 @@ class TLB : public BaseTLB
/** Remove any entries that match both a va and asn
*/
void flush(const TLBIMVA &tlbi_op);
void flush(const ITLBIMVA &tlbi_op);
void flush(const DTLBIMVA &tlbi_op);
/** Remove any entries that match the asn
*/
void flush(const TLBIASID &tlbi_op);
void flush(const ITLBIASID &tlbi_op);
void flush(const DTLBIASID &tlbi_op);
/** Remove all entries that match the va regardless of asn
*/
@@ -283,10 +296,11 @@ class TLB : public BaseTLB
* @param secure_lookup if the operation affects the secure world
* @param ignore_asn if the flush should ignore the asn
* @param in_host if hcr.e2h == 1 and hcr.tge == 1 for VHE.
* @param entry_type type of entry to flush (instruction/data/unified)
*/
void _flushMva(Addr mva, uint64_t asn, bool secure_lookup,
bool ignore_asn, ExceptionLevel target_el,
bool in_host);
bool in_host, TypeTLB entry_type);
};
} // namespace ArmISA