arch-arm: Define a Lookup structure to simplify TLB code

The lookup/matching function signatures have been constantly amended to
include new parameters. We are replacing the parameter list with a
single lookup structure. This will make it easier to add new forms of
lookups and to propagate them through the MMU/TLB code

Change-Id: Ic45a64d778460b6d308551333c9dc230a02ecb6e
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/51669
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-08-05 10:52:49 +01:00
parent b29349671c
commit f49a15e00f
4 changed files with 91 additions and 75 deletions

View File

@@ -149,9 +149,20 @@ MMU::translateFunctional(ThreadContext *tc, Addr va, Addr &pa)
auto tlb = getTlb(BaseMMU::Read, state.directToStage2);
TlbEntry *e = tlb->lookup(
va, state.asid, state.vmid, state.isHyp, state.isSecure, true, false,
state.aarch64 ? state.aarch64EL : EL1, false, BaseMMU::Read);
TlbEntry::Lookup lookup_data;
lookup_data.va = va;
lookup_data.asn = state.asid;
lookup_data.ignoreAsn = false;
lookup_data.vmid = state.vmid;
lookup_data.hyp = state.isHyp;
lookup_data.secure = state.isSecure;
lookup_data.functional = true;
lookup_data.targetEL = state.aarch64 ? state.aarch64EL : EL1;
lookup_data.inHost = false;
lookup_data.mode = BaseMMU::Read;
TlbEntry *e = tlb->multiLookup(lookup_data);
if (!e)
return false;
@@ -1375,8 +1386,21 @@ MMU::lookup(Addr va, uint16_t asid, vmid_t vmid, bool hyp, bool secure,
bool in_host, bool stage2, BaseMMU::Mode mode)
{
TLB *tlb = getTlb(mode, stage2);
return tlb->multiLookup(va, asid, vmid, hyp, secure, functional,
ignore_asn, target_el, in_host, mode);
TlbEntry::Lookup lookup_data;
lookup_data.va = va;
lookup_data.asn = asid;
lookup_data.ignoreAsn = ignore_asn;
lookup_data.vmid = vmid;
lookup_data.hyp = hyp;
lookup_data.secure = secure;
lookup_data.functional = functional;
lookup_data.targetEL = target_el;
lookup_data.inHost = in_host;
lookup_data.mode = mode;
return tlb->multiLookup(lookup_data);
}
Fault

View File

@@ -46,6 +46,7 @@
#include "arch/arm/page_size.hh"
#include "arch/arm/types.hh"
#include "arch/arm/utility.hh"
#include "arch/generic/mmu.hh"
#include "enums/TypeTLB.hh"
#include "sim/serialize.hh"
@@ -102,6 +103,30 @@ struct TlbEntry : public Serializable
Manager
};
struct Lookup
{
// virtual address
Addr va = 0;
// context id/address space id to use
uint16_t asn = 0;
// if on lookup asn should be ignored
bool ignoreAsn = false;
// The virtual machine ID used for stage 2 translation
vmid_t vmid = 0;
// if the lookup is done from hyp mode
bool hyp = false;
// if the lookup is secure
bool secure = false;
// if the lookup should modify state
bool functional = false;
// selecting the translation regime
ExceptionLevel targetEL = EL0;
// if we are in host (EL2&0 regime)
bool inHost = false;
// mode to differentiate between read/writes/fetches.
BaseMMU::Mode mode = BaseMMU::Read;
};
// Matching variables
Addr pfn;
Addr size; // Size of this entry, == Type of TLB Rec
@@ -198,30 +223,20 @@ struct TlbEntry : public Serializable
}
bool
match(Addr va, vmid_t _vmid, bool hyp_lookup, bool secure_lookup,
ExceptionLevel target_el, bool in_host) const
{
return match(va, 0, _vmid, hyp_lookup, secure_lookup, true,
target_el, in_host);
}
bool
match(Addr va, uint16_t asn, vmid_t _vmid, bool hyp_lookup,
bool secure_lookup, bool ignore_asn, ExceptionLevel target_el,
bool in_host) const
match(const Lookup &lookup) const
{
bool match = false;
Addr v = vpn << N;
if (valid && va >= v && va <= v + size && (secure_lookup == !nstid) &&
(hyp_lookup == isHyp))
if (valid && lookup.va >= v && lookup.va <= v + size &&
(lookup.secure == !nstid) && (lookup.hyp == isHyp))
{
match = checkELMatch(target_el, in_host);
match = checkELMatch(lookup.targetEL, lookup.inHost);
if (match && !ignore_asn) {
match = global || (asn == asid);
if (match && !lookup.ignoreAsn) {
match = global || (lookup.asn == asid);
}
if (match && nstid) {
match = isHyp || (_vmid == vmid);
match = isHyp || (lookup.vmid == vmid);
}
}
return match;

View File

@@ -79,20 +79,16 @@ TLB::setTableWalker(TableWalker *table_walker)
}
TlbEntry*
TLB::lookup(Addr va, uint16_t asn, vmid_t vmid, bool hyp, bool secure,
bool functional, bool ignore_asn, ExceptionLevel target_el,
bool in_host, BaseMMU::Mode mode)
TLB::lookup(const Lookup &lookup_data)
{
TlbEntry *retval = NULL;
const auto functional = lookup_data.functional;
const auto mode = lookup_data.mode;
// Maintaining LRU array
int x = 0;
while (retval == NULL && x < size) {
if ((!ignore_asn && table[x].match(va, asn, vmid, hyp, secure, false,
target_el, in_host)) ||
(ignore_asn && table[x].match(va, vmid, hyp, secure, target_el,
in_host))) {
if (table[x].match(lookup_data)) {
// We only move the hit entry ahead when the position is higher
// than rangeMRU
if (x > rangeMRU && !functional) {
@@ -112,9 +108,11 @@ TLB::lookup(Addr va, uint16_t asn, vmid_t vmid, bool hyp, bool secure,
DPRINTF(TLBVerbose, "Lookup %#x, asn %#x -> %s vmn 0x%x hyp %d secure %d "
"ppn %#x size: %#x pa: %#x ap:%d ns:%d nstid:%d g:%d asid: %d "
"el: %d\n",
va, asn, retval ? "hit" : "miss", vmid, hyp, secure,
lookup_data.va, lookup_data.asn, retval ? "hit" : "miss",
lookup_data.vmid, lookup_data.hyp, lookup_data.secure,
retval ? retval->pfn : 0, retval ? retval->size : 0,
retval ? retval->pAddr(va) : 0, retval ? retval->ap : 0,
retval ? retval->pAddr(lookup_data.va) : 0,
retval ? retval->ap : 0,
retval ? retval->ns : 0, retval ? retval->nstid : 0,
retval ? retval->global : 0, retval ? retval->asid : 0,
retval ? retval->el : 0);
@@ -142,20 +140,16 @@ TLB::lookup(Addr va, uint16_t asn, vmid_t vmid, bool hyp, bool secure,
}
TlbEntry*
TLB::multiLookup(Addr va, uint16_t asid, vmid_t vmid, bool hyp, bool secure,
bool functional, bool ignore_asn, ExceptionLevel target_el,
bool in_host, BaseMMU::Mode mode)
TLB::multiLookup(const Lookup &lookup_data)
{
TlbEntry* te = lookup(va, asid, vmid, hyp, secure, functional,
ignore_asn, target_el, in_host, mode);
TlbEntry* te = lookup(lookup_data);
if (te) {
checkPromotion(te, mode);
checkPromotion(te, lookup_data.mode);
} else {
if (auto tlb = static_cast<TLB*>(nextLevel())) {
te = tlb->multiLookup(va, asid, vmid, hyp, secure, functional,
ignore_asn, target_el, in_host, mode);
if (te && !functional)
te = tlb->multiLookup(lookup_data);
if (te && !lookup_data.functional)
insert(*te);
}
}
@@ -521,13 +515,20 @@ TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
TypeTLB entry_type)
{
TlbEntry *te;
// D5.7.2: Sign-extend address to 64 bits
mva = sext<56>(mva);
Lookup lookup_data;
bool hyp = target_el == EL2;
lookup_data.va = sext<56>(mva);
lookup_data.asn = asn;
lookup_data.ignoreAsn = ignore_asn;
lookup_data.vmid = vmid;
lookup_data.hyp = target_el == EL2;
lookup_data.secure = secure_lookup;
lookup_data.functional = true;
lookup_data.targetEL = target_el;
lookup_data.inHost = in_host;
lookup_data.mode = BaseMMU::Read;
te = lookup(mva, asn, vmid, hyp, secure_lookup, true, ignore_asn,
target_el, in_host, BaseMMU::Read);
te = lookup(lookup_data);
while (te != NULL) {
bool matching_type = (te->type & entry_type);
if (matching_type && secure_lookup == !te->nstid) {
@@ -535,8 +536,7 @@ TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
te->valid = false;
stats.flushedEntries++;
}
te = lookup(mva, asn, vmid, hyp, secure_lookup, true, ignore_asn,
target_el, in_host, BaseMMU::Read);
te = lookup(lookup_data);
}
}

View File

@@ -157,46 +157,23 @@ class TLB : public BaseTLB
public:
using Params = ArmTLBParams;
using Lookup = TlbEntry::Lookup;
TLB(const Params &p);
TLB(const Params &p, int _size, TableWalker *_walker);
/** Lookup an entry in the TLB
* @param vpn virtual address
* @param asn context id/address space id to use
* @param vmid The virtual machine ID used for stage 2 translation
* @param secure if the lookup is secure
* @param hyp if the lookup is done from hyp mode
* @param functional if the lookup should modify state
* @param ignore_asn if on lookup asn should be ignored
* @param target_el selecting the translation regime
* @param in_host if we are in host (EL2&0 regime)
* @param mode to differentiate between read/writes/fetches.
* @return pointer to TLB entry if it exists
*/
TlbEntry *lookup(Addr vpn, uint16_t asn, vmid_t vmid, bool hyp,
bool secure, bool functional,
bool ignore_asn, ExceptionLevel target_el,
bool in_host, BaseMMU::Mode mode);
TlbEntry *lookup(const Lookup &lookup_data);
/** Lookup an entry in the TLB and in the next levels by
* following the nextLevel pointer
*
* @param vpn virtual address
* @param asn context id/address space id to use
* @param vmid The virtual machine ID used for stage 2 translation
* @param secure if the lookup is secure
* @param hyp if the lookup is done from hyp mode
* @param functional if the lookup should modify state
* @param ignore_asn if on lookup asn should be ignored
* @param target_el selecting the translation regime
* @param in_host if we are in host (EL2&0 regime)
* @param mode to differentiate between read/writes/fetches.
* @return pointer to TLB entry if it exists
*/
TlbEntry *multiLookup(Addr vpn, uint16_t asn, vmid_t vmid, bool hyp,
bool secure, bool functional,
bool ignore_asn, ExceptionLevel target_el,
bool in_host, BaseMMU::Mode mode);
TlbEntry *multiLookup(const Lookup &lookup_data);
virtual ~TLB();