45a46
> #define NUM_WALKERS 2 // 2 should be enough to handle crossing page boundaries
50,52c51,55
< : MemObject(p), port(NULL), tlb(NULL), tc(NULL), req(NULL),
< doL1DescEvent(this), doL2DescEvent(this)
< {}
---
> : MemObject(p), stateQueue(NUM_WALKERS), port(NULL), tlb(NULL),
> currState(NULL), doL1DescEvent(this), doL2DescEvent(this)
> {
> sctlr = NULL;
> }
86,90c89,93
< // Right now 1 CPU == 1 TLB == 1 TLB walker
< // In the future we might want to change this as multiple
< // threads/contexts could share a walker and/or a TLB
< if (tc || req)
< panic("Overlapping TLB walks attempted\n");
---
> if (!currState) {
> // For atomic mode, a new WalkerState instance should be only created
> // once per TLB. For timing mode, a new instance is generated for every
> // TLB miss.
> DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
92,98c95,100
< tc = _tc;
< transState = _trans;
< req = _req;
< fault = NoFault;
< contextId = _cid;
< timing = _timing;
< mode = _mode;
---
> currState = new WalkerState();
> currState->tableWalker = this;
> }
> else if (_timing) {
> panic("currState should always be empty in timing mode!\n");
> }
99a102,109
> currState->tc = _tc;
> currState->transState = _trans;
> currState->req = _req;
> currState->fault = NoFault;
> currState->contextId = _cid;
> currState->timing = _timing;
> currState->mode = _mode;
>
102,106c112,116
< vaddr = req->getVaddr() & ~PcModeMask;
< sctlr = tc->readMiscReg(MISCREG_SCTLR);
< cpsr = tc->readMiscReg(MISCREG_CPSR);
< N = tc->readMiscReg(MISCREG_TTBCR);
< Addr ttbr = 0;
---
> currState->vaddr = currState->req->getVaddr() & ~PcModeMask;
> currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
> sctlr = currState->sctlr;
> currState->cpsr = currState->tc->readMiscReg(MISCREG_CPSR);
> currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
108,110c118,120
< isFetch = (mode == TLB::Execute);
< isWrite = (mode == TLB::Write);
< isPriv = (cpsr.mode != MODE_USER);
---
> currState->isFetch = (currState->mode == TLB::Execute);
> currState->isWrite = (currState->mode == TLB::Write);
> currState->isPriv = (currState->cpsr.mode != MODE_USER);
111a122,123
> Addr ttbr = 0;
>
113c125
< assert(sctlr.m);
---
> assert(currState->sctlr.m);
116c128,129
< vaddr, N, mbits(vaddr, 31, 32-N));
---
> currState->vaddr, currState->N, mbits(currState->vaddr, 31,
> 32-currState->N));
118c131
< if (N == 0 || !mbits(vaddr, 31, 32-N)) {
---
> if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
120c133
< ttbr = tc->readMiscReg(MISCREG_TTBR0);
---
> ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
123,124c136,137
< ttbr = tc->readMiscReg(MISCREG_TTBR1);
< N = 0;
---
> ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
> currState->N = 0;
127c140,141
< Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(vaddr,31-N,20) << 2);
---
> Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) |
> (bits(currState->vaddr,31-currState->N,20) << 2);
132,137c146,152
< fault = tlb->walkTrickBoxCheck(l1desc_addr, vaddr, sizeof(uint32_t),
< isFetch, isWrite, 0, true);
< if (fault) {
< tc = NULL;
< req = NULL;
< return fault;
---
> Fault f;
> f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
> currState->isFetch, currState->isWrite, 0, true);
> if (f) {
> currState->tc = NULL;
> currState->req = NULL;
> return f;
140c155
< if (timing) {
---
> if (currState->timing) {
142c157,161
< &doL1DescEvent, (uint8_t*)&l1Desc.data, (Tick)0);
---
> &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, (Tick)0);
> DPRINTF(TLBVerbose, "Adding to walker fifo: %d free before adding\n",
> stateQueue.free_slots());
> stateQueue.add(*currState);
> currState = NULL;
145c164
< NULL, (uint8_t*)&l1Desc.data, (Tick)0);
---
> NULL, (uint8_t*)&currState->l1Desc.data, (Tick)0);
146a166
> f = currState->fault;
149c169
< return fault;
---
> return f;
153c173,174
< TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, uint8_t texcb, bool s)
---
> TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
> uint8_t texcb, bool s)
155c176,177
< // Note: tc local variable is hiding tc class variable
---
> // Note: tc and sctlr local variables are hiding tc and sctrl class
> // variables
159c181
< if (sctlr.tre == 0) {
---
> if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
194a217
> panic("Reserved texcb value!\n");
196a220
> panic("Implementation-defined texcb value!\n");
211a236
> panic("Reserved texcb value!\n");
306d330
< //te.shareable = outer_shareable;
345a370,372
> DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
> outerAttrs: %d\n",
> te.shareable, te.innerAttrs, te.outerAttrs);
378c405,406
< DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data);
---
> DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
> currState->vaddr, currState->l1Desc.data);
381c409
< switch (l1Desc.type()) {
---
> switch (currState->l1Desc.type()) {
384,386c412,414
< if (!delayed) {
< tc = NULL;
< req = NULL;
---
> if (!currState->delayed) {
> currState->tc = NULL;
> currState->req = NULL;
389,390c417,419
< if (isFetch)
< fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
---
> if (currState->isFetch)
> currState->fault =
> new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
392c421,422
< fault = new DataAbort(vaddr, NULL, isWrite,
---
> currState->fault =
> new DataAbort(currState->vaddr, NULL, currState->isWrite,
396c426
< if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) {
---
> if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
402c432,433
< fault = new DataAbort(vaddr, NULL, isWrite,
---
> currState->fault =
> new DataAbort(currState->vaddr, NULL, currState->isWrite,
406c437
< if (l1Desc.supersection()) {
---
> if (currState->l1Desc.supersection()) {
410c441
< te.pfn = l1Desc.pfn();
---
> te.pfn = currState->l1Desc.pfn();
412c443
< te.global = !l1Desc.global();
---
> te.global = !currState->l1Desc.global();
414c445
< te.vpn = vaddr >> te.N;
---
> te.vpn = currState->vaddr >> te.N;
416,420c447,452
< te.xn = l1Desc.xn();
< te.ap = l1Desc.ap();
< te.domain = l1Desc.domain();
< te.asid = contextId;
< memAttrs(tc, te, l1Desc.texcb(), l1Desc.shareable());
---
> te.xn = currState->l1Desc.xn();
> te.ap = currState->l1Desc.ap();
> te.domain = currState->l1Desc.domain();
> te.asid = currState->contextId;
> memAttrs(currState->tc, te, currState->sctlr,
> currState->l1Desc.texcb(), currState->l1Desc.shareable());
428c460,461
< l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF );
---
> currState->l1Desc.domain(), currState->l1Desc.data,
> (currState->l1Desc.data >> 5) & 0xF );
430,432c463,465
< if (!timing) {
< tc = NULL;
< req = NULL;
---
> if (!currState->timing) {
> currState->tc = NULL;
> currState->req = NULL;
434c467
< tlb->insert(vaddr, te);
---
> tlb->insert(currState->vaddr, te);
439c472,473
< l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2);
---
> l2desc_addr = currState->l1Desc.l2Addr() |
> (bits(currState->vaddr, 19,12) << 2);
444,449c478,485
< fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
< isFetch, isWrite, l1Desc.domain(), false);
< if (fault) {
< if (!timing) {
< tc = NULL;
< req = NULL;
---
> currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr,
> sizeof(uint32_t), currState->isFetch, currState->isWrite,
> currState->l1Desc.domain(), false);
>
> if (currState->fault) {
> if (!currState->timing) {
> currState->tc = NULL;
> currState->req = NULL;
455,456c491,492
< if (timing) {
< delayed = true;
---
> if (currState->timing) {
> currState->delayed = true;
458c494
< &doL2DescEvent, (uint8_t*)&l2Desc.data, 0);
---
> &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 0);
461c497
< NULL, (uint8_t*)&l2Desc.data, 0);
---
> NULL, (uint8_t*)&currState->l2Desc.data, 0);
473c509,510
< DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data);
---
> DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
> currState->vaddr, currState->l2Desc.data);
476c513
< if (l2Desc.invalid()) {
---
> if (currState->l2Desc.invalid()) {
478,480c515,517
< if (!delayed) {
< tc = NULL;
< req = NULL;
---
> if (!currState->delayed) {
> currState->tc = NULL;
> currState->req = NULL;
482,483c519,521
< if (isFetch)
< fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
---
> if (currState->isFetch)
> currState->fault =
> new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
485,486c523,525
< fault = new DataAbort(vaddr, l1Desc.domain(), isWrite,
< ArmFault::Translation1);
---
> currState->fault =
> new DataAbort(currState->vaddr, currState->l1Desc.domain(),
> currState->isWrite, ArmFault::Translation1);
490c529
< if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) {
---
> if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
495c534,537
< fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1);
---
> currState->fault =
> new DataAbort(currState->vaddr, NULL, currState->isWrite,
> ArmFault::AccessFlag1);
>
498c540
< if (l2Desc.large()) {
---
> if (currState->l2Desc.large()) {
500c542
< te.pfn = l2Desc.pfn();
---
> te.pfn = currState->l2Desc.pfn();
503c545
< te.pfn = l2Desc.pfn();
---
> te.pfn = currState->l2Desc.pfn();
508c550
< te.asid = contextId;
---
> te.asid = currState->contextId;
510,515c552,558
< te.vpn = vaddr >> te.N;
< te.global = l2Desc.global();
< te.xn = l2Desc.xn();
< te.ap = l2Desc.ap();
< te.domain = l1Desc.domain();
< memAttrs(tc, te, l2Desc.texcb(), l2Desc.shareable());
---
> te.vpn = currState->vaddr >> te.N;
> te.global = currState->l2Desc.global();
> te.xn = currState->l2Desc.xn();
> te.ap = currState->l2Desc.ap();
> te.domain = currState->l1Desc.domain();
> memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(),
> currState->l2Desc.shareable());
517,519c560,562
< if (!delayed) {
< tc = NULL;
< req = NULL;
---
> if (!currState->delayed) {
> currState->tc = NULL;
> currState->req = NULL;
521c564
< tlb->insert(vaddr, te);
---
> tlb->insert(currState->vaddr, te);
527c570,571
< delayed = false;
---
> currState = stateQueue.peek();
> currState->delayed = false;
529c573
< DPRINTF(TLBVerbose, "calling doL1Descriptor\n");
---
> DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
533,534c577,579
< if (fault != NoFault) {
< transState->finish(fault, req, tc, mode);
---
> if (currState->fault != NoFault) {
> currState->transState->finish(currState->fault, currState->req,
> currState->tc, currState->mode);
536,538c581,585
< req = NULL;
< tc = NULL;
< delayed = false;
---
> currState->req = NULL;
> currState->tc = NULL;
> currState->delayed = false;
>
> stateQueue.remove();
540c587
< else if (!delayed) {
---
> else if (!currState->delayed) {
542c589,590
< fault = tlb->translateTiming(req, tc, transState, mode);
---
> currState->fault = tlb->translateTiming(currState->req, currState->tc,
> currState->transState, currState->mode);
544,546c592,596
< req = NULL;
< tc = NULL;
< delayed = false;
---
> currState->req = NULL;
> currState->tc = NULL;
> currState->delayed = false;
>
> stateQueue.remove();
547a598
> currState = NULL;
553c604,605
< assert(delayed);
---
> currState = stateQueue.peek();
> assert(currState->delayed);
555c607,608
< DPRINTF(TLBVerbose, "calling doL2Descriptor\n");
---
> DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
> currState->vaddr);
559,560c612,614
< if (fault != NoFault) {
< transState->finish(fault, req, tc, mode);
---
> if (currState->fault != NoFault) {
> currState->transState->finish(currState->fault, currState->req,
> currState->tc, currState->mode);
564c618,619
< fault = tlb->translateTiming(req, tc, transState, mode);
---
> currState->fault = tlb->translateTiming(currState->req, currState->tc,
> currState->transState, currState->mode);
567,569c622,627
< req = NULL;
< tc = NULL;
< delayed = false;
---
> currState->req = NULL;
> currState->tc = NULL;
> currState->delayed = false;
>
> stateQueue.remove();
> currState = NULL;