]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/smmuv3-internal.h
hw/fsi: Introduce IBM's cfam
[mirror_qemu.git] / hw / arm / smmuv3-internal.h
CommitLineData
10a83cb9
PM
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
58ea30f5
MA
21#ifndef HW_ARM_SMMUV3_INTERNAL_H
22#define HW_ARM_SMMUV3_INTERNAL_H
10a83cb9 23
7b31c2db 24#include "hw/registerfields.h"
10a83cb9
PM
25#include "hw/arm/smmu-common.h"
26
9122bea9
JH
27typedef 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
10a83cb9
PM
35/* MMIO Registers */
36
37REG32(IDR0, 0x0)
263d0e48 38 FIELD(IDR0, S2P, 0 , 1)
10a83cb9
PM
39 FIELD(IDR0, S1P, 1 , 1)
40 FIELD(IDR0, TTF, 2 , 2)
41 FIELD(IDR0, COHACC, 4 , 1)
cbaf9404
PM
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)
10a83cb9 48 FIELD(IDR0, ASID16, 12, 1)
cbaf9404
PM
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)
263d0e48 54 FIELD(IDR0, VMID16, 18, 1)
cbaf9404
PM
55 FIELD(IDR0, CD2L, 19, 1)
56 FIELD(IDR0, VATOS, 20, 1)
10a83cb9 57 FIELD(IDR0, TTENDIAN, 21, 2)
cbaf9404 58 FIELD(IDR0, ATSRECERR, 23, 1)
10a83cb9
PM
59 FIELD(IDR0, STALL_MODEL, 24, 2)
60 FIELD(IDR0, TERM_MODEL, 26, 1)
61 FIELD(IDR0, STLEVEL, 27, 2)
cbaf9404 62 FIELD(IDR0, RME_IMPL, 30, 1)
10a83cb9
PM
63
64REG32(IDR1, 0x4)
65 FIELD(IDR1, SIDSIZE, 0 , 6)
cbaf9404
PM
66 FIELD(IDR1, SSIDSIZE, 6 , 5)
67 FIELD(IDR1, PRIQS, 11, 5)
10a83cb9
PM
68 FIELD(IDR1, EVENTQS, 16, 5)
69 FIELD(IDR1, CMDQS, 21, 5)
cbaf9404
PM
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)
10a83cb9
PM
76
77#define SMMU_IDR1_SIDSIZE 16
78#define SMMU_CMDQS 19
79#define SMMU_EVENTQS 19
80
81REG32(IDR2, 0x8)
cbaf9404
PM
82 FIELD(IDR2, BA_VATOS, 0, 10)
83
10a83cb9 84REG32(IDR3, 0xc)
e7c3b9d9 85 FIELD(IDR3, HAD, 2, 1);
cbaf9404
PM
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);
de206dfd 92 FIELD(IDR3, RIL, 10, 1);
f8e7163d 93 FIELD(IDR3, BBML, 11, 2);
cbaf9404
PM
94 FIELD(IDR3, E0PD, 13, 1);
95 FIELD(IDR3, PTWNNC, 14, 1);
96 FIELD(IDR3, DPT, 15, 1);
97
10a83cb9 98REG32(IDR4, 0x10)
cbaf9404 99
10a83cb9
PM
100REG32(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);
cbaf9404
PM
105 FIELD(IDR5, VAX, 10, 2);
106 FIELD(IDR5, STALL_MAX, 16, 16);
10a83cb9
PM
107
108#define SMMU_IDR5_OAS 4
109
f0ec277c 110REG32(IIDR, 0x18)
5888f0ad 111REG32(AIDR, 0x1c)
10a83cb9
PM
112REG32(CR0, 0x20)
113 FIELD(CR0, SMMU_ENABLE, 0, 1)
114 FIELD(CR0, EVENTQEN, 2, 1)
115 FIELD(CR0, CMDQEN, 3, 1)
116
fae4be38
EA
117#define SMMU_CR0_RESERVED 0xFFFFFC20
118
10a83cb9
PM
119REG32(CR0ACK, 0x24)
120REG32(CR1, 0x28)
121REG32(CR2, 0x2c)
122REG32(STATUSR, 0x40)
c2ecb424
MS
123REG32(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
10a83cb9
PM
130REG32(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
135REG32(IRQ_CTRL_ACK, 0x54)
136REG32(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
146REG32(GERRORN, 0x64)
147
148#define A_GERROR_IRQ_CFG0 0x68 /* 64b */
149REG32(GERROR_IRQ_CFG1, 0x70)
150REG32(GERROR_IRQ_CFG2, 0x74)
151
152#define A_STRTAB_BASE 0x80 /* 64b */
153
3293b9f5 154#define SMMU_BASE_ADDR_MASK 0xfffffffffffc0
10a83cb9
PM
155
156REG32(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 */
162REG32(CMDQ_PROD, 0x98)
163REG32(CMDQ_CONS, 0x9c)
164 FIELD(CMDQ_CONS, ERR, 24, 7)
165
166#define A_EVENTQ_BASE 0xa0 /* 64b */
167REG32(EVENTQ_PROD, 0xa8)
168REG32(EVENTQ_CONS, 0xac)
169
170#define A_EVENTQ_IRQ_CFG0 0xb0 /* 64b */
171REG32(EVENTQ_IRQ_CFG1, 0xb8)
172REG32(EVENTQ_IRQ_CFG2, 0xbc)
173
174#define A_IDREGS 0xfd0
175
176static inline int smmu_enabled(SMMUv3State *s)
177{
178 return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE);
179}
180
181/* Command Queue Entry */
182typedef struct Cmd {
183 uint32_t word[4];
184} Cmd;
185
186/* Event Queue Entry */
187typedef struct Evt {
188 uint32_t word[8];
189} Evt;
190
191static 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
6a736033
EA
204static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s)
205{
206 return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN);
207}
208
209static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
210{
211 return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
212}
213
dadd1a08
EA
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
230static inline bool smmuv3_q_full(SMMUQueue *q)
231{
232 return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q);
233}
234
235static inline bool smmuv3_q_empty(SMMUQueue *q)
236{
237 return (q->cons & WRAP_INDEX_MASK(q)) == (q->prod & WRAP_INDEX_MASK(q));
238}
239
240static inline void queue_prod_incr(SMMUQueue *q)
241{
242 q->prod = (q->prod + 1) & WRAP_INDEX_MASK(q);
243}
244
245static 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
254static inline bool smmuv3_cmdq_enabled(SMMUv3State *s)
255{
256 return FIELD_EX32(s->cr[0], CR0, CMDQEN);
257}
258
259static inline bool smmuv3_eventq_enabled(SMMUv3State *s)
260{
261 return FIELD_EX32(s->cr[0], CR0, EVENTQEN);
262}
263
264static 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
dadd1a08
EA
269/* Commands */
270
271typedef 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
300static 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
328static 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
339typedef enum {
340 SMMU_CERROR_NONE = 0,
341 SMMU_CERROR_ILL,
342 SMMU_CERROR_ABT,
343 SMMU_CERROR_ATC_INV_SYNC,
344} SMMUCmdError;
345
346enum { /* 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)
d5291561
EA
353#define CMD_NUM(x) extract32((x)->word[0], 12 , 5)
354#define CMD_SCALE(x) extract32((x)->word[0], 20 , 5)
dadd1a08
EA
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)
d5291561
EA
367#define CMD_TTL(x) extract32((x)->word[2], 8 , 2)
368#define CMD_TG(x) extract32((x)->word[2], 10, 2)
dadd1a08 369#define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5)
84abccdd
PM
370#define CMD_ADDR(x) \
371 (((uint64_t)((x)->word[3]) << 32) | \
372 ((extract64((x)->word[2], 12, 20)) << 12))
dadd1a08 373
fae4be38 374#define SMMU_FEATURE_2LVL_STE (1 << 0)
dadd1a08 375
bb981004
EA
376/* Events */
377
378typedef enum SMMUEventType {
9122bea9 379 SMMU_EVT_NONE = 0x00,
bb981004
EA
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
400static const char *event_stringify[] = {
9122bea9 401 [SMMU_EVT_NONE] = "no recorded event",
bb981004
EA
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
422static 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 */
432typedef struct SMMUEventInfo {
433 SMMUEventType type;
434 uint32_t sid;
435 bool recorded;
3499ec08 436 bool inval_ste_allowed;
bb981004
EA
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
9f4d2a13
EA
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))
bb981004
EA
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 { \
a7f65ceb
SV
516 (x)->word[7] = (uint32_t)(addr >> 32); \
517 (x)->word[6] = (uint32_t)(addr & 0xffffffff); \
bb981004
EA
518 } while (0)
519
520void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
521
9bde7f06
EA
522/* Configuration Data */
523
524/* STE Level 1 Descriptor */
525typedef struct STEDesc {
526 uint32_t word[2];
527} STEDesc;
528
529/* CD Level 1 Descriptor */
530typedef struct CDDesc {
531 uint32_t word[2];
532} CDDesc;
533
534/* Stream Table Entry(STE) */
535typedef struct STE {
536 uint32_t word[16];
537} STE;
538
539/* Context Descriptor(CD) */
540typedef 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)
21eb5b5c
MS
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
84abccdd
PM
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))
9bde7f06
EA
579
580static 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
599static 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
1b41847a 614#define CD_VALID(x) extract32((x)->word[0], 31, 1)
9bde7f06 615#define CD_ASID(x) extract32((x)->word[1], 16, 16)
84abccdd
PM
616#define CD_TTB(x, sel) \
617 ((extract64((x)->word[(sel) * 2 + 3], 0, 19) << 32) | \
618 ((x)->word[(sel) * 2 + 2] & ~0xfULL))
619
e7c3b9d9 620#define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1)
9bde7f06
EA
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
9bde7f06
EA
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 */
641static 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
657static 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
d9aad887 666#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
9bde7f06 667
10a83cb9 668#endif