arch: Provide an alternative view of the TLBs in the BaseMMU
It is possible from the MMU to traverse the entire hierarchy of TLBs, starting from the DTB and ITB (generally speaking from the first level) up to the last level via the nextLevel pointer. So in theory no extra data should be stored in the BaseMMU. This design makes some operations a bit more complex. For example if we have a unified (I+D) L2, it will be pointed by both ITB and DTB. If we want to invalidate all TLB entries, we should be careful to not invalidate L2 twice, but if we simply follow the next level pointer, we might do so. This is not a problem from a functional perspective but alters the TLB statistics (a single invalidation is recorded twice) We then provide a different view of the set of TLBs in the system. At the init phase we traverse the TLB hierarchy and we add every TLB to the appropriate set. This makes invalidation (and any operation targeting a specific kind of TLBs) easier. JIRA: https://gem5.atlassian.net/browse/GEM5-790 Change-Id: Ieb833c2328e9daeaf50a32b79b970f77f3e874f7 Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48146 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
@@ -99,6 +99,8 @@ MMU::init()
|
||||
|
||||
getITBPtr()->setTableWalker(itbWalker);
|
||||
getDTBPtr()->setTableWalker(dtbWalker);
|
||||
|
||||
BaseMMU::init();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012,2016-2017, 2019-2020 ARM Limited
|
||||
* Copyright (c) 2011-2012,2016-2017, 2019-2021 Arm Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -47,11 +47,48 @@
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
void
|
||||
BaseMMU::init()
|
||||
{
|
||||
auto traverse_hierarchy = [this](BaseTLB *starter) {
|
||||
for (BaseTLB *tlb = starter; tlb; tlb = tlb->nextLevel()) {
|
||||
switch (tlb->type()) {
|
||||
case TypeTLB::instruction:
|
||||
if (instruction.find(tlb) == instruction.end())
|
||||
instruction.insert(tlb);
|
||||
break;
|
||||
case TypeTLB::data:
|
||||
if (data.find(tlb) == data.end())
|
||||
data.insert(tlb);
|
||||
break;
|
||||
case TypeTLB::unified:
|
||||
if (unified.find(tlb) == unified.end())
|
||||
unified.insert(tlb);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid TLB type\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
traverse_hierarchy(itb);
|
||||
traverse_hierarchy(dtb);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMMU::flushAll()
|
||||
{
|
||||
dtb->flushAll();
|
||||
itb->flushAll();
|
||||
for (auto tlb : instruction) {
|
||||
tlb->flushAll();
|
||||
}
|
||||
|
||||
for (auto tlb : data) {
|
||||
tlb->flushAll();
|
||||
}
|
||||
|
||||
for (auto tlb : unified) {
|
||||
tlb->flushAll();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 ARM Limited
|
||||
* Copyright (c) 2020-2021 Arm Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -38,6 +38,8 @@
|
||||
#ifndef __ARCH_GENERIC_MMU_HH__
|
||||
#define __ARCH_GENERIC_MMU_HH__
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "params/BaseMMU.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
@@ -98,6 +100,12 @@ class BaseMMU : public SimObject
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Called at init time, this method is traversing the TLB hierarchy
|
||||
* and pupulating the instruction/data/unified containers accordingly
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
virtual void flushAll();
|
||||
|
||||
void demapPage(Addr vaddr, uint64_t asn);
|
||||
@@ -123,6 +131,31 @@ class BaseMMU : public SimObject
|
||||
public:
|
||||
BaseTLB* dtb;
|
||||
BaseTLB* itb;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* It is possible from the MMU to traverse the entire hierarchy of
|
||||
* TLBs, starting from the DTB and ITB (generally speaking from the
|
||||
* first level) up to the last level via the nextLevel pointer. So
|
||||
* in theory no extra data should be stored in the BaseMMU.
|
||||
*
|
||||
* This design makes some operations a bit more complex. For example
|
||||
* if we have a unified (I+D) L2, it will be pointed by both ITB and
|
||||
* DTB. If we want to invalidate all TLB entries, we should be
|
||||
* careful to not invalidate L2 twice, but if we simply follow the
|
||||
* next level pointer, we might do so. This is not a problem from
|
||||
* a functional perspective but alters the TLB statistics (a single
|
||||
* invalidation is recorded twice)
|
||||
*
|
||||
* We then provide a different view of the set of TLBs in the system.
|
||||
* At the init phase we traverse the TLB hierarchy and we add every
|
||||
* TLB to the appropriate set. This makes invalidation (and any
|
||||
* operation targeting a specific kind of TLBs) easier.
|
||||
*/
|
||||
std::set<BaseTLB*> instruction;
|
||||
std::set<BaseTLB*> data;
|
||||
std::set<BaseTLB*> unified;
|
||||
|
||||
};
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
Reference in New Issue
Block a user