ARM: Support table walks in timing mode.
This commit is contained in:
parent
6c8dd32fa4
commit
6b00c7fa22
3 changed files with 86 additions and 15 deletions
|
@ -80,7 +80,7 @@ TableWalker::getPort(const std::string &if_name, int idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault
|
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)
|
TLB::Translation *_trans, bool _timing)
|
||||||
{
|
{
|
||||||
// Right now 1 CPU == 1 TLB == 1 TLB walker
|
// 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;
|
fault = NoFault;
|
||||||
contextId = _cid;
|
contextId = _cid;
|
||||||
timing = _timing;
|
timing = _timing;
|
||||||
|
mode = _mode;
|
||||||
|
|
||||||
/** @todo These should be cached or grabbed from cached copies in
|
/** @todo These should be cached or grabbed from cached copies in
|
||||||
the TLB, all these miscreg reads are expensive */
|
the TLB, all these miscreg reads are expensive */
|
||||||
|
@ -378,8 +379,10 @@ TableWalker::doL1Descriptor()
|
||||||
switch (l1Desc.type()) {
|
switch (l1Desc.type()) {
|
||||||
case L1Descriptor::Ignore:
|
case L1Descriptor::Ignore:
|
||||||
case L1Descriptor::Reserved:
|
case L1Descriptor::Reserved:
|
||||||
tc = NULL;
|
if (!delayed) {
|
||||||
req = NULL;
|
tc = NULL;
|
||||||
|
req = NULL;
|
||||||
|
}
|
||||||
DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
|
DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
|
||||||
if (isFetch)
|
if (isFetch)
|
||||||
fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
|
fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
|
||||||
|
@ -422,8 +425,10 @@ TableWalker::doL1Descriptor()
|
||||||
DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
|
DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
|
||||||
l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF );
|
l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF );
|
||||||
|
|
||||||
tc = NULL;
|
if (!timing) {
|
||||||
req = NULL;
|
tc = NULL;
|
||||||
|
req = NULL;
|
||||||
|
}
|
||||||
tlb->insert(vaddr, te);
|
tlb->insert(vaddr, te);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -437,13 +442,16 @@ TableWalker::doL1Descriptor()
|
||||||
fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
|
fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
|
||||||
isFetch, isWrite, l1Desc.domain(), false);
|
isFetch, isWrite, l1Desc.domain(), false);
|
||||||
if (fault) {
|
if (fault) {
|
||||||
tc = NULL;
|
if (!timing) {
|
||||||
req = NULL;
|
tc = NULL;
|
||||||
return;
|
req = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (timing) {
|
if (timing) {
|
||||||
|
delayed = true;
|
||||||
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||||
&doL2DescEvent, (uint8_t*)&l2Desc.data, 0);
|
&doL2DescEvent, (uint8_t*)&l2Desc.data, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -465,8 +473,10 @@ TableWalker::doL2Descriptor()
|
||||||
|
|
||||||
if (l2Desc.invalid()) {
|
if (l2Desc.invalid()) {
|
||||||
DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
|
DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
|
||||||
tc = NULL;
|
if (!delayed) {
|
||||||
req = NULL;
|
tc = NULL;
|
||||||
|
req = NULL;
|
||||||
|
}
|
||||||
if (isFetch)
|
if (isFetch)
|
||||||
fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
|
fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
|
||||||
else
|
else
|
||||||
|
@ -502,11 +512,61 @@ TableWalker::doL2Descriptor()
|
||||||
te.domain = l1Desc.domain();
|
te.domain = l1Desc.domain();
|
||||||
memAttrs(te, l2Desc.texcb(), l2Desc.shareable());
|
memAttrs(te, l2Desc.texcb(), l2Desc.shareable());
|
||||||
|
|
||||||
tc = NULL;
|
if (!delayed) {
|
||||||
req = NULL;
|
tc = NULL;
|
||||||
|
req = NULL;
|
||||||
|
}
|
||||||
tlb->insert(vaddr, te);
|
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 *
|
ArmISA::TableWalker *
|
||||||
ArmTableWalkerParams::create()
|
ArmTableWalkerParams::create()
|
||||||
{
|
{
|
||||||
|
|
|
@ -289,6 +289,12 @@ class TableWalker : public MemObject
|
||||||
L1Descriptor l1Desc;
|
L1Descriptor l1Desc;
|
||||||
L2Descriptor l2Desc;
|
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:
|
public:
|
||||||
typedef ArmTableWalkerParams Params;
|
typedef ArmTableWalkerParams Params;
|
||||||
TableWalker(const Params *p);
|
TableWalker(const Params *p);
|
||||||
|
@ -312,10 +318,12 @@ class TableWalker : public MemObject
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void doL1Descriptor();
|
void doL1Descriptor();
|
||||||
EventWrapper<TableWalker, &TableWalker::doL1Descriptor> doL1DescEvent;
|
void doL1DescriptorWrapper();
|
||||||
|
EventWrapper<TableWalker, &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
|
||||||
|
|
||||||
void doL2Descriptor();
|
void doL2Descriptor();
|
||||||
EventWrapper<TableWalker, &TableWalker::doL2Descriptor> doL2DescEvent;
|
void doL2DescriptorWrapper();
|
||||||
|
EventWrapper<TableWalker, &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -408,8 +408,11 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
|
||||||
vaddr, context_id);
|
vaddr, context_id);
|
||||||
fault = tableWalker->walk(req, tc, context_id, mode, translation,
|
fault = tableWalker->walk(req, tc, context_id, mode, translation,
|
||||||
timing);
|
timing);
|
||||||
if (timing)
|
if (timing) {
|
||||||
delay = true;
|
delay = true;
|
||||||
|
// for timing mode, return and wait for table walk
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
if (fault)
|
if (fault)
|
||||||
return fault;
|
return fault;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue