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
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue