1 /* 2 * ARM SMMUv3 support - Internal API 3 * 4 * Copyright (C) 2014-2016 Broadcom Corporation 5 * Copyright (c) 2017 Red Hat, Inc. 6 * Written by Prem Mallappa, Eric Auger 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef HW_ARM_SMMUV3_INTERNAL_H 22 #define HW_ARM_SMMUV3_INTERNAL_H 23 24 #include "hw/registerfields.h" 25 #include "hw/arm/smmu-common.h" 26 27 typedef enum SMMUTranslationStatus { 28 SMMU_TRANS_DISABLE, 29 SMMU_TRANS_ABORT, 30 SMMU_TRANS_BYPASS, 31 SMMU_TRANS_ERROR, 32 SMMU_TRANS_SUCCESS, 33 } SMMUTranslationStatus; 34 35 /* MMIO Registers */ 36 37 REG32(IDR0, 0x0) 38 FIELD(IDR0, S2P, 0 , 1) 39 FIELD(IDR0, S1P, 1 , 1) 40 FIELD(IDR0, TTF, 2 , 2) 41 FIELD(IDR0, COHACC, 4 , 1) 42 FIELD(IDR0, BTM, 5 , 1) 43 FIELD(IDR0, HTTU, 6 , 2) 44 FIELD(IDR0, DORMHINT, 8 , 1) 45 FIELD(IDR0, HYP, 9 , 1) 46 FIELD(IDR0, ATS, 10, 1) 47 FIELD(IDR0, NS1ATS, 11, 1) 48 FIELD(IDR0, ASID16, 12, 1) 49 FIELD(IDR0, MSI, 13, 1) 50 FIELD(IDR0, SEV, 14, 1) 51 FIELD(IDR0, ATOS, 15, 1) 52 FIELD(IDR0, PRI, 16, 1) 53 FIELD(IDR0, VMW, 17, 1) 54 FIELD(IDR0, VMID16, 18, 1) 55 FIELD(IDR0, CD2L, 19, 1) 56 FIELD(IDR0, VATOS, 20, 1) 57 FIELD(IDR0, TTENDIAN, 21, 2) 58 FIELD(IDR0, ATSRECERR, 23, 1) 59 FIELD(IDR0, STALL_MODEL, 24, 2) 60 FIELD(IDR0, TERM_MODEL, 26, 1) 61 FIELD(IDR0, STLEVEL, 27, 2) 62 FIELD(IDR0, RME_IMPL, 30, 1) 63 64 REG32(IDR1, 0x4) 65 FIELD(IDR1, SIDSIZE, 0 , 6) 66 FIELD(IDR1, SSIDSIZE, 6 , 5) 67 FIELD(IDR1, PRIQS, 11, 5) 68 FIELD(IDR1, EVENTQS, 16, 5) 69 FIELD(IDR1, CMDQS, 21, 5) 70 FIELD(IDR1, ATTR_PERMS_OVR, 26, 1) 71 FIELD(IDR1, ATTR_TYPES_OVR, 27, 1) 72 FIELD(IDR1, REL, 28, 1) 73 FIELD(IDR1, QUEUES_PRESET, 29, 1) 74 FIELD(IDR1, TABLES_PRESET, 30, 1) 75 FIELD(IDR1, ECMDQ, 31, 1) 76 77 #define SMMU_IDR1_SIDSIZE 16 78 #define SMMU_CMDQS 19 79 #define SMMU_EVENTQS 19 80 81 REG32(IDR2, 0x8) 82 FIELD(IDR2, BA_VATOS, 0, 10) 83 84 REG32(IDR3, 0xc) 85 FIELD(IDR3, HAD, 2, 1); 86 FIELD(IDR3, PBHA, 3, 1); 87 FIELD(IDR3, XNX, 4, 1); 88 FIELD(IDR3, PPS, 5, 1); 89 FIELD(IDR3, MPAM, 7, 1); 90 FIELD(IDR3, FWB, 8, 1); 91 FIELD(IDR3, STT, 9, 1); 92 FIELD(IDR3, RIL, 10, 1); 93 FIELD(IDR3, BBML, 11, 2); 94 FIELD(IDR3, E0PD, 13, 1); 95 FIELD(IDR3, PTWNNC, 14, 1); 96 FIELD(IDR3, DPT, 15, 1); 97 98 REG32(IDR4, 0x10) 99 100 REG32(IDR5, 0x14) 101 FIELD(IDR5, OAS, 0, 3); 102 FIELD(IDR5, GRAN4K, 4, 1); 103 FIELD(IDR5, GRAN16K, 5, 1); 104 FIELD(IDR5, GRAN64K, 6, 1); 105 FIELD(IDR5, VAX, 10, 2); 106 FIELD(IDR5, STALL_MAX, 16, 16); 107 108 #define SMMU_IDR5_OAS 4 109 110 REG32(IIDR, 0x18) 111 REG32(AIDR, 0x1c) 112 REG32(CR0, 0x20) 113 FIELD(CR0, SMMU_ENABLE, 0, 1) 114 FIELD(CR0, EVENTQEN, 2, 1) 115 FIELD(CR0, CMDQEN, 3, 1) 116 117 #define SMMU_CR0_RESERVED 0xFFFFFC20 118 119 REG32(CR0ACK, 0x24) 120 REG32(CR1, 0x28) 121 REG32(CR2, 0x2c) 122 REG32(STATUSR, 0x40) 123 REG32(GBPA, 0x44) 124 FIELD(GBPA, ABORT, 20, 1) 125 FIELD(GBPA, UPDATE, 31, 1) 126 127 /* Use incoming. */ 128 #define SMMU_GBPA_RESET_VAL 0x1000 129 130 REG32(IRQ_CTRL, 0x50) 131 FIELD(IRQ_CTRL, GERROR_IRQEN, 0, 1) 132 FIELD(IRQ_CTRL, PRI_IRQEN, 1, 1) 133 FIELD(IRQ_CTRL, EVENTQ_IRQEN, 2, 1) 134 135 REG32(IRQ_CTRL_ACK, 0x54) 136 REG32(GERROR, 0x60) 137 FIELD(GERROR, CMDQ_ERR, 0, 1) 138 FIELD(GERROR, EVENTQ_ABT_ERR, 2, 1) 139 FIELD(GERROR, PRIQ_ABT_ERR, 3, 1) 140 FIELD(GERROR, MSI_CMDQ_ABT_ERR, 4, 1) 141 FIELD(GERROR, MSI_EVENTQ_ABT_ERR, 5, 1) 142 FIELD(GERROR, MSI_PRIQ_ABT_ERR, 6, 1) 143 FIELD(GERROR, MSI_GERROR_ABT_ERR, 7, 1) 144 FIELD(GERROR, MSI_SFM_ERR, 8, 1) 145 146 REG32(GERRORN, 0x64) 147 148 #define A_GERROR_IRQ_CFG0 0x68 /* 64b */ 149 REG32(GERROR_IRQ_CFG1, 0x70) 150 REG32(GERROR_IRQ_CFG2, 0x74) 151 152 #define A_STRTAB_BASE 0x80 /* 64b */ 153 154 #define SMMU_BASE_ADDR_MASK 0xfffffffffffc0 155 156 REG32(STRTAB_BASE_CFG, 0x88) 157 FIELD(STRTAB_BASE_CFG, FMT, 16, 2) 158 FIELD(STRTAB_BASE_CFG, SPLIT, 6 , 5) 159 FIELD(STRTAB_BASE_CFG, LOG2SIZE, 0 , 6) 160 161 #define A_CMDQ_BASE 0x90 /* 64b */ 162 REG32(CMDQ_PROD, 0x98) 163 REG32(CMDQ_CONS, 0x9c) 164 FIELD(CMDQ_CONS, ERR, 24, 7) 165 166 #define A_EVENTQ_BASE 0xa0 /* 64b */ 167 REG32(EVENTQ_PROD, 0xa8) 168 REG32(EVENTQ_CONS, 0xac) 169 170 #define A_EVENTQ_IRQ_CFG0 0xb0 /* 64b */ 171 REG32(EVENTQ_IRQ_CFG1, 0xb8) 172 REG32(EVENTQ_IRQ_CFG2, 0xbc) 173 174 #define A_IDREGS 0xfd0 175 176 static inline int smmu_enabled(SMMUv3State *s) 177 { 178 return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE); 179 } 180 181 /* Command Queue Entry */ 182 typedef struct Cmd { 183 uint32_t word[4]; 184 } Cmd; 185 186 /* Event Queue Entry */ 187 typedef struct Evt { 188 uint32_t word[8]; 189 } Evt; 190 191 static inline uint32_t smmuv3_idreg(int regoffset) 192 { 193 /* 194 * Return the value of the Primecell/Corelink ID registers at the 195 * specified offset from the first ID register. 196 * These value indicate an ARM implementation of MMU600 p1 197 */ 198 static const uint8_t smmuv3_ids[] = { 199 0x04, 0, 0, 0, 0x84, 0xB4, 0xF0, 0x10, 0x0D, 0xF0, 0x05, 0xB1 200 }; 201 return smmuv3_ids[regoffset / 4]; 202 } 203 204 static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s) 205 { 206 return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN); 207 } 208 209 static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s) 210 { 211 return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN); 212 } 213 214 /* Queue Handling */ 215 216 #define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK) 217 #define WRAP_MASK(q) (1 << (q)->log2size) 218 #define INDEX_MASK(q) (((1 << (q)->log2size)) - 1) 219 #define WRAP_INDEX_MASK(q) ((1 << ((q)->log2size + 1)) - 1) 220 221 #define Q_CONS(q) ((q)->cons & INDEX_MASK(q)) 222 #define Q_PROD(q) ((q)->prod & INDEX_MASK(q)) 223 224 #define Q_CONS_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_CONS(q)) 225 #define Q_PROD_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_PROD(q)) 226 227 #define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size) 228 #define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size) 229 230 static inline bool smmuv3_q_full(SMMUQueue *q) 231 { 232 return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q); 233 } 234 235 static inline bool smmuv3_q_empty(SMMUQueue *q) 236 { 237 return (q->cons & WRAP_INDEX_MASK(q)) == (q->prod & WRAP_INDEX_MASK(q)); 238 } 239 240 static inline void queue_prod_incr(SMMUQueue *q) 241 { 242 q->prod = (q->prod + 1) & WRAP_INDEX_MASK(q); 243 } 244 245 static inline void queue_cons_incr(SMMUQueue *q) 246 { 247 /* 248 * We have to use deposit for the CONS registers to preserve 249 * the ERR field in the high bits. 250 */ 251 q->cons = deposit32(q->cons, 0, q->log2size + 1, q->cons + 1); 252 } 253 254 static inline bool smmuv3_cmdq_enabled(SMMUv3State *s) 255 { 256 return FIELD_EX32(s->cr[0], CR0, CMDQEN); 257 } 258 259 static inline bool smmuv3_eventq_enabled(SMMUv3State *s) 260 { 261 return FIELD_EX32(s->cr[0], CR0, EVENTQEN); 262 } 263 264 static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type) 265 { 266 s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type); 267 } 268 269 /* Commands */ 270 271 typedef enum SMMUCommandType { 272 SMMU_CMD_NONE = 0x00, 273 SMMU_CMD_PREFETCH_CONFIG , 274 SMMU_CMD_PREFETCH_ADDR, 275 SMMU_CMD_CFGI_STE, 276 SMMU_CMD_CFGI_STE_RANGE, 277 SMMU_CMD_CFGI_CD, 278 SMMU_CMD_CFGI_CD_ALL, 279 SMMU_CMD_CFGI_ALL, 280 SMMU_CMD_TLBI_NH_ALL = 0x10, 281 SMMU_CMD_TLBI_NH_ASID, 282 SMMU_CMD_TLBI_NH_VA, 283 SMMU_CMD_TLBI_NH_VAA, 284 SMMU_CMD_TLBI_EL3_ALL = 0x18, 285 SMMU_CMD_TLBI_EL3_VA = 0x1a, 286 SMMU_CMD_TLBI_EL2_ALL = 0x20, 287 SMMU_CMD_TLBI_EL2_ASID, 288 SMMU_CMD_TLBI_EL2_VA, 289 SMMU_CMD_TLBI_EL2_VAA, 290 SMMU_CMD_TLBI_S12_VMALL = 0x28, 291 SMMU_CMD_TLBI_S2_IPA = 0x2a, 292 SMMU_CMD_TLBI_NSNH_ALL = 0x30, 293 SMMU_CMD_ATC_INV = 0x40, 294 SMMU_CMD_PRI_RESP, 295 SMMU_CMD_RESUME = 0x44, 296 SMMU_CMD_STALL_TERM, 297 SMMU_CMD_SYNC, 298 } SMMUCommandType; 299 300 static const char *cmd_stringify[] = { 301 [SMMU_CMD_PREFETCH_CONFIG] = "SMMU_CMD_PREFETCH_CONFIG", 302 [SMMU_CMD_PREFETCH_ADDR] = "SMMU_CMD_PREFETCH_ADDR", 303 [SMMU_CMD_CFGI_STE] = "SMMU_CMD_CFGI_STE", 304 [SMMU_CMD_CFGI_STE_RANGE] = "SMMU_CMD_CFGI_STE_RANGE", 305 [SMMU_CMD_CFGI_CD] = "SMMU_CMD_CFGI_CD", 306 [SMMU_CMD_CFGI_CD_ALL] = "SMMU_CMD_CFGI_CD_ALL", 307 [SMMU_CMD_CFGI_ALL] = "SMMU_CMD_CFGI_ALL", 308 [SMMU_CMD_TLBI_NH_ALL] = "SMMU_CMD_TLBI_NH_ALL", 309 [SMMU_CMD_TLBI_NH_ASID] = "SMMU_CMD_TLBI_NH_ASID", 310 [SMMU_CMD_TLBI_NH_VA] = "SMMU_CMD_TLBI_NH_VA", 311 [SMMU_CMD_TLBI_NH_VAA] = "SMMU_CMD_TLBI_NH_VAA", 312 [SMMU_CMD_TLBI_EL3_ALL] = "SMMU_CMD_TLBI_EL3_ALL", 313 [SMMU_CMD_TLBI_EL3_VA] = "SMMU_CMD_TLBI_EL3_VA", 314 [SMMU_CMD_TLBI_EL2_ALL] = "SMMU_CMD_TLBI_EL2_ALL", 315 [SMMU_CMD_TLBI_EL2_ASID] = "SMMU_CMD_TLBI_EL2_ASID", 316 [SMMU_CMD_TLBI_EL2_VA] = "SMMU_CMD_TLBI_EL2_VA", 317 [SMMU_CMD_TLBI_EL2_VAA] = "SMMU_CMD_TLBI_EL2_VAA", 318 [SMMU_CMD_TLBI_S12_VMALL] = "SMMU_CMD_TLBI_S12_VMALL", 319 [SMMU_CMD_TLBI_S2_IPA] = "SMMU_CMD_TLBI_S2_IPA", 320 [SMMU_CMD_TLBI_NSNH_ALL] = "SMMU_CMD_TLBI_NSNH_ALL", 321 [SMMU_CMD_ATC_INV] = "SMMU_CMD_ATC_INV", 322 [SMMU_CMD_PRI_RESP] = "SMMU_CMD_PRI_RESP", 323 [SMMU_CMD_RESUME] = "SMMU_CMD_RESUME", 324 [SMMU_CMD_STALL_TERM] = "SMMU_CMD_STALL_TERM", 325 [SMMU_CMD_SYNC] = "SMMU_CMD_SYNC", 326 }; 327 328 static inline const char *smmu_cmd_string(SMMUCommandType type) 329 { 330 if (type > SMMU_CMD_NONE && type < ARRAY_SIZE(cmd_stringify)) { 331 return cmd_stringify[type] ? cmd_stringify[type] : "UNKNOWN"; 332 } else { 333 return "INVALID"; 334 } 335 } 336 337 /* CMDQ fields */ 338 339 typedef enum { 340 SMMU_CERROR_NONE = 0, 341 SMMU_CERROR_ILL, 342 SMMU_CERROR_ABT, 343 SMMU_CERROR_ATC_INV_SYNC, 344 } SMMUCmdError; 345 346 enum { /* Command completion notification */ 347 CMD_SYNC_SIG_NONE, 348 CMD_SYNC_SIG_IRQ, 349 CMD_SYNC_SIG_SEV, 350 }; 351 352 #define CMD_TYPE(x) extract32((x)->word[0], 0 , 8) 353 #define CMD_NUM(x) extract32((x)->word[0], 12 , 5) 354 #define CMD_SCALE(x) extract32((x)->word[0], 20 , 5) 355 #define CMD_SSEC(x) extract32((x)->word[0], 10, 1) 356 #define CMD_SSV(x) extract32((x)->word[0], 11, 1) 357 #define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1) 358 #define CMD_RESUME_AB(x) extract32((x)->word[0], 13, 1) 359 #define CMD_SYNC_CS(x) extract32((x)->word[0], 12, 2) 360 #define CMD_SSID(x) extract32((x)->word[0], 12, 20) 361 #define CMD_SID(x) ((x)->word[1]) 362 #define CMD_VMID(x) extract32((x)->word[1], 0 , 16) 363 #define CMD_ASID(x) extract32((x)->word[1], 16, 16) 364 #define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16) 365 #define CMD_RESP(x) extract32((x)->word[2], 11, 2) 366 #define CMD_LEAF(x) extract32((x)->word[2], 0 , 1) 367 #define CMD_TTL(x) extract32((x)->word[2], 8 , 2) 368 #define CMD_TG(x) extract32((x)->word[2], 10, 2) 369 #define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5) 370 #define CMD_ADDR(x) \ 371 (((uint64_t)((x)->word[3]) << 32) | \ 372 ((extract64((x)->word[2], 12, 20)) << 12)) 373 374 #define SMMU_FEATURE_2LVL_STE (1 << 0) 375 376 /* Events */ 377 378 typedef enum SMMUEventType { 379 SMMU_EVT_NONE = 0x00, 380 SMMU_EVT_F_UUT , 381 SMMU_EVT_C_BAD_STREAMID , 382 SMMU_EVT_F_STE_FETCH , 383 SMMU_EVT_C_BAD_STE , 384 SMMU_EVT_F_BAD_ATS_TREQ , 385 SMMU_EVT_F_STREAM_DISABLED , 386 SMMU_EVT_F_TRANS_FORBIDDEN , 387 SMMU_EVT_C_BAD_SUBSTREAMID , 388 SMMU_EVT_F_CD_FETCH , 389 SMMU_EVT_C_BAD_CD , 390 SMMU_EVT_F_WALK_EABT , 391 SMMU_EVT_F_TRANSLATION = 0x10, 392 SMMU_EVT_F_ADDR_SIZE , 393 SMMU_EVT_F_ACCESS , 394 SMMU_EVT_F_PERMISSION , 395 SMMU_EVT_F_TLB_CONFLICT = 0x20, 396 SMMU_EVT_F_CFG_CONFLICT , 397 SMMU_EVT_E_PAGE_REQ = 0x24, 398 } SMMUEventType; 399 400 static const char *event_stringify[] = { 401 [SMMU_EVT_NONE] = "no recorded event", 402 [SMMU_EVT_F_UUT] = "SMMU_EVT_F_UUT", 403 [SMMU_EVT_C_BAD_STREAMID] = "SMMU_EVT_C_BAD_STREAMID", 404 [SMMU_EVT_F_STE_FETCH] = "SMMU_EVT_F_STE_FETCH", 405 [SMMU_EVT_C_BAD_STE] = "SMMU_EVT_C_BAD_STE", 406 [SMMU_EVT_F_BAD_ATS_TREQ] = "SMMU_EVT_F_BAD_ATS_TREQ", 407 [SMMU_EVT_F_STREAM_DISABLED] = "SMMU_EVT_F_STREAM_DISABLED", 408 [SMMU_EVT_F_TRANS_FORBIDDEN] = "SMMU_EVT_F_TRANS_FORBIDDEN", 409 [SMMU_EVT_C_BAD_SUBSTREAMID] = "SMMU_EVT_C_BAD_SUBSTREAMID", 410 [SMMU_EVT_F_CD_FETCH] = "SMMU_EVT_F_CD_FETCH", 411 [SMMU_EVT_C_BAD_CD] = "SMMU_EVT_C_BAD_CD", 412 [SMMU_EVT_F_WALK_EABT] = "SMMU_EVT_F_WALK_EABT", 413 [SMMU_EVT_F_TRANSLATION] = "SMMU_EVT_F_TRANSLATION", 414 [SMMU_EVT_F_ADDR_SIZE] = "SMMU_EVT_F_ADDR_SIZE", 415 [SMMU_EVT_F_ACCESS] = "SMMU_EVT_F_ACCESS", 416 [SMMU_EVT_F_PERMISSION] = "SMMU_EVT_F_PERMISSION", 417 [SMMU_EVT_F_TLB_CONFLICT] = "SMMU_EVT_F_TLB_CONFLICT", 418 [SMMU_EVT_F_CFG_CONFLICT] = "SMMU_EVT_F_CFG_CONFLICT", 419 [SMMU_EVT_E_PAGE_REQ] = "SMMU_EVT_E_PAGE_REQ", 420 }; 421 422 static inline const char *smmu_event_string(SMMUEventType type) 423 { 424 if (type < ARRAY_SIZE(event_stringify)) { 425 return event_stringify[type] ? event_stringify[type] : "UNKNOWN"; 426 } else { 427 return "INVALID"; 428 } 429 } 430 431 /* Encode an event record */ 432 typedef struct SMMUEventInfo { 433 SMMUEventType type; 434 uint32_t sid; 435 bool recorded; 436 bool inval_ste_allowed; 437 union { 438 struct { 439 uint32_t ssid; 440 bool ssv; 441 dma_addr_t addr; 442 bool rnw; 443 bool pnu; 444 bool ind; 445 } f_uut; 446 struct SSIDInfo { 447 uint32_t ssid; 448 bool ssv; 449 } c_bad_streamid; 450 struct SSIDAddrInfo { 451 uint32_t ssid; 452 bool ssv; 453 dma_addr_t addr; 454 } f_ste_fetch; 455 struct SSIDInfo c_bad_ste; 456 struct { 457 dma_addr_t addr; 458 bool rnw; 459 } f_transl_forbidden; 460 struct { 461 uint32_t ssid; 462 } c_bad_substream; 463 struct SSIDAddrInfo f_cd_fetch; 464 struct SSIDInfo c_bad_cd; 465 struct FullInfo { 466 bool stall; 467 uint16_t stag; 468 uint32_t ssid; 469 bool ssv; 470 bool s2; 471 dma_addr_t addr; 472 bool rnw; 473 bool pnu; 474 bool ind; 475 uint8_t class; 476 dma_addr_t addr2; 477 } f_walk_eabt; 478 struct FullInfo f_translation; 479 struct FullInfo f_addr_size; 480 struct FullInfo f_access; 481 struct FullInfo f_permission; 482 struct SSIDInfo f_cfg_conflict; 483 /** 484 * not supported yet: 485 * F_BAD_ATS_TREQ 486 * F_BAD_ATS_TREQ 487 * F_TLB_CONFLICT 488 * E_PAGE_REQUEST 489 * IMPDEF_EVENTn 490 */ 491 } u; 492 } SMMUEventInfo; 493 494 /* EVTQ fields */ 495 496 #define EVT_Q_OVERFLOW (1 << 31) 497 498 #define EVT_SET_TYPE(x, v) ((x)->word[0] = deposit32((x)->word[0], 0 , 8 , v)) 499 #define EVT_SET_SSV(x, v) ((x)->word[0] = deposit32((x)->word[0], 11, 1 , v)) 500 #define EVT_SET_SSID(x, v) ((x)->word[0] = deposit32((x)->word[0], 12, 20, v)) 501 #define EVT_SET_SID(x, v) ((x)->word[1] = v) 502 #define EVT_SET_STAG(x, v) ((x)->word[2] = deposit32((x)->word[2], 0 , 16, v)) 503 #define EVT_SET_STALL(x, v) ((x)->word[2] = deposit32((x)->word[2], 31, 1 , v)) 504 #define EVT_SET_PNU(x, v) ((x)->word[3] = deposit32((x)->word[3], 1 , 1 , v)) 505 #define EVT_SET_IND(x, v) ((x)->word[3] = deposit32((x)->word[3], 2 , 1 , v)) 506 #define EVT_SET_RNW(x, v) ((x)->word[3] = deposit32((x)->word[3], 3 , 1 , v)) 507 #define EVT_SET_S2(x, v) ((x)->word[3] = deposit32((x)->word[3], 7 , 1 , v)) 508 #define EVT_SET_CLASS(x, v) ((x)->word[3] = deposit32((x)->word[3], 8 , 2 , v)) 509 #define EVT_SET_ADDR(x, addr) \ 510 do { \ 511 (x)->word[5] = (uint32_t)(addr >> 32); \ 512 (x)->word[4] = (uint32_t)(addr & 0xffffffff); \ 513 } while (0) 514 #define EVT_SET_ADDR2(x, addr) \ 515 do { \ 516 (x)->word[7] = (uint32_t)(addr >> 32); \ 517 (x)->word[6] = (uint32_t)(addr & 0xffffffff); \ 518 } while (0) 519 520 void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); 521 522 /* Configuration Data */ 523 524 /* STE Level 1 Descriptor */ 525 typedef struct STEDesc { 526 uint32_t word[2]; 527 } STEDesc; 528 529 /* CD Level 1 Descriptor */ 530 typedef struct CDDesc { 531 uint32_t word[2]; 532 } CDDesc; 533 534 /* Stream Table Entry(STE) */ 535 typedef struct STE { 536 uint32_t word[16]; 537 } STE; 538 539 /* Context Descriptor(CD) */ 540 typedef struct CD { 541 uint32_t word[16]; 542 } CD; 543 544 /* STE fields */ 545 546 #define STE_VALID(x) extract32((x)->word[0], 0, 1) 547 548 #define STE_CONFIG(x) extract32((x)->word[0], 1, 3) 549 #define STE_CFG_S1_ENABLED(config) (config & 0x1) 550 #define STE_CFG_S2_ENABLED(config) (config & 0x2) 551 #define STE_CFG_ABORT(config) (!(config & 0x4)) 552 #define STE_CFG_BYPASS(config) (config == 0x4) 553 554 #define STE_S1FMT(x) extract32((x)->word[0], 4 , 2) 555 #define STE_S1CDMAX(x) extract32((x)->word[1], 27, 5) 556 #define STE_S1STALLD(x) extract32((x)->word[2], 27, 1) 557 #define STE_EATS(x) extract32((x)->word[2], 28, 2) 558 #define STE_STRW(x) extract32((x)->word[2], 30, 2) 559 #define STE_S2VMID(x) extract32((x)->word[4], 0 , 16) 560 #define STE_S2T0SZ(x) extract32((x)->word[5], 0 , 6) 561 #define STE_S2SL0(x) extract32((x)->word[5], 6 , 2) 562 #define STE_S2TG(x) extract32((x)->word[5], 14, 2) 563 #define STE_S2PS(x) extract32((x)->word[5], 16, 3) 564 #define STE_S2AA64(x) extract32((x)->word[5], 19, 1) 565 #define STE_S2ENDI(x) extract32((x)->word[5], 20, 1) 566 #define STE_S2AFFD(x) extract32((x)->word[5], 21, 1) 567 #define STE_S2HD(x) extract32((x)->word[5], 23, 1) 568 #define STE_S2HA(x) extract32((x)->word[5], 24, 1) 569 #define STE_S2S(x) extract32((x)->word[5], 25, 1) 570 #define STE_S2R(x) extract32((x)->word[5], 26, 1) 571 572 #define STE_CTXPTR(x) \ 573 ((extract64((x)->word[1], 0, 16) << 32) | \ 574 ((x)->word[0] & 0xffffffc0)) 575 576 #define STE_S2TTB(x) \ 577 ((extract64((x)->word[7], 0, 16) << 32) | \ 578 ((x)->word[6] & 0xfffffff0)) 579 580 static inline int oas2bits(int oas_field) 581 { 582 switch (oas_field) { 583 case 0: 584 return 32; 585 case 1: 586 return 36; 587 case 2: 588 return 40; 589 case 3: 590 return 42; 591 case 4: 592 return 44; 593 case 5: 594 return 48; 595 } 596 return -1; 597 } 598 599 static inline int pa_range(STE *ste) 600 { 601 int oas_field = MIN(STE_S2PS(ste), SMMU_IDR5_OAS); 602 603 if (!STE_S2AA64(ste)) { 604 return 40; 605 } 606 607 return oas2bits(oas_field); 608 } 609 610 #define MAX_PA(ste) ((1 << pa_range(ste)) - 1) 611 612 /* CD fields */ 613 614 #define CD_VALID(x) extract32((x)->word[0], 31, 1) 615 #define CD_ASID(x) extract32((x)->word[1], 16, 16) 616 #define CD_TTB(x, sel) \ 617 ((extract64((x)->word[(sel) * 2 + 3], 0, 19) << 32) | \ 618 ((x)->word[(sel) * 2 + 2] & ~0xfULL)) 619 620 #define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1) 621 622 #define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6) 623 #define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2) 624 #define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1) 625 #define CD_ENDI(x) extract32((x)->word[0], 15, 1) 626 #define CD_IPS(x) extract32((x)->word[1], 0 , 3) 627 #define CD_TBI(x) extract32((x)->word[1], 6 , 2) 628 #define CD_HD(x) extract32((x)->word[1], 10 , 1) 629 #define CD_HA(x) extract32((x)->word[1], 11 , 1) 630 #define CD_S(x) extract32((x)->word[1], 12, 1) 631 #define CD_R(x) extract32((x)->word[1], 13, 1) 632 #define CD_A(x) extract32((x)->word[1], 14, 1) 633 #define CD_AARCH64(x) extract32((x)->word[1], 9 , 1) 634 635 /** 636 * tg2granule - Decodes the CD translation granule size field according 637 * to the ttbr in use 638 * @bits: TG0/1 fields 639 * @ttbr: ttbr index in use 640 */ 641 static inline int tg2granule(int bits, int ttbr) 642 { 643 switch (bits) { 644 case 0: 645 return ttbr ? 0 : 12; 646 case 1: 647 return ttbr ? 14 : 16; 648 case 2: 649 return ttbr ? 12 : 14; 650 case 3: 651 return ttbr ? 16 : 0; 652 default: 653 return 0; 654 } 655 } 656 657 static inline uint64_t l1std_l2ptr(STEDesc *desc) 658 { 659 uint64_t hi, lo; 660 661 hi = desc->word[1]; 662 lo = desc->word[0] & ~0x1fULL; 663 return hi << 32 | lo; 664 } 665 666 #define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5)) 667 668 #endif 669