c1d998ea0f2f2b8da4fb5a37dc2ca07c2f2fd295
2 * Copyright (c) 2013, 2018-2019 ARM Limited
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.
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.
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.
37 * Authors: Stan Czerniawski
40 #include "dev/arm/smmu_v3_transl.hh"
42 #include "debug/SMMUv3.hh"
43 #include "debug/SMMUv3Hazard.hh"
44 #include "dev/arm/amba.hh"
45 #include "dev/arm/smmu_v3.hh"
46 #include "sim/system.hh"
49 SMMUTranslRequest::fromPacket(PacketPtr pkt
, bool ats
)
51 SMMUTranslRequest req
;
52 req
.addr
= pkt
->getAddr();
53 req
.size
= pkt
->getSize();
54 req
.sid
= pkt
->req
->streamId();
55 req
.ssid
= pkt
->req
->hasSubstreamId() ?
56 pkt
->req
->substreamId() : 0;
57 req
.isWrite
= pkt
->isWrite();
58 req
.isPrefetch
= false;
59 req
.isAtsRequest
= ats
;
66 SMMUTranslRequest::prefetch(Addr addr
, uint32_t sid
, uint32_t ssid
)
68 SMMUTranslRequest req
;
74 req
.isPrefetch
= true;
75 req
.isAtsRequest
= false;
81 SMMUTranslationProcess::SMMUTranslationProcess(const std::string
&name
,
82 SMMUv3
&_smmu
, SMMUv3SlaveInterface
&_ifc
)
84 SMMUProcess(name
, _smmu
),
87 // Decrease number of pending translation slots on the slave interface
88 assert(ifc
.xlateSlotsRemaining
> 0);
89 ifc
.xlateSlotsRemaining
--;
93 SMMUTranslationProcess::~SMMUTranslationProcess()
95 // Increase number of pending translation slots on the slave interface
96 ifc
.xlateSlotsRemaining
++;
97 // If no more SMMU translations are pending (all slots available),
98 // signal SMMU Slave Interface as drained
99 if (ifc
.xlateSlotsRemaining
== ifc
.params()->xlate_slots
) {
100 ifc
.signalDrainDone();
105 SMMUTranslationProcess::beginTransaction(const SMMUTranslRequest
&req
)
113 SMMUTranslationProcess::resumeTransaction()
115 assert(smmu
.system
.isTimingMode());
117 assert(!"Stalls are broken");
119 Tick resumeTick
= curTick();
122 DPRINTF(SMMUv3
, "Resume at tick = %d. Fault duration = %d (%.3fus)\n",
123 resumeTick
, resumeTick
-faultTick
, (resumeTick
-faultTick
) / 1e6
);
125 beginTransaction(request
);
127 smmu
.runProcessTiming(this, request
.pkt
);
131 SMMUTranslationProcess::main(Yield
&yield
)
134 // The coroutine starts running as soon as it's created.
135 // But we need to wait for request data esp. in atomic mode.
137 a
.type
= ACTION_INITIAL_NOP
;
141 const Addr next4k
= (request
.addr
+ 0x1000ULL
) & ~0xfffULL
;
143 if ((request
.addr
+ request
.size
) > next4k
)
144 panic("Transaction crosses 4k boundary (addr=%#x size=%#x)!\n",
145 request
.addr
, request
.size
);
148 unsigned numSlaveBeats
= request
.isWrite
?
149 (request
.size
+ (ifc
.portWidth
- 1)) / ifc
.portWidth
: 1;
151 doSemaphoreDown(yield
, ifc
.slavePortSem
);
152 doDelay(yield
, Cycles(numSlaveBeats
));
153 doSemaphoreUp(ifc
.slavePortSem
);
156 recvTick
= curTick();
159 if (!(smmu
.regs
.cr0
& 0x1)) {
161 doDelay(yield
, Cycles(1));
162 completeTransaction(yield
, bypass(request
.addr
));
167 bool wasPrefetched
= false;
169 if (request
.isPrefetch
) {
170 // Abort prefetch if:
171 // - there's already a transaction looking up the same 4k page, OR
172 // - requested address is already in the TLB.
173 if (hazard4kCheck() || ifcTLBLookup(yield
, tr
, wasPrefetched
))
174 completePrefetch(yield
); // this never returns
178 tr
= smmuTranslation(yield
);
180 if (tr
.fault
== FAULT_NONE
)
181 ifcTLBUpdate(yield
, tr
);
185 completePrefetch(yield
);
189 if (!microTLBLookup(yield
, tr
)) {
190 bool hit
= ifcTLBLookup(yield
, tr
, wasPrefetched
);
192 while (!hit
&& hazard4kCheck()) {
194 hit
= ifcTLBLookup(yield
, tr
, wasPrefetched
);
198 // Issue prefetch if:
199 // - there was a TLB hit and the entry was prefetched, OR
200 // - TLB miss was successfully serviced
203 issuePrefetch(next4k
);
207 tr
= smmuTranslation(yield
);
209 if (tr
.fault
== FAULT_NONE
) {
210 ifcTLBUpdate(yield
, tr
);
212 issuePrefetch(next4k
);
218 if (tr
.fault
== FAULT_NONE
)
219 microTLBUpdate(yield
, tr
);
225 if (tr
.fault
!= FAULT_NONE
)
228 completeTransaction(yield
, tr
);
232 SMMUTranslationProcess::TranslResult
233 SMMUTranslationProcess::bypass(Addr addr
) const
236 tr
.fault
= FAULT_NONE
;
244 SMMUTranslationProcess::TranslResult
245 SMMUTranslationProcess::smmuTranslation(Yield
&yield
)
249 // Need SMMU credit to proceed
250 doSemaphoreDown(yield
, smmu
.transSem
);
252 // Simulate pipelined IFC->SMMU link
253 doSemaphoreDown(yield
, smmu
.ifcSmmuSem
);
254 doDelay(yield
, Cycles(1)); // serialize transactions
255 doSemaphoreUp(smmu
.ifcSmmuSem
);
256 doDelay(yield
, smmu
.ifcSmmuLat
- Cycles(1)); // remaining pipeline delay
258 bool haveConfig
= true;
259 if (!configCacheLookup(yield
, context
)) {
260 if(findConfig(yield
, context
, tr
)) {
261 configCacheUpdate(yield
, context
);
267 if (haveConfig
&& !smmuTLBLookup(yield
, tr
)) {
268 // SMMU main TLB miss
270 // Need PTW slot to proceed
271 doSemaphoreDown(yield
, smmu
.ptwSem
);
274 Tick ptwStartTick
= curTick();
276 if (context
.stage1Enable
) {
277 tr
= translateStage1And2(yield
, request
.addr
);
278 } else if (context
.stage2Enable
) {
279 tr
= translateStage2(yield
, request
.addr
, true);
281 tr
= bypass(request
.addr
);
284 if (context
.stage1Enable
|| context
.stage2Enable
)
285 smmu
.ptwTimeDist
.sample(curTick() - ptwStartTick
);
288 doSemaphoreUp(smmu
.ptwSem
);
290 if (tr
.fault
== FAULT_NONE
)
291 smmuTLBUpdate(yield
, tr
);
294 // Simulate pipelined SMMU->SLAVE INTERFACE link
295 doSemaphoreDown(yield
, smmu
.smmuIfcSem
);
296 doDelay(yield
, Cycles(1)); // serialize transactions
297 doSemaphoreUp(smmu
.smmuIfcSem
);
298 doDelay(yield
, smmu
.smmuIfcLat
- Cycles(1)); // remaining pipeline delay
300 // return SMMU credit
301 doSemaphoreUp(smmu
.transSem
);
307 SMMUTranslationProcess::microTLBLookup(Yield
&yield
, TranslResult
&tr
)
309 if (!ifc
.microTLBEnable
)
312 doSemaphoreDown(yield
, ifc
.microTLBSem
);
313 doDelay(yield
, ifc
.microTLBLat
);
314 const SMMUTLB::Entry
*e
=
315 ifc
.microTLB
->lookup(request
.sid
, request
.ssid
, request
.addr
);
316 doSemaphoreUp(ifc
.microTLBSem
);
319 DPRINTF(SMMUv3
, "micro TLB miss vaddr=%#x sid=%#x ssid=%#x\n",
320 request
.addr
, request
.sid
, request
.ssid
);
326 "micro TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x paddr=%#x\n",
327 request
.addr
, e
->vaMask
, request
.sid
, request
.ssid
, e
->pa
);
329 tr
.fault
= FAULT_NONE
;
330 tr
.addr
= e
->pa
+ (request
.addr
& ~e
->vaMask
);;
331 tr
.addrMask
= e
->vaMask
;
332 tr
.writable
= e
->permissions
;
338 SMMUTranslationProcess::ifcTLBLookup(Yield
&yield
, TranslResult
&tr
,
341 if (!ifc
.mainTLBEnable
)
344 doSemaphoreDown(yield
, ifc
.mainTLBSem
);
345 doDelay(yield
, ifc
.mainTLBLat
);
346 const SMMUTLB::Entry
*e
=
347 ifc
.mainTLB
->lookup(request
.sid
, request
.ssid
, request
.addr
);
348 doSemaphoreUp(ifc
.mainTLBSem
);
352 "SLAVE Interface TLB miss vaddr=%#x sid=%#x ssid=%#x\n",
353 request
.addr
, request
.sid
, request
.ssid
);
359 "SLAVE Interface TLB hit vaddr=%#x amask=%#x sid=%#x ssid=%#x "
360 "paddr=%#x\n", request
.addr
, e
->vaMask
, request
.sid
,
361 request
.ssid
, e
->pa
);
363 tr
.fault
= FAULT_NONE
;
364 tr
.addr
= e
->pa
+ (request
.addr
& ~e
->vaMask
);;
365 tr
.addrMask
= e
->vaMask
;
366 tr
.writable
= e
->permissions
;
367 wasPrefetched
= e
->prefetched
;
373 SMMUTranslationProcess::smmuTLBLookup(Yield
&yield
, TranslResult
&tr
)
378 doSemaphoreDown(yield
, smmu
.tlbSem
);
379 doDelay(yield
, smmu
.tlbLat
);
380 const ARMArchTLB::Entry
*e
=
381 smmu
.tlb
.lookup(request
.addr
, context
.asid
, context
.vmid
);
382 doSemaphoreUp(smmu
.tlbSem
);
385 DPRINTF(SMMUv3
, "SMMU TLB miss vaddr=%#x asid=%#x vmid=%#x\n",
386 request
.addr
, context
.asid
, context
.vmid
);
392 "SMMU TLB hit vaddr=%#x amask=%#x asid=%#x vmid=%#x paddr=%#x\n",
393 request
.addr
, e
->vaMask
, context
.asid
, context
.vmid
, e
->pa
);
395 tr
.fault
= FAULT_NONE
;
396 tr
.addr
= e
->pa
+ (request
.addr
& ~e
->vaMask
);;
397 tr
.addrMask
= e
->vaMask
;
398 tr
.writable
= e
->permissions
;
404 SMMUTranslationProcess::microTLBUpdate(Yield
&yield
,
405 const TranslResult
&tr
)
407 assert(tr
.fault
== FAULT_NONE
);
409 if (!ifc
.microTLBEnable
)
414 e
.prefetched
= false;
416 e
.ssid
= request
.ssid
;
417 e
.vaMask
= tr
.addrMask
;
418 e
.va
= request
.addr
& e
.vaMask
;
419 e
.pa
= tr
.addr
& e
.vaMask
;
420 e
.permissions
= tr
.writable
;
421 e
.asid
= context
.asid
;
422 e
.vmid
= context
.vmid
;
424 doSemaphoreDown(yield
, ifc
.microTLBSem
);
427 "micro TLB upd vaddr=%#x amask=%#x paddr=%#x sid=%#x ssid=%#x\n",
428 e
.va
, e
.vaMask
, e
.pa
, e
.sid
, e
.ssid
);
430 ifc
.microTLB
->store(e
, SMMUTLB::ALLOC_ANY_WAY
);
432 doSemaphoreUp(ifc
.microTLBSem
);
436 SMMUTranslationProcess::ifcTLBUpdate(Yield
&yield
,
437 const TranslResult
&tr
)
439 assert(tr
.fault
== FAULT_NONE
);
441 if (!ifc
.mainTLBEnable
)
446 e
.prefetched
= request
.isPrefetch
;
448 e
.ssid
= request
.ssid
;
449 e
.vaMask
= tr
.addrMask
;
450 e
.va
= request
.addr
& e
.vaMask
;
451 e
.pa
= tr
.addr
& e
.vaMask
;
452 e
.permissions
= tr
.writable
;
453 e
.asid
= context
.asid
;
454 e
.vmid
= context
.vmid
;
456 SMMUTLB::AllocPolicy alloc
= SMMUTLB::ALLOC_ANY_WAY
;
457 if (ifc
.prefetchEnable
&& ifc
.prefetchReserveLastWay
)
458 alloc
= request
.isPrefetch
?
459 SMMUTLB::ALLOC_LAST_WAY
: SMMUTLB::ALLOC_ANY_BUT_LAST_WAY
;
461 doSemaphoreDown(yield
, ifc
.mainTLBSem
);
464 "SLAVE Interface upd vaddr=%#x amask=%#x paddr=%#x sid=%#x "
465 "ssid=%#x\n", e
.va
, e
.vaMask
, e
.pa
, e
.sid
, e
.ssid
);
467 ifc
.mainTLB
->store(e
, alloc
);
469 doSemaphoreUp(ifc
.mainTLBSem
);
473 SMMUTranslationProcess::smmuTLBUpdate(Yield
&yield
,
474 const TranslResult
&tr
)
476 assert(tr
.fault
== FAULT_NONE
);
483 e
.vaMask
= tr
.addrMask
;
484 e
.va
= request
.addr
& e
.vaMask
;
485 e
.asid
= context
.asid
;
486 e
.vmid
= context
.vmid
;
487 e
.pa
= tr
.addr
& e
.vaMask
;
488 e
.permissions
= tr
.writable
;
490 doSemaphoreDown(yield
, smmu
.tlbSem
);
493 "SMMU TLB upd vaddr=%#x amask=%#x paddr=%#x asid=%#x vmid=%#x\n",
494 e
.va
, e
.vaMask
, e
.pa
, e
.asid
, e
.vmid
);
498 doSemaphoreUp(smmu
.tlbSem
);
502 SMMUTranslationProcess::configCacheLookup(Yield
&yield
, TranslContext
&tc
)
504 if (!smmu
.configCacheEnable
)
507 doSemaphoreDown(yield
, smmu
.configSem
);
508 doDelay(yield
, smmu
.configLat
);
509 const ConfigCache::Entry
*e
=
510 smmu
.configCache
.lookup(request
.sid
, request
.ssid
);
511 doSemaphoreUp(smmu
.configSem
);
514 DPRINTF(SMMUv3
, "Config miss sid=%#x ssid=%#x\n",
515 request
.sid
, request
.ssid
);
520 DPRINTF(SMMUv3
, "Config hit sid=%#x ssid=%#x ttb=%#08x asid=%#x\n",
521 request
.sid
, request
.ssid
, e
->ttb0
, e
->asid
);
523 tc
.stage1Enable
= e
->stage1_en
;
524 tc
.stage2Enable
= e
->stage2_en
;
532 tc
.stage1TranslGranule
= e
->stage1_tg
;
533 tc
.stage2TranslGranule
= e
->stage2_tg
;
536 tc
.s2t0sz
= e
->s2t0sz
;
542 SMMUTranslationProcess::configCacheUpdate(Yield
&yield
,
543 const TranslContext
&tc
)
545 if (!smmu
.configCacheEnable
)
548 ConfigCache::Entry e
;
551 e
.ssid
= request
.ssid
;
552 e
.stage1_en
= tc
.stage1Enable
;
553 e
.stage2_en
= tc
.stage2Enable
;
559 e
.stage1_tg
= tc
.stage1TranslGranule
;
560 e
.stage2_tg
= tc
.stage2TranslGranule
;
562 e
.s2t0sz
= tc
.s2t0sz
;
564 doSemaphoreDown(yield
, smmu
.configSem
);
566 DPRINTF(SMMUv3
, "Config upd sid=%#x ssid=%#x\n", e
.sid
, e
.ssid
);
568 smmu
.configCache
.store(e
);
570 doSemaphoreUp(smmu
.configSem
);
574 SMMUTranslationProcess::findConfig(Yield
&yield
,
578 tc
.stage1Enable
= false;
579 tc
.stage2Enable
= false;
581 StreamTableEntry ste
;
582 doReadSTE(yield
, ste
, request
.sid
);
584 switch (ste
.dw0
.config
) {
585 case STE_CONFIG_BYPASS
:
588 case STE_CONFIG_STAGE1_ONLY
:
589 tc
.stage1Enable
= true;
592 case STE_CONFIG_STAGE2_ONLY
:
593 tc
.stage2Enable
= true;
596 case STE_CONFIG_STAGE1_AND_2
:
597 tc
.stage1Enable
= true;
598 tc
.stage2Enable
= true;
602 panic("Bad or unimplemented STE config %d\n",
607 // Establish stage 2 context first since
608 // Context Descriptors can be in IPA space.
609 if (tc
.stage2Enable
) {
610 tc
.httb
= ste
.dw3
.s2ttb
<< STE_S2TTB_SHIFT
;
611 tc
.vmid
= ste
.dw2
.s2vmid
;
612 tc
.stage2TranslGranule
= ste
.dw2
.s2tg
;
613 tc
.s2t0sz
= ste
.dw2
.s2t0sz
;
615 tc
.httb
= 0xdeadbeef;
617 tc
.stage2TranslGranule
= TRANS_GRANULE_INVALID
;
622 // Now fetch stage 1 config.
623 if (context
.stage1Enable
) {
624 ContextDescriptor cd
;
625 doReadCD(yield
, cd
, ste
, request
.sid
, request
.ssid
);
627 tc
.ttb0
= cd
.dw1
.ttb0
<< CD_TTB_SHIFT
;
628 tc
.ttb1
= cd
.dw2
.ttb1
<< CD_TTB_SHIFT
;
629 tc
.asid
= cd
.dw0
.asid
;
630 tc
.stage1TranslGranule
= cd
.dw0
.tg0
;
631 tc
.t0sz
= cd
.dw0
.t0sz
;
633 tc
.ttb0
= 0xcafebabe;
634 tc
.ttb1
= 0xcafed00d;
636 tc
.stage1TranslGranule
= TRANS_GRANULE_INVALID
;
644 SMMUTranslationProcess::walkCacheLookup(
646 const WalkCache::Entry
*&walkEntry
,
647 Addr addr
, uint16_t asid
, uint16_t vmid
,
648 unsigned stage
, unsigned level
)
650 const char *indent
= stage
==2 ? " " : "";
651 (void) indent
; // this is only used in DPRINTFs
653 const PageTableOps
*pt_ops
=
655 smmu
.getPageTableOps(context
.stage1TranslGranule
) :
656 smmu
.getPageTableOps(context
.stage2TranslGranule
);
658 unsigned walkCacheLevels
=
659 smmu
.walkCacheEnable
?
660 (stage
== 1 ? smmu
.walkCacheS1Levels
: smmu
.walkCacheS2Levels
) :
663 if ((1 << level
) & walkCacheLevels
) {
664 doSemaphoreDown(yield
, smmu
.walkSem
);
665 doDelay(yield
, smmu
.walkLat
);
667 walkEntry
= smmu
.walkCache
.lookup(addr
, pt_ops
->walkMask(level
),
668 asid
, vmid
, stage
, level
);
671 DPRINTF(SMMUv3
, "%sWalkCache hit va=%#x asid=%#x vmid=%#x "
672 "base=%#x (S%d, L%d)\n",
673 indent
, addr
, asid
, vmid
, walkEntry
->pa
, stage
, level
);
675 DPRINTF(SMMUv3
, "%sWalkCache miss va=%#x asid=%#x vmid=%#x "
677 indent
, addr
, asid
, vmid
, stage
, level
);
680 doSemaphoreUp(smmu
.walkSem
);
685 SMMUTranslationProcess::walkCacheUpdate(Yield
&yield
, Addr va
,
686 Addr vaMask
, Addr pa
,
687 unsigned stage
, unsigned level
,
688 bool leaf
, uint8_t permissions
)
690 unsigned walkCacheLevels
=
691 stage
== 1 ? smmu
.walkCacheS1Levels
: smmu
.walkCacheS2Levels
;
693 if (smmu
.walkCacheEnable
&& ((1<<level
) & walkCacheLevels
)) {
698 e
.asid
= stage
==1 ? context
.asid
: 0;
699 e
.vmid
= context
.vmid
;
704 e
.permissions
= permissions
;
706 doSemaphoreDown(yield
, smmu
.walkSem
);
708 DPRINTF(SMMUv3
, "%sWalkCache upd va=%#x mask=%#x asid=%#x vmid=%#x "
709 "tpa=%#x leaf=%s (S%d, L%d)\n",
710 e
.stage
==2 ? " " : "",
711 e
.va
, e
.vaMask
, e
.asid
, e
.vmid
,
712 e
.pa
, e
.leaf
, e
.stage
, e
.level
);
714 smmu
.walkCache
.store(e
);
716 doSemaphoreUp(smmu
.walkSem
);
722 * This does not deal with the case where stage 1 page size
723 * is larger than stage 2 page size.
725 SMMUTranslationProcess::TranslResult
726 SMMUTranslationProcess::walkStage1And2(Yield
&yield
, Addr addr
,
727 const PageTableOps
*pt_ops
,
728 unsigned level
, Addr walkPtr
)
730 PageTableOps::pte_t pte
= 0;
732 doSemaphoreDown(yield
, smmu
.cycleSem
);
733 doDelay(yield
, Cycles(1));
734 doSemaphoreUp(smmu
.cycleSem
);
736 for (; level
<= pt_ops
->lastLevel(); level
++) {
737 Addr pte_addr
= walkPtr
+ pt_ops
->index(addr
, level
);
739 DPRINTF(SMMUv3
, "Fetching S1 L%d PTE from pa=%#08x\n",
742 doReadPTE(yield
, addr
, pte_addr
, &pte
, 1, level
);
744 DPRINTF(SMMUv3
, "Got S1 L%d PTE=%#x from pa=%#08x\n",
745 level
, pte
, pte_addr
);
747 doSemaphoreDown(yield
, smmu
.cycleSem
);
748 doDelay(yield
, Cycles(1));
749 doSemaphoreUp(smmu
.cycleSem
);
751 bool valid
= pt_ops
->isValid(pte
, level
);
752 bool leaf
= pt_ops
->isLeaf(pte
, level
);
755 DPRINTF(SMMUv3
, "S1 PTE not valid - fault\n");
758 tr
.fault
= FAULT_TRANSLATION
;
762 if (valid
&& leaf
&& request
.isWrite
&&
763 !pt_ops
->isWritable(pte
, level
, false))
765 DPRINTF(SMMUv3
, "S1 page not writable - fault\n");
768 tr
.fault
= FAULT_PERMISSION
;
772 walkPtr
= pt_ops
->nextLevelPointer(pte
, level
);
777 if (context
.stage2Enable
) {
778 TranslResult s2tr
= translateStage2(yield
, walkPtr
, false);
779 if (s2tr
.fault
!= FAULT_NONE
)
785 walkCacheUpdate(yield
, addr
, pt_ops
->walkMask(level
), walkPtr
,
790 tr
.fault
= FAULT_NONE
;
791 tr
.addrMask
= pt_ops
->pageMask(pte
, level
);
792 tr
.addr
= walkPtr
+ (addr
& ~tr
.addrMask
);
793 tr
.writable
= pt_ops
->isWritable(pte
, level
, false);
795 if (context
.stage2Enable
) {
796 TranslResult s2tr
= translateStage2(yield
, tr
.addr
, true);
797 if (s2tr
.fault
!= FAULT_NONE
)
800 tr
= combineTranslations(tr
, s2tr
);
803 walkCacheUpdate(yield
, addr
, tr
.addrMask
, tr
.addr
,
804 1, level
, true, tr
.writable
);
809 SMMUTranslationProcess::TranslResult
810 SMMUTranslationProcess::walkStage2(Yield
&yield
, Addr addr
, bool final_tr
,
811 const PageTableOps
*pt_ops
,
812 unsigned level
, Addr walkPtr
)
814 PageTableOps::pte_t pte
;
816 doSemaphoreDown(yield
, smmu
.cycleSem
);
817 doDelay(yield
, Cycles(1));
818 doSemaphoreUp(smmu
.cycleSem
);
820 for (; level
<= pt_ops
->lastLevel(); level
++) {
821 Addr pte_addr
= walkPtr
+ pt_ops
->index(addr
, level
);
823 DPRINTF(SMMUv3
, " Fetching S2 L%d PTE from pa=%#08x\n",
826 doReadPTE(yield
, addr
, pte_addr
, &pte
, 2, level
);
828 DPRINTF(SMMUv3
, " Got S2 L%d PTE=%#x from pa=%#08x\n",
829 level
, pte
, pte_addr
);
831 doSemaphoreDown(yield
, smmu
.cycleSem
);
832 doDelay(yield
, Cycles(1));
833 doSemaphoreUp(smmu
.cycleSem
);
835 bool valid
= pt_ops
->isValid(pte
, level
);
836 bool leaf
= pt_ops
->isLeaf(pte
, level
);
839 DPRINTF(SMMUv3
, " S2 PTE not valid - fault\n");
842 tr
.fault
= FAULT_TRANSLATION
;
846 if (valid
&& leaf
&& request
.isWrite
&&
847 !pt_ops
->isWritable(pte
, level
, true))
849 DPRINTF(SMMUv3
, " S2 PTE not writable = fault\n");
852 tr
.fault
= FAULT_PERMISSION
;
856 walkPtr
= pt_ops
->nextLevelPointer(pte
, level
);
858 if (final_tr
|| smmu
.walkCacheNonfinalEnable
)
859 walkCacheUpdate(yield
, addr
, pt_ops
->walkMask(level
), walkPtr
,
861 leaf
? pt_ops
->isWritable(pte
, level
, true) : 0);
867 tr
.fault
= FAULT_NONE
;
868 tr
.addrMask
= pt_ops
->pageMask(pte
, level
);
869 tr
.addr
= walkPtr
+ (addr
& ~tr
.addrMask
);
870 tr
.writable
= pt_ops
->isWritable(pte
, level
, true);
875 SMMUTranslationProcess::TranslResult
876 SMMUTranslationProcess::translateStage1And2(Yield
&yield
, Addr addr
)
878 const PageTableOps
*pt_ops
=
879 smmu
.getPageTableOps(context
.stage1TranslGranule
);
881 const WalkCache::Entry
*walk_ep
= NULL
;
884 // Level here is actually (level+1) so we can count down
885 // to 0 using unsigned int.
886 for (level
= pt_ops
->lastLevel() + 1;
887 level
> pt_ops
->firstLevel(context
.t0sz
);
890 walkCacheLookup(yield
, walk_ep
, addr
,
891 context
.asid
, context
.vmid
, 1, level
-1);
897 // Correct level (see above).
903 tr
.fault
= FAULT_NONE
;
904 tr
.addr
= walk_ep
->pa
+ (addr
& ~walk_ep
->vaMask
);
905 tr
.addrMask
= walk_ep
->vaMask
;
906 tr
.writable
= walk_ep
->permissions
;
908 tr
= walkStage1And2(yield
, addr
, pt_ops
, level
+1, walk_ep
->pa
);
911 Addr table_addr
= context
.ttb0
;
912 if (context
.stage2Enable
) {
913 TranslResult s2tr
= translateStage2(yield
, table_addr
, false);
914 if (s2tr
.fault
!= FAULT_NONE
)
917 table_addr
= s2tr
.addr
;
920 tr
= walkStage1And2(yield
, addr
, pt_ops
,
921 pt_ops
->firstLevel(context
.t0sz
),
925 if (tr
.fault
== FAULT_NONE
)
926 DPRINTF(SMMUv3
, "Translated vaddr %#x to paddr %#x\n", addr
, tr
.addr
);
931 SMMUTranslationProcess::TranslResult
932 SMMUTranslationProcess::translateStage2(Yield
&yield
, Addr addr
, bool final_tr
)
934 const PageTableOps
*pt_ops
=
935 smmu
.getPageTableOps(context
.stage2TranslGranule
);
937 const IPACache::Entry
*ipa_ep
= NULL
;
938 if (smmu
.ipaCacheEnable
) {
939 doSemaphoreDown(yield
, smmu
.ipaSem
);
940 doDelay(yield
, smmu
.ipaLat
);
941 ipa_ep
= smmu
.ipaCache
.lookup(addr
, context
.vmid
);
942 doSemaphoreUp(smmu
.ipaSem
);
947 tr
.fault
= FAULT_NONE
;
948 tr
.addr
= ipa_ep
->pa
+ (addr
& ~ipa_ep
->ipaMask
);
949 tr
.addrMask
= ipa_ep
->ipaMask
;
950 tr
.writable
= ipa_ep
->permissions
;
952 DPRINTF(SMMUv3
, " IPACache hit ipa=%#x vmid=%#x pa=%#x\n",
953 addr
, context
.vmid
, tr
.addr
);
956 } else if (smmu
.ipaCacheEnable
) {
957 DPRINTF(SMMUv3
, " IPACache miss ipa=%#x vmid=%#x\n",
961 const WalkCache::Entry
*walk_ep
= NULL
;
962 unsigned level
= pt_ops
->firstLevel(context
.s2t0sz
);
964 if (final_tr
|| smmu
.walkCacheNonfinalEnable
) {
965 // Level here is actually (level+1) so we can count down
966 // to 0 using unsigned int.
967 for (level
= pt_ops
->lastLevel() + 1;
968 level
> pt_ops
->firstLevel(context
.s2t0sz
);
971 walkCacheLookup(yield
, walk_ep
, addr
,
972 0, context
.vmid
, 2, level
-1);
978 // Correct level (see above).
985 tr
.fault
= FAULT_NONE
;
986 tr
.addr
= walk_ep
->pa
+ (addr
& ~walk_ep
->vaMask
);
987 tr
.addrMask
= walk_ep
->vaMask
;
988 tr
.writable
= walk_ep
->permissions
;
990 tr
= walkStage2(yield
, addr
, final_tr
, pt_ops
,
991 level
+ 1, walk_ep
->pa
);
994 tr
= walkStage2(yield
, addr
, final_tr
, pt_ops
,
995 pt_ops
->firstLevel(context
.s2t0sz
),
999 if (tr
.fault
== FAULT_NONE
)
1000 DPRINTF(SMMUv3
, " Translated %saddr %#x to paddr %#x\n",
1001 context
.stage1Enable
? "ip" : "v", addr
, tr
.addr
);
1003 if (smmu
.ipaCacheEnable
) {
1006 e
.ipaMask
= tr
.addrMask
;
1007 e
.ipa
= addr
& e
.ipaMask
;
1008 e
.pa
= tr
.addr
& tr
.addrMask
;
1009 e
.permissions
= tr
.writable
;
1010 e
.vmid
= context
.vmid
;
1012 doSemaphoreDown(yield
, smmu
.ipaSem
);
1013 smmu
.ipaCache
.store(e
);
1014 doSemaphoreUp(smmu
.ipaSem
);
1020 SMMUTranslationProcess::TranslResult
1021 SMMUTranslationProcess::combineTranslations(const TranslResult
&s1tr
,
1022 const TranslResult
&s2tr
) const
1024 if (s2tr
.fault
!= FAULT_NONE
)
1027 assert(s1tr
.fault
== FAULT_NONE
);
1030 tr
.fault
= FAULT_NONE
;
1031 tr
.addr
= s2tr
.addr
;
1032 tr
.addrMask
= s1tr
.addrMask
| s2tr
.addrMask
;
1033 tr
.writable
= s1tr
.writable
& s2tr
.writable
;
1039 SMMUTranslationProcess::hazard4kCheck()
1041 Addr addr4k
= request
.addr
& ~0xfffULL
;
1043 for (auto it
= ifc
.duplicateReqs
.begin();
1044 it
!= ifc
.duplicateReqs
.end();
1047 Addr other4k
= (*it
)->request
.addr
& ~0xfffULL
;
1048 if (addr4k
== other4k
)
1056 SMMUTranslationProcess::hazard4kRegister()
1058 DPRINTF(SMMUv3Hazard
, "4kReg: p=%p a4k=%#x\n",
1059 this, request
.addr
& ~0xfffULL
);
1061 ifc
.duplicateReqs
.push_back(this);
1065 SMMUTranslationProcess::hazard4kHold(Yield
&yield
)
1067 Addr addr4k
= request
.addr
& ~0xfffULL
;
1072 found_hazard
= false;
1074 for (auto it
= ifc
.duplicateReqs
.begin();
1075 it
!=ifc
.duplicateReqs
.end() && *it
!=this;
1078 Addr other4k
= (*it
)->request
.addr
& ~0xfffULL
;
1080 DPRINTF(SMMUv3Hazard
, "4kHold: p=%p a4k=%#x Q: p=%p a4k=%#x\n",
1081 this, addr4k
, *it
, other4k
);
1083 if (addr4k
== other4k
) {
1084 DPRINTF(SMMUv3Hazard
,
1085 "4kHold: p=%p a4k=%#x WAIT on p=%p a4k=%#x\n",
1086 this, addr4k
, *it
, other4k
);
1088 doWaitForSignal(yield
, ifc
.duplicateReqRemoved
);
1090 DPRINTF(SMMUv3Hazard
, "4kHold: p=%p a4k=%#x RESUME\n",
1093 // This is to avoid checking *it!=this after doWaitForSignal()
1094 // since it could have been deleted.
1095 found_hazard
= true;
1099 } while (found_hazard
);
1103 SMMUTranslationProcess::hazard4kRelease()
1105 DPRINTF(SMMUv3Hazard
, "4kRel: p=%p a4k=%#x\n",
1106 this, request
.addr
& ~0xfffULL
);
1108 std::list
<SMMUTranslationProcess
*>::iterator it
;
1110 for (it
= ifc
.duplicateReqs
.begin(); it
!= ifc
.duplicateReqs
.end(); ++it
)
1114 if (it
== ifc
.duplicateReqs
.end())
1115 panic("hazard4kRelease: request not found");
1117 ifc
.duplicateReqs
.erase(it
);
1119 doBroadcastSignal(ifc
.duplicateReqRemoved
);
1123 SMMUTranslationProcess::hazardIdRegister()
1125 auto orderId
= AMBA::orderId(request
.pkt
);
1127 DPRINTF(SMMUv3Hazard
, "IdReg: p=%p oid=%d\n", this, orderId
);
1129 assert(orderId
< SMMU_MAX_TRANS_ID
);
1131 std::list
<SMMUTranslationProcess
*> &depReqs
=
1133 ifc
.dependentWrites
[orderId
] : ifc
.dependentReads
[orderId
];
1134 depReqs
.push_back(this);
1138 SMMUTranslationProcess::hazardIdHold(Yield
&yield
)
1140 auto orderId
= AMBA::orderId(request
.pkt
);
1142 DPRINTF(SMMUv3Hazard
, "IdHold: p=%p oid=%d\n", this, orderId
);
1144 std::list
<SMMUTranslationProcess
*> &depReqs
=
1146 ifc
.dependentWrites
[orderId
] : ifc
.dependentReads
[orderId
];
1147 std::list
<SMMUTranslationProcess
*>::iterator it
;
1152 found_hazard
= false;
1154 for (auto it
= depReqs
.begin(); it
!=depReqs
.end() && *it
!=this; ++it
) {
1155 DPRINTF(SMMUv3Hazard
, "IdHold: p=%p oid=%d Q: %p\n",
1156 this, orderId
, *it
);
1158 if (AMBA::orderId((*it
)->request
.pkt
) == orderId
) {
1159 DPRINTF(SMMUv3Hazard
, "IdHold: p=%p oid=%d WAIT on=%p\n",
1160 this, orderId
, *it
);
1162 doWaitForSignal(yield
, ifc
.dependentReqRemoved
);
1164 DPRINTF(SMMUv3Hazard
, "IdHold: p=%p oid=%d RESUME\n",
1167 // This is to avoid checking *it!=this after doWaitForSignal()
1168 // since it could have been deleted.
1169 found_hazard
= true;
1173 } while (found_hazard
);
1177 SMMUTranslationProcess::hazardIdRelease()
1179 auto orderId
= AMBA::orderId(request
.pkt
);
1181 DPRINTF(SMMUv3Hazard
, "IdRel: p=%p oid=%d\n", this, orderId
);
1183 std::list
<SMMUTranslationProcess
*> &depReqs
=
1185 ifc
.dependentWrites
[orderId
] : ifc
.dependentReads
[orderId
];
1186 std::list
<SMMUTranslationProcess
*>::iterator it
;
1188 for (it
= depReqs
.begin(); it
!= depReqs
.end(); ++it
) {
1193 if (it
== depReqs
.end())
1194 panic("hazardIdRelease: request not found");
1198 doBroadcastSignal(ifc
.dependentReqRemoved
);
1202 SMMUTranslationProcess::issuePrefetch(Addr addr
)
1204 if (!smmu
.system
.isTimingMode())
1207 if (!ifc
.prefetchEnable
|| ifc
.xlateSlotsRemaining
== 0)
1210 std::string proc_name
= csprintf("%sprf", name());
1211 SMMUTranslationProcess
*proc
=
1212 new SMMUTranslationProcess(proc_name
, smmu
, ifc
);
1214 proc
->beginTransaction(
1215 SMMUTranslRequest::prefetch(addr
, request
.sid
, request
.ssid
));
1216 proc
->scheduleWakeup(smmu
.clockEdge(Cycles(1)));
1220 SMMUTranslationProcess::completeTransaction(Yield
&yield
,
1221 const TranslResult
&tr
)
1223 assert(tr
.fault
== FAULT_NONE
);
1225 unsigned numMasterBeats
= request
.isWrite
?
1226 (request
.size
+ (smmu
.masterPortWidth
-1))
1227 / smmu
.masterPortWidth
:
1230 doSemaphoreDown(yield
, smmu
.masterPortSem
);
1231 doDelay(yield
, Cycles(numMasterBeats
));
1232 doSemaphoreUp(smmu
.masterPortSem
);
1235 smmu
.translationTimeDist
.sample(curTick() - recvTick
);
1236 if (!request
.isAtsRequest
&& request
.isWrite
)
1237 ifc
.wrBufSlotsRemaining
+=
1238 (request
.size
+ (ifc
.portWidth
-1)) / ifc
.portWidth
;
1240 smmu
.scheduleSlaveRetries();
1245 if (request
.isAtsRequest
) {
1246 a
.type
= ACTION_SEND_RESP_ATS
;
1248 if (smmu
.system
.isAtomicMode()) {
1249 request
.pkt
->makeAtomicResponse();
1250 } else if (smmu
.system
.isTimingMode()) {
1251 request
.pkt
->makeTimingResponse();
1253 panic("Not in atomic or timing mode");
1256 a
.type
= ACTION_SEND_REQ_FINAL
;
1260 a
.pkt
= request
.pkt
;
1263 a
.pkt
->setAddr(tr
.addr
);
1264 a
.pkt
->req
->setPaddr(tr
.addr
);
1268 if (!request
.isAtsRequest
) {
1269 PacketPtr pkt
= yield
.get();
1270 pkt
->setAddr(request
.addr
);
1272 a
.type
= ACTION_SEND_RESP
;
1281 SMMUTranslationProcess::completePrefetch(Yield
&yield
)
1284 a
.type
= ACTION_TERMINATE
;
1292 SMMUTranslationProcess::sendEvent(Yield
&yield
, const SMMUEvent
&ev
)
1294 int sizeMask
= mask(smmu
.regs
.eventq_base
& Q_BASE_SIZE_MASK
);
1296 if (((smmu
.regs
.eventq_prod
+1) & sizeMask
) ==
1297 (smmu
.regs
.eventq_cons
& sizeMask
))
1298 panic("Event queue full - aborting\n");
1301 (smmu
.regs
.eventq_base
& Q_BASE_ADDR_MASK
) +
1302 (smmu
.regs
.eventq_prod
& sizeMask
) * sizeof(ev
);
1304 DPRINTF(SMMUv3
, "Sending event to addr=%#08x (pos=%d): type=%#x stag=%#x "
1305 "flags=%#x sid=%#x ssid=%#x va=%#08x ipa=%#x\n",
1306 event_addr
, smmu
.regs
.eventq_prod
, ev
.type
, ev
.stag
,
1307 ev
.flags
, ev
.streamId
, ev
.substreamId
, ev
.va
, ev
.ipa
);
1309 // This deliberately resets the overflow field in eventq_prod!
1310 smmu
.regs
.eventq_prod
= (smmu
.regs
.eventq_prod
+ 1) & sizeMask
;
1312 doWrite(yield
, event_addr
, &ev
, sizeof(ev
));
1314 if (!(smmu
.regs
.eventq_irq_cfg0
& E_BASE_ENABLE_MASK
))
1315 panic("eventq msi not enabled\n");
1317 doWrite(yield
, smmu
.regs
.eventq_irq_cfg0
& E_BASE_ADDR_MASK
,
1318 &smmu
.regs
.eventq_irq_cfg1
, sizeof(smmu
.regs
.eventq_irq_cfg1
));
1322 SMMUTranslationProcess::doReadSTE(Yield
&yield
,
1323 StreamTableEntry
&ste
,
1326 unsigned max_sid
= 1 << (smmu
.regs
.strtab_base_cfg
& ST_CFG_SIZE_MASK
);
1328 panic("SID %#x out of range, max=%#x", sid
, max_sid
);
1332 if ((smmu
.regs
.strtab_base_cfg
& ST_CFG_FMT_MASK
) == ST_CFG_FMT_2LEVEL
) {
1334 (smmu
.regs
.strtab_base_cfg
& ST_CFG_SPLIT_MASK
) >> ST_CFG_SPLIT_SHIFT
;
1336 if (split
!= 7 && split
!=8 && split
!=16)
1337 panic("Invalid stream table split %d", split
);
1341 (smmu
.regs
.strtab_base
& VMT_BASE_ADDR_MASK
) +
1342 bits(sid
, 32, split
) * sizeof(l2_ptr
);
1344 DPRINTF(SMMUv3
, "Read L1STE at %#x\n", l2_addr
);
1346 doReadConfig(yield
, l2_addr
, &l2_ptr
, sizeof(l2_ptr
), sid
, 0);
1348 DPRINTF(SMMUv3
, "Got L1STE L1 at %#x: 0x%016x\n", l2_addr
, l2_ptr
);
1350 unsigned span
= l2_ptr
& ST_L2_SPAN_MASK
;
1352 panic("Invalid level 1 stream table descriptor");
1354 unsigned index
= bits(sid
, split
-1, 0);
1355 if (index
>= (1 << span
))
1356 panic("StreamID %d out of level 1 descriptor range %d",
1359 ste_addr
= (l2_ptr
& ST_L2_ADDR_MASK
) + index
* sizeof(ste
);
1361 smmu
.steL1Fetches
++;
1362 } else if ((smmu
.regs
.strtab_base_cfg
& ST_CFG_FMT_MASK
) == ST_CFG_FMT_LINEAR
) {
1364 (smmu
.regs
.strtab_base
& VMT_BASE_ADDR_MASK
) + sid
* sizeof(ste
);
1366 panic("Invalid stream table format");
1369 DPRINTF(SMMUv3
, "Read STE at %#x\n", ste_addr
);
1371 doReadConfig(yield
, ste_addr
, &ste
, sizeof(ste
), sid
, 0);
1373 DPRINTF(SMMUv3
, "Got STE at %#x [0]: 0x%016x\n", ste_addr
, ste
.dw0
);
1374 DPRINTF(SMMUv3
, " STE at %#x [1]: 0x%016x\n", ste_addr
, ste
.dw1
);
1375 DPRINTF(SMMUv3
, " STE at %#x [2]: 0x%016x\n", ste_addr
, ste
.dw2
);
1376 DPRINTF(SMMUv3
, " STE at %#x [3]: 0x%016x\n", ste_addr
, ste
.dw3
);
1377 DPRINTF(SMMUv3
, " STE at %#x [4]: 0x%016x\n", ste_addr
, ste
._pad
[0]);
1378 DPRINTF(SMMUv3
, " STE at %#x [5]: 0x%016x\n", ste_addr
, ste
._pad
[1]);
1379 DPRINTF(SMMUv3
, " STE at %#x [6]: 0x%016x\n", ste_addr
, ste
._pad
[2]);
1380 DPRINTF(SMMUv3
, " STE at %#x [7]: 0x%016x\n", ste_addr
, ste
._pad
[3]);
1383 panic("STE @ %#x not valid\n", ste_addr
);
1389 SMMUTranslationProcess::doReadCD(Yield
&yield
,
1390 ContextDescriptor
&cd
,
1391 const StreamTableEntry
&ste
,
1392 uint32_t sid
, uint32_t ssid
)
1396 if (ste
.dw0
.s1cdmax
== 0) {
1397 cd_addr
= ste
.dw0
.s1ctxptr
<< ST_CD_ADDR_SHIFT
;
1399 unsigned max_ssid
= 1 << ste
.dw0
.s1cdmax
;
1400 if (ssid
>= max_ssid
)
1401 panic("SSID %#x out of range, max=%#x", ssid
, max_ssid
);
1403 if (ste
.dw0
.s1fmt
==STAGE1_CFG_2L_4K
||
1404 ste
.dw0
.s1fmt
==STAGE1_CFG_2L_64K
)
1406 unsigned split
= ste
.dw0
.s1fmt
==STAGE1_CFG_2L_4K
? 7 : 11;
1409 uint64_t l2_addr
= (ste
.dw0
.s1ctxptr
<< ST_CD_ADDR_SHIFT
) +
1410 bits(ssid
, 24, split
) * sizeof(l2_ptr
);
1412 if (context
.stage2Enable
)
1413 l2_addr
= translateStage2(yield
, l2_addr
, false).addr
;
1415 DPRINTF(SMMUv3
, "Read L1CD at %#x\n", l2_addr
);
1417 doReadConfig(yield
, l2_addr
, &l2_ptr
, sizeof(l2_ptr
), sid
, ssid
);
1419 DPRINTF(SMMUv3
, "Got L1CD at %#x: 0x%016x\n", l2_addr
, l2_ptr
);
1421 cd_addr
= l2_ptr
+ bits(ssid
, split
-1, 0) * sizeof(cd
);
1424 } else if (ste
.dw0
.s1fmt
== STAGE1_CFG_1L
) {
1425 cd_addr
= (ste
.dw0
.s1ctxptr
<< ST_CD_ADDR_SHIFT
) + ssid
*sizeof(cd
);
1429 if (context
.stage2Enable
)
1430 cd_addr
= translateStage2(yield
, cd_addr
, false).addr
;
1432 DPRINTF(SMMUv3
, "Read CD at %#x\n", cd_addr
);
1434 doReadConfig(yield
, cd_addr
, &cd
, sizeof(cd
), sid
, ssid
);
1436 DPRINTF(SMMUv3
, "Got CD at %#x [0]: 0x%016x\n", cd_addr
, cd
.dw0
);
1437 DPRINTF(SMMUv3
, " CD at %#x [1]: 0x%016x\n", cd_addr
, cd
.dw1
);
1438 DPRINTF(SMMUv3
, " CD at %#x [2]: 0x%016x\n", cd_addr
, cd
.dw2
);
1439 DPRINTF(SMMUv3
, " CD at %#x [3]: 0x%016x\n", cd_addr
, cd
.mair
);
1440 DPRINTF(SMMUv3
, " CD at %#x [4]: 0x%016x\n", cd_addr
, cd
.amair
);
1441 DPRINTF(SMMUv3
, " CD at %#x [5]: 0x%016x\n", cd_addr
, cd
._pad
[0]);
1442 DPRINTF(SMMUv3
, " CD at %#x [6]: 0x%016x\n", cd_addr
, cd
._pad
[1]);
1443 DPRINTF(SMMUv3
, " CD at %#x [7]: 0x%016x\n", cd_addr
, cd
._pad
[2]);
1447 panic("CD @ %#x not valid\n", cd_addr
);
1453 SMMUTranslationProcess::doReadConfig(Yield
&yield
, Addr addr
,
1454 void *ptr
, size_t size
,
1455 uint32_t sid
, uint32_t ssid
)
1457 doRead(yield
, addr
, ptr
, size
);
1461 SMMUTranslationProcess::doReadPTE(Yield
&yield
, Addr va
, Addr addr
,
1462 void *ptr
, unsigned stage
,
1465 size_t pte_size
= sizeof(PageTableOps::pte_t
);
1467 Addr mask
= pte_size
- 1;
1468 Addr base
= addr
& ~mask
;
1470 doRead(yield
, base
, ptr
, pte_size
);