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++;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user