summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/table_walker.cc84
-rw-r--r--src/arch/arm/table_walker.hh12
-rw-r--r--src/arch/arm/tlb.cc5
3 files changed, 86 insertions, 15 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 85d5b00cf..ecdb8a53e 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -80,7 +80,7 @@ TableWalker::getPort(const std::string &if_name, int idx)
}
Fault
-TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode mode,
+TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
TLB::Translation *_trans, bool _timing)
{
// Right now 1 CPU == 1 TLB == 1 TLB walker
@@ -95,6 +95,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode m
fault = NoFault;
contextId = _cid;
timing = _timing;
+ mode = _mode;
/** @todo These should be cached or grabbed from cached copies in
the TLB, all these miscreg reads are expensive */
@@ -378,8 +379,10 @@ TableWalker::doL1Descriptor()
switch (l1Desc.type()) {
case L1Descriptor::Ignore:
case L1Descriptor::Reserved:
- tc = NULL;
- req = NULL;
+ if (!delayed) {
+ tc = NULL;
+ req = NULL;
+ }
DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
if (isFetch)
fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
@@ -422,8 +425,10 @@ TableWalker::doL1Descriptor()
DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF );
- tc = NULL;
- req = NULL;
+ if (!timing) {
+ tc = NULL;
+ req = NULL;
+ }
tlb->insert(vaddr, te);
return;
@@ -437,13 +442,16 @@ TableWalker::doL1Descriptor()
fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
isFetch, isWrite, l1Desc.domain(), false);
if (fault) {
- tc = NULL;
- req = NULL;
- return;
+ if (!timing) {
+ tc = NULL;
+ req = NULL;
+ }
+ return;
}
if (timing) {
+ delayed = true;
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
&doL2DescEvent, (uint8_t*)&l2Desc.data, 0);
} else {
@@ -465,8 +473,10 @@ TableWalker::doL2Descriptor()
if (l2Desc.invalid()) {
DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
- tc = NULL;
- req = NULL;
+ if (!delayed) {
+ tc = NULL;
+ req = NULL;
+ }
if (isFetch)
fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
else
@@ -502,11 +512,61 @@ TableWalker::doL2Descriptor()
te.domain = l1Desc.domain();
memAttrs(te, l2Desc.texcb(), l2Desc.shareable());
- tc = NULL;
- req = NULL;
+ if (!delayed) {
+ tc = NULL;
+ req = NULL;
+ }
tlb->insert(vaddr, te);
}
+void
+TableWalker::doL1DescriptorWrapper()
+{
+ delayed = false;
+
+ DPRINTF(TLBVerbose, "calling doL1Descriptor\n");
+ doL1Descriptor();
+
+ // Check if fault was generated
+ if (fault != NoFault) {
+ transState->finish(fault, req, tc, mode);
+
+ req = NULL;
+ tc = NULL;
+ delayed = false;
+ }
+ else if (!delayed) {
+ DPRINTF(TLBVerbose, "calling translateTiming again\n");
+ fault = tlb->translateTiming(req, tc, transState, mode);
+
+ req = NULL;
+ tc = NULL;
+ delayed = false;
+ }
+}
+
+void
+TableWalker::doL2DescriptorWrapper()
+{
+ assert(delayed);
+
+ DPRINTF(TLBVerbose, "calling doL2Descriptor\n");
+ doL2Descriptor();
+
+ // Check if fault was generated
+ if (fault != NoFault) {
+ transState->finish(fault, req, tc, mode);
+ }
+ else {
+ DPRINTF(TLBVerbose, "calling translateTiming again\n");
+ fault = tlb->translateTiming(req, tc, transState, mode);
+ }
+
+ req = NULL;
+ tc = NULL;
+ delayed = false;
+}
+
ArmISA::TableWalker *
ArmTableWalkerParams::create()
{
diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh
index f6d3bee06..fbb9133e1 100644
--- a/src/arch/arm/table_walker.hh
+++ b/src/arch/arm/table_walker.hh
@@ -289,6 +289,12 @@ class TableWalker : public MemObject
L1Descriptor l1Desc;
L2Descriptor l2Desc;
+ /** Save mode for use in delayed response */
+ BaseTLB::Mode mode;
+
+ /** Whether L1/L2 descriptor response is delayed in timing mode */
+ bool delayed;
+
public:
typedef ArmTableWalkerParams Params;
TableWalker(const Params *p);
@@ -312,10 +318,12 @@ class TableWalker : public MemObject
private:
void doL1Descriptor();
- EventWrapper<TableWalker, &TableWalker::doL1Descriptor> doL1DescEvent;
+ void doL1DescriptorWrapper();
+ EventWrapper<TableWalker, &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
void doL2Descriptor();
- EventWrapper<TableWalker, &TableWalker::doL2Descriptor> doL2DescEvent;
+ void doL2DescriptorWrapper();
+ EventWrapper<TableWalker, &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
};
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 7f02061b0..422ac68f4 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -408,8 +408,11 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
vaddr, context_id);
fault = tableWalker->walk(req, tc, context_id, mode, translation,
timing);
- if (timing)
+ if (timing) {
delay = true;
+ // for timing mode, return and wait for table walk
+ return fault;
+ }
if (fault)
return fault;