From 55580e6a8810e9d31b01a2efdf58b13d09f30f58 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 24 Jul 2019 12:22:05 +0100 Subject: [PATCH] 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 Reviewed-by: Michiel van Tol Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19668 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg Tested-by: kokoro --- src/dev/arm/smmu_v3.cc | 180 +++++++++++++++++++----------------- src/dev/arm/smmu_v3_defs.hh | 66 +++++++++---- 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 { -- 2.30.2