summaryrefslogtreecommitdiff
path: root/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_impl.h
blob: 00117955c16c8fb38917725d7a3b8904f8026586 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	_AMD_IOMMU_IMPL_H
#define	_AMD_IOMMU_IMPL_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/pci.h>

#ifdef	_KERNEL

#define	AMD_IOMMU_PCI_PROG_IF	(0x0)

#define	AMD_IOMMU_CAP		(0x3)

#define	AMD_IOMMU_REG_SIZE	(0x2028)
#define	AMD_IOMMU_DEVTBL_SZ	(16)
#define	AMD_IOMMU_CMDBUF_SZ	(15)
#define	AMD_IOMMU_EVENTLOG_SZ	(15)
#define	AMD_IOMMU_DEVENT_SZ	(32)
#define	AMD_IOMMU_CMD_SZ	(16)
#define	AMD_IOMMU_EVENT_SZ	(16)

/* Capability Register offsets */
#define	AMD_IOMMU_CAP_HDR_OFF		(0x00)
#define	AMD_IOMMU_CAP_ADDR_LOW_OFF	(0x04)
#define	AMD_IOMMU_CAP_ADDR_HI_OFF	(0x08)
#define	AMD_IOMMU_CAP_RANGE_OFF		(0x0C)
#define	AMD_IOMMU_CAP_MISC_OFF		(0x10)

/* ControL Registers offsets */
#define	AMD_IOMMU_DEVTBL_REG_OFF	(0x00)
#define	AMD_IOMMU_CMDBUF_REG_OFF	(0x08)
#define	AMD_IOMMU_EVENTLOG_REG_OFF	(0x10)
#define	AMD_IOMMU_CTRL_REG_OFF		(0x18)
#define	AMD_IOMMU_EXCL_BASE_REG_OFF	(0x20)
#define	AMD_IOMMU_EXCL_LIM_REG_OFF	(0x28)
#define	AMD_IOMMU_CMDBUF_HEAD_REG_OFF	(0x2000)
#define	AMD_IOMMU_CMDBUF_TAIL_REG_OFF	(0x2008)
#define	AMD_IOMMU_EVENTLOG_HEAD_REG_OFF	(0x2010)
#define	AMD_IOMMU_EVENTLOG_TAIL_REG_OFF	(0x2018)
#define	AMD_IOMMU_STATUS_REG_OFF	(0x2020)

/* Capability Header Register Bits */
#define	AMD_IOMMU_CAP_NPCACHE	(26 << 16 | 26)
#define	AMD_IOMMU_CAP_HTTUN	(25 << 16 | 25)
#define	AMD_IOMMU_CAP_IOTLB	(24 << 16 | 24)
#define	AMD_IOMMU_CAP_TYPE	(18 << 16 | 16)
#define	AMD_IOMMU_CAP_ID	(7 << 16 | 0)

/* Capability Range Register bits */
#define	AMD_IOMMU_LAST_DEVFN	(31 << 16 | 24)
#define	AMD_IOMMU_FIRST_DEVFN	(23 << 16 | 16)
#define	AMD_IOMMU_RNG_BUS	(15 << 16 | 8)
#define	AMD_IOMMU_RNG_VALID	(7 << 16 | 7)
#define	AMD_IOMMU_HT_UNITID	(4 << 16 | 0)


/* Capability Misc Register bits */
#define	AMD_IOMMU_HT_ATSRSV	(22 << 16 | 22)
#define	AMD_IOMMU_VA_SIZE	(21 << 16 | 15)
#define	AMD_IOMMU_PA_SIZE	(14 << 16 | 8)
#define	AMD_IOMMU_MSINUM	(4 << 16 | 0)

/* Device Table Base Address register bits */
#define	AMD_IOMMU_DEVTABBASE	(51 << 16 | 12)
#define	AMD_IOMMU_DEVTABSIZE	(8 << 16 | 0)

/* Command Buffer Base Address register bits */
#define	AMD_IOMMU_COMLEN	(59 << 16 | 56)
#define	AMD_IOMMU_COMBASE	(51 << 16 | 12)

#define	AMD_IOMMU_CMDBUF_MINSZ	(8)
#define	AMD_IOMMU_CMDBUF_MAXSZ	(15)

/* Event Log Base Address register bits */
#define	AMD_IOMMU_EVENTLEN	(59 << 16 | 56)
#define	AMD_IOMMU_EVENTBASE	(51 << 16 | 12)

#define	AMD_IOMMU_EVENTLOG_MINSZ	(8)
#define	AMD_IOMMU_EVENTLOG_MAXSZ	(15)

/* Control register bits */
#define	AMD_IOMMU_CMDBUF_ENABLE		(12 << 16 | 12)
#define	AMD_IOMMU_ISOC			(11 << 16 | 11)
#define	AMD_IOMMU_COHERENT		(10 << 16 | 10)
#define	AMD_IOMMU_RESPASSPW		(9 << 16 | 9)
#define	AMD_IOMMU_PASSPW		(8 << 16 | 8)
#define	AMD_IOMMU_INVTO			(7 << 16 | 5)
#define	AMD_IOMMU_COMWAITINT_ENABLE	(4 << 16 | 4)
#define	AMD_IOMMU_EVENTINT_ENABLE	(3 << 16 | 3)
#define	AMD_IOMMU_EVENTLOG_ENABLE	(2 << 16 | 2)
#define	AMD_IOMMU_HT_TUN_ENABLE		(1 << 16 | 1)
#define	AMD_IOMMU_ENABLE		(0 << 16 | 0)

/* Exclusion Base Register bits */
#define	AMD_IOMMU_EXCL_BASE_ADDR	(51 << 16 | 12)
#define	AMD_IOMMU_EXCL_BASE_ALLOW	(1 << 16 | 1)
#define	AMD_IOMMU_EXCL_BASE_EXEN	(0 << 16 | 0)

/* Exclusion Limit Register bits */
#define	AMD_IOMMU_EXCL_LIM		(51 << 16 | 12)

/* Command Buffer Head Pointer Register bits */
#define	AMD_IOMMU_CMDHEADPTR		(18 << 16 | 4)

/* Command Buffer Tail Pointer Register bits */
#define	AMD_IOMMU_CMDTAILPTR		(18 << 16 | 4)

/* Event Log Head Pointer Register bits */
#define	AMD_IOMMU_EVENTHEADPTR		(18 << 16 | 4)

/* Event Log Tail Pointer Register bits */
#define	AMD_IOMMU_EVENTTAILPTR		(18 << 16 | 4)

/* Status Register bits */
#define	AMD_IOMMU_CMDBUF_RUN		(4 << 16 | 4)
#define	AMD_IOMMU_EVENT_LOG_RUN		(3 << 16 | 3)
#define	AMD_IOMMU_COMWAIT_INT		(2 << 16 | 2)
#define	AMD_IOMMU_EVENT_LOG_INT		(1 << 16 | 1)
#define	AMD_IOMMU_EVENT_OVERFLOW_INT	(0 << 16 | 0)

/* Device Table Bits */

/* size in bytes of each device table entry */
#define	AMD_IOMMU_DEVTBL_ENTRY_SZ	(32)

/* Interrupt Remapping related Device Table bits */
#define	AMD_IOMMU_DEVTBL_LINT1PASS	((191-128) << 16 | (191-128))
#define	AMD_IOMMU_DEVTBL_LINT0PASS	((190-128) << 16 | (190-128))
#define	AMD_IOMMU_DEVTBL_INTCTL		((189-128) << 16 | (188-128))
#define	AMD_IOMMU_DEVTBL_NMIPASS	((186-128) << 16 | (186-128))
#define	AMD_IOMMU_DEVTBL_EXTINTPAS	((185-128) << 16 | (185-128))
#define	AMD_IOMMU_DEVTBL_INITPASS	((184-128) << 16 | (184-128))
#define	AMD_IOMMU_DEVTBL_INTR_ROOT	((179-128) << 16 | (134-128))
#define	AMD_IOMMU_DEVTBL_IG		((133-128) << 16 | (133-128))
#define	AMD_IOMMU_DEVTBL_INTTABLEN	((132-128) << 16 | (129-128))
#define	AMD_IOMMU_DEVTBL_IV		((128-128) << 16 | (128-128))

/* DMA Remapping related Device Table Bits */
#define	AMD_IOMMU_DEVTBL_SYSMGT		((105-64) << 16 | (104-64))
#define	AMD_IOMMU_DEVTBL_EX		((103-64) << 16 | (103-64))
#define	AMD_IOMMU_DEVTBL_SD		((102-64) << 16 | (102-64))
#define	AMD_IOMMU_DEVTBL_CACHE		((101-64) << 16 | (101-64))
#define	AMD_IOMMU_DEVTBL_IOCTL		((100-64) << 16 | (99-64))
#define	AMD_IOMMU_DEVTBL_SA		((98-64) << 16 | (98-64))
#define	AMD_IOMMU_DEVTBL_SE		((97-64) << 16 | (97-64))
#define	AMD_IOMMU_DEVTBL_IOTLB		((96-64) << 16 | (96-64))
#define	AMD_IOMMU_DEVTBL_DOMAINID	((79-64) << 16 | (64-64))
#define	AMD_IOMMU_DEVTBL_IW		(62 << 16 | 62)
#define	AMD_IOMMU_DEVTBL_IR		(61 << 16 | 61)
#define	AMD_IOMMU_DEVTBL_ROOT_PGTBL	(51 << 16 | 12)
#define	AMD_IOMMU_DEVTBL_PG_MODE	(11 << 16 | 9)
#define	AMD_IOMMU_DEVTBL_TV		(1 << 16 | 1)
#define	AMD_IOMMU_DEVTBL_V		(0 << 16 | 0)

#define	BUS_DEVFN_TO_BDF(b, devfn)	(devfn)
#define	AMD_IOMMU_ALIAS_HASH_SZ		(256)

#define	AMD_IOMMU_REG_ADDR_LOCKED	(0x1)

/*
 * IOMMU Command bits
 */

typedef enum {
	AMD_IOMMU_CMD_INVAL = 0,
	AMD_IOMMU_CMD_COMPL_WAIT,
	AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
	AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
	AMD_IOMMU_CMD_INVAL_IOTLB_PAGES,
	AMD_IOMMU_CMD_INVAL_INTR_TABLE,
} amd_iommu_cmd_t;

typedef enum {
	AMD_IOMMU_CMD_FLAGS_NONE = 0,
	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT = 1,
	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F = 2,
	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S = 4,
	AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL = 8,
	AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S = 16,
	AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S = 32
} amd_iommu_cmd_flags_t;

/* Common command bits */
#define	AMD_IOMMU_CMD_OPCODE		(31 << 16 | 28)

/* Completion Wait command bits */
#define	AMD_IOMMU_CMD_COMPL_WAIT_S		(0 << 16 | 0)
#define	AMD_IOMMU_CMD_COMPL_WAIT_I		(1 << 16 | 1)
#define	AMD_IOMMU_CMD_COMPL_WAIT_F		(2 << 16 | 2)
#define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO	(31 << 16 | 3)
#define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI	(19 << 16 | 0)

/* Invalidate Device Table entry command bits */
#define	AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID		(15 << 16 | 0)

/* Invalidate IOMMU Pages command bits */
#define	AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID		(15 << 16 | 0)
#define	AMD_IOMMU_CMD_INVAL_PAGES_S			(0 << 16 | 0)
#define	AMD_IOMMU_CMD_INVAL_PAGES_PDE			(1 << 16 | 1)
#define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO		(31 << 16 | 12)
#define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI		(63 << 16 | 32)


/* Invalidate IOTLB command bits */
#define	AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID		(15 << 16 | 0)
#define	AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND		(31 << 16 | 24)
#define	AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID		(15 << 16 | 0)
#define	AMD_IOMMU_CMD_INVAL_IOTLB_S			(0 << 16 | 0)
#define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO		(31 << 16 | 12)
#define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI		(31 << 16 | 0)

#define	AMD_IOMMU_DEFAULT_MAXPEND			(10)

/* Invalidate Interrupt Table bits */
#define	AMD_IOMMU_CMD_INVAL_INTR_DEVICEID		(15 << 16 | 0)

#if defined(__amd64)
#define	dmac_cookie_addr	dmac_laddress
#else
#define	dmac_cookie_addr	dmac_address
#endif

#define	AMD_IOMMU_TABLE_ALIGN	((1ULL << 12) - 1)

#define	AMD_IOMMU_MAX_DEVICEID	(0xFFFF)

/*
 * DMA sync macros
 * TODO: optimize sync only small ranges
 */
#define	SYNC_FORDEV(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORDEV)
#define	SYNC_FORKERN(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORKERNEL)

#define	WAIT_SEC(s)	drv_usecwait(1000000*(s))

#define	CMD2OFF(c)	((c) << 4)
#define	OFF2CMD(o)	((o) >> 4)

typedef union split {
	uint64_t u64;
	uint32_t u32[2];
} split_t;

#define	BITPOS_START(b)	((b) >> 16)
#define	BITPOS_END(b)	((b) & 0xFFFF)

#define	START_MASK64(s)	(((s) == 63) ? ~((uint64_t)0) : \
	(uint64_t)((1ULL << ((s)+1)) - 1))
#define	START_MASK32(s)	(((s) == 31) ? ~((uint32_t)0) : \
	(uint32_t)((1ULL << ((s)+1)) - 1))
#define	START_MASK16(s)	(((s) == 15) ? ~((uint16_t)0) : \
	(uint16_t)((1ULL << ((s)+1)) - 1))
#define	START_MASK8(s)	(((s) == 7) ? ~((uint8_t)0) : \
	(uint8_t)((1ULL << ((s)+1)) - 1))

#define	END_MASK(e)	((1ULL << (e)) - 1)

#define	BIT_MASK64(s, e)	(uint64_t)(START_MASK64(s) & ~END_MASK(e))
#define	BIT_MASK32(s, e)	(uint32_t)(START_MASK32(s) & ~END_MASK(e))
#define	BIT_MASK16(s, e)	(uint16_t)(START_MASK16(s) & ~END_MASK(e))
#define	BIT_MASK8(s, e)		(uint8_t)(START_MASK8(s) & ~END_MASK(e))

#define	AMD_IOMMU_REG_GET64_IMPL(rp, b) \
	(((*(rp)) & (START_MASK64(BITPOS_START(b)))) >> BITPOS_END(b))
#define	AMD_IOMMU_REG_GET64(rp, b) 					 \
	((amd_iommu_64bit_bug) ? amd_iommu_reg_get64_workaround(rp, b) : \
	AMD_IOMMU_REG_GET64_IMPL(rp, b))
#define	AMD_IOMMU_REG_GET32(rp, b) \
	(((*(rp)) & (START_MASK32(BITPOS_START(b)))) >> BITPOS_END(b))
#define	AMD_IOMMU_REG_GET16(rp, b) \
	(((*(rp)) & (START_MASK16(BITPOS_START(b)))) >> BITPOS_END(b))
#define	AMD_IOMMU_REG_GET8(rp, b) \
	(((*(rp)) & (START_MASK8(BITPOS_START(b)))) >> BITPOS_END(b))

#define	AMD_IOMMU_REG_SET64_IMPL(rp, b, v) \
	((*(rp)) = \
	(((uint64_t)(*(rp)) & ~(BIT_MASK64(BITPOS_START(b), BITPOS_END(b)))) \
	| ((uint64_t)(v) << BITPOS_END(b))))

#define	AMD_IOMMU_REG_SET64(rp, b, v) 			\
	(void) ((amd_iommu_64bit_bug) ?			\
	amd_iommu_reg_set64_workaround(rp, b, v) : 	\
	AMD_IOMMU_REG_SET64_IMPL(rp, b, v))

#define	AMD_IOMMU_REG_SET32(rp, b, v) \
	((*(rp)) = \
	(((uint32_t)(*(rp)) & ~(BIT_MASK32(BITPOS_START(b), BITPOS_END(b)))) \
	| ((uint32_t)(v) << BITPOS_END(b))))

#define	AMD_IOMMU_REG_SET16(rp, b, v) \
	((*(rp)) = \
	(((uint16_t)(*(rp)) & ~(BIT_MASK16(BITPOS_START(b), BITPOS_END(b)))) \
	| ((uint16_t)(v) << BITPOS_END(b))))

#define	AMD_IOMMU_REG_SET8(rp, b, v) \
	((*(rp)) = \
	(((uint8_t)(*(rp)) & ~(BIT_MASK8(BITPOS_START(b), BITPOS_END(b)))) \
	| ((uint8_t)(v) << BITPOS_END(b))))

/*
 * Cast a 64 bit pointer to a uint64_t *
 */
#define	REGADDR64(a)	((uint64_t *)(uintptr_t)(a))

typedef enum {
	AMD_IOMMU_INTR_INVALID = 0,
	AMD_IOMMU_INTR_TABLE,
	AMD_IOMMU_INTR_ALLOCED,
	AMD_IOMMU_INTR_HANDLER,
	AMD_IOMMU_INTR_ENABLED
} amd_iommu_intr_state_t;


typedef struct amd_iommu {
	kmutex_t aiomt_mutex;
	kmutex_t aiomt_eventlock;
	kmutex_t aiomt_cmdlock;
	dev_info_t *aiomt_dip;
	uint16_t aiomt_bdf;
	int aiomt_idx;
	iommulib_handle_t aiomt_iommulib_handle;
	iommulib_ops_t *aiomt_iommulib_ops;
	uint32_t aiomt_cap_hdr;
	uint8_t aiomt_npcache;
	uint8_t aiomt_httun;
	uint8_t aiomt_iotlb;
	uint8_t aiomt_captype;
	uint8_t aiomt_capid;
	uint32_t aiomt_low_addr32;
	uint32_t aiomt_hi_addr32;
	uint64_t aiomt_reg_pa;
	uint64_t aiomt_va;
	uint64_t aiomt_reg_va;
	uint32_t aiomt_range;
	uint8_t aiomt_rng_bus;
	uint8_t aiomt_first_devfn;
	uint8_t aiomt_last_devfn;
	uint8_t aiomt_rng_valid;
	uint8_t aiomt_ht_unitid;
	uint32_t aiomt_misc;
	uint8_t aiomt_htatsresv;
	uint8_t aiomt_vasize;
	uint8_t aiomt_pasize;
	uint8_t aiomt_msinum;
	uint8_t aiomt_reg_pages;
	uint32_t aiomt_reg_size;
	uint32_t aiomt_devtbl_sz;
	uint32_t aiomt_cmdbuf_sz;
	uint32_t aiomt_eventlog_sz;
	caddr_t aiomt_devtbl;
	caddr_t aiomt_cmdbuf;
	caddr_t aiomt_eventlog;
	uint32_t *aiomt_cmd_tail;
	uint32_t *aiomt_event_head;
	ddi_dma_handle_t aiomt_dmahdl;
	void *aiomt_dma_bufva;
	uint64_t aiomt_dma_mem_realsz;
	ddi_acc_handle_t aiomt_dma_mem_hdl;
	ddi_dma_cookie_t aiomt_buf_dma_cookie;
	uint_t aiomt_buf_dma_ncookie;
	amd_iommu_intr_state_t aiomt_intr_state;
	ddi_intr_handle_t *aiomt_intr_htable;
	uint32_t aiomt_intr_htable_sz;
	uint32_t aiomt_actual_intrs;
	uint32_t aiomt_intr_cap;
	uint64_t aiomt_reg_devtbl_va;
	uint64_t aiomt_reg_cmdbuf_va;
	uint64_t aiomt_reg_eventlog_va;
	uint64_t aiomt_reg_ctrl_va;
	uint64_t aiomt_reg_excl_base_va;
	uint64_t aiomt_reg_excl_lim_va;
	uint64_t aiomt_reg_cmdbuf_head_va;
	uint64_t aiomt_reg_cmdbuf_tail_va;
	uint64_t aiomt_reg_eventlog_head_va;
	uint64_t aiomt_reg_eventlog_tail_va;
	uint64_t aiomt_reg_status_va;
	struct amd_iommu *aiomt_next;
} amd_iommu_t;

typedef struct amd_iommu_dma_devtbl_ent {
	uint16_t de_domainid;
	uint8_t de_R;
	uint8_t de_W;
	caddr_t de_root_pgtbl;
	uint8_t de_pgmode;
} amd_iommu_dma_devtbl_entry_t;

typedef struct amd_iommu_alias {
	uint16_t al_bdf;
	uint16_t al_src_bdf;
	struct amd_iommu_alias *al_next;
} amd_iommu_alias_t;

typedef struct amd_iommu_cmdargs {
	uint64_t ca_addr;
	uint16_t ca_domainid;
	uint16_t ca_deviceid;
} amd_iommu_cmdargs_t;

struct amd_iommu_page_table;

typedef struct amd_iommu_page_table_hash {
	kmutex_t ampt_lock;
	struct amd_iommu_page_table **ampt_hash;
} amd_iommu_page_table_hash_t;

typedef enum {
	AMD_IOMMU_LOG_INVALID_OP = 0,
	AMD_IOMMU_LOG_DISPLAY,
	AMD_IOMMU_LOG_DISCARD
} amd_iommu_log_op_t;

typedef enum {
	AMD_IOMMU_DEBUG_NONE = 0,
	AMD_IOMMU_DEBUG_ALLOCHDL = 0x1,
	AMD_IOMMU_DEBUG_FREEHDL = 0x2,
	AMD_IOMMU_DEBUG_BIND = 0x4,
	AMD_IOMMU_DEBUG_UNBIND = 0x8,
	AMD_IOMMU_DEBUG_WIN = 0x10,
	AMD_IOMMU_DEBUG_PAGE_TABLES = 0x20,
	AMD_IOMMU_DEBUG_DEVTBL = 0x40,
	AMD_IOMMU_DEBUG_CMDBUF = 0x80,
	AMD_IOMMU_DEBUG_EVENTLOG = 0x100,
	AMD_IOMMU_DEBUG_ACPI = 0x200,
	AMD_IOMMU_DEBUG_PA2VA = 0x400,
	AMD_IOMMU_DEBUG_TABLES = 0x800,
	AMD_IOMMU_DEBUG_EXCL = 0x1000,
	AMD_IOMMU_DEBUG_INTR = 0x2000
} amd_iommu_debug_t;

extern const char *amd_iommu_modname;
extern kmutex_t amd_iommu_global_lock;
extern amd_iommu_alias_t **amd_iommu_alias;
extern amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
extern ddi_device_acc_attr_t amd_iommu_devacc;
extern amd_iommu_debug_t amd_iommu_debug;

extern uint8_t amd_iommu_htatsresv;
extern uint8_t amd_iommu_vasize;
extern uint8_t amd_iommu_pasize;
extern int amd_iommu_64bit_bug;
extern int amd_iommu_unity_map;
extern int amd_iommu_no_RW_perms;
extern int amd_iommu_no_unmap;
extern int amd_iommu_pageva_inval_all;
extern int amd_iommu_disable;
extern char *amd_iommu_disable_list;

extern uint64_t amd_iommu_reg_get64_workaround(uint64_t *regp, uint32_t bits);
extern uint64_t amd_iommu_reg_set64_workaround(uint64_t *regp, uint32_t bits,
    uint64_t value);
extern dev_info_t *amd_iommu_pci_dip(dev_info_t *rdip, const char *path);

int amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
    amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held);
int amd_iommu_page_table_hash_init(amd_iommu_page_table_hash_t *ampt);
void amd_iommu_page_table_hash_fini(amd_iommu_page_table_hash_t *ampt);

int amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op);
void amd_iommu_read_boot_props(void);
void amd_iommu_lookup_conf_props(dev_info_t *dip);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _AMD_IOMMU_IMPL_H */