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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user