gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
smmu_v3_transl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, 2018-2019 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
39 
40 #include "debug/SMMUv3.hh"
41 #include "debug/SMMUv3Hazard.hh"
42 #include "dev/arm/amba.hh"
43 #include "dev/arm/smmu_v3.hh"
44 #include "sim/system.hh"
45 
48 {
50  req.addr = pkt->getAddr();
51  req.size = pkt->getSize();
52  req.sid = pkt->req->streamId();
53  req.ssid = pkt->req->hasSubstreamId() ?
54  pkt->req->substreamId() : 0;
55  req.isWrite = pkt->isWrite();
56  req.isPrefetch = false;
57  req.isAtsRequest = ats;
58  req.pkt = pkt;
59 
60  return req;
61 }
62 
65 {
67  req.addr = addr;
68  req.size = 0;
69  req.sid = sid;
70  req.ssid = ssid;
71  req.isWrite = false;
72  req.isPrefetch = true;
73  req.isAtsRequest = false;
74  req.pkt = NULL;
75 
76  return req;
77 }
78 
80  SMMUv3 &_smmu, SMMUv3SlaveInterface &_ifc)
81  :
82  SMMUProcess(name, _smmu),
83  ifc(_ifc)
84 {
85  // Decrease number of pending translation slots on the slave interface
86  assert(ifc.xlateSlotsRemaining > 0);
88 
90  reinit();
91 }
92 
94 {
95  // Increase number of pending translation slots on the slave interface
96  assert(ifc.pendingMemAccesses > 0);
98 
99  // If no more SMMU memory accesses are pending,
100  // signal SMMU Slave Interface as drained
101  if (ifc.pendingMemAccesses == 0) {
103  }
104 }
105 
106 void
108 {
109  request = req;
110 
111  reinit();
112 }
113 
114 void
116 {
117  assert(smmu.system.isTimingMode());
118 
119  assert(!"Stalls are broken");
120 
121  Tick resumeTick = curTick();
122 
123  (void) resumeTick;
124  DPRINTF(SMMUv3, "Resume at tick = %d. Fault duration = %d (%.3fus)\n",
125  resumeTick, resumeTick-faultTick, (resumeTick-faultTick) / 1e6);
126 
128 
130 }
131 
132 void
134 {
135  // Hack:
136  // The coroutine starts running as soon as it's created.
137  // But we need to wait for request data esp. in atomic mode.
138  SMMUAction a;
140  a.pkt = NULL;
141  yield(a);
142 
143  const Addr next4k = (request.addr + 0x1000ULL) & ~0xfffULL;
144 
145  if ((request.addr + request.size) > next4k)
146  panic("Transaction crosses 4k boundary (addr=%#x size=%#x)!\n",
148 
149 
150  unsigned numSlaveBeats = request.isWrite ?
151  (request.size + (ifc.portWidth - 1)) / ifc.portWidth : 1;
152 
154  doDelay(yield, Cycles(numSlaveBeats));
156 
157 
158  recvTick = curTick();
159 
160  if (!(smmu.regs.cr0 & CR0_SMMUEN_MASK)) {
161  // SMMU disabled
162  doDelay(yield, Cycles(1));
164  return;
165  }
166 
167  TranslResult tr;
168  bool wasPrefetched = false;
169 
170  if (request.isPrefetch) {
171  // Abort prefetch if:
172  // - there's already a transaction looking up the same 4k page, OR
173  // - requested address is already in the TLB.
174  if (hazard4kCheck() || ifcTLBLookup(yield, tr, wasPrefetched))
175  completePrefetch(yield); // this never returns
176 
178 
179  tr = smmuTranslation(yield);
180 
181  if (tr.fault == FAULT_NONE)
182  ifcTLBUpdate(yield, tr);
183 
184  hazard4kRelease();
185 
186  completePrefetch(yield);
187  } else {
189 
190  if (!microTLBLookup(yield, tr)) {
191  bool hit = ifcTLBLookup(yield, tr, wasPrefetched);
192  if (!hit) {
193  while (!hit && hazard4kCheck()) {
194  hazard4kHold(yield);
195  hit = ifcTLBLookup(yield, tr, wasPrefetched);
196  }
197  }
198 
199  // Issue prefetch if:
200  // - there was a TLB hit and the entry was prefetched, OR
201  // - TLB miss was successfully serviced
202  if (hit) {
203  if (wasPrefetched)
204  issuePrefetch(next4k);
205  } else {
207 
208  tr = smmuTranslation(yield);
209 
210  if (tr.fault == FAULT_NONE) {
211  ifcTLBUpdate(yield, tr);
212 
213  issuePrefetch(next4k);
214  }
215 
216  hazard4kRelease();
217  }
218 
219  if (tr.fault == FAULT_NONE)
220  microTLBUpdate(yield, tr);
221  }
222 
223  hazardIdHold(yield);
224  hazardIdRelease();
225 
226  if (tr.fault != FAULT_NONE)
227  panic("Translation Fault (addr=%#x, size=%#x, sid=%d, ssid=%d, "
228  "isWrite=%d, isPrefetch=%d, isAtsRequest=%d)\n",
231 
232  completeTransaction(yield, tr);
233  }
234 }
235 
238 {
239  TranslResult tr;
240  tr.fault = FAULT_NONE;
241  tr.addr = addr;
242  tr.addrMask = 0;
243  tr.writable = 1;
244 
245  return tr;
246 }
247 
250 {
251  TranslResult tr;
252 
253  // Need SMMU credit to proceed
254  doSemaphoreDown(yield, smmu.transSem);
255 
256  // Simulate pipelined IFC->SMMU link
258  doDelay(yield, Cycles(1)); // serialize transactions
260  doDelay(yield, smmu.ifcSmmuLat - Cycles(1)); // remaining pipeline delay
261 
262  bool haveConfig = true;
263  if (!configCacheLookup(yield, context)) {
264  if(findConfig(yield, context, tr)) {
265  configCacheUpdate(yield, context);
266  } else {
267  haveConfig = false;
268  }
269  }
270 
271  if (haveConfig && !smmuTLBLookup(yield, tr)) {
272  // SMMU main TLB miss
273 
274  // Need PTW slot to proceed
275  doSemaphoreDown(yield, smmu.ptwSem);
276 
277  // Page table walk
278  Tick ptwStartTick = curTick();
279 
280  if (context.stage1Enable) {
281  tr = translateStage1And2(yield, request.addr);
282  } else if (context.stage2Enable) {
283  tr = translateStage2(yield, request.addr, true);
284  } else {
285  tr = bypass(request.addr);
286  }
287 
289  smmu.ptwTimeDist.sample(curTick() - ptwStartTick);
290 
291  // Free PTW slot
293 
294  if (tr.fault == FAULT_NONE)
295  smmuTLBUpdate(yield, tr);
296  }
297 
298  // Simulate pipelined SMMU->SLAVE INTERFACE link
300  doDelay(yield, Cycles(1)); // serialize transactions
302  doDelay(yield, smmu.smmuIfcLat - Cycles(1)); // remaining pipeline delay
303 
304  // return SMMU credit
306 
307  return tr;
308 }
309 
310 bool
312 {
313  if (!ifc.microTLBEnable)
314  return false;
315 
317  doDelay(yield, ifc.microTLBLat);
318  const SMMUTLB::Entry *e =
321 
322  if (!e) {
323  DPRINTF(SMMUv3, "micro TLB miss vaddr=%#x sid=%#x ssid=%#x\n",
325 
326  return false;
327  }
328 
329  DPRINTF(SMMUv3,
330  "micro TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x paddr=%#x\n",
332 
333  tr.fault = FAULT_NONE;
334  tr.addr = e->pa + (request.addr & ~e->vaMask);;
335  tr.addrMask = e->vaMask;
336  tr.writable = e->permissions;
337 
338  return true;
339 }
340 
341 bool
343  bool &wasPrefetched)
344 {
345  if (!ifc.mainTLBEnable)
346  return false;
347 
349  doDelay(yield, ifc.mainTLBLat);
350  const SMMUTLB::Entry *e =
353 
354  if (!e) {
355  DPRINTF(SMMUv3,
356  "SLAVE Interface TLB miss vaddr=%#x sid=%#x ssid=%#x\n",
358 
359  return false;
360  }
361 
362  DPRINTF(SMMUv3,
363  "SLAVE Interface TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x "
364  "paddr=%#x\n", request.addr, e->vaMask, request.sid,
365  request.ssid, e->pa);
366 
367  tr.fault = FAULT_NONE;
368  tr.addr = e->pa + (request.addr & ~e->vaMask);;
369  tr.addrMask = e->vaMask;
370  tr.writable = e->permissions;
371  wasPrefetched = e->prefetched;
372 
373  return true;
374 }
375 
376 bool
378 {
379  if (!smmu.tlbEnable)
380  return false;
381 
382  doSemaphoreDown(yield, smmu.tlbSem);
383  doDelay(yield, smmu.tlbLat);
384  const ARMArchTLB::Entry *e =
387 
388  if (!e) {
389  DPRINTF(SMMUv3, "SMMU TLB miss vaddr=%#x asid=%#x vmid=%#x\n",
391 
392  return false;
393  }
394 
395  DPRINTF(SMMUv3,
396  "SMMU TLB hit vaddr=%#x amask=%#x asid=%#x vmid=%#x paddr=%#x\n",
398 
399  tr.fault = FAULT_NONE;
400  tr.addr = e->pa + (request.addr & ~e->vaMask);;
401  tr.addrMask = e->vaMask;
402  tr.writable = e->permissions;
403 
404  return true;
405 }
406 
407 void
409  const TranslResult &tr)
410 {
411  assert(tr.fault == FAULT_NONE);
412 
413  if (!ifc.microTLBEnable)
414  return;
415 
417  e.valid = true;
418  e.prefetched = false;
419  e.sid = request.sid;
420  e.ssid = request.ssid;
421  e.vaMask = tr.addrMask;
422  e.va = request.addr & e.vaMask;
423  e.pa = tr.addr & e.vaMask;
424  e.permissions = tr.writable;
425  e.asid = context.asid;
426  e.vmid = context.vmid;
427 
429 
430  DPRINTF(SMMUv3,
431  "micro TLB upd vaddr=%#x amask=%#x paddr=%#x sid=%#x ssid=%#x\n",
432  e.va, e.vaMask, e.pa, e.sid, e.ssid);
433 
435 
437 }
438 
439 void
441  const TranslResult &tr)
442 {
443  assert(tr.fault == FAULT_NONE);
444 
445  if (!ifc.mainTLBEnable)
446  return;
447 
449  e.valid = true;
451  e.sid = request.sid;
452  e.ssid = request.ssid;
453  e.vaMask = tr.addrMask;
454  e.va = request.addr & e.vaMask;
455  e.pa = tr.addr & e.vaMask;
456  e.permissions = tr.writable;
457  e.asid = context.asid;
458  e.vmid = context.vmid;
459 
462  alloc = request.isPrefetch ?
464 
466 
467  DPRINTF(SMMUv3,
468  "SLAVE Interface upd vaddr=%#x amask=%#x paddr=%#x sid=%#x "
469  "ssid=%#x\n", e.va, e.vaMask, e.pa, e.sid, e.ssid);
470 
471  ifc.mainTLB->store(e, alloc);
472 
474 }
475 
476 void
478  const TranslResult &tr)
479 {
480  assert(tr.fault == FAULT_NONE);
481 
482  if (!smmu.tlbEnable)
483  return;
484 
486  e.valid = true;
487  e.vaMask = tr.addrMask;
488  e.va = request.addr & e.vaMask;
489  e.asid = context.asid;
490  e.vmid = context.vmid;
491  e.pa = tr.addr & e.vaMask;
492  e.permissions = tr.writable;
493 
494  doSemaphoreDown(yield, smmu.tlbSem);
495 
496  DPRINTF(SMMUv3,
497  "SMMU TLB upd vaddr=%#x amask=%#x paddr=%#x asid=%#x vmid=%#x\n",
498  e.va, e.vaMask, e.pa, e.asid, e.vmid);
499 
500  smmu.tlb.store(e);
501 
503 }
504 
505 bool
507 {
508  if (!smmu.configCacheEnable)
509  return false;
510 
512  doDelay(yield, smmu.configLat);
513  const ConfigCache::Entry *e =
516 
517  if (!e) {
518  DPRINTF(SMMUv3, "Config miss sid=%#x ssid=%#x\n",
520 
521  return false;
522  }
523 
524  DPRINTF(SMMUv3, "Config hit sid=%#x ssid=%#x ttb=%#08x asid=%#x\n",
525  request.sid, request.ssid, e->ttb0, e->asid);
526 
527  tc.stage1Enable = e->stage1_en;
528  tc.stage2Enable = e->stage2_en;
529 
530  tc.ttb0 = e->ttb0;
531  tc.ttb1 = e->ttb1;
532  tc.asid = e->asid;
533  tc.httb = e->httb;
534  tc.vmid = e->vmid;
535 
538 
539  tc.t0sz = e->t0sz;
540  tc.s2t0sz = e->s2t0sz;
541 
542  return true;
543 }
544 
545 void
547  const TranslContext &tc)
548 {
549  if (!smmu.configCacheEnable)
550  return;
551 
553  e.valid = true;
554  e.sid = request.sid;
555  e.ssid = request.ssid;
556  e.stage1_en = tc.stage1Enable;
557  e.stage2_en = tc.stage2Enable;
558  e.ttb0 = tc.ttb0;
559  e.ttb1 = tc.ttb1;
560  e.asid = tc.asid;
561  e.httb = tc.httb;
562  e.vmid = tc.vmid;
565  e.t0sz = tc.t0sz;
566  e.s2t0sz = tc.s2t0sz;
567 
569 
570  DPRINTF(SMMUv3, "Config upd sid=%#x ssid=%#x\n", e.sid, e.ssid);
571 
573 
575 }
576 
577 bool
579  TranslContext &tc,
580  TranslResult &tr)
581 {
582  tc.stage1Enable = false;
583  tc.stage2Enable = false;
584 
585  StreamTableEntry ste;
586  doReadSTE(yield, ste, request.sid);
587 
588  switch (ste.dw0.config) {
589  case STE_CONFIG_BYPASS:
590  break;
591 
593  tc.stage1Enable = true;
594  break;
595 
597  tc.stage2Enable = true;
598  break;
599 
601  tc.stage1Enable = true;
602  tc.stage2Enable = true;
603  break;
604 
605  default:
606  panic("Bad or unimplemented STE config %d\n",
607  ste.dw0.config);
608  }
609 
610 
611  // Establish stage 2 context first since
612  // Context Descriptors can be in IPA space.
613  if (tc.stage2Enable) {
614  tc.httb = ste.dw3.s2ttb << STE_S2TTB_SHIFT;
615  tc.vmid = ste.dw2.s2vmid;
616  tc.stage2TranslGranule = ste.dw2.s2tg;
617  tc.s2t0sz = ste.dw2.s2t0sz;
618  } else {
619  tc.httb = 0xdeadbeef;
620  tc.vmid = 0;
622  tc.s2t0sz = 0;
623  }
624 
625 
626  // Now fetch stage 1 config.
627  if (context.stage1Enable) {
629  doReadCD(yield, cd, ste, request.sid, request.ssid);
630 
631  tc.ttb0 = cd.dw1.ttb0 << CD_TTB_SHIFT;
632  tc.ttb1 = cd.dw2.ttb1 << CD_TTB_SHIFT;
633  tc.asid = cd.dw0.asid;
634  tc.stage1TranslGranule = cd.dw0.tg0;
635  tc.t0sz = cd.dw0.t0sz;
636  } else {
637  tc.ttb0 = 0xcafebabe;
638  tc.ttb1 = 0xcafed00d;
639  tc.asid = 0;
641  tc.t0sz = 0;
642  }
643 
644  return true;
645 }
646 
647 void
649  Yield &yield,
650  const WalkCache::Entry *&walkEntry,
651  Addr addr, uint16_t asid, uint16_t vmid,
652  unsigned stage, unsigned level)
653 {
654  const char *indent = stage==2 ? " " : "";
655  (void) indent; // this is only used in DPRINTFs
656 
657  const PageTableOps *pt_ops =
658  stage == 1 ?
661 
662  unsigned walkCacheLevels =
664  (stage == 1 ? smmu.walkCacheS1Levels : smmu.walkCacheS2Levels) :
665  0;
666 
667  if ((1 << level) & walkCacheLevels) {
668  doSemaphoreDown(yield, smmu.walkSem);
669  doDelay(yield, smmu.walkLat);
670 
671  walkEntry = smmu.walkCache.lookup(addr, pt_ops->walkMask(level),
672  asid, vmid, stage, level);
673 
674  if (walkEntry) {
675  DPRINTF(SMMUv3, "%sWalkCache hit va=%#x asid=%#x vmid=%#x "
676  "base=%#x (S%d, L%d)\n",
677  indent, addr, asid, vmid, walkEntry->pa, stage, level);
678  } else {
679  DPRINTF(SMMUv3, "%sWalkCache miss va=%#x asid=%#x vmid=%#x "
680  "(S%d, L%d)\n",
681  indent, addr, asid, vmid, stage, level);
682  }
683 
685  }
686 }
687 
688 void
690  Addr vaMask, Addr pa,
691  unsigned stage, unsigned level,
692  bool leaf, uint8_t permissions)
693 {
694  unsigned walkCacheLevels =
696 
697  if (smmu.walkCacheEnable && ((1<<level) & walkCacheLevels)) {
699  e.valid = true;
700  e.va = va;
701  e.vaMask = vaMask;
702  e.asid = stage==1 ? context.asid : 0;
703  e.vmid = context.vmid;
704  e.stage = stage;
705  e.level = level;
706  e.leaf = leaf;
707  e.pa = pa;
708  e.permissions = permissions;
709 
710  doSemaphoreDown(yield, smmu.walkSem);
711 
712  DPRINTF(SMMUv3, "%sWalkCache upd va=%#x mask=%#x asid=%#x vmid=%#x "
713  "tpa=%#x leaf=%s (S%d, L%d)\n",
714  e.stage==2 ? " " : "",
715  e.va, e.vaMask, e.asid, e.vmid,
716  e.pa, e.leaf, e.stage, e.level);
717 
718  smmu.walkCache.store(e);
719 
721  }
722 }
723 
724 /*
725  * Please note:
726  * This does not deal with the case where stage 1 page size
727  * is larger than stage 2 page size.
728  */
731  const PageTableOps *pt_ops,
732  unsigned level, Addr walkPtr)
733 {
734  PageTableOps::pte_t pte = 0;
735 
736  doSemaphoreDown(yield, smmu.cycleSem);
737  doDelay(yield, Cycles(1));
739 
740  for (; level <= pt_ops->lastLevel(); level++) {
741  Addr pte_addr = walkPtr + pt_ops->index(addr, level);
742 
743  DPRINTF(SMMUv3, "Fetching S1 L%d PTE from pa=%#08x\n",
744  level, pte_addr);
745 
746  doReadPTE(yield, addr, pte_addr, &pte, 1, level);
747 
748  DPRINTF(SMMUv3, "Got S1 L%d PTE=%#x from pa=%#08x\n",
749  level, pte, pte_addr);
750 
751  doSemaphoreDown(yield, smmu.cycleSem);
752  doDelay(yield, Cycles(1));
754 
755  bool valid = pt_ops->isValid(pte, level);
756  bool leaf = pt_ops->isLeaf(pte, level);
757 
758  if (!valid) {
759  DPRINTF(SMMUv3, "S1 PTE not valid - fault\n");
760 
761  TranslResult tr;
763  return tr;
764  }
765 
766  if (valid && leaf && request.isWrite &&
767  !pt_ops->isWritable(pte, level, false))
768  {
769  DPRINTF(SMMUv3, "S1 page not writable - fault\n");
770 
771  TranslResult tr;
772  tr.fault = FAULT_PERMISSION;
773  return tr;
774  }
775 
776  walkPtr = pt_ops->nextLevelPointer(pte, level);
777 
778  if (leaf)
779  break;
780 
781  if (context.stage2Enable) {
782  TranslResult s2tr = translateStage2(yield, walkPtr, false);
783  if (s2tr.fault != FAULT_NONE)
784  return s2tr;
785 
786  walkPtr = s2tr.addr;
787  }
788 
789  walkCacheUpdate(yield, addr, pt_ops->walkMask(level), walkPtr,
790  1, level, leaf, 0);
791  }
792 
793  TranslResult tr;
794  tr.fault = FAULT_NONE;
795  tr.addrMask = pt_ops->pageMask(pte, level);
796  tr.addr = walkPtr + (addr & ~tr.addrMask);
797  tr.writable = pt_ops->isWritable(pte, level, false);
798 
799  if (context.stage2Enable) {
800  TranslResult s2tr = translateStage2(yield, tr.addr, true);
801  if (s2tr.fault != FAULT_NONE)
802  return s2tr;
803 
804  tr = combineTranslations(tr, s2tr);
805  }
806 
807  walkCacheUpdate(yield, addr, tr.addrMask, walkPtr,
808  1, level, true, tr.writable);
809 
810  return tr;
811 }
812 
815  const PageTableOps *pt_ops,
816  unsigned level, Addr walkPtr)
817 {
819 
820  doSemaphoreDown(yield, smmu.cycleSem);
821  doDelay(yield, Cycles(1));
823 
824  for (; level <= pt_ops->lastLevel(); level++) {
825  Addr pte_addr = walkPtr + pt_ops->index(addr, level);
826 
827  DPRINTF(SMMUv3, " Fetching S2 L%d PTE from pa=%#08x\n",
828  level, pte_addr);
829 
830  doReadPTE(yield, addr, pte_addr, &pte, 2, level);
831 
832  DPRINTF(SMMUv3, " Got S2 L%d PTE=%#x from pa=%#08x\n",
833  level, pte, pte_addr);
834 
835  doSemaphoreDown(yield, smmu.cycleSem);
836  doDelay(yield, Cycles(1));
838 
839  bool valid = pt_ops->isValid(pte, level);
840  bool leaf = pt_ops->isLeaf(pte, level);
841 
842  if (!valid) {
843  DPRINTF(SMMUv3, " S2 PTE not valid - fault\n");
844 
845  TranslResult tr;
847  return tr;
848  }
849 
850  if (valid && leaf && request.isWrite &&
851  !pt_ops->isWritable(pte, level, true))
852  {
853  DPRINTF(SMMUv3, " S2 PTE not writable = fault\n");
854 
855  TranslResult tr;
856  tr.fault = FAULT_PERMISSION;
857  return tr;
858  }
859 
860  walkPtr = pt_ops->nextLevelPointer(pte, level);
861 
862  if (final_tr || smmu.walkCacheNonfinalEnable)
863  walkCacheUpdate(yield, addr, pt_ops->walkMask(level), walkPtr,
864  2, level, leaf,
865  leaf ? pt_ops->isWritable(pte, level, true) : 0);
866  if (leaf)
867  break;
868  }
869 
870  TranslResult tr;
871  tr.fault = FAULT_NONE;
872  tr.addrMask = pt_ops->pageMask(pte, level);
873  tr.addr = walkPtr + (addr & ~tr.addrMask);
874  tr.writable = pt_ops->isWritable(pte, level, true);
875 
876  return tr;
877 }
878 
881 {
882  const PageTableOps *pt_ops =
884 
885  const WalkCache::Entry *walk_ep = NULL;
886  unsigned level;
887 
888  // Level here is actually (level+1) so we can count down
889  // to 0 using unsigned int.
890  for (level = pt_ops->lastLevel() + 1;
891  level > pt_ops->firstLevel(context.t0sz);
892  level--)
893  {
894  walkCacheLookup(yield, walk_ep, addr,
895  context.asid, context.vmid, 1, level-1);
896 
897  if (walk_ep)
898  break;
899  }
900 
901  // Correct level (see above).
902  level -= 1;
903 
904  TranslResult tr;
905  if (walk_ep) {
906  if (walk_ep->leaf) {
907  tr.fault = FAULT_NONE;
908  tr.addr = walk_ep->pa + (addr & ~walk_ep->vaMask);
909  tr.addrMask = walk_ep->vaMask;
910  tr.writable = walk_ep->permissions;
911  } else {
912  tr = walkStage1And2(yield, addr, pt_ops, level+1, walk_ep->pa);
913  }
914  } else {
915  Addr table_addr = context.ttb0;
916  if (context.stage2Enable) {
917  TranslResult s2tr = translateStage2(yield, table_addr, false);
918  if (s2tr.fault != FAULT_NONE)
919  return s2tr;
920 
921  table_addr = s2tr.addr;
922  }
923 
924  tr = walkStage1And2(yield, addr, pt_ops,
925  pt_ops->firstLevel(context.t0sz),
926  table_addr);
927  }
928 
929  if (tr.fault == FAULT_NONE)
930  DPRINTF(SMMUv3, "Translated vaddr %#x to paddr %#x\n", addr, tr.addr);
931 
932  return tr;
933 }
934 
937 {
938  const PageTableOps *pt_ops =
940 
941  const IPACache::Entry *ipa_ep = NULL;
942  if (smmu.ipaCacheEnable) {
943  doSemaphoreDown(yield, smmu.ipaSem);
944  doDelay(yield, smmu.ipaLat);
945  ipa_ep = smmu.ipaCache.lookup(addr, context.vmid);
947  }
948 
949  if (ipa_ep) {
950  TranslResult tr;
951  tr.fault = FAULT_NONE;
952  tr.addr = ipa_ep->pa + (addr & ~ipa_ep->ipaMask);
953  tr.addrMask = ipa_ep->ipaMask;
954  tr.writable = ipa_ep->permissions;
955 
956  DPRINTF(SMMUv3, " IPACache hit ipa=%#x vmid=%#x pa=%#x\n",
957  addr, context.vmid, tr.addr);
958 
959  return tr;
960  } else if (smmu.ipaCacheEnable) {
961  DPRINTF(SMMUv3, " IPACache miss ipa=%#x vmid=%#x\n",
962  addr, context.vmid);
963  }
964 
965  const WalkCache::Entry *walk_ep = NULL;
966  unsigned level = pt_ops->firstLevel(context.s2t0sz);
967 
968  if (final_tr || smmu.walkCacheNonfinalEnable) {
969  // Level here is actually (level+1) so we can count down
970  // to 0 using unsigned int.
971  for (level = pt_ops->lastLevel() + 1;
972  level > pt_ops->firstLevel(context.s2t0sz);
973  level--)
974  {
975  walkCacheLookup(yield, walk_ep, addr,
976  0, context.vmid, 2, level-1);
977 
978  if (walk_ep)
979  break;
980  }
981 
982  // Correct level (see above).
983  level -= 1;
984  }
985 
986  TranslResult tr;
987  if (walk_ep) {
988  if (walk_ep->leaf) {
989  tr.fault = FAULT_NONE;
990  tr.addr = walk_ep->pa + (addr & ~walk_ep->vaMask);
991  tr.addrMask = walk_ep->vaMask;
992  tr.writable = walk_ep->permissions;
993  } else {
994  tr = walkStage2(yield, addr, final_tr, pt_ops,
995  level + 1, walk_ep->pa);
996  }
997  } else {
998  tr = walkStage2(yield, addr, final_tr, pt_ops,
999  pt_ops->firstLevel(context.s2t0sz),
1000  context.httb);
1001  }
1002 
1003  if (tr.fault == FAULT_NONE)
1004  DPRINTF(SMMUv3, " Translated %saddr %#x to paddr %#x\n",
1005  context.stage1Enable ? "ip" : "v", addr, tr.addr);
1006 
1007  if (smmu.ipaCacheEnable) {
1009  e.valid = true;
1010  e.ipaMask = tr.addrMask;
1011  e.ipa = addr & e.ipaMask;
1012  e.pa = tr.addr & tr.addrMask;
1013  e.permissions = tr.writable;
1014  e.vmid = context.vmid;
1015 
1016  doSemaphoreDown(yield, smmu.ipaSem);
1017  smmu.ipaCache.store(e);
1019  }
1020 
1021  return tr;
1022 }
1023 
1026  const TranslResult &s2tr) const
1027 {
1028  if (s2tr.fault != FAULT_NONE)
1029  return s2tr;
1030 
1031  assert(s1tr.fault == FAULT_NONE);
1032 
1033  TranslResult tr;
1034  tr.fault = FAULT_NONE;
1035  tr.addr = s2tr.addr;
1036  tr.addrMask = s1tr.addrMask | s2tr.addrMask;
1037  tr.writable = s1tr.writable & s2tr.writable;
1038 
1039  return tr;
1040 }
1041 
1042 bool
1044 {
1045  Addr addr4k = request.addr & ~0xfffULL;
1046 
1047  for (auto it = ifc.duplicateReqs.begin();
1048  it != ifc.duplicateReqs.end();
1049  ++it)
1050  {
1051  Addr other4k = (*it)->request.addr & ~0xfffULL;
1052  if (addr4k == other4k)
1053  return true;
1054  }
1055 
1056  return false;
1057 }
1058 
1059 void
1061 {
1062  DPRINTF(SMMUv3Hazard, "4kReg: p=%p a4k=%#x\n",
1063  this, request.addr & ~0xfffULL);
1064 
1065  ifc.duplicateReqs.push_back(this);
1066 }
1067 
1068 void
1070 {
1071  Addr addr4k = request.addr & ~0xfffULL;
1072 
1073  bool found_hazard;
1074 
1075  do {
1076  found_hazard = false;
1077 
1078  for (auto it = ifc.duplicateReqs.begin();
1079  it!=ifc.duplicateReqs.end() && *it!=this;
1080  ++it)
1081  {
1082  Addr other4k = (*it)->request.addr & ~0xfffULL;
1083 
1084  DPRINTF(SMMUv3Hazard, "4kHold: p=%p a4k=%#x Q: p=%p a4k=%#x\n",
1085  this, addr4k, *it, other4k);
1086 
1087  if (addr4k == other4k) {
1088  DPRINTF(SMMUv3Hazard,
1089  "4kHold: p=%p a4k=%#x WAIT on p=%p a4k=%#x\n",
1090  this, addr4k, *it, other4k);
1091 
1093 
1094  DPRINTF(SMMUv3Hazard, "4kHold: p=%p a4k=%#x RESUME\n",
1095  this, addr4k);
1096 
1097  // This is to avoid checking *it!=this after doWaitForSignal()
1098  // since it could have been deleted.
1099  found_hazard = true;
1100  break;
1101  }
1102  }
1103  } while (found_hazard);
1104 }
1105 
1106 void
1108 {
1109  DPRINTF(SMMUv3Hazard, "4kRel: p=%p a4k=%#x\n",
1110  this, request.addr & ~0xfffULL);
1111 
1113 
1114  for (it = ifc.duplicateReqs.begin(); it != ifc.duplicateReqs.end(); ++it)
1115  if (*it == this)
1116  break;
1117 
1118  if (it == ifc.duplicateReqs.end())
1119  panic("hazard4kRelease: request not found");
1120 
1121  ifc.duplicateReqs.erase(it);
1122 
1124 }
1125 
1126 void
1128 {
1129  auto orderId = AMBA::orderId(request.pkt);
1130 
1131  DPRINTF(SMMUv3Hazard, "IdReg: p=%p oid=%d\n", this, orderId);
1132 
1133  assert(orderId < SMMU_MAX_TRANS_ID);
1134 
1136  request.isWrite ?
1138  depReqs.push_back(this);
1139 }
1140 
1141 void
1143 {
1144  auto orderId = AMBA::orderId(request.pkt);
1145 
1146  DPRINTF(SMMUv3Hazard, "IdHold: p=%p oid=%d\n", this, orderId);
1147 
1149  request.isWrite ?
1152 
1153  bool found_hazard;
1154 
1155  do {
1156  found_hazard = false;
1157 
1158  for (auto it = depReqs.begin(); it!=depReqs.end() && *it!=this; ++it) {
1159  DPRINTF(SMMUv3Hazard, "IdHold: p=%p oid=%d Q: %p\n",
1160  this, orderId, *it);
1161 
1162  if (AMBA::orderId((*it)->request.pkt) == orderId) {
1163  DPRINTF(SMMUv3Hazard, "IdHold: p=%p oid=%d WAIT on=%p\n",
1164  this, orderId, *it);
1165 
1167 
1168  DPRINTF(SMMUv3Hazard, "IdHold: p=%p oid=%d RESUME\n",
1169  this, orderId);
1170 
1171  // This is to avoid checking *it!=this after doWaitForSignal()
1172  // since it could have been deleted.
1173  found_hazard = true;
1174  break;
1175  }
1176  }
1177  } while (found_hazard);
1178 }
1179 
1180 void
1182 {
1183  auto orderId = AMBA::orderId(request.pkt);
1184 
1185  DPRINTF(SMMUv3Hazard, "IdRel: p=%p oid=%d\n", this, orderId);
1186 
1188  request.isWrite ?
1191 
1192  for (it = depReqs.begin(); it != depReqs.end(); ++it) {
1193  if (*it == this)
1194  break;
1195  }
1196 
1197  if (it == depReqs.end())
1198  panic("hazardIdRelease: request not found");
1199 
1200  depReqs.erase(it);
1201 
1203 }
1204 
1205 void
1207 {
1208  if (!smmu.system.isTimingMode())
1209  return;
1210 
1212  return;
1213 
1214  std::string proc_name = csprintf("%sprf", name());
1215  SMMUTranslationProcess *proc =
1216  new SMMUTranslationProcess(proc_name, smmu, ifc);
1217 
1218  proc->beginTransaction(
1220  proc->scheduleWakeup(smmu.clockEdge(Cycles(1)));
1221 }
1222 
1223 void
1225  const TranslResult &tr)
1226 {
1227  assert(tr.fault == FAULT_NONE);
1228 
1229  unsigned numMasterBeats = request.isWrite ?
1231  / smmu.masterPortWidth :
1232  1;
1233 
1235  doDelay(yield, Cycles(numMasterBeats));
1237 
1238 
1243  (request.size + (ifc.portWidth-1)) / ifc.portWidth;
1244 
1246 
1247 
1248  SMMUAction a;
1249 
1250  if (request.isAtsRequest) {
1252 
1253  if (smmu.system.isAtomicMode()) {
1255  } else if (smmu.system.isTimingMode()) {
1257  } else {
1258  panic("Not in atomic or timing mode");
1259  }
1260  } else {
1262  a.ifc = &ifc;
1263  }
1264 
1265  a.pkt = request.pkt;
1266  a.delay = 0;
1267 
1268  a.pkt->setAddr(tr.addr);
1269  a.pkt->req->setPaddr(tr.addr);
1270 
1271  yield(a);
1272 
1273  if (!request.isAtsRequest) {
1274  PacketPtr pkt = yield.get();
1275  pkt->setAddr(request.addr);
1276 
1277  a.type = ACTION_SEND_RESP;
1278  a.pkt = pkt;
1279  a.ifc = &ifc;
1280  a.delay = 0;
1281  yield(a);
1282  }
1283 }
1284 
1285 void
1287 {
1289 
1290  SMMUAction a;
1291  a.type = ACTION_TERMINATE;
1292  a.pkt = NULL;
1293  a.ifc = &ifc;
1294  a.delay = 0;
1295  yield(a);
1296 }
1297 
1298 void
1300 {
1301  int sizeMask = mask(smmu.regs.eventq_base & Q_BASE_SIZE_MASK);
1302 
1303  if (((smmu.regs.eventq_prod+1) & sizeMask) ==
1304  (smmu.regs.eventq_cons & sizeMask))
1305  panic("Event queue full - aborting\n");
1306 
1307  Addr event_addr =
1309  (smmu.regs.eventq_prod & sizeMask) * sizeof(ev);
1310 
1311  DPRINTF(SMMUv3, "Sending event to addr=%#08x (pos=%d): type=%#x stag=%#x "
1312  "flags=%#x sid=%#x ssid=%#x va=%#08x ipa=%#x\n",
1313  event_addr, smmu.regs.eventq_prod, ev.type, ev.stag,
1314  ev.flags, ev.streamId, ev.substreamId, ev.va, ev.ipa);
1315 
1316  // This deliberately resets the overflow field in eventq_prod!
1317  smmu.regs.eventq_prod = (smmu.regs.eventq_prod + 1) & sizeMask;
1318 
1319  doWrite(yield, event_addr, &ev, sizeof(ev));
1320 
1322  panic("eventq msi not enabled\n");
1323 
1326 }
1327 
1328 void
1330  StreamTableEntry &ste,
1331  uint32_t sid)
1332 {
1333  unsigned max_sid = 1 << (smmu.regs.strtab_base_cfg & ST_CFG_SIZE_MASK);
1334  if (sid >= max_sid)
1335  panic("SID %#x out of range, max=%#x", sid, max_sid);
1336 
1337  Addr ste_addr;
1338 
1340  unsigned split =
1342 
1343  if (split!= 7 && split!=8 && split!=16)
1344  panic("Invalid stream table split %d", split);
1345 
1346  uint64_t l2_ptr;
1347  uint64_t l2_addr =
1349  bits(sid, 32, split) * sizeof(l2_ptr);
1350 
1351  DPRINTF(SMMUv3, "Read L1STE at %#x\n", l2_addr);
1352 
1353  doReadConfig(yield, l2_addr, &l2_ptr, sizeof(l2_ptr), sid, 0);
1354 
1355  DPRINTF(SMMUv3, "Got L1STE L1 at %#x: 0x%016x\n", l2_addr, l2_ptr);
1356 
1357  unsigned span = l2_ptr & ST_L2_SPAN_MASK;
1358  if (span == 0)
1359  panic("Invalid level 1 stream table descriptor");
1360 
1361  unsigned index = bits(sid, split-1, 0);
1362  if (index >= (1 << span))
1363  panic("StreamID %d out of level 1 descriptor range %d",
1364  sid, 1<<span);
1365 
1366  ste_addr = (l2_ptr & ST_L2_ADDR_MASK) + index * sizeof(ste);
1367 
1368  smmu.steL1Fetches++;
1370  ste_addr =
1371  (smmu.regs.strtab_base & VMT_BASE_ADDR_MASK) + sid * sizeof(ste);
1372  } else {
1373  panic("Invalid stream table format");
1374  }
1375 
1376  DPRINTF(SMMUv3, "Read STE at %#x\n", ste_addr);
1377 
1378  doReadConfig(yield, ste_addr, &ste, sizeof(ste), sid, 0);
1379 
1380  DPRINTF(SMMUv3, "Got STE at %#x [0]: 0x%016x\n", ste_addr, ste.dw0);
1381  DPRINTF(SMMUv3, " STE at %#x [1]: 0x%016x\n", ste_addr, ste.dw1);
1382  DPRINTF(SMMUv3, " STE at %#x [2]: 0x%016x\n", ste_addr, ste.dw2);
1383  DPRINTF(SMMUv3, " STE at %#x [3]: 0x%016x\n", ste_addr, ste.dw3);
1384  DPRINTF(SMMUv3, " STE at %#x [4]: 0x%016x\n", ste_addr, ste._pad[0]);
1385  DPRINTF(SMMUv3, " STE at %#x [5]: 0x%016x\n", ste_addr, ste._pad[1]);
1386  DPRINTF(SMMUv3, " STE at %#x [6]: 0x%016x\n", ste_addr, ste._pad[2]);
1387  DPRINTF(SMMUv3, " STE at %#x [7]: 0x%016x\n", ste_addr, ste._pad[3]);
1388 
1389  if (!ste.dw0.valid)
1390  panic("STE @ %#x not valid\n", ste_addr);
1391 
1392  smmu.steFetches++;
1393 }
1394 
1395 void
1398  const StreamTableEntry &ste,
1399  uint32_t sid, uint32_t ssid)
1400 {
1401  Addr cd_addr;
1402 
1403  if (ste.dw0.s1cdmax == 0) {
1404  cd_addr = ste.dw0.s1ctxptr << ST_CD_ADDR_SHIFT;
1405  } else {
1406  unsigned max_ssid = 1 << ste.dw0.s1cdmax;
1407  if (ssid >= max_ssid)
1408  panic("SSID %#x out of range, max=%#x", ssid, max_ssid);
1409 
1410  if (ste.dw0.s1fmt==STAGE1_CFG_2L_4K ||
1411  ste.dw0.s1fmt==STAGE1_CFG_2L_64K)
1412  {
1413  unsigned split = ste.dw0.s1fmt==STAGE1_CFG_2L_4K ? 7 : 11;
1414 
1415  uint64_t l2_ptr;
1416  uint64_t l2_addr = (ste.dw0.s1ctxptr << ST_CD_ADDR_SHIFT) +
1417  bits(ssid, 24, split) * sizeof(l2_ptr);
1418 
1419  if (context.stage2Enable)
1420  l2_addr = translateStage2(yield, l2_addr, false).addr;
1421 
1422  DPRINTF(SMMUv3, "Read L1CD at %#x\n", l2_addr);
1423 
1424  doReadConfig(yield, l2_addr, &l2_ptr, sizeof(l2_ptr), sid, ssid);
1425 
1426  DPRINTF(SMMUv3, "Got L1CD at %#x: 0x%016x\n", l2_addr, l2_ptr);
1427 
1428  cd_addr = l2_ptr + bits(ssid, split-1, 0) * sizeof(cd);
1429 
1430  smmu.cdL1Fetches++;
1431  } else if (ste.dw0.s1fmt == STAGE1_CFG_1L) {
1432  cd_addr = (ste.dw0.s1ctxptr << ST_CD_ADDR_SHIFT) + ssid*sizeof(cd);
1433  }
1434  }
1435 
1436  if (context.stage2Enable)
1437  cd_addr = translateStage2(yield, cd_addr, false).addr;
1438 
1439  DPRINTF(SMMUv3, "Read CD at %#x\n", cd_addr);
1440 
1441  doReadConfig(yield, cd_addr, &cd, sizeof(cd), sid, ssid);
1442 
1443  DPRINTF(SMMUv3, "Got CD at %#x [0]: 0x%016x\n", cd_addr, cd.dw0);
1444  DPRINTF(SMMUv3, " CD at %#x [1]: 0x%016x\n", cd_addr, cd.dw1);
1445  DPRINTF(SMMUv3, " CD at %#x [2]: 0x%016x\n", cd_addr, cd.dw2);
1446  DPRINTF(SMMUv3, " CD at %#x [3]: 0x%016x\n", cd_addr, cd.mair);
1447  DPRINTF(SMMUv3, " CD at %#x [4]: 0x%016x\n", cd_addr, cd.amair);
1448  DPRINTF(SMMUv3, " CD at %#x [5]: 0x%016x\n", cd_addr, cd._pad[0]);
1449  DPRINTF(SMMUv3, " CD at %#x [6]: 0x%016x\n", cd_addr, cd._pad[1]);
1450  DPRINTF(SMMUv3, " CD at %#x [7]: 0x%016x\n", cd_addr, cd._pad[2]);
1451 
1452 
1453  if (!cd.dw0.valid)
1454  panic("CD @ %#x not valid\n", cd_addr);
1455 
1456  smmu.cdFetches++;
1457 }
1458 
1459 void
1461  void *ptr, size_t size,
1462  uint32_t sid, uint32_t ssid)
1463 {
1464  doRead(yield, addr, ptr, size);
1465 }
1466 
1467 void
1469  void *ptr, unsigned stage,
1470  unsigned level)
1471 {
1472  size_t pte_size = sizeof(PageTableOps::pte_t);
1473 
1474  Addr mask = pte_size - 1;
1475  Addr base = addr & ~mask;
1476 
1477  doRead(yield, base, ptr, pte_size);
1478 }
SMMUSemaphore ifcSmmuSem
Definition: smmu_v3.hh:114
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
static SMMUTranslRequest prefetch(Addr addr, uint32_t sid, uint32_t ssid)
const Cycles tlbLat
Definition: smmu_v3.hh:126
#define DPRINTF(x,...)
Definition: trace.hh:222
IPACache ipaCache
Definition: smmu_v3.hh:99
void sendEvent(Yield &yield, const SMMUEvent &ev)
void ifcTLBUpdate(Yield &yield, const TranslResult &tr)
void store(const Entry &incoming, AllocPolicy alloc)
Bitfield< 30, 0 > index
void doDelay(Yield &yield, Cycles cycles)
void walkCacheLookup(Yield &yield, const WalkCache::Entry *&walkEntry, Addr addr, uint16_t asid, uint16_t vmid, unsigned stage, unsigned level)
Bitfield< 51, 4 > ttb0
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:81
SMMUSemaphore tlbSem
Definition: smmu_v3.hh:113
void doReadSTE(Yield &yield, StreamTableEntry &ste, uint32_t sid)
void completePrefetch(Yield &yield)
Stats::Scalar steFetches
Definition: smmu_v3.hh:135
Stats::Distribution translationTimeDist
Definition: smmu_v3.hh:138
const std::string & name()
Definition: trace.cc:50
void hazard4kHold(Yield &yield)
virtual void main(Yield &yield)
const Entry * lookup(uint32_t sid, uint32_t ssid, Addr va, bool updStats=true)
void smmuTLBUpdate(Yield &yield, const TranslResult &tr)
SMMUSemaphore ptwSem
Definition: smmu_v3.hh:122
const Entry * lookup(Addr ipa, uint16_t vmid, bool updStats=true)
SMMUSemaphore ipaSem
Definition: smmu_v3.hh:117
void store(const Entry &incoming)
void makeTimingResponse()
Definition: packet.hh:949
const Cycles smmuIfcLat
Definition: smmu_v3.hh:128
uint64_t _pad[4]
const Cycles ifcSmmuLat
Definition: smmu_v3.hh:127
uint64_t eventq_base
Bitfield< 8 > a
void hazardIdHold(Yield &yield)
virtual Addr index(Addr va, unsigned level) const =0
void doReadConfig(Yield &yield, Addr addr, void *ptr, size_t size, uint32_t sid, uint32_t ssid)
SMMUSignal dependentReqRemoved
ip6_addr_t addr
Definition: inet.hh:330
Bitfield< 7, 6 > tg0
Bitfield< 23 > span
void scheduleSlaveRetries()
Definition: smmu_v3.cc:211
const unsigned walkCacheS1Levels
Definition: smmu_v3.hh:109
const unsigned masterPortWidth
Definition: smmu_v3.hh:111
SMMUv3SlaveInterface * ifc
Definition: smmu_v3_proc.hh:70
Stats::Scalar steL1Fetches
Definition: smmu_v3.hh:134
uint64_t ipa
TranslResult translateStage1And2(Yield &yield, Addr addr)
TranslResult bypass(Addr addr) const
virtual Addr walkMask(unsigned level) const =0
bool microTLBLookup(Yield &yield, TranslResult &tr)
bool isWrite() const
Definition: packet.hh:523
void reinit()
Definition: smmu_v3_proc.cc:61
const bool tlbEnable
Definition: smmu_v3.hh:102
virtual bool isWritable(pte_t pte, unsigned level, bool stage2) const =0
void doBroadcastSignal(SMMUSignal &sig)
void walkCacheUpdate(Yield &yield, Addr va, Addr vaMask, Addr pa, unsigned stage, unsigned level, bool leaf, uint8_t permissions)
Stats::Scalar cdFetches
Definition: smmu_v3.hh:137
std::list< SMMUTranslationProcess * > dependentReads[SMMU_MAX_TRANS_ID]
std::list< SMMUTranslationProcess * > dependentWrites[SMMU_MAX_TRANS_ID]
bool smmuTLBLookup(Yield &yield, TranslResult &tr)
SMMUSemaphore microTLBSem
virtual unsigned lastLevel() const =0
PacketPtr pkt
Definition: smmu_v3_proc.hh:69
CallerType: A reference to an object of this class will be passed to the coroutine task...
Definition: coroutine.hh:83
uint16_t type
Stats::Scalar cdL1Fetches
Definition: smmu_v3.hh:136
const bool prefetchReserveLastWay
void hazardIdRegister()
Used to force ordering on transactions with the same orderId.
RequestPtr req
A pointer to the original request.
Definition: packet.hh:321
Bitfield< 51, 6 > s1ctxptr
void doRead(Yield &yield, Addr addr, void *ptr, size_t size)
Definition: smmu_v3_proc.cc:69
unsigned getSize() const
Definition: packet.hh:730
TranslResult combineTranslations(const TranslResult &s1tr, const TranslResult &s2tr) const
bool isAtomicMode() const
Is the system in atomic mode?
Definition: system.hh:131
Tick curTick()
The current simulated tick.
Definition: core.hh:44
void beginTransaction(const SMMUTranslRequest &req)
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
void doWrite(Yield &yield, Addr addr, const void *ptr, size_t size)
Definition: smmu_v3_proc.cc:98
virtual Addr nextLevelPointer(pte_t pte, unsigned level) const =0
TranslResult smmuTranslation(Yield &yield)
void makeAtomicResponse()
Definition: packet.hh:943
uint32_t eventq_prod
SMMUSemaphore transSem
Definition: smmu_v3.hh:121
const Cycles ipaLat
Definition: smmu_v3.hh:130
uint64_t Tick
Tick count type.
Definition: types.hh:61
Stats::Distribution ptwTimeDist
Definition: smmu_v3.hh:139
uint64_t strtab_base
uint64_t va
SMMUActionType type
Definition: smmu_v3_proc.hh:68
void doSemaphoreUp(SMMUSemaphore &sem)
void scheduleWakeup(Tick when)
SMMUTranslationProcess(const std::string &name, SMMUv3 &_smmu, SMMUv3SlaveInterface &_ifc)
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
SMMUSemaphore smmuIfcSem
Definition: smmu_v3.hh:115
Bitfield< 39, 12 > pa
virtual bool isValid(pte_t pte, unsigned level) const =0
const Entry * lookup(Addr va, uint16_t asid, uint16_t vmid, bool updStats=true)
Bitfield< 63, 48 > asid
const Cycles walkLat
Definition: smmu_v3.hh:131
Addr getAddr() const
Definition: packet.hh:720
static SMMUTranslRequest fromPacket(PacketPtr pkt, bool ats=false)
Bitfield< 5, 4 > s1fmt
void store(const Entry &incoming)
uint32_t strtab_base_cfg
STL list class.
Definition: stl.hh:51
void completeTransaction(Yield &yield, const TranslResult &tr)
WalkCache walkCache
Definition: smmu_v3.hh:100
Bitfield< 63, 59 > s1cdmax
Bitfield< 51, 4 > ttb1
virtual bool isLeaf(pte_t pte, unsigned level) const =0
SMMUSignal duplicateReqRemoved
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
SMMUSemaphore masterPortSem
Definition: smmu_v3.hh:119
static OrderID orderId(PacketPtr pkt)
Definition: amba.hh:49
#define ULL(N)
uint64_t constant
Definition: types.hh:48
void doReadCD(Yield &yield, ContextDescriptor &cd, const StreamTableEntry &ste, uint32_t sid, uint32_t ssid)
uint64_t eventq_irq_cfg0
Bitfield< 37, 32 > s2t0sz
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
Bitfield< 8 > va
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
void store(const Entry &incoming)
uint32_t substreamId
Tick M5_CLASS_VAR_USED faultTick
uint16_t stag
ARMArchTLB tlb
Definition: smmu_v3.hh:97
SMMUv3SlaveInterface & ifc
SMMUSemaphore configSem
Definition: smmu_v3.hh:116
Bitfield< 20 > level
Definition: intmessage.hh:47
uint32_t eventq_irq_cfg1
This is an implementation of the SMMUv3 architecture.
Bitfield< 9 > e
TranslResult walkStage1And2(Yield &yield, Addr addr, const PageTableOps *pt_ops, unsigned level, Addr walkPtr)
uint32_t eventq_cons
const Entry * lookup(uint32_t sid, uint32_t ssid, bool updStats=true)
bool ifcTLBLookup(Yield &yield, TranslResult &tr, bool &wasPrefetched)
SMMUv3 & smmu
void setAddr(Addr _addr)
Update the address of this packet mid-transaction.
Definition: packet.hh:728
TranslResult walkStage2(Yield &yield, Addr addr, bool final_tr, const PageTableOps *pt_ops, unsigned level, Addr walkPtr)
uint32_t cr0
SMMUAction runProcessTiming(SMMUProcess *proc, PacketPtr pkt)
Definition: smmu_v3.cc:280
SMMURegs regs
Definition: smmu_v3.hh:146
void doReadPTE(Yield &yield, Addr va, Addr addr, void *ptr, unsigned stage, unsigned level)
SMMUSemaphore walkSem
Definition: smmu_v3.hh:118
const System & system
Definition: smmu_v3.hh:90
void doWaitForSignal(Yield &yield, SMMUSignal &sig)
void store(const Entry &incoming)
const Entry * lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid, unsigned stage, unsigned level, bool updStats=true)
Bitfield< 47, 46 > s2tg
void issuePrefetch(Addr addr)
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:289
const unsigned portWidth
uint32_t streamId
const PageTableOps * getPageTableOps(uint8_t trans_granule)
Definition: smmu_v3.cc:564
const bool walkCacheNonfinalEnable
Definition: smmu_v3.hh:108
SMMUSemaphore cycleSem
Definition: smmu_v3.hh:123
std::enable_if<!std::is_same< T, void >::value, T >::type get()
get() is the way we can extrapolate arguments from the coroutine caller.
Definition: coroutine.hh:134
uint32_t flags
const bool walkCacheEnable
Definition: smmu_v3.hh:105
void doSemaphoreDown(Yield &yield, SMMUSemaphore &sem)
SMMUTranslRequest request
Bitfield< 3, 1 > config
Bitfield< 3, 0 > mask
Definition: types.hh:62
const bool ipaCacheEnable
Definition: smmu_v3.hh:104
void microTLBUpdate(Yield &yield, const TranslResult &tr)
const unsigned walkCacheS2Levels
Definition: smmu_v3.hh:110
Bitfield< 32 > cd
void configCacheUpdate(Yield &yield, const TranslContext &tc)
virtual ~SMMUTranslationProcess()
ConfigCache configCache
Definition: smmu_v3.hh:98
bool isTimingMode() const
Is the system in timing mode?
Definition: system.hh:142
bool configCacheLookup(Yield &yield, TranslContext &tc)
const std::string name() const
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71
SMMUSemaphore mainTLBSem
Bitfield< 31 > valid
const bool configCacheEnable
Definition: smmu_v3.hh:103
virtual Addr pageMask(pte_t pte, unsigned level) const =0
uint64_t _pad[3]
bool findConfig(Yield &yield, TranslContext &tc, TranslResult &tr)
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1896
std::list< SMMUTranslationProcess * > duplicateReqs
virtual unsigned firstLevel(uint8_t tsz) const =0
SMMUSemaphore slavePortSem
TranslResult translateStage2(Yield &yield, Addr addr, bool final_tr)
const Cycles configLat
Definition: smmu_v3.hh:129
bool hazard4kCheck()
Used to force ordering on transactions with same (SID, SSID, 4k page) to avoid multiple identical pag...

Generated on Mon Jun 8 2020 15:45:10 for gem5 by doxygen 1.8.13