110a83cb9SPrem Mallappa /* 210a83cb9SPrem Mallappa * ARM SMMUv3 support - Internal API 310a83cb9SPrem Mallappa * 410a83cb9SPrem Mallappa * Copyright (C) 2014-2016 Broadcom Corporation 510a83cb9SPrem Mallappa * Copyright (c) 2017 Red Hat, Inc. 610a83cb9SPrem Mallappa * Written by Prem Mallappa, Eric Auger 710a83cb9SPrem Mallappa * 810a83cb9SPrem Mallappa * This program is free software; you can redistribute it and/or modify 910a83cb9SPrem Mallappa * it under the terms of the GNU General Public License version 2 as 1010a83cb9SPrem Mallappa * published by the Free Software Foundation. 1110a83cb9SPrem Mallappa * 1210a83cb9SPrem Mallappa * This program is distributed in the hope that it will be useful, 1310a83cb9SPrem Mallappa * but WITHOUT ANY WARRANTY; without even the implied warranty of 1410a83cb9SPrem Mallappa * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1510a83cb9SPrem Mallappa * GNU General Public License for more details. 1610a83cb9SPrem Mallappa * 1710a83cb9SPrem Mallappa * You should have received a copy of the GNU General Public License along 1810a83cb9SPrem Mallappa * with this program; if not, see <http://www.gnu.org/licenses/>. 1910a83cb9SPrem Mallappa */ 2010a83cb9SPrem Mallappa 2158ea30f5SMarkus Armbruster #ifndef HW_ARM_SMMUV3_INTERNAL_H 2258ea30f5SMarkus Armbruster #define HW_ARM_SMMUV3_INTERNAL_H 2310a83cb9SPrem Mallappa 2410a83cb9SPrem Mallappa #include "hw/arm/smmu-common.h" 2510a83cb9SPrem Mallappa 269122bea9SJia He typedef enum SMMUTranslationStatus { 279122bea9SJia He SMMU_TRANS_DISABLE, 289122bea9SJia He SMMU_TRANS_ABORT, 299122bea9SJia He SMMU_TRANS_BYPASS, 309122bea9SJia He SMMU_TRANS_ERROR, 319122bea9SJia He SMMU_TRANS_SUCCESS, 329122bea9SJia He } SMMUTranslationStatus; 339122bea9SJia He 3410a83cb9SPrem Mallappa /* MMIO Registers */ 3510a83cb9SPrem Mallappa 3610a83cb9SPrem Mallappa REG32(IDR0, 0x0) 37263d0e48SMostafa Saleh FIELD(IDR0, S2P, 0 , 1) 3810a83cb9SPrem Mallappa FIELD(IDR0, S1P, 1 , 1) 3910a83cb9SPrem Mallappa FIELD(IDR0, TTF, 2 , 2) 4010a83cb9SPrem Mallappa FIELD(IDR0, COHACC, 4 , 1) 4110a83cb9SPrem Mallappa FIELD(IDR0, ASID16, 12, 1) 42263d0e48SMostafa Saleh FIELD(IDR0, VMID16, 18, 1) 4310a83cb9SPrem Mallappa FIELD(IDR0, TTENDIAN, 21, 2) 4410a83cb9SPrem Mallappa FIELD(IDR0, STALL_MODEL, 24, 2) 4510a83cb9SPrem Mallappa FIELD(IDR0, TERM_MODEL, 26, 1) 4610a83cb9SPrem Mallappa FIELD(IDR0, STLEVEL, 27, 2) 4710a83cb9SPrem Mallappa 4810a83cb9SPrem Mallappa REG32(IDR1, 0x4) 4910a83cb9SPrem Mallappa FIELD(IDR1, SIDSIZE, 0 , 6) 5010a83cb9SPrem Mallappa FIELD(IDR1, EVENTQS, 16, 5) 5110a83cb9SPrem Mallappa FIELD(IDR1, CMDQS, 21, 5) 5210a83cb9SPrem Mallappa 5310a83cb9SPrem Mallappa #define SMMU_IDR1_SIDSIZE 16 5410a83cb9SPrem Mallappa #define SMMU_CMDQS 19 5510a83cb9SPrem Mallappa #define SMMU_EVENTQS 19 5610a83cb9SPrem Mallappa 5710a83cb9SPrem Mallappa REG32(IDR2, 0x8) 5810a83cb9SPrem Mallappa REG32(IDR3, 0xc) 59e7c3b9d9SEric Auger FIELD(IDR3, HAD, 2, 1); 60de206dfdSEric Auger FIELD(IDR3, RIL, 10, 1); 61f8e7163dSPeter Maydell FIELD(IDR3, BBML, 11, 2); 6210a83cb9SPrem Mallappa REG32(IDR4, 0x10) 6310a83cb9SPrem Mallappa REG32(IDR5, 0x14) 6410a83cb9SPrem Mallappa FIELD(IDR5, OAS, 0, 3); 6510a83cb9SPrem Mallappa FIELD(IDR5, GRAN4K, 4, 1); 6610a83cb9SPrem Mallappa FIELD(IDR5, GRAN16K, 5, 1); 6710a83cb9SPrem Mallappa FIELD(IDR5, GRAN64K, 6, 1); 6810a83cb9SPrem Mallappa 6910a83cb9SPrem Mallappa #define SMMU_IDR5_OAS 4 7010a83cb9SPrem Mallappa 71f0ec277cSEric Auger REG32(IIDR, 0x18) 725888f0adSEric Auger REG32(AIDR, 0x1c) 7310a83cb9SPrem Mallappa REG32(CR0, 0x20) 7410a83cb9SPrem Mallappa FIELD(CR0, SMMU_ENABLE, 0, 1) 7510a83cb9SPrem Mallappa FIELD(CR0, EVENTQEN, 2, 1) 7610a83cb9SPrem Mallappa FIELD(CR0, CMDQEN, 3, 1) 7710a83cb9SPrem Mallappa 78fae4be38SEric Auger #define SMMU_CR0_RESERVED 0xFFFFFC20 79fae4be38SEric Auger 8010a83cb9SPrem Mallappa REG32(CR0ACK, 0x24) 8110a83cb9SPrem Mallappa REG32(CR1, 0x28) 8210a83cb9SPrem Mallappa REG32(CR2, 0x2c) 8310a83cb9SPrem Mallappa REG32(STATUSR, 0x40) 84c2ecb424SMostafa Saleh REG32(GBPA, 0x44) 85c2ecb424SMostafa Saleh FIELD(GBPA, ABORT, 20, 1) 86c2ecb424SMostafa Saleh FIELD(GBPA, UPDATE, 31, 1) 87c2ecb424SMostafa Saleh 88c2ecb424SMostafa Saleh /* Use incoming. */ 89c2ecb424SMostafa Saleh #define SMMU_GBPA_RESET_VAL 0x1000 90c2ecb424SMostafa Saleh 9110a83cb9SPrem Mallappa REG32(IRQ_CTRL, 0x50) 9210a83cb9SPrem Mallappa FIELD(IRQ_CTRL, GERROR_IRQEN, 0, 1) 9310a83cb9SPrem Mallappa FIELD(IRQ_CTRL, PRI_IRQEN, 1, 1) 9410a83cb9SPrem Mallappa FIELD(IRQ_CTRL, EVENTQ_IRQEN, 2, 1) 9510a83cb9SPrem Mallappa 9610a83cb9SPrem Mallappa REG32(IRQ_CTRL_ACK, 0x54) 9710a83cb9SPrem Mallappa REG32(GERROR, 0x60) 9810a83cb9SPrem Mallappa FIELD(GERROR, CMDQ_ERR, 0, 1) 9910a83cb9SPrem Mallappa FIELD(GERROR, EVENTQ_ABT_ERR, 2, 1) 10010a83cb9SPrem Mallappa FIELD(GERROR, PRIQ_ABT_ERR, 3, 1) 10110a83cb9SPrem Mallappa FIELD(GERROR, MSI_CMDQ_ABT_ERR, 4, 1) 10210a83cb9SPrem Mallappa FIELD(GERROR, MSI_EVENTQ_ABT_ERR, 5, 1) 10310a83cb9SPrem Mallappa FIELD(GERROR, MSI_PRIQ_ABT_ERR, 6, 1) 10410a83cb9SPrem Mallappa FIELD(GERROR, MSI_GERROR_ABT_ERR, 7, 1) 10510a83cb9SPrem Mallappa FIELD(GERROR, MSI_SFM_ERR, 8, 1) 10610a83cb9SPrem Mallappa 10710a83cb9SPrem Mallappa REG32(GERRORN, 0x64) 10810a83cb9SPrem Mallappa 10910a83cb9SPrem Mallappa #define A_GERROR_IRQ_CFG0 0x68 /* 64b */ 11010a83cb9SPrem Mallappa REG32(GERROR_IRQ_CFG1, 0x70) 11110a83cb9SPrem Mallappa REG32(GERROR_IRQ_CFG2, 0x74) 11210a83cb9SPrem Mallappa 11310a83cb9SPrem Mallappa #define A_STRTAB_BASE 0x80 /* 64b */ 11410a83cb9SPrem Mallappa 1153293b9f5SSimon Veith #define SMMU_BASE_ADDR_MASK 0xfffffffffffc0 11610a83cb9SPrem Mallappa 11710a83cb9SPrem Mallappa REG32(STRTAB_BASE_CFG, 0x88) 11810a83cb9SPrem Mallappa FIELD(STRTAB_BASE_CFG, FMT, 16, 2) 11910a83cb9SPrem Mallappa FIELD(STRTAB_BASE_CFG, SPLIT, 6 , 5) 12010a83cb9SPrem Mallappa FIELD(STRTAB_BASE_CFG, LOG2SIZE, 0 , 6) 12110a83cb9SPrem Mallappa 12210a83cb9SPrem Mallappa #define A_CMDQ_BASE 0x90 /* 64b */ 12310a83cb9SPrem Mallappa REG32(CMDQ_PROD, 0x98) 12410a83cb9SPrem Mallappa REG32(CMDQ_CONS, 0x9c) 12510a83cb9SPrem Mallappa FIELD(CMDQ_CONS, ERR, 24, 7) 12610a83cb9SPrem Mallappa 12710a83cb9SPrem Mallappa #define A_EVENTQ_BASE 0xa0 /* 64b */ 12810a83cb9SPrem Mallappa REG32(EVENTQ_PROD, 0xa8) 12910a83cb9SPrem Mallappa REG32(EVENTQ_CONS, 0xac) 13010a83cb9SPrem Mallappa 13110a83cb9SPrem Mallappa #define A_EVENTQ_IRQ_CFG0 0xb0 /* 64b */ 13210a83cb9SPrem Mallappa REG32(EVENTQ_IRQ_CFG1, 0xb8) 13310a83cb9SPrem Mallappa REG32(EVENTQ_IRQ_CFG2, 0xbc) 13410a83cb9SPrem Mallappa 13510a83cb9SPrem Mallappa #define A_IDREGS 0xfd0 13610a83cb9SPrem Mallappa 13710a83cb9SPrem Mallappa static inline int smmu_enabled(SMMUv3State *s) 13810a83cb9SPrem Mallappa { 13910a83cb9SPrem Mallappa return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE); 14010a83cb9SPrem Mallappa } 14110a83cb9SPrem Mallappa 14210a83cb9SPrem Mallappa /* Command Queue Entry */ 14310a83cb9SPrem Mallappa typedef struct Cmd { 14410a83cb9SPrem Mallappa uint32_t word[4]; 14510a83cb9SPrem Mallappa } Cmd; 14610a83cb9SPrem Mallappa 14710a83cb9SPrem Mallappa /* Event Queue Entry */ 14810a83cb9SPrem Mallappa typedef struct Evt { 14910a83cb9SPrem Mallappa uint32_t word[8]; 15010a83cb9SPrem Mallappa } Evt; 15110a83cb9SPrem Mallappa 15210a83cb9SPrem Mallappa static inline uint32_t smmuv3_idreg(int regoffset) 15310a83cb9SPrem Mallappa { 15410a83cb9SPrem Mallappa /* 15510a83cb9SPrem Mallappa * Return the value of the Primecell/Corelink ID registers at the 15610a83cb9SPrem Mallappa * specified offset from the first ID register. 15710a83cb9SPrem Mallappa * These value indicate an ARM implementation of MMU600 p1 15810a83cb9SPrem Mallappa */ 15910a83cb9SPrem Mallappa static const uint8_t smmuv3_ids[] = { 16010a83cb9SPrem Mallappa 0x04, 0, 0, 0, 0x84, 0xB4, 0xF0, 0x10, 0x0D, 0xF0, 0x05, 0xB1 16110a83cb9SPrem Mallappa }; 16210a83cb9SPrem Mallappa return smmuv3_ids[regoffset / 4]; 16310a83cb9SPrem Mallappa } 16410a83cb9SPrem Mallappa 1656a736033SEric Auger static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s) 1666a736033SEric Auger { 1676a736033SEric Auger return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN); 1686a736033SEric Auger } 1696a736033SEric Auger 1706a736033SEric Auger static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s) 1716a736033SEric Auger { 1726a736033SEric Auger return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN); 1736a736033SEric Auger } 1746a736033SEric Auger 175dadd1a08SEric Auger /* Queue Handling */ 176dadd1a08SEric Auger 177dadd1a08SEric Auger #define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK) 178dadd1a08SEric Auger #define WRAP_MASK(q) (1 << (q)->log2size) 179dadd1a08SEric Auger #define INDEX_MASK(q) (((1 << (q)->log2size)) - 1) 180dadd1a08SEric Auger #define WRAP_INDEX_MASK(q) ((1 << ((q)->log2size + 1)) - 1) 181dadd1a08SEric Auger 182dadd1a08SEric Auger #define Q_CONS(q) ((q)->cons & INDEX_MASK(q)) 183dadd1a08SEric Auger #define Q_PROD(q) ((q)->prod & INDEX_MASK(q)) 184dadd1a08SEric Auger 185dadd1a08SEric Auger #define Q_CONS_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_CONS(q)) 186dadd1a08SEric Auger #define Q_PROD_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_PROD(q)) 187dadd1a08SEric Auger 188dadd1a08SEric Auger #define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size) 189dadd1a08SEric Auger #define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size) 190dadd1a08SEric Auger 191dadd1a08SEric Auger static inline bool smmuv3_q_full(SMMUQueue *q) 192dadd1a08SEric Auger { 193dadd1a08SEric Auger return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q); 194dadd1a08SEric Auger } 195dadd1a08SEric Auger 196dadd1a08SEric Auger static inline bool smmuv3_q_empty(SMMUQueue *q) 197dadd1a08SEric Auger { 198dadd1a08SEric Auger return (q->cons & WRAP_INDEX_MASK(q)) == (q->prod & WRAP_INDEX_MASK(q)); 199dadd1a08SEric Auger } 200dadd1a08SEric Auger 201dadd1a08SEric Auger static inline void queue_prod_incr(SMMUQueue *q) 202dadd1a08SEric Auger { 203dadd1a08SEric Auger q->prod = (q->prod + 1) & WRAP_INDEX_MASK(q); 204dadd1a08SEric Auger } 205dadd1a08SEric Auger 206dadd1a08SEric Auger static inline void queue_cons_incr(SMMUQueue *q) 207dadd1a08SEric Auger { 208dadd1a08SEric Auger /* 209dadd1a08SEric Auger * We have to use deposit for the CONS registers to preserve 210dadd1a08SEric Auger * the ERR field in the high bits. 211dadd1a08SEric Auger */ 212dadd1a08SEric Auger q->cons = deposit32(q->cons, 0, q->log2size + 1, q->cons + 1); 213dadd1a08SEric Auger } 214dadd1a08SEric Auger 215dadd1a08SEric Auger static inline bool smmuv3_cmdq_enabled(SMMUv3State *s) 216dadd1a08SEric Auger { 217dadd1a08SEric Auger return FIELD_EX32(s->cr[0], CR0, CMDQEN); 218dadd1a08SEric Auger } 219dadd1a08SEric Auger 220dadd1a08SEric Auger static inline bool smmuv3_eventq_enabled(SMMUv3State *s) 221dadd1a08SEric Auger { 222dadd1a08SEric Auger return FIELD_EX32(s->cr[0], CR0, EVENTQEN); 223dadd1a08SEric Auger } 224dadd1a08SEric Auger 225dadd1a08SEric Auger static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type) 226dadd1a08SEric Auger { 227dadd1a08SEric Auger s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type); 228dadd1a08SEric Auger } 229dadd1a08SEric Auger 230dadd1a08SEric Auger /* Commands */ 231dadd1a08SEric Auger 232dadd1a08SEric Auger typedef enum SMMUCommandType { 233dadd1a08SEric Auger SMMU_CMD_NONE = 0x00, 234dadd1a08SEric Auger SMMU_CMD_PREFETCH_CONFIG , 235dadd1a08SEric Auger SMMU_CMD_PREFETCH_ADDR, 236dadd1a08SEric Auger SMMU_CMD_CFGI_STE, 237dadd1a08SEric Auger SMMU_CMD_CFGI_STE_RANGE, 238dadd1a08SEric Auger SMMU_CMD_CFGI_CD, 239dadd1a08SEric Auger SMMU_CMD_CFGI_CD_ALL, 240dadd1a08SEric Auger SMMU_CMD_CFGI_ALL, 241dadd1a08SEric Auger SMMU_CMD_TLBI_NH_ALL = 0x10, 242dadd1a08SEric Auger SMMU_CMD_TLBI_NH_ASID, 243dadd1a08SEric Auger SMMU_CMD_TLBI_NH_VA, 244dadd1a08SEric Auger SMMU_CMD_TLBI_NH_VAA, 245dadd1a08SEric Auger SMMU_CMD_TLBI_EL3_ALL = 0x18, 246dadd1a08SEric Auger SMMU_CMD_TLBI_EL3_VA = 0x1a, 247dadd1a08SEric Auger SMMU_CMD_TLBI_EL2_ALL = 0x20, 248dadd1a08SEric Auger SMMU_CMD_TLBI_EL2_ASID, 249dadd1a08SEric Auger SMMU_CMD_TLBI_EL2_VA, 250dadd1a08SEric Auger SMMU_CMD_TLBI_EL2_VAA, 251dadd1a08SEric Auger SMMU_CMD_TLBI_S12_VMALL = 0x28, 252dadd1a08SEric Auger SMMU_CMD_TLBI_S2_IPA = 0x2a, 253dadd1a08SEric Auger SMMU_CMD_TLBI_NSNH_ALL = 0x30, 254dadd1a08SEric Auger SMMU_CMD_ATC_INV = 0x40, 255dadd1a08SEric Auger SMMU_CMD_PRI_RESP, 256dadd1a08SEric Auger SMMU_CMD_RESUME = 0x44, 257dadd1a08SEric Auger SMMU_CMD_STALL_TERM, 258dadd1a08SEric Auger SMMU_CMD_SYNC, 259dadd1a08SEric Auger } SMMUCommandType; 260dadd1a08SEric Auger 261dadd1a08SEric Auger static const char *cmd_stringify[] = { 262dadd1a08SEric Auger [SMMU_CMD_PREFETCH_CONFIG] = "SMMU_CMD_PREFETCH_CONFIG", 263dadd1a08SEric Auger [SMMU_CMD_PREFETCH_ADDR] = "SMMU_CMD_PREFETCH_ADDR", 264dadd1a08SEric Auger [SMMU_CMD_CFGI_STE] = "SMMU_CMD_CFGI_STE", 265dadd1a08SEric Auger [SMMU_CMD_CFGI_STE_RANGE] = "SMMU_CMD_CFGI_STE_RANGE", 266dadd1a08SEric Auger [SMMU_CMD_CFGI_CD] = "SMMU_CMD_CFGI_CD", 267dadd1a08SEric Auger [SMMU_CMD_CFGI_CD_ALL] = "SMMU_CMD_CFGI_CD_ALL", 268dadd1a08SEric Auger [SMMU_CMD_CFGI_ALL] = "SMMU_CMD_CFGI_ALL", 269dadd1a08SEric Auger [SMMU_CMD_TLBI_NH_ALL] = "SMMU_CMD_TLBI_NH_ALL", 270dadd1a08SEric Auger [SMMU_CMD_TLBI_NH_ASID] = "SMMU_CMD_TLBI_NH_ASID", 271dadd1a08SEric Auger [SMMU_CMD_TLBI_NH_VA] = "SMMU_CMD_TLBI_NH_VA", 272dadd1a08SEric Auger [SMMU_CMD_TLBI_NH_VAA] = "SMMU_CMD_TLBI_NH_VAA", 273dadd1a08SEric Auger [SMMU_CMD_TLBI_EL3_ALL] = "SMMU_CMD_TLBI_EL3_ALL", 274dadd1a08SEric Auger [SMMU_CMD_TLBI_EL3_VA] = "SMMU_CMD_TLBI_EL3_VA", 275dadd1a08SEric Auger [SMMU_CMD_TLBI_EL2_ALL] = "SMMU_CMD_TLBI_EL2_ALL", 276dadd1a08SEric Auger [SMMU_CMD_TLBI_EL2_ASID] = "SMMU_CMD_TLBI_EL2_ASID", 277dadd1a08SEric Auger [SMMU_CMD_TLBI_EL2_VA] = "SMMU_CMD_TLBI_EL2_VA", 278dadd1a08SEric Auger [SMMU_CMD_TLBI_EL2_VAA] = "SMMU_CMD_TLBI_EL2_VAA", 279dadd1a08SEric Auger [SMMU_CMD_TLBI_S12_VMALL] = "SMMU_CMD_TLBI_S12_VMALL", 280dadd1a08SEric Auger [SMMU_CMD_TLBI_S2_IPA] = "SMMU_CMD_TLBI_S2_IPA", 281dadd1a08SEric Auger [SMMU_CMD_TLBI_NSNH_ALL] = "SMMU_CMD_TLBI_NSNH_ALL", 282dadd1a08SEric Auger [SMMU_CMD_ATC_INV] = "SMMU_CMD_ATC_INV", 283dadd1a08SEric Auger [SMMU_CMD_PRI_RESP] = "SMMU_CMD_PRI_RESP", 284dadd1a08SEric Auger [SMMU_CMD_RESUME] = "SMMU_CMD_RESUME", 285dadd1a08SEric Auger [SMMU_CMD_STALL_TERM] = "SMMU_CMD_STALL_TERM", 286dadd1a08SEric Auger [SMMU_CMD_SYNC] = "SMMU_CMD_SYNC", 287dadd1a08SEric Auger }; 288dadd1a08SEric Auger 289dadd1a08SEric Auger static inline const char *smmu_cmd_string(SMMUCommandType type) 290dadd1a08SEric Auger { 291dadd1a08SEric Auger if (type > SMMU_CMD_NONE && type < ARRAY_SIZE(cmd_stringify)) { 292dadd1a08SEric Auger return cmd_stringify[type] ? cmd_stringify[type] : "UNKNOWN"; 293dadd1a08SEric Auger } else { 294dadd1a08SEric Auger return "INVALID"; 295dadd1a08SEric Auger } 296dadd1a08SEric Auger } 297dadd1a08SEric Auger 298dadd1a08SEric Auger /* CMDQ fields */ 299dadd1a08SEric Auger 300dadd1a08SEric Auger typedef enum { 301dadd1a08SEric Auger SMMU_CERROR_NONE = 0, 302dadd1a08SEric Auger SMMU_CERROR_ILL, 303dadd1a08SEric Auger SMMU_CERROR_ABT, 304dadd1a08SEric Auger SMMU_CERROR_ATC_INV_SYNC, 305dadd1a08SEric Auger } SMMUCmdError; 306dadd1a08SEric Auger 307dadd1a08SEric Auger enum { /* Command completion notification */ 308dadd1a08SEric Auger CMD_SYNC_SIG_NONE, 309dadd1a08SEric Auger CMD_SYNC_SIG_IRQ, 310dadd1a08SEric Auger CMD_SYNC_SIG_SEV, 311dadd1a08SEric Auger }; 312dadd1a08SEric Auger 313dadd1a08SEric Auger #define CMD_TYPE(x) extract32((x)->word[0], 0 , 8) 314d5291561SEric Auger #define CMD_NUM(x) extract32((x)->word[0], 12 , 5) 315d5291561SEric Auger #define CMD_SCALE(x) extract32((x)->word[0], 20 , 5) 316dadd1a08SEric Auger #define CMD_SSEC(x) extract32((x)->word[0], 10, 1) 317dadd1a08SEric Auger #define CMD_SSV(x) extract32((x)->word[0], 11, 1) 318dadd1a08SEric Auger #define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1) 319dadd1a08SEric Auger #define CMD_RESUME_AB(x) extract32((x)->word[0], 13, 1) 320dadd1a08SEric Auger #define CMD_SYNC_CS(x) extract32((x)->word[0], 12, 2) 321dadd1a08SEric Auger #define CMD_SSID(x) extract32((x)->word[0], 12, 20) 322dadd1a08SEric Auger #define CMD_SID(x) ((x)->word[1]) 323dadd1a08SEric Auger #define CMD_VMID(x) extract32((x)->word[1], 0 , 16) 324dadd1a08SEric Auger #define CMD_ASID(x) extract32((x)->word[1], 16, 16) 325dadd1a08SEric Auger #define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16) 326dadd1a08SEric Auger #define CMD_RESP(x) extract32((x)->word[2], 11, 2) 327dadd1a08SEric Auger #define CMD_LEAF(x) extract32((x)->word[2], 0 , 1) 328d5291561SEric Auger #define CMD_TTL(x) extract32((x)->word[2], 8 , 2) 329d5291561SEric Auger #define CMD_TG(x) extract32((x)->word[2], 10, 2) 330dadd1a08SEric Auger #define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5) 331*84abccddSPeter Maydell #define CMD_ADDR(x) \ 332*84abccddSPeter Maydell (((uint64_t)((x)->word[3]) << 32) | \ 333*84abccddSPeter Maydell ((extract64((x)->word[2], 12, 20)) << 12)) 334dadd1a08SEric Auger 335fae4be38SEric Auger #define SMMU_FEATURE_2LVL_STE (1 << 0) 336dadd1a08SEric Auger 337bb981004SEric Auger /* Events */ 338bb981004SEric Auger 339bb981004SEric Auger typedef enum SMMUEventType { 3409122bea9SJia He SMMU_EVT_NONE = 0x00, 341bb981004SEric Auger SMMU_EVT_F_UUT , 342bb981004SEric Auger SMMU_EVT_C_BAD_STREAMID , 343bb981004SEric Auger SMMU_EVT_F_STE_FETCH , 344bb981004SEric Auger SMMU_EVT_C_BAD_STE , 345bb981004SEric Auger SMMU_EVT_F_BAD_ATS_TREQ , 346bb981004SEric Auger SMMU_EVT_F_STREAM_DISABLED , 347bb981004SEric Auger SMMU_EVT_F_TRANS_FORBIDDEN , 348bb981004SEric Auger SMMU_EVT_C_BAD_SUBSTREAMID , 349bb981004SEric Auger SMMU_EVT_F_CD_FETCH , 350bb981004SEric Auger SMMU_EVT_C_BAD_CD , 351bb981004SEric Auger SMMU_EVT_F_WALK_EABT , 352bb981004SEric Auger SMMU_EVT_F_TRANSLATION = 0x10, 353bb981004SEric Auger SMMU_EVT_F_ADDR_SIZE , 354bb981004SEric Auger SMMU_EVT_F_ACCESS , 355bb981004SEric Auger SMMU_EVT_F_PERMISSION , 356bb981004SEric Auger SMMU_EVT_F_TLB_CONFLICT = 0x20, 357bb981004SEric Auger SMMU_EVT_F_CFG_CONFLICT , 358bb981004SEric Auger SMMU_EVT_E_PAGE_REQ = 0x24, 359bb981004SEric Auger } SMMUEventType; 360bb981004SEric Auger 361bb981004SEric Auger static const char *event_stringify[] = { 3629122bea9SJia He [SMMU_EVT_NONE] = "no recorded event", 363bb981004SEric Auger [SMMU_EVT_F_UUT] = "SMMU_EVT_F_UUT", 364bb981004SEric Auger [SMMU_EVT_C_BAD_STREAMID] = "SMMU_EVT_C_BAD_STREAMID", 365bb981004SEric Auger [SMMU_EVT_F_STE_FETCH] = "SMMU_EVT_F_STE_FETCH", 366bb981004SEric Auger [SMMU_EVT_C_BAD_STE] = "SMMU_EVT_C_BAD_STE", 367bb981004SEric Auger [SMMU_EVT_F_BAD_ATS_TREQ] = "SMMU_EVT_F_BAD_ATS_TREQ", 368bb981004SEric Auger [SMMU_EVT_F_STREAM_DISABLED] = "SMMU_EVT_F_STREAM_DISABLED", 369bb981004SEric Auger [SMMU_EVT_F_TRANS_FORBIDDEN] = "SMMU_EVT_F_TRANS_FORBIDDEN", 370bb981004SEric Auger [SMMU_EVT_C_BAD_SUBSTREAMID] = "SMMU_EVT_C_BAD_SUBSTREAMID", 371bb981004SEric Auger [SMMU_EVT_F_CD_FETCH] = "SMMU_EVT_F_CD_FETCH", 372bb981004SEric Auger [SMMU_EVT_C_BAD_CD] = "SMMU_EVT_C_BAD_CD", 373bb981004SEric Auger [SMMU_EVT_F_WALK_EABT] = "SMMU_EVT_F_WALK_EABT", 374bb981004SEric Auger [SMMU_EVT_F_TRANSLATION] = "SMMU_EVT_F_TRANSLATION", 375bb981004SEric Auger [SMMU_EVT_F_ADDR_SIZE] = "SMMU_EVT_F_ADDR_SIZE", 376bb981004SEric Auger [SMMU_EVT_F_ACCESS] = "SMMU_EVT_F_ACCESS", 377bb981004SEric Auger [SMMU_EVT_F_PERMISSION] = "SMMU_EVT_F_PERMISSION", 378bb981004SEric Auger [SMMU_EVT_F_TLB_CONFLICT] = "SMMU_EVT_F_TLB_CONFLICT", 379bb981004SEric Auger [SMMU_EVT_F_CFG_CONFLICT] = "SMMU_EVT_F_CFG_CONFLICT", 380bb981004SEric Auger [SMMU_EVT_E_PAGE_REQ] = "SMMU_EVT_E_PAGE_REQ", 381bb981004SEric Auger }; 382bb981004SEric Auger 383bb981004SEric Auger static inline const char *smmu_event_string(SMMUEventType type) 384bb981004SEric Auger { 385bb981004SEric Auger if (type < ARRAY_SIZE(event_stringify)) { 386bb981004SEric Auger return event_stringify[type] ? event_stringify[type] : "UNKNOWN"; 387bb981004SEric Auger } else { 388bb981004SEric Auger return "INVALID"; 389bb981004SEric Auger } 390bb981004SEric Auger } 391bb981004SEric Auger 392bb981004SEric Auger /* Encode an event record */ 393bb981004SEric Auger typedef struct SMMUEventInfo { 394bb981004SEric Auger SMMUEventType type; 395bb981004SEric Auger uint32_t sid; 396bb981004SEric Auger bool recorded; 3973499ec08SEric Auger bool inval_ste_allowed; 398bb981004SEric Auger union { 399bb981004SEric Auger struct { 400bb981004SEric Auger uint32_t ssid; 401bb981004SEric Auger bool ssv; 402bb981004SEric Auger dma_addr_t addr; 403bb981004SEric Auger bool rnw; 404bb981004SEric Auger bool pnu; 405bb981004SEric Auger bool ind; 406bb981004SEric Auger } f_uut; 407bb981004SEric Auger struct SSIDInfo { 408bb981004SEric Auger uint32_t ssid; 409bb981004SEric Auger bool ssv; 410bb981004SEric Auger } c_bad_streamid; 411bb981004SEric Auger struct SSIDAddrInfo { 412bb981004SEric Auger uint32_t ssid; 413bb981004SEric Auger bool ssv; 414bb981004SEric Auger dma_addr_t addr; 415bb981004SEric Auger } f_ste_fetch; 416bb981004SEric Auger struct SSIDInfo c_bad_ste; 417bb981004SEric Auger struct { 418bb981004SEric Auger dma_addr_t addr; 419bb981004SEric Auger bool rnw; 420bb981004SEric Auger } f_transl_forbidden; 421bb981004SEric Auger struct { 422bb981004SEric Auger uint32_t ssid; 423bb981004SEric Auger } c_bad_substream; 424bb981004SEric Auger struct SSIDAddrInfo f_cd_fetch; 425bb981004SEric Auger struct SSIDInfo c_bad_cd; 426bb981004SEric Auger struct FullInfo { 427bb981004SEric Auger bool stall; 428bb981004SEric Auger uint16_t stag; 429bb981004SEric Auger uint32_t ssid; 430bb981004SEric Auger bool ssv; 431bb981004SEric Auger bool s2; 432bb981004SEric Auger dma_addr_t addr; 433bb981004SEric Auger bool rnw; 434bb981004SEric Auger bool pnu; 435bb981004SEric Auger bool ind; 436bb981004SEric Auger uint8_t class; 437bb981004SEric Auger dma_addr_t addr2; 438bb981004SEric Auger } f_walk_eabt; 439bb981004SEric Auger struct FullInfo f_translation; 440bb981004SEric Auger struct FullInfo f_addr_size; 441bb981004SEric Auger struct FullInfo f_access; 442bb981004SEric Auger struct FullInfo f_permission; 443bb981004SEric Auger struct SSIDInfo f_cfg_conflict; 444bb981004SEric Auger /** 445bb981004SEric Auger * not supported yet: 446bb981004SEric Auger * F_BAD_ATS_TREQ 447bb981004SEric Auger * F_BAD_ATS_TREQ 448bb981004SEric Auger * F_TLB_CONFLICT 449bb981004SEric Auger * E_PAGE_REQUEST 450bb981004SEric Auger * IMPDEF_EVENTn 451bb981004SEric Auger */ 452bb981004SEric Auger } u; 453bb981004SEric Auger } SMMUEventInfo; 454bb981004SEric Auger 455bb981004SEric Auger /* EVTQ fields */ 456bb981004SEric Auger 457bb981004SEric Auger #define EVT_Q_OVERFLOW (1 << 31) 458bb981004SEric Auger 4599f4d2a13SEric Auger #define EVT_SET_TYPE(x, v) ((x)->word[0] = deposit32((x)->word[0], 0 , 8 , v)) 4609f4d2a13SEric Auger #define EVT_SET_SSV(x, v) ((x)->word[0] = deposit32((x)->word[0], 11, 1 , v)) 4619f4d2a13SEric Auger #define EVT_SET_SSID(x, v) ((x)->word[0] = deposit32((x)->word[0], 12, 20, v)) 462bb981004SEric Auger #define EVT_SET_SID(x, v) ((x)->word[1] = v) 4639f4d2a13SEric Auger #define EVT_SET_STAG(x, v) ((x)->word[2] = deposit32((x)->word[2], 0 , 16, v)) 4649f4d2a13SEric Auger #define EVT_SET_STALL(x, v) ((x)->word[2] = deposit32((x)->word[2], 31, 1 , v)) 4659f4d2a13SEric Auger #define EVT_SET_PNU(x, v) ((x)->word[3] = deposit32((x)->word[3], 1 , 1 , v)) 4669f4d2a13SEric Auger #define EVT_SET_IND(x, v) ((x)->word[3] = deposit32((x)->word[3], 2 , 1 , v)) 4679f4d2a13SEric Auger #define EVT_SET_RNW(x, v) ((x)->word[3] = deposit32((x)->word[3], 3 , 1 , v)) 4689f4d2a13SEric Auger #define EVT_SET_S2(x, v) ((x)->word[3] = deposit32((x)->word[3], 7 , 1 , v)) 4699f4d2a13SEric Auger #define EVT_SET_CLASS(x, v) ((x)->word[3] = deposit32((x)->word[3], 8 , 2 , v)) 470bb981004SEric Auger #define EVT_SET_ADDR(x, addr) \ 471bb981004SEric Auger do { \ 472bb981004SEric Auger (x)->word[5] = (uint32_t)(addr >> 32); \ 473bb981004SEric Auger (x)->word[4] = (uint32_t)(addr & 0xffffffff); \ 474bb981004SEric Auger } while (0) 475bb981004SEric Auger #define EVT_SET_ADDR2(x, addr) \ 476bb981004SEric Auger do { \ 477a7f65cebSSimon Veith (x)->word[7] = (uint32_t)(addr >> 32); \ 478a7f65cebSSimon Veith (x)->word[6] = (uint32_t)(addr & 0xffffffff); \ 479bb981004SEric Auger } while (0) 480bb981004SEric Auger 481bb981004SEric Auger void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); 482bb981004SEric Auger 4839bde7f06SEric Auger /* Configuration Data */ 4849bde7f06SEric Auger 4859bde7f06SEric Auger /* STE Level 1 Descriptor */ 4869bde7f06SEric Auger typedef struct STEDesc { 4879bde7f06SEric Auger uint32_t word[2]; 4889bde7f06SEric Auger } STEDesc; 4899bde7f06SEric Auger 4909bde7f06SEric Auger /* CD Level 1 Descriptor */ 4919bde7f06SEric Auger typedef struct CDDesc { 4929bde7f06SEric Auger uint32_t word[2]; 4939bde7f06SEric Auger } CDDesc; 4949bde7f06SEric Auger 4959bde7f06SEric Auger /* Stream Table Entry(STE) */ 4969bde7f06SEric Auger typedef struct STE { 4979bde7f06SEric Auger uint32_t word[16]; 4989bde7f06SEric Auger } STE; 4999bde7f06SEric Auger 5009bde7f06SEric Auger /* Context Descriptor(CD) */ 5019bde7f06SEric Auger typedef struct CD { 5029bde7f06SEric Auger uint32_t word[16]; 5039bde7f06SEric Auger } CD; 5049bde7f06SEric Auger 5059bde7f06SEric Auger /* STE fields */ 5069bde7f06SEric Auger 5079bde7f06SEric Auger #define STE_VALID(x) extract32((x)->word[0], 0, 1) 5089bde7f06SEric Auger 5099bde7f06SEric Auger #define STE_CONFIG(x) extract32((x)->word[0], 1, 3) 5109bde7f06SEric Auger #define STE_CFG_S1_ENABLED(config) (config & 0x1) 5119bde7f06SEric Auger #define STE_CFG_S2_ENABLED(config) (config & 0x2) 5129bde7f06SEric Auger #define STE_CFG_ABORT(config) (!(config & 0x4)) 5139bde7f06SEric Auger #define STE_CFG_BYPASS(config) (config == 0x4) 5149bde7f06SEric Auger 5159bde7f06SEric Auger #define STE_S1FMT(x) extract32((x)->word[0], 4 , 2) 5169bde7f06SEric Auger #define STE_S1CDMAX(x) extract32((x)->word[1], 27, 5) 5179bde7f06SEric Auger #define STE_S1STALLD(x) extract32((x)->word[2], 27, 1) 5189bde7f06SEric Auger #define STE_EATS(x) extract32((x)->word[2], 28, 2) 5199bde7f06SEric Auger #define STE_STRW(x) extract32((x)->word[2], 30, 2) 5209bde7f06SEric Auger #define STE_S2VMID(x) extract32((x)->word[4], 0 , 16) 5219bde7f06SEric Auger #define STE_S2T0SZ(x) extract32((x)->word[5], 0 , 6) 5229bde7f06SEric Auger #define STE_S2SL0(x) extract32((x)->word[5], 6 , 2) 5239bde7f06SEric Auger #define STE_S2TG(x) extract32((x)->word[5], 14, 2) 5249bde7f06SEric Auger #define STE_S2PS(x) extract32((x)->word[5], 16, 3) 5259bde7f06SEric Auger #define STE_S2AA64(x) extract32((x)->word[5], 19, 1) 52621eb5b5cSMostafa Saleh #define STE_S2ENDI(x) extract32((x)->word[5], 20, 1) 52721eb5b5cSMostafa Saleh #define STE_S2AFFD(x) extract32((x)->word[5], 21, 1) 52821eb5b5cSMostafa Saleh #define STE_S2HD(x) extract32((x)->word[5], 23, 1) 52921eb5b5cSMostafa Saleh #define STE_S2HA(x) extract32((x)->word[5], 24, 1) 53021eb5b5cSMostafa Saleh #define STE_S2S(x) extract32((x)->word[5], 25, 1) 53121eb5b5cSMostafa Saleh #define STE_S2R(x) extract32((x)->word[5], 26, 1) 53221eb5b5cSMostafa Saleh 5339bde7f06SEric Auger #define STE_CTXPTR(x) \ 534*84abccddSPeter Maydell ((extract64((x)->word[1], 0, 16) << 32) | \ 535*84abccddSPeter Maydell ((x)->word[0] & 0xffffffc0)) 5369bde7f06SEric Auger 5379bde7f06SEric Auger #define STE_S2TTB(x) \ 538*84abccddSPeter Maydell ((extract64((x)->word[7], 0, 16) << 32) | \ 539*84abccddSPeter Maydell ((x)->word[6] & 0xfffffff0)) 5409bde7f06SEric Auger 5419bde7f06SEric Auger static inline int oas2bits(int oas_field) 5429bde7f06SEric Auger { 5439bde7f06SEric Auger switch (oas_field) { 5449bde7f06SEric Auger case 0: 5459bde7f06SEric Auger return 32; 5469bde7f06SEric Auger case 1: 5479bde7f06SEric Auger return 36; 5489bde7f06SEric Auger case 2: 5499bde7f06SEric Auger return 40; 5509bde7f06SEric Auger case 3: 5519bde7f06SEric Auger return 42; 5529bde7f06SEric Auger case 4: 5539bde7f06SEric Auger return 44; 5549bde7f06SEric Auger case 5: 5559bde7f06SEric Auger return 48; 5569bde7f06SEric Auger } 5579bde7f06SEric Auger return -1; 5589bde7f06SEric Auger } 5599bde7f06SEric Auger 5609bde7f06SEric Auger static inline int pa_range(STE *ste) 5619bde7f06SEric Auger { 5629bde7f06SEric Auger int oas_field = MIN(STE_S2PS(ste), SMMU_IDR5_OAS); 5639bde7f06SEric Auger 5649bde7f06SEric Auger if (!STE_S2AA64(ste)) { 5659bde7f06SEric Auger return 40; 5669bde7f06SEric Auger } 5679bde7f06SEric Auger 5689bde7f06SEric Auger return oas2bits(oas_field); 5699bde7f06SEric Auger } 5709bde7f06SEric Auger 5719bde7f06SEric Auger #define MAX_PA(ste) ((1 << pa_range(ste)) - 1) 5729bde7f06SEric Auger 5739bde7f06SEric Auger /* CD fields */ 5749bde7f06SEric Auger 5751b41847aSJoe Komlodi #define CD_VALID(x) extract32((x)->word[0], 31, 1) 5769bde7f06SEric Auger #define CD_ASID(x) extract32((x)->word[1], 16, 16) 5779bde7f06SEric Auger #define CD_TTB(x, sel) \ 578*84abccddSPeter Maydell ((extract64((x)->word[(sel) * 2 + 3], 0, 19) << 32) | \ 579*84abccddSPeter Maydell ((x)->word[(sel) * 2 + 2] & ~0xfULL)) 580*84abccddSPeter Maydell 581e7c3b9d9SEric Auger #define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1) 5829bde7f06SEric Auger 5839bde7f06SEric Auger #define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6) 5849bde7f06SEric Auger #define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2) 5859bde7f06SEric Auger #define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1) 5869bde7f06SEric Auger #define CD_ENDI(x) extract32((x)->word[0], 15, 1) 5879bde7f06SEric Auger #define CD_IPS(x) extract32((x)->word[1], 0 , 3) 5889bde7f06SEric Auger #define CD_TBI(x) extract32((x)->word[1], 6 , 2) 5899bde7f06SEric Auger #define CD_HD(x) extract32((x)->word[1], 10 , 1) 5909bde7f06SEric Auger #define CD_HA(x) extract32((x)->word[1], 11 , 1) 5919bde7f06SEric Auger #define CD_S(x) extract32((x)->word[1], 12, 1) 5929bde7f06SEric Auger #define CD_R(x) extract32((x)->word[1], 13, 1) 5939bde7f06SEric Auger #define CD_A(x) extract32((x)->word[1], 14, 1) 5949bde7f06SEric Auger #define CD_AARCH64(x) extract32((x)->word[1], 9 , 1) 5959bde7f06SEric Auger 5969bde7f06SEric Auger /** 5979bde7f06SEric Auger * tg2granule - Decodes the CD translation granule size field according 5989bde7f06SEric Auger * to the ttbr in use 5999bde7f06SEric Auger * @bits: TG0/1 fields 6009bde7f06SEric Auger * @ttbr: ttbr index in use 6019bde7f06SEric Auger */ 6029bde7f06SEric Auger static inline int tg2granule(int bits, int ttbr) 6039bde7f06SEric Auger { 6049bde7f06SEric Auger switch (bits) { 6059bde7f06SEric Auger case 0: 6069bde7f06SEric Auger return ttbr ? 0 : 12; 6079bde7f06SEric Auger case 1: 6089bde7f06SEric Auger return ttbr ? 14 : 16; 6099bde7f06SEric Auger case 2: 6109bde7f06SEric Auger return ttbr ? 12 : 14; 6119bde7f06SEric Auger case 3: 6129bde7f06SEric Auger return ttbr ? 16 : 0; 6139bde7f06SEric Auger default: 6149bde7f06SEric Auger return 0; 6159bde7f06SEric Auger } 6169bde7f06SEric Auger } 6179bde7f06SEric Auger 6189bde7f06SEric Auger static inline uint64_t l1std_l2ptr(STEDesc *desc) 6199bde7f06SEric Auger { 6209bde7f06SEric Auger uint64_t hi, lo; 6219bde7f06SEric Auger 6229bde7f06SEric Auger hi = desc->word[1]; 6239bde7f06SEric Auger lo = desc->word[0] & ~0x1fULL; 6249bde7f06SEric Auger return hi << 32 | lo; 6259bde7f06SEric Auger } 6269bde7f06SEric Auger 627d9aad887SKunkun Jiang #define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5)) 6289bde7f06SEric Auger 62910a83cb9SPrem Mallappa #endif 630