gem5 v24.0.0.0
Loading...
Searching...
No Matches
smmu_v3.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013, 2018-2020, 2024 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
38#include "dev/arm/smmu_v3.hh"
39
40#include <cstddef>
41#include <cstring>
42
43#include "base/bitfield.hh"
44#include "base/cast.hh"
45#include "base/compiler.hh"
46#include "base/logging.hh"
47#include "base/trace.hh"
48#include "base/types.hh"
49#include "debug/Checkpoint.hh"
50#include "debug/SMMUv3.hh"
51#include "dev/arm/base_gic.hh"
53#include "mem/packet_access.hh"
54#include "sim/system.hh"
55
56namespace gem5
57{
58
59SMMUv3::SMMUv3(const SMMUv3Params &params) :
60 ClockedObject(params),
61 system(*params.system),
62 requestorId(params.system->getRequestorId(this)),
63 requestPort(name() + ".request", *this),
64 tableWalkPort(name() + ".walker", *this),
65 controlPort(name() + ".control", *this, params.reg_map),
66 eventqInterrupt(params.eventq_irq ? params.eventq_irq->get() : nullptr),
67 tlb(params.tlb_entries, params.tlb_assoc, params.tlb_policy, this),
68 configCache(params.cfg_entries, params.cfg_assoc, params.cfg_policy, this),
69 ipaCache(params.ipa_entries, params.ipa_assoc, params.ipa_policy, this),
70 walkCache({ { params.walk_S1L0, params.walk_S1L1,
71 params.walk_S1L2, params.walk_S1L3,
72 params.walk_S2L0, params.walk_S2L1,
73 params.walk_S2L2, params.walk_S2L3 } },
74 params.walk_assoc, params.walk_policy, this),
75 tlbEnable(params.tlb_enable),
76 configCacheEnable(params.cfg_enable),
77 ipaCacheEnable(params.ipa_enable),
78 walkCacheEnable(params.walk_enable),
79 tableWalkPortEnable(false),
80 walkCacheNonfinalEnable(params.wc_nonfinal_enable),
81 walkCacheS1Levels(params.wc_s1_levels),
82 walkCacheS2Levels(params.wc_s2_levels),
83 requestPortWidth(params.request_port_width),
84 tlbSem(params.tlb_slots),
85 ifcSmmuSem(1),
86 smmuIfcSem(1),
87 configSem(params.cfg_slots),
88 ipaSem(params.ipa_slots),
89 walkSem(params.walk_slots),
90 requestPortSem(1),
91 transSem(params.xlate_slots),
92 ptwSem(params.ptw_slots),
93 cycleSem(1),
94 tlbLat(params.tlb_lat),
95 ifcSmmuLat(params.ifc_smmu_lat),
96 smmuIfcLat(params.smmu_ifc_lat),
97 configLat(params.cfg_lat),
98 ipaLat(params.ipa_lat),
99 walkLat(params.walk_lat),
100 stats(this),
101 deviceInterfaces(params.device_interfaces),
102 commandExecutor(name() + ".cmd_exec", *this),
103 regsMap(params.reg_map),
104 processCommandsEvent(*this)
105{
106 fatal_if(regsMap.size() != SMMU_REG_SIZE,
107 "Invalid register map size: %#x different than SMMU_REG_SIZE = %#x\n",
108 regsMap.size(), SMMU_REG_SIZE);
109
110 // Init smmu registers to 0
111 memset(&regs, 0, sizeof(regs));
112
113 // Setup RO ID registers
114 regs.idr0 = params.smmu_idr0;
115 regs.idr1 = params.smmu_idr1;
116 regs.idr2 = params.smmu_idr2;
117 regs.idr3 = params.smmu_idr3;
118 regs.idr4 = params.smmu_idr4;
119 regs.idr5 = params.smmu_idr5;
120 regs.iidr = params.smmu_iidr;
121 regs.aidr = params.smmu_aidr;
122
123 // TODO: At the moment it possible to set the ID registers to hold
124 // any possible value. It would be nice to have a sanity check here
125 // at construction time in case some idx registers are programmed to
126 // store an unallowed values or if the are configuration conflicts.
127 warn("SMMUv3 IDx register values unchecked\n");
128
129 for (auto ifc : deviceInterfaces)
130 ifc->setSMMU(this);
131}
132
133bool
135{
136 DPRINTF(SMMUv3, "[t] requestor resp addr=%#x size=%#x\n",
137 pkt->getAddr(), pkt->getSize());
138
139 // @todo: We need to pay for this and not just zero it out
140 pkt->headerDelay = pkt->payloadDelay = 0;
141
142 SMMUProcess *proc =
144
145 runProcessTiming(proc, pkt);
146
147 return true;
148}
149
150void
152{
153 assert(!packetsToRetry.empty());
154
155 while (!packetsToRetry.empty()) {
156 SMMUAction a = packetsToRetry.front();
157
158 assert(a.type==ACTION_SEND_REQ || a.type==ACTION_SEND_REQ_FINAL);
159
160 DPRINTF(SMMUv3, "[t] requestor retr addr=%#x size=%#x\n",
161 a.pkt->getAddr(), a.pkt->getSize());
162
163 if (!requestPort.sendTimingReq(a.pkt))
164 break;
165
166 packetsToRetry.pop();
167
168 /*
169 * ACTION_SEND_REQ_FINAL means that we have just forwarded the packet
170 * on the requestor interface; this means that we no longer hold on to
171 * that transaction and therefore can accept a new one.
172 * If the response port was stalled then unstall it (send retry).
173 */
174 if (a.type == ACTION_SEND_REQ_FINAL)
176 }
177}
178
179bool
181{
182 DPRINTF(SMMUv3, "[t] requestor HWTW resp addr=%#x size=%#x\n",
183 pkt->getAddr(), pkt->getSize());
184
185 // @todo: We need to pay for this and not just zero it out
186 pkt->headerDelay = pkt->payloadDelay = 0;
187
188 SMMUProcess *proc =
190
191 runProcessTiming(proc, pkt);
192
193 return true;
194}
195
196void
198{
199 assert(tableWalkPortEnable);
200 assert(!packetsTableWalkToRetry.empty());
201
202 while (!packetsTableWalkToRetry.empty()) {
204
205 assert(a.type==ACTION_SEND_REQ);
206
207 DPRINTF(SMMUv3, "[t] requestor HWTW retr addr=%#x size=%#x\n",
208 a.pkt->getAddr(), a.pkt->getSize());
209
210 if (!tableWalkPort.sendTimingReq(a.pkt))
211 break;
212
214 }
215}
216
217void
219{
220 for (auto ifc : deviceInterfaces) {
221 ifc->scheduleDeviceRetry();
222 }
223}
224
227{
228 if (system.isAtomicMode()) {
229 return runProcessAtomic(proc, pkt);
230 } else if (system.isTimingMode()) {
231 return runProcessTiming(proc, pkt);
232 } else {
233 panic("Not in timing or atomic mode!");
234 }
235}
236
239{
240 SMMUAction action;
241 Tick delay = 0;
242 bool finished = false;
243
244 do {
245 action = proc->run(pkt);
246
247 switch (action.type) {
248 case ACTION_SEND_REQ:
249 // Send an MMU initiated request on the table walk port if
250 // it is enabled. Otherwise, fall through and handle same
251 // as the final ACTION_SEND_REQ_FINAL request.
253 delay += tableWalkPort.sendAtomic(action.pkt);
254 pkt = action.pkt;
255 break;
256 }
257 [[fallthrough]];
259 delay += requestPort.sendAtomic(action.pkt);
260 pkt = action.pkt;
261 break;
262
263 case ACTION_SEND_RESP:
265 case ACTION_SLEEP:
266 finished = true;
267 break;
268
269 case ACTION_DELAY:
270 delay += action.delay;
271 break;
272
273 case ACTION_TERMINATE:
274 panic("ACTION_TERMINATE in atomic mode\n");
275
276 default:
277 panic("Unknown action\n");
278 }
279 } while (!finished);
280
281 action.delay = delay;
282
283 return action;
284}
285
288{
289 SMMUAction action = proc->run(pkt);
290
291 switch (action.type) {
292 case ACTION_SEND_REQ:
293 // Send an MMU initiated request on the table walk port if it is
294 // enabled. Otherwise, fall through and handle same as the final
295 // ACTION_SEND_REQ_FINAL request.
297 action.pkt->pushSenderState(proc);
298
299 DPRINTF(SMMUv3, "[t] requestor HWTW req addr=%#x size=%#x\n",
300 action.pkt->getAddr(), action.pkt->getSize());
301
302 if (packetsTableWalkToRetry.empty()
303 && tableWalkPort.sendTimingReq(action.pkt)) {
305 } else {
306 DPRINTF(SMMUv3, "[t] requestor HWTW req needs retry,"
307 " qlen=%d\n", packetsTableWalkToRetry.size());
308 packetsTableWalkToRetry.push(action);
309 }
310
311 break;
312 }
313 [[fallthrough]];
315 action.pkt->pushSenderState(proc);
316
317 DPRINTF(SMMUv3, "[t] requestor req addr=%#x size=%#x\n",
318 action.pkt->getAddr(), action.pkt->getSize());
319
320 if (packetsToRetry.empty() &&
321 requestPort.sendTimingReq(action.pkt)) {
323 } else {
324 DPRINTF(SMMUv3, "[t] requestor req needs retry, qlen=%d\n",
325 packetsToRetry.size());
326 packetsToRetry.push(action);
327 }
328
329 break;
330
331 case ACTION_SEND_RESP:
332 // @todo: We need to pay for this and not just zero it out
333 action.pkt->headerDelay = action.pkt->payloadDelay = 0;
334
335 DPRINTF(SMMUv3, "[t] responder resp addr=%#x size=%#x\n",
336 action.pkt->getAddr(),
337 action.pkt->getSize());
338
339 assert(action.ifc);
340 action.ifc->schedTimingResp(action.pkt);
341
342 delete proc;
343 break;
344
346 // @todo: We need to pay for this and not just zero it out
347 action.pkt->headerDelay = action.pkt->payloadDelay = 0;
348
349 DPRINTF(SMMUv3, "[t] ATS responder resp addr=%#x size=%#x\n",
350 action.pkt->getAddr(), action.pkt->getSize());
351
352 assert(action.ifc);
353 action.ifc->schedAtsTimingResp(action.pkt);
354
355 delete proc;
356 break;
357
358 case ACTION_DELAY:
359 case ACTION_SLEEP:
360 break;
361
362 case ACTION_TERMINATE:
363 delete proc;
364 break;
365
366 default:
367 panic("Unknown action\n");
368 }
369
370 return action;
371}
372
373void
375{
376 DPRINTF(SMMUv3, "processCommands()\n");
377
378 if (system.isAtomicMode()) {
380 (void) a;
381 } else if (system.isTimingMode()) {
382 if (!commandExecutor.isBusy())
384 } else {
385 panic("Not in timing or atomic mode!");
386 }
387}
388
389void
391{
392 switch (cmd.dw0.type) {
393 case CMD_PRF_CONFIG:
394 DPRINTF(SMMUv3, "CMD_PREFETCH_CONFIG - ignored\n");
395 break;
396
397 case CMD_PRF_ADDR:
398 DPRINTF(SMMUv3, "CMD_PREFETCH_ADDR - ignored\n");
399 break;
400
401 case CMD_CFGI_STE: {
402 DPRINTF(SMMUv3, "CMD_CFGI_STE sid=%#x\n", cmd.dw0.sid);
404
405 for (auto dev_interface : deviceInterfaces) {
406 dev_interface->microTLB->invalidateSID(cmd.dw0.sid);
407 dev_interface->mainTLB->invalidateSID(cmd.dw0.sid);
408 }
409 break;
410 }
411
412 case CMD_CFGI_STE_RANGE: {
413 const auto range = cmd.dw1.range;
414 if (range == 31) {
415 // CMD_CFGI_ALL is an alias of CMD_CFGI_STE_RANGE with
416 // range = 31
417 DPRINTF(SMMUv3, "CMD_CFGI_ALL\n");
419
420 for (auto dev_interface : deviceInterfaces) {
421 dev_interface->microTLB->invalidateAll();
422 dev_interface->mainTLB->invalidateAll();
423 }
424 } else {
425 DPRINTF(SMMUv3, "CMD_CFGI_STE_RANGE\n");
426 const auto start_sid = cmd.dw0.sid & ~((1 << (range + 1)) - 1);
427 const auto end_sid = start_sid + (1 << (range + 1)) - 1;
428 for (auto sid = start_sid; sid <= end_sid; sid++) {
430
431 for (auto dev_interface : deviceInterfaces) {
432 dev_interface->microTLB->invalidateSID(sid);
433 dev_interface->mainTLB->invalidateSID(sid);
434 }
435 }
436 }
437 break;
438 }
439
440 case CMD_CFGI_CD: {
441 DPRINTF(SMMUv3, "CMD_CFGI_CD sid=%#x ssid=%#x\n",
442 cmd.dw0.sid, cmd.dw0.ssid);
443 configCache.invalidateSSID(cmd.dw0.sid, cmd.dw0.ssid);
444
445 for (auto dev_interface : deviceInterfaces) {
446 dev_interface->microTLB->invalidateSSID(
447 cmd.dw0.sid, cmd.dw0.ssid);
448 dev_interface->mainTLB->invalidateSSID(
449 cmd.dw0.sid, cmd.dw0.ssid);
450 }
451 break;
452 }
453
454 case CMD_CFGI_CD_ALL: {
455 DPRINTF(SMMUv3, "CMD_CFGI_CD_ALL sid=%#x\n", cmd.dw0.sid);
457
458 for (auto dev_interface : deviceInterfaces) {
459 dev_interface->microTLB->invalidateSID(cmd.dw0.sid);
460 dev_interface->mainTLB->invalidateSID(cmd.dw0.sid);
461 }
462 break;
463 }
464
465 case CMD_TLBI_NH_ALL: {
466 DPRINTF(SMMUv3, "CMD_TLBI_NH_ALL vmid=%#x\n", cmd.dw0.vmid);
467 for (auto dev_interface : deviceInterfaces) {
468 dev_interface->microTLB->invalidateVMID(cmd.dw0.vmid);
469 dev_interface->mainTLB->invalidateVMID(cmd.dw0.vmid);
470 }
471 tlb.invalidateVMID(cmd.dw0.vmid);
473 break;
474 }
475
476 case CMD_TLBI_NH_ASID: {
477 DPRINTF(SMMUv3, "CMD_TLBI_NH_ASID asid=%#x vmid=%#x\n",
478 cmd.dw0.asid, cmd.dw0.vmid);
479 for (auto dev_interface : deviceInterfaces) {
480 dev_interface->microTLB->invalidateASID(
481 cmd.dw0.asid, cmd.dw0.vmid);
482 dev_interface->mainTLB->invalidateASID(
483 cmd.dw0.asid, cmd.dw0.vmid);
484 }
485 tlb.invalidateASID(cmd.dw0.asid, cmd.dw0.vmid);
486 walkCache.invalidateASID(cmd.dw0.asid, cmd.dw0.vmid);
487 break;
488 }
489
490 case CMD_TLBI_NH_VAA: {
491 const Addr addr = cmd.addr();
492 DPRINTF(SMMUv3, "CMD_TLBI_NH_VAA va=%#08x vmid=%#x\n",
493 addr, cmd.dw0.vmid);
494 for (auto dev_interface : deviceInterfaces) {
495 dev_interface->microTLB->invalidateVAA(
496 addr, cmd.dw0.vmid);
497 dev_interface->mainTLB->invalidateVAA(
498 addr, cmd.dw0.vmid);
499 }
500 tlb.invalidateVAA(addr, cmd.dw0.vmid);
501 const bool leaf_only = cmd.dw1.leaf ? true : false;
502 walkCache.invalidateVAA(addr, cmd.dw0.vmid, leaf_only);
503 break;
504 }
505
506 case CMD_TLBI_NH_VA: {
507 const Addr addr = cmd.addr();
508 DPRINTF(SMMUv3, "CMD_TLBI_NH_VA va=%#08x asid=%#x vmid=%#x\n",
509 addr, cmd.dw0.asid, cmd.dw0.vmid);
510 for (auto dev_interface : deviceInterfaces) {
511 dev_interface->microTLB->invalidateVA(
512 addr, cmd.dw0.asid, cmd.dw0.vmid);
513 dev_interface->mainTLB->invalidateVA(
514 addr, cmd.dw0.asid, cmd.dw0.vmid);
515 }
516 tlb.invalidateVA(addr, cmd.dw0.asid, cmd.dw0.vmid);
517 const bool leaf_only = cmd.dw1.leaf ? true : false;
518 walkCache.invalidateVA(addr, cmd.dw0.asid, cmd.dw0.vmid,
519 leaf_only);
520 break;
521 }
522
523 case CMD_TLBI_S2_IPA: {
524 const Addr addr = cmd.addr();
525 DPRINTF(SMMUv3, "CMD_TLBI_S2_IPA ipa=%#08x vmid=%#x\n",
526 addr, cmd.dw0.vmid);
527 // This does not invalidate TLBs containing
528 // combined Stage1 + Stage2 translations, as per the spec.
530
531 if (!cmd.dw1.leaf)
533 break;
534 }
535
536 case CMD_TLBI_S12_VMALL: {
537 DPRINTF(SMMUv3, "CMD_TLBI_S12_VMALL vmid=%#x\n", cmd.dw0.vmid);
538 for (auto dev_interface : deviceInterfaces) {
539 dev_interface->microTLB->invalidateVMID(cmd.dw0.vmid);
540 dev_interface->mainTLB->invalidateVMID(cmd.dw0.vmid);
541 }
542 tlb.invalidateVMID(cmd.dw0.vmid);
545 break;
546 }
547
548 case CMD_TLBI_NSNH_ALL: {
549 DPRINTF(SMMUv3, "CMD_TLBI_NSNH_ALL\n");
550 for (auto dev_interface : deviceInterfaces) {
551 dev_interface->microTLB->invalidateAll();
552 dev_interface->mainTLB->invalidateAll();
553 }
557 break;
558 }
559
560 case CMD_RESUME:
561 DPRINTF(SMMUv3, "CMD_RESUME\n");
562 panic("resume unimplemented");
563 break;
564
565 default:
566 warn("Unimplemented command %#x\n", cmd.dw0.type);
567 break;
568 }
569}
570
571Tick
573{
574 DPRINTF(SMMUv3, "readControl: addr=%08x size=%d\n",
575 pkt->getAddr(), pkt->getSize());
576
577 int offset = pkt->getAddr() - regsMap.start();
578 assert(offset >= 0 && offset < SMMU_REG_SIZE);
579
580 if (inSecureBlock(offset)) {
581 warn("smmu: secure registers (0x%x) are not implemented\n",
582 offset);
583 }
584
585 auto reg_ptr = regs.data + offset;
586
587 switch (pkt->getSize()) {
588 case sizeof(uint32_t):
589 pkt->setLE<uint32_t>(*reinterpret_cast<uint32_t *>(reg_ptr));
590 break;
591 case sizeof(uint64_t):
592 pkt->setLE<uint64_t>(*reinterpret_cast<uint64_t *>(reg_ptr));
593 break;
594 default:
595 panic("smmu: unallowed access size: %d bytes\n", pkt->getSize());
596 break;
597 }
598
599 pkt->makeAtomicResponse();
600
601 return 0;
602}
603
604Tick
606{
607 int offset = pkt->getAddr() - regsMap.start();
608 assert(offset >= 0 && offset < SMMU_REG_SIZE);
609
610 DPRINTF(SMMUv3, "writeControl: addr=%08x size=%d data=%16x\n",
611 pkt->getAddr(), pkt->getSize(),
612 pkt->getSize() == sizeof(uint64_t) ?
613 pkt->getLE<uint64_t>() : pkt->getLE<uint32_t>());
614
615 switch (offset) {
616 case offsetof(SMMURegs, cr0):
617 assert(pkt->getSize() == sizeof(uint32_t));
618 regs.cr0 = regs.cr0ack = pkt->getLE<uint32_t>();
619 break;
620 case offsetof(SMMURegs, irq_ctrl):
621 assert(pkt->getSize() == sizeof(uint32_t));
622 warn("SMMUv3::%s No support for GERROR and PRI interrupt sources",
623 __func__);
624 regs.irq_ctrl = regs.irq_ctrlack = pkt->getLE<uint32_t>();
625 break;
626
627 case offsetof(SMMURegs, cr1):
628 case offsetof(SMMURegs, cr2):
629 case offsetof(SMMURegs, strtab_base_cfg):
630 case offsetof(SMMURegs, eventq_cons):
631 case offsetof(SMMURegs, eventq_irq_cfg1):
632 case offsetof(SMMURegs, priq_cons):
633 assert(pkt->getSize() == sizeof(uint32_t));
634 *reinterpret_cast<uint32_t *>(regs.data + offset) =
635 pkt->getLE<uint32_t>();
636 break;
637
638 case offsetof(SMMURegs, cmdq_cons):
639 assert(pkt->getSize() == sizeof(uint32_t));
640 if (regs.cr0 & CR0_CMDQEN_MASK) {
641 warn("CMDQ is enabled: ignoring write to CMDQ_CONS\n");
642 } else {
643 *reinterpret_cast<uint32_t *>(regs.data + offset) =
644 pkt->getLE<uint32_t>();
645 }
646 break;
647
648 case offsetof(SMMURegs, cmdq_prod):
649 assert(pkt->getSize() == sizeof(uint32_t));
650 *reinterpret_cast<uint32_t *>(regs.data + offset) =
651 pkt->getLE<uint32_t>();
653 break;
654
655 case offsetof(SMMURegs, strtab_base):
656 case offsetof(SMMURegs, eventq_irq_cfg0):
657 assert(pkt->getSize() == sizeof(uint64_t));
658 *reinterpret_cast<uint64_t *>(regs.data + offset) =
659 pkt->getLE<uint64_t>();
660 break;
661
662 case offsetof(SMMURegs, cmdq_base):
663 assert(pkt->getSize() == sizeof(uint64_t));
664 if (regs.cr0 & CR0_CMDQEN_MASK) {
665 warn("CMDQ is enabled: ignoring write to CMDQ_BASE\n");
666 } else {
667 *reinterpret_cast<uint64_t *>(regs.data + offset) =
668 pkt->getLE<uint64_t>();
669 regs.cmdq_cons = 0;
670 regs.cmdq_prod = 0;
671 }
672 break;
673
674 case offsetof(SMMURegs, eventq_base):
675 assert(pkt->getSize() == sizeof(uint64_t));
676 *reinterpret_cast<uint64_t *>(regs.data + offset) =
677 pkt->getLE<uint64_t>();
678 regs.eventq_cons = 0;
679 regs.eventq_prod = 0;
680 break;
681
682 case offsetof(SMMURegs, priq_base):
683 assert(pkt->getSize() == sizeof(uint64_t));
684 *reinterpret_cast<uint64_t *>(regs.data + offset) =
685 pkt->getLE<uint64_t>();
686 regs.priq_cons = 0;
687 regs.priq_prod = 0;
688 break;
689
690 default:
691 if (inSecureBlock(offset)) {
692 warn("smmu: secure registers (0x%x) are not implemented\n",
693 offset);
694 } else {
695 warn("smmu: write to read-only/undefined register at 0x%x\n",
696 offset);
697 }
698 }
699
700 pkt->makeAtomicResponse();
701
702 return 0;
703}
704
705bool
706SMMUv3::inSecureBlock(uint32_t offs) const
707{
708 if (offs >= offsetof(SMMURegs, _secure_regs) && offs < SMMU_SECURE_SZ)
709 return true;
710 else
711 return false;
712}
713
714void
716{
717 // make sure both sides are connected and have the same block size
719 fatal("Request port is not connected.\n");
720
721 // If the second request port is connected for the table walks, enable
722 // the mode to send table walks through this port instead
724 tableWalkPortEnable = true;
725
726 // notify the request side of our address ranges
727 for (auto ifc : deviceInterfaces) {
728 ifc->sendRange();
729 }
730
733}
734
736 : statistics::Group(parent),
737 ADD_STAT(steL1Fetches, statistics::units::Count::get(), "STE L1 fetches"),
738 ADD_STAT(steFetches, statistics::units::Count::get(), "STE fetches"),
739 ADD_STAT(cdL1Fetches, statistics::units::Count::get(), "CD L1 fetches"),
740 ADD_STAT(cdFetches, statistics::units::Count::get(), "CD fetches"),
741 ADD_STAT(translationTimeDist, statistics::units::Tick::get(),
742 "Time to translate address"),
743 ADD_STAT(ptwTimeDist, statistics::units::Tick::get(),
744 "Time to walk page tables")
745{
746 using namespace statistics;
747
749 .flags(pdf);
750
752 .flags(pdf);
753
755 .flags(pdf);
756
758 .flags(pdf);
759
761 .init(0, 2000000, 2000)
762 .flags(pdf);
763
765 .init(0, 2000000, 2000)
766 .flags(pdf);
767}
768
771{
772 // Wait until the Command Executor is not busy
773 if (commandExecutor.isBusy()) {
775 }
776 return DrainState::Drained;
777}
778
779void
781{
782 DPRINTF(Checkpoint, "Serializing SMMUv3\n");
783
784 SERIALIZE_ARRAY(regs.data, sizeof(regs.data) / sizeof(regs.data[0]));
785}
786
787void
789{
790 DPRINTF(Checkpoint, "Unserializing SMMUv3\n");
791
792 UNSERIALIZE_ARRAY(regs.data, sizeof(regs.data) / sizeof(regs.data[0]));
793}
794
795Port&
796SMMUv3::getPort(const std::string &name, PortID id)
797{
798 if (name == "request") {
799 return requestPort;
800 } else if (name == "walker") {
801 return tableWalkPort;
802 } else if (name == "control") {
803 return controlPort;
804 } else {
805 return ClockedObject::getPort(name, id);
806 }
807}
808
809} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
Base class for ARM GIC implementations.
void invalidateVAA(Addr va, uint16_t vmid)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
void invalidateSID(uint32_t sid)
void invalidateSSID(uint32_t sid, uint32_t ssid)
void invalidateVMID(uint16_t vmid)
void invalidateIPA(Addr ipa, uint16_t vmid)
virtual std::string name() const
Definition named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setLE(T v)
Set the value in the data pointer to v as little endian.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition packet.hh:449
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition packet.hh:431
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
Definition packet.cc:334
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition packet.cc:342
unsigned getSize() const
Definition packet.hh:817
void makeAtomicResponse()
Definition packet.hh:1074
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Ports are used to interface objects to each other.
Definition port.hh:62
bool isConnected() const
Is this port currently connected to a peer?
Definition port.hh:133
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
Definition port.hh:552
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
void sendRangeChange() const
Called by the owner to send a range change.
Definition port.hh:380
SMMUAction run(PacketPtr pkt)
void schedAtsTimingResp(PacketPtr pkt)
void schedTimingResp(PacketPtr pkt)
const System & system
Definition smmu_v3.hh:95
SMMUCommandExecProcess commandExecutor
Definition smmu_v3.hh:156
const AddrRange regsMap
Definition smmu_v3.hh:158
Tick readControl(PacketPtr pkt)
Definition smmu_v3.cc:572
void recvReqRetry()
Definition smmu_v3.cc:151
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition smmu_v3.cc:780
SMMUAction runProcess(SMMUProcess *proc, PacketPtr pkt)
Definition smmu_v3.cc:226
std::vector< SMMUv3DeviceInterface * > deviceInterfaces
Definition smmu_v3.hh:154
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition smmu_v3.cc:788
ARMArchTLB tlb
Definition smmu_v3.hh:106
ConfigCache configCache
Definition smmu_v3.hh:107
SMMUControlPort controlPort
Definition smmu_v3.hh:100
SMMUTableWalkPort tableWalkPort
Definition smmu_v3.hh:99
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition smmu_v3.cc:715
WalkCache walkCache
Definition smmu_v3.hh:109
SMMUAction runProcessAtomic(SMMUProcess *proc, PacketPtr pkt)
Definition smmu_v3.cc:238
bool recvTimingResp(PacketPtr pkt)
Definition smmu_v3.cc:134
bool inSecureBlock(uint32_t offs) const
Definition smmu_v3.cc:706
virtual Port & getPort(const std::string &name, PortID id=InvalidPortID) override
Get a port with a given name and index.
Definition smmu_v3.cc:796
Tick writeControl(PacketPtr pkt)
Definition smmu_v3.cc:605
SMMURequestPort requestPort
Definition smmu_v3.hh:98
void scheduleDeviceRetries()
Definition smmu_v3.cc:218
std::queue< SMMUAction > packetsTableWalkToRetry
Definition smmu_v3.hh:164
DrainState drain() override
Provide a default implementation of the drain interface for objects that don't need draining.
Definition smmu_v3.cc:770
IPACache ipaCache
Definition smmu_v3.hh:108
bool tableWalkPortEnable
Definition smmu_v3.hh:115
std::queue< SMMUAction > packetsToRetry
Definition smmu_v3.hh:163
void processCommand(const SMMUCommand &cmd)
Definition smmu_v3.cc:390
void tableWalkRecvReqRetry()
Definition smmu_v3.cc:197
SMMURegs regs
Definition smmu_v3.hh:159
SMMUv3(const SMMUv3Params &p)
Definition smmu_v3.cc:59
MemberEventWrapper<&SMMUv3::processCommands > processCommandsEvent
Definition smmu_v3.hh:174
void processCommands()
Definition smmu_v3.cc:374
SMMUAction runProcessTiming(SMMUProcess *proc, PacketPtr pkt)
Definition smmu_v3.cc:287
bool tableWalkRecvTimingResp(PacketPtr pkt)
Definition smmu_v3.cc:180
bool isAtomicMode() const
Is the system in atomic mode?
Definition system.hh:258
bool isTimingMode() const
Is the system in timing mode?
Definition system.hh:270
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
Addr start() const
Get the start address of the range.
DrainState
Object drain/handover states.
Definition drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
#define UNSERIALIZE_ARRAY(member, size)
Definition serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition serialize.hh:610
const Params & params() const
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
#define warn(...)
Definition logging.hh:256
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 59, 56 > tlb
Bitfield< 15 > system
Definition misc.hh:1032
Bitfield< 3 > addr
Definition types.hh:84
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition info.hh:61
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
T safe_cast(U &&ref_or_ptr)
Definition cast.hh:74
@ CR0_CMDQEN_MASK
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
@ CMD_CFGI_STE
@ CMD_TLBI_S2_IPA
@ CMD_TLBI_S12_VMALL
@ CMD_CFGI_STE_RANGE
@ CMD_TLBI_NH_ASID
@ CMD_TLBI_NH_VA
@ CMD_CFGI_CD_ALL
@ CMD_PRF_CONFIG
@ CMD_TLBI_NSNH_ALL
@ CMD_CFGI_CD
@ CMD_TLBI_NH_ALL
@ CMD_PRF_ADDR
@ CMD_TLBI_NH_VAA
@ SMMU_SECURE_SZ
@ SMMU_REG_SIZE
@ ACTION_SEND_RESP
@ ACTION_DELAY
@ ACTION_SLEEP
@ ACTION_TERMINATE
@ ACTION_SEND_REQ
@ ACTION_SEND_RESP_ATS
@ ACTION_SEND_REQ_FINAL
This is an implementation of the SMMUv3 architecture.
SMMUActionType type
SMMUv3DeviceInterface * ifc
Bitfield< 63, 48 > asid
Bitfield< 63, 32 > sid
Bitfield< 47, 32 > vmid
Bitfield< 31, 12 > ssid
Bitfield< 4, 0 > range
uint64_t addr() const
SMMUv3Stats(statistics::Group *parent)
Definition smmu_v3.cc:735
statistics::Distribution ptwTimeDist
Definition smmu_v3.hh:151
statistics::Scalar cdL1Fetches
Definition smmu_v3.hh:148
statistics::Scalar steL1Fetches
Definition smmu_v3.hh:146
statistics::Scalar steFetches
Definition smmu_v3.hh:147
statistics::Distribution translationTimeDist
Definition smmu_v3.hh:150
statistics::Scalar cdFetches
Definition smmu_v3.hh:149
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0