summaryrefslogtreecommitdiff
path: root/src/dev/arm
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
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')
-rw-r--r--src/dev/arm/smmu_v3.cc180
-rw-r--r--src/dev/arm/smmu_v3_defs.hh66
2 files changed, 142 insertions, 104 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;
}
}
diff --git a/src/dev/arm/smmu_v3_defs.hh b/src/dev/arm/smmu_v3_defs.hh
index d993fd715..655835f55 100644
--- a/src/dev/arm/smmu_v3_defs.hh
+++ b/src/dev/arm/smmu_v3_defs.hh
@@ -321,28 +321,58 @@ enum {
};
enum SMMUCommandType {
- CMD_PRF_CONFIG = 0x1000,
- CMD_PRF_ADDR = 0x1001,
- CMD_INV_STE = 0x1100,
- CMD_INV_CD = 0x1101,
- CMD_INV_CD_ALL = 0x1102,
- CMD_INV_ALL = 0x1104,
- CMD_TLBI_ALL = 0x1110,
- CMD_TLBI_ASID = 0x1111,
- CMD_TLBI_VAAL = 0x1112,
- CMD_TLBI_VAA = 0x1113,
- CMD_TLBI_VAL = 0x1114,
- CMD_TLBI_VA = 0x1115,
- CMD_TLBI_VM_IPAL = 0x1120,
- CMD_TLBI_VM_IPA = 0x1121,
- CMD_TLBI_VM_S12 = 0x1122,
- CMD_RESUME_S = 0x1200,
+ CMD_PRF_CONFIG = 0x01,
+ CMD_PRF_ADDR = 0x02,
+ CMD_CFGI_STE = 0x03,
+ CMD_CFGI_STE_RANGE = 0x04,
+ CMD_CFGI_CD = 0x05,
+ CMD_CFGI_CD_ALL = 0x06,
+ CMD_TLBI_NH_ALL = 0x10,
+ CMD_TLBI_NH_ASID = 0x11,
+ CMD_TLBI_NH_VAA = 0x13,
+ CMD_TLBI_NH_VA = 0x12,
+ CMD_TLBI_EL3_ALL = 0x18,
+ CMD_TLBI_EL3_VA = 0x1A,
+ CMD_TLBI_EL2_ALL = 0x20,
+ CMD_TLBI_EL2_ASID = 0x21,
+ CMD_TLBI_EL2_VA = 0x22,
+ CMD_TLBI_EL2_VAA = 0x23,
+ CMD_TLBI_S2_IPA = 0x2a,
+ CMD_TLBI_S12_VMALL = 0x28,
+ CMD_TLBI_NSNH_ALL = 0x30,
+ CMD_ATC_INV = 0x40,
+ CMD_PRI_RESP = 0x41,
+ CMD_RESUME = 0x44,
+ CMD_STALL_TERM = 0x45,
+ CMD_SYNC = 0x46,
};
struct SMMUCommand
{
- uint32_t type;
- uint32_t data[3];
+ BitUnion64(DWORD0)
+ Bitfield<7, 0> type;
+ Bitfield<10> ssec;
+ Bitfield<11> ssv;
+ Bitfield<31, 12> ssid;
+ Bitfield<47, 32> vmid;
+ Bitfield<63, 48> asid;
+ Bitfield<63, 32> sid;
+ EndBitUnion(DWORD0)
+ DWORD0 dw0;
+
+ BitUnion64(DWORD1)
+ Bitfield<0> leaf;
+ Bitfield<4, 0> size;
+ Bitfield<4, 0> range;
+ Bitfield<63, 12> address;
+ EndBitUnion(DWORD1)
+ DWORD1 dw1;
+
+ uint64_t addr() const
+ {
+ uint64_t address = (uint64_t)(dw1.address) << 12;
+ return address;
+ }
};
enum SMMUEventTypes {