summaryrefslogtreecommitdiff
path: root/src/dev/arm/smmu_v3.cc
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2019-07-24 12:22:05 +0100
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2019-07-30 12:05:33 +0000
commit55580e6a8810e9d31b01a2efdf58b13d09f30f58 (patch)
treeb331ab1207099cc5e624a6cb7b68b918010eca34 /src/dev/arm/smmu_v3.cc
parent9871b73329be93c5749ef45d49079072ecbd9685 (diff)
downloadgem5-55580e6a8810e9d31b01a2efdf58b13d09f30f58.tar.xz
dev-arm: Rewrite SMMUv3 Commands
This patch is rewriting the SMMUv3::processCommand method for the following reasons: * Command names were not matching spec * Command encoding/opcode was wrong The patch is not adding any new command: there is still a subset of unimplemented commands; those are: * CMD_TLBI_EL3_ALL * CMD_TLBI_EL3_VA * CMD_TLBI_EL2_ALL * CMD_TLBI_EL2_VA * CMD_TLBI_EL2_VAA * CMD_TLBI_EL2_ASID which require StreamWorld support, and * CMD_ATC_INV * CMD_PRI_RESP * CMD_RESUME * CMD_STALL_TERM which require in sequence: ATS, PRI, Stall Model support Change-Id: Ia2dd47b5588738402d9584a00cfc88c94c253ad0 Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Michiel van Tol <michiel.vantol@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19668 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/dev/arm/smmu_v3.cc')
-rw-r--r--src/dev/arm/smmu_v3.cc180
1 files changed, 94 insertions, 86 deletions
diff --git a/src/dev/arm/smmu_v3.cc b/src/dev/arm/smmu_v3.cc
index 2c974b57b..28539297c 100644
--- a/src/dev/arm/smmu_v3.cc
+++ b/src/dev/arm/smmu_v3.cc
@@ -383,7 +383,7 @@ SMMUv3::processCommands()
void
SMMUv3::processCommand(const SMMUCommand &cmd)
{
- switch (cmd.type) {
+ switch (cmd.dw0.type) {
case CMD_PRF_CONFIG:
DPRINTF(SMMUv3, "CMD_PREFETCH_CONFIG - ignored\n");
break;
@@ -392,137 +392,145 @@ SMMUv3::processCommand(const SMMUCommand &cmd)
DPRINTF(SMMUv3, "CMD_PREFETCH_ADDR - ignored\n");
break;
- case CMD_INV_STE:
- DPRINTF(SMMUv3, "CMD_INV_STE sid=%#x\n", cmd.data[0]);
- configCache.invalidateSID(cmd.data[0]);
+ case CMD_CFGI_STE: {
+ DPRINTF(SMMUv3, "CMD_CFGI_STE sid=%#x\n", cmd.dw0.sid);
+ configCache.invalidateSID(cmd.dw0.sid);
break;
+ }
- case CMD_INV_CD:
- DPRINTF(SMMUv3, "CMD_INV_CD sid=%#x ssid=%#x\n",
- cmd.data[0], cmd.data[1]);
- configCache.invalidateSSID(cmd.data[0], cmd.data[1]);
+ case CMD_CFGI_STE_RANGE: {
+ const auto range = cmd.dw1.range;
+ if (range == 31) {
+ // CMD_CFGI_ALL is an alias of CMD_CFGI_STE_RANGE with
+ // range = 31
+ DPRINTF(SMMUv3, "CMD_CFGI_ALL\n");
+ configCache.invalidateAll();
+ } else {
+ DPRINTF(SMMUv3, "CMD_CFGI_STE_RANGE\n");
+ const auto start_sid = cmd.dw0.sid & ~((1 << (range + 1)) - 1);
+ const auto end_sid = start_sid + (1 << (range + 1)) - 1;
+ for (auto sid = start_sid; sid <= end_sid; sid++)
+ configCache.invalidateSID(sid);
+ }
break;
+ }
- case CMD_INV_CD_ALL:
- DPRINTF(SMMUv3, "CMD_INV_CD_ALL sid=%#x\n", cmd.data[0]);
- configCache.invalidateSID(cmd.data[0]);
+ case CMD_CFGI_CD: {
+ DPRINTF(SMMUv3, "CMD_CFGI_CD sid=%#x ssid=%#x\n",
+ cmd.dw0.sid, cmd.dw0.ssid);
+ configCache.invalidateSSID(cmd.dw0.sid, cmd.dw0.ssid);
break;
+ }
- case CMD_INV_ALL:
- DPRINTF(SMMUv3, "CMD_INV_ALL\n");
- configCache.invalidateAll();
+ case CMD_CFGI_CD_ALL: {
+ DPRINTF(SMMUv3, "CMD_CFGI_CD_ALL sid=%#x\n", cmd.dw0.sid);
+ configCache.invalidateSID(cmd.dw0.sid);
break;
+ }
- case CMD_TLBI_ALL:
- DPRINTF(SMMUv3, "CMD_TLBI_ALL\n");
+ case CMD_TLBI_NH_ALL: {
+ DPRINTF(SMMUv3, "CMD_TLBI_NH_ALL vmid=%#x\n", cmd.dw0.vmid);
for (auto slave_interface : slaveInterfaces) {
- slave_interface->microTLB->invalidateAll();
- slave_interface->mainTLB->invalidateAll();
+ slave_interface->microTLB->invalidateVMID(cmd.dw0.vmid);
+ slave_interface->mainTLB->invalidateVMID(cmd.dw0.vmid);
}
- tlb.invalidateAll();
- ipaCache.invalidateAll();
- walkCache.invalidateAll();
+ tlb.invalidateVMID(cmd.dw0.vmid);
+ walkCache.invalidateVMID(cmd.dw0.vmid);
break;
+ }
- case CMD_TLBI_ASID:
- DPRINTF(SMMUv3, "CMD_TLBI_ASID asid=%#x vmid=%#x\n",
- cmd.data[0], cmd.data[1]);
+ case CMD_TLBI_NH_ASID: {
+ DPRINTF(SMMUv3, "CMD_TLBI_NH_ASID asid=%#x vmid=%#x\n",
+ cmd.dw0.asid, cmd.dw0.vmid);
for (auto slave_interface : slaveInterfaces) {
slave_interface->microTLB->invalidateASID(
- cmd.data[0], cmd.data[1]);
+ cmd.dw0.asid, cmd.dw0.vmid);
slave_interface->mainTLB->invalidateASID(
- cmd.data[0], cmd.data[1]);
+ cmd.dw0.asid, cmd.dw0.vmid);
}
- tlb.invalidateASID(cmd.data[0], cmd.data[1]);
- walkCache.invalidateASID(cmd.data[0], cmd.data[1]);
+ tlb.invalidateASID(cmd.dw0.asid, cmd.dw0.vmid);
+ walkCache.invalidateASID(cmd.dw0.asid, cmd.dw0.vmid);
break;
+ }
- case CMD_TLBI_VAAL:
- DPRINTF(SMMUv3, "CMD_TLBI_VAAL va=%#08x vmid=%#x\n",
- cmd.data[0], cmd.data[1]);
+ case CMD_TLBI_NH_VAA: {
+ const Addr addr = cmd.addr();
+ DPRINTF(SMMUv3, "CMD_TLBI_NH_VAA va=%#08x vmid=%#x\n",
+ addr, cmd.dw0.vmid);
for (auto slave_interface : slaveInterfaces) {
slave_interface->microTLB->invalidateVAA(
- cmd.data[0], cmd.data[1]);
+ addr, cmd.dw0.vmid);
slave_interface->mainTLB->invalidateVAA(
- cmd.data[0], cmd.data[1]);
+ addr, cmd.dw0.vmid);
}
- tlb.invalidateVAA(cmd.data[0], cmd.data[1]);
- break;
+ tlb.invalidateVAA(addr, cmd.dw0.vmid);
- case CMD_TLBI_VAA:
- DPRINTF(SMMUv3, "CMD_TLBI_VAA va=%#08x vmid=%#x\n",
- cmd.data[0], cmd.data[1]);
- for (auto slave_interface : slaveInterfaces) {
- slave_interface->microTLB->invalidateVAA(
- cmd.data[0], cmd.data[1]);
- slave_interface->mainTLB->invalidateVAA(
- cmd.data[0], cmd.data[1]);
- }
- tlb.invalidateVAA(cmd.data[0], cmd.data[1]);
- walkCache.invalidateVAA(cmd.data[0], cmd.data[1]);
+ if (!cmd.dw1.leaf)
+ walkCache.invalidateVAA(addr, cmd.dw0.vmid);
break;
+ }
- case CMD_TLBI_VAL:
- DPRINTF(SMMUv3, "CMD_TLBI_VAL va=%#08x asid=%#x vmid=%#x\n",
- cmd.data[0], cmd.data[1], cmd.data[2]);
+ case CMD_TLBI_NH_VA: {
+ const Addr addr = cmd.addr();
+ DPRINTF(SMMUv3, "CMD_TLBI_NH_VA va=%#08x asid=%#x vmid=%#x\n",
+ addr, cmd.dw0.asid, cmd.dw0.vmid);
for (auto slave_interface : slaveInterfaces) {
slave_interface->microTLB->invalidateVA(
- cmd.data[0], cmd.data[1], cmd.data[2]);
+ addr, cmd.dw0.asid, cmd.dw0.vmid);
slave_interface->mainTLB->invalidateVA(
- cmd.data[0], cmd.data[1], cmd.data[2]);
+ addr, cmd.dw0.asid, cmd.dw0.vmid);
}
- tlb.invalidateVA(cmd.data[0], cmd.data[1], cmd.data[2]);
- break;
+ tlb.invalidateVA(addr, cmd.dw0.asid, cmd.dw0.vmid);
- case CMD_TLBI_VA:
- DPRINTF(SMMUv3, "CMD_TLBI_VA va=%#08x asid=%#x vmid=%#x\n",
- cmd.data[0], cmd.data[1], cmd.data[2]);
- for (auto slave_interface : slaveInterfaces) {
- slave_interface->microTLB->invalidateVA(
- cmd.data[0], cmd.data[1], cmd.data[2]);
- slave_interface->mainTLB->invalidateVA(
- cmd.data[0], cmd.data[1], cmd.data[2]);
- }
- tlb.invalidateVA(cmd.data[0], cmd.data[1], cmd.data[2]);
- walkCache.invalidateVA(cmd.data[0], cmd.data[1], cmd.data[2]);
+ if (!cmd.dw1.leaf)
+ walkCache.invalidateVA(addr, cmd.dw0.asid, cmd.dw0.vmid);
break;
+ }
- case CMD_TLBI_VM_IPAL:
- DPRINTF(SMMUv3, "CMD_TLBI_VM_IPAL ipa=%#08x vmid=%#x\n",
- cmd.data[0], cmd.data[1]);
+ case CMD_TLBI_S2_IPA: {
+ const Addr addr = cmd.addr();
+ DPRINTF(SMMUv3, "CMD_TLBI_S2_IPA ipa=%#08x vmid=%#x\n",
+ addr, cmd.dw0.vmid);
// This does not invalidate TLBs containing
// combined Stage1 + Stage2 translations, as per the spec.
- ipaCache.invalidateIPA(cmd.data[0], cmd.data[1]);
- walkCache.invalidateVMID(cmd.data[1]);
+ ipaCache.invalidateIPA(addr, cmd.dw0.vmid);
+
+ if (!cmd.dw1.leaf)
+ walkCache.invalidateVMID(cmd.dw0.vmid);
break;
+ }
- case CMD_TLBI_VM_IPA:
- DPRINTF(SMMUv3, "CMD_TLBI_VM_IPA ipa=%#08x vmid=%#x\n",
- cmd.data[0], cmd.data[1]);
- // This does not invalidate TLBs containing
- // combined Stage1 + Stage2 translations, as per the spec.
- ipaCache.invalidateIPA(cmd.data[0], cmd.data[1]);
- walkCache.invalidateVMID(cmd.data[1]);
+ case CMD_TLBI_S12_VMALL: {
+ DPRINTF(SMMUv3, "CMD_TLBI_S12_VMALL vmid=%#x\n", cmd.dw0.vmid);
+ for (auto slave_interface : slaveInterfaces) {
+ slave_interface->microTLB->invalidateVMID(cmd.dw0.vmid);
+ slave_interface->mainTLB->invalidateVMID(cmd.dw0.vmid);
+ }
+ tlb.invalidateVMID(cmd.dw0.vmid);
+ ipaCache.invalidateVMID(cmd.dw0.vmid);
+ walkCache.invalidateVMID(cmd.dw0.vmid);
break;
+ }
- case CMD_TLBI_VM_S12:
- DPRINTF(SMMUv3, "CMD_TLBI_VM_S12 vmid=%#x\n", cmd.data[0]);
+ case CMD_TLBI_NSNH_ALL: {
+ DPRINTF(SMMUv3, "CMD_TLBI_NSNH_ALL\n");
for (auto slave_interface : slaveInterfaces) {
- slave_interface->microTLB->invalidateVMID(cmd.data[0]);
- slave_interface->mainTLB->invalidateVMID(cmd.data[0]);
+ slave_interface->microTLB->invalidateAll();
+ slave_interface->mainTLB->invalidateAll();
}
- tlb.invalidateVMID(cmd.data[0]);
- ipaCache.invalidateVMID(cmd.data[0]);
- walkCache.invalidateVMID(cmd.data[0]);
+ tlb.invalidateAll();
+ ipaCache.invalidateAll();
+ walkCache.invalidateAll();
break;
+ }
- case CMD_RESUME_S:
- DPRINTF(SMMUv3, "CMD_RESUME_S\n");
+ case CMD_RESUME:
+ DPRINTF(SMMUv3, "CMD_RESUME\n");
panic("resume unimplemented");
break;
default:
- warn("Unimplemented command %#x\n", cmd.type);
+ warn("Unimplemented command %#x\n", cmd.dw0.type);
break;
}
}