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>
This commit is contained in:
@@ -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,29 +392,128 @@ 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->invalidateVMID(cmd.dw0.vmid);
|
||||
slave_interface->mainTLB->invalidateVMID(cmd.dw0.vmid);
|
||||
}
|
||||
tlb.invalidateVMID(cmd.dw0.vmid);
|
||||
walkCache.invalidateVMID(cmd.dw0.vmid);
|
||||
break;
|
||||
}
|
||||
|
||||
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.dw0.asid, cmd.dw0.vmid);
|
||||
slave_interface->mainTLB->invalidateASID(
|
||||
cmd.dw0.asid, cmd.dw0.vmid);
|
||||
}
|
||||
tlb.invalidateASID(cmd.dw0.asid, cmd.dw0.vmid);
|
||||
walkCache.invalidateASID(cmd.dw0.asid, cmd.dw0.vmid);
|
||||
break;
|
||||
}
|
||||
|
||||
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(
|
||||
addr, cmd.dw0.vmid);
|
||||
slave_interface->mainTLB->invalidateVAA(
|
||||
addr, cmd.dw0.vmid);
|
||||
}
|
||||
tlb.invalidateVAA(addr, cmd.dw0.vmid);
|
||||
|
||||
if (!cmd.dw1.leaf)
|
||||
walkCache.invalidateVAA(addr, cmd.dw0.vmid);
|
||||
break;
|
||||
}
|
||||
|
||||
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(
|
||||
addr, cmd.dw0.asid, cmd.dw0.vmid);
|
||||
slave_interface->mainTLB->invalidateVA(
|
||||
addr, cmd.dw0.asid, cmd.dw0.vmid);
|
||||
}
|
||||
tlb.invalidateVA(addr, cmd.dw0.asid, cmd.dw0.vmid);
|
||||
|
||||
if (!cmd.dw1.leaf)
|
||||
walkCache.invalidateVA(addr, cmd.dw0.asid, cmd.dw0.vmid);
|
||||
break;
|
||||
}
|
||||
|
||||
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(addr, cmd.dw0.vmid);
|
||||
|
||||
if (!cmd.dw1.leaf)
|
||||
walkCache.invalidateVMID(cmd.dw0.vmid);
|
||||
break;
|
||||
}
|
||||
|
||||
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_NSNH_ALL: {
|
||||
DPRINTF(SMMUv3, "CMD_TLBI_NSNH_ALL\n");
|
||||
for (auto slave_interface : slaveInterfaces) {
|
||||
slave_interface->microTLB->invalidateAll();
|
||||
slave_interface->mainTLB->invalidateAll();
|
||||
@@ -423,106 +522,15 @@ SMMUv3::processCommand(const SMMUCommand &cmd)
|
||||
ipaCache.invalidateAll();
|
||||
walkCache.invalidateAll();
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_TLBI_ASID:
|
||||
DPRINTF(SMMUv3, "CMD_TLBI_ASID asid=%#x vmid=%#x\n",
|
||||
cmd.data[0], cmd.data[1]);
|
||||
for (auto slave_interface : slaveInterfaces) {
|
||||
slave_interface->microTLB->invalidateASID(
|
||||
cmd.data[0], cmd.data[1]);
|
||||
slave_interface->mainTLB->invalidateASID(
|
||||
cmd.data[0], cmd.data[1]);
|
||||
}
|
||||
tlb.invalidateASID(cmd.data[0], cmd.data[1]);
|
||||
walkCache.invalidateASID(cmd.data[0], cmd.data[1]);
|
||||
break;
|
||||
|
||||
case CMD_TLBI_VAAL:
|
||||
DPRINTF(SMMUv3, "CMD_TLBI_VAAL 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]);
|
||||
break;
|
||||
|
||||
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]);
|
||||
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]);
|
||||
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]);
|
||||
break;
|
||||
|
||||
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]);
|
||||
break;
|
||||
|
||||
case CMD_TLBI_VM_IPAL:
|
||||
DPRINTF(SMMUv3, "CMD_TLBI_VM_IPAL 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]);
|
||||
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]);
|
||||
break;
|
||||
|
||||
case CMD_TLBI_VM_S12:
|
||||
DPRINTF(SMMUv3, "CMD_TLBI_VM_S12 vmid=%#x\n", cmd.data[0]);
|
||||
for (auto slave_interface : slaveInterfaces) {
|
||||
slave_interface->microTLB->invalidateVMID(cmd.data[0]);
|
||||
slave_interface->mainTLB->invalidateVMID(cmd.data[0]);
|
||||
}
|
||||
tlb.invalidateVMID(cmd.data[0]);
|
||||
ipaCache.invalidateVMID(cmd.data[0]);
|
||||
walkCache.invalidateVMID(cmd.data[0]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user