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:
Giacomo Travaglini
2021-07-13 16:40:01 +01:00
parent 76996ea806
commit 46a8bc2f56
3 changed files with 76 additions and 4 deletions

View File

@@ -99,6 +99,8 @@ MMU::init()
getITBPtr()->setTableWalker(itbWalker);
getDTBPtr()->setTableWalker(dtbWalker);
BaseMMU::init();
}
void

View File

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

View File

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