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