16732dbb3SVikram Hegde /*
26732dbb3SVikram Hegde  * CDDL HEADER START
36732dbb3SVikram Hegde  *
46732dbb3SVikram Hegde  * The contents of this file are subject to the terms of the
56732dbb3SVikram Hegde  * Common Development and Distribution License (the "License").
66732dbb3SVikram Hegde  * You may not use this file except in compliance with the License.
76732dbb3SVikram Hegde  *
86732dbb3SVikram Hegde  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96732dbb3SVikram Hegde  * or http://www.opensolaris.org/os/licensing.
106732dbb3SVikram Hegde  * See the License for the specific language governing permissions
116732dbb3SVikram Hegde  * and limitations under the License.
126732dbb3SVikram Hegde  *
136732dbb3SVikram Hegde  * When distributing Covered Code, include this CDDL HEADER in each
146732dbb3SVikram Hegde  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156732dbb3SVikram Hegde  * If applicable, add the following below this CDDL HEADER, with the
166732dbb3SVikram Hegde  * fields enclosed by brackets "[]" replaced with your own identifying
176732dbb3SVikram Hegde  * information: Portions Copyright [yyyy] [name of copyright owner]
186732dbb3SVikram Hegde  *
196732dbb3SVikram Hegde  * CDDL HEADER END
206732dbb3SVikram Hegde  */
216732dbb3SVikram Hegde /*
22*ba758cf1SJerry Gilliam  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
236732dbb3SVikram Hegde  */
246732dbb3SVikram Hegde 
256732dbb3SVikram Hegde #ifndef	_AMD_IOMMU_IMPL_H
266732dbb3SVikram Hegde #define	_AMD_IOMMU_IMPL_H
276732dbb3SVikram Hegde 
286732dbb3SVikram Hegde #ifdef	__cplusplus
296732dbb3SVikram Hegde extern "C" {
306732dbb3SVikram Hegde #endif
316732dbb3SVikram Hegde 
326732dbb3SVikram Hegde #include <sys/pci.h>
336732dbb3SVikram Hegde 
346732dbb3SVikram Hegde #ifdef	_KERNEL
356732dbb3SVikram Hegde 
366732dbb3SVikram Hegde #define	AMD_IOMMU_PCI_PROG_IF	(0x0)
376732dbb3SVikram Hegde 
386732dbb3SVikram Hegde #define	AMD_IOMMU_CAP		(0x3)
396732dbb3SVikram Hegde 
406732dbb3SVikram Hegde #define	AMD_IOMMU_REG_SIZE	(0x2028)
416732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_SZ	(16)
426732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_SZ	(15)
436732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_SZ	(15)
446732dbb3SVikram Hegde #define	AMD_IOMMU_DEVENT_SZ	(32)
456732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_SZ	(16)
466732dbb3SVikram Hegde #define	AMD_IOMMU_EVENT_SZ	(16)
476732dbb3SVikram Hegde 
486732dbb3SVikram Hegde /* Capability Register offsets */
496732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_HDR_OFF		(0x00)
506732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_ADDR_LOW_OFF	(0x04)
516732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_ADDR_HI_OFF	(0x08)
526732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_RANGE_OFF		(0x0C)
536732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_MISC_OFF		(0x10)
546732dbb3SVikram Hegde 
556732dbb3SVikram Hegde /* ControL Registers offsets */
566732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_REG_OFF	(0x00)
576732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_REG_OFF	(0x08)
586732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_REG_OFF	(0x10)
596732dbb3SVikram Hegde #define	AMD_IOMMU_CTRL_REG_OFF		(0x18)
606732dbb3SVikram Hegde #define	AMD_IOMMU_EXCL_BASE_REG_OFF	(0x20)
616732dbb3SVikram Hegde #define	AMD_IOMMU_EXCL_LIM_REG_OFF	(0x28)
626732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_HEAD_REG_OFF	(0x2000)
636732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_TAIL_REG_OFF	(0x2008)
646732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_HEAD_REG_OFF	(0x2010)
656732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_TAIL_REG_OFF	(0x2018)
666732dbb3SVikram Hegde #define	AMD_IOMMU_STATUS_REG_OFF	(0x2020)
676732dbb3SVikram Hegde 
686732dbb3SVikram Hegde /* Capability Header Register Bits */
696732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_NPCACHE	(26 << 16 | 26)
706732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_HTTUN	(25 << 16 | 25)
716732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_IOTLB	(24 << 16 | 24)
726732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_TYPE	(18 << 16 | 16)
736732dbb3SVikram Hegde #define	AMD_IOMMU_CAP_ID	(7 << 16 | 0)
746732dbb3SVikram Hegde 
756732dbb3SVikram Hegde /* Capability Range Register bits */
766732dbb3SVikram Hegde #define	AMD_IOMMU_LAST_DEVFN	(31 << 16 | 24)
776732dbb3SVikram Hegde #define	AMD_IOMMU_FIRST_DEVFN	(23 << 16 | 16)
786732dbb3SVikram Hegde #define	AMD_IOMMU_RNG_BUS	(15 << 16 | 8)
796732dbb3SVikram Hegde #define	AMD_IOMMU_RNG_VALID	(7 << 16 | 7)
806732dbb3SVikram Hegde #define	AMD_IOMMU_HT_UNITID	(4 << 16 | 0)
816732dbb3SVikram Hegde 
826732dbb3SVikram Hegde 
836732dbb3SVikram Hegde /* Capability Misc Register bits */
846732dbb3SVikram Hegde #define	AMD_IOMMU_HT_ATSRSV	(22 << 16 | 22)
856732dbb3SVikram Hegde #define	AMD_IOMMU_VA_SIZE	(21 << 16 | 15)
866732dbb3SVikram Hegde #define	AMD_IOMMU_PA_SIZE	(14 << 16 | 8)
876732dbb3SVikram Hegde #define	AMD_IOMMU_MSINUM	(4 << 16 | 0)
886732dbb3SVikram Hegde 
896732dbb3SVikram Hegde /* Device Table Base Address register bits */
906732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTABBASE	(51 << 16 | 12)
916732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTABSIZE	(8 << 16 | 0)
926732dbb3SVikram Hegde 
936732dbb3SVikram Hegde /* Command Buffer Base Address register bits */
946732dbb3SVikram Hegde #define	AMD_IOMMU_COMLEN	(59 << 16 | 56)
956732dbb3SVikram Hegde #define	AMD_IOMMU_COMBASE	(51 << 16 | 12)
966732dbb3SVikram Hegde 
976732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_MINSZ	(8)
986732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_MAXSZ	(15)
996732dbb3SVikram Hegde 
1006732dbb3SVikram Hegde /* Event Log Base Address register bits */
1016732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLEN	(59 << 16 | 56)
1026732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTBASE	(51 << 16 | 12)
1036732dbb3SVikram Hegde 
1046732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_MINSZ	(8)
1056732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_MAXSZ	(15)
1066732dbb3SVikram Hegde 
1076732dbb3SVikram Hegde /* Control register bits */
1086732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_ENABLE		(12 << 16 | 12)
1096732dbb3SVikram Hegde #define	AMD_IOMMU_ISOC			(11 << 16 | 11)
1106732dbb3SVikram Hegde #define	AMD_IOMMU_COHERENT		(10 << 16 | 10)
1116732dbb3SVikram Hegde #define	AMD_IOMMU_RESPASSPW		(9 << 16 | 9)
1126732dbb3SVikram Hegde #define	AMD_IOMMU_PASSPW		(8 << 16 | 8)
1136732dbb3SVikram Hegde #define	AMD_IOMMU_INVTO			(7 << 16 | 5)
1146732dbb3SVikram Hegde #define	AMD_IOMMU_COMWAITINT_ENABLE	(4 << 16 | 4)
1156732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTINT_ENABLE	(3 << 16 | 3)
1166732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTLOG_ENABLE	(2 << 16 | 2)
1176732dbb3SVikram Hegde #define	AMD_IOMMU_HT_TUN_ENABLE		(1 << 16 | 1)
1186732dbb3SVikram Hegde #define	AMD_IOMMU_ENABLE		(0 << 16 | 0)
1196732dbb3SVikram Hegde 
1206732dbb3SVikram Hegde /* Exclusion Base Register bits */
1216732dbb3SVikram Hegde #define	AMD_IOMMU_EXCL_BASE_ADDR	(51 << 16 | 12)
1226732dbb3SVikram Hegde #define	AMD_IOMMU_EXCL_BASE_ALLOW	(1 << 16 | 1)
1236732dbb3SVikram Hegde #define	AMD_IOMMU_EXCL_BASE_EXEN	(0 << 16 | 0)
1246732dbb3SVikram Hegde 
1256732dbb3SVikram Hegde /* Exclusion Limit Register bits */
1266732dbb3SVikram Hegde #define	AMD_IOMMU_EXCL_LIM		(51 << 16 | 12)
1276732dbb3SVikram Hegde 
1286732dbb3SVikram Hegde /* Command Buffer Head Pointer Register bits */
1296732dbb3SVikram Hegde #define	AMD_IOMMU_CMDHEADPTR		(18 << 16 | 4)
1306732dbb3SVikram Hegde 
1316732dbb3SVikram Hegde /* Command Buffer Tail Pointer Register bits */
1326732dbb3SVikram Hegde #define	AMD_IOMMU_CMDTAILPTR		(18 << 16 | 4)
1336732dbb3SVikram Hegde 
1346732dbb3SVikram Hegde /* Event Log Head Pointer Register bits */
1356732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTHEADPTR		(18 << 16 | 4)
1366732dbb3SVikram Hegde 
1376732dbb3SVikram Hegde /* Event Log Tail Pointer Register bits */
1386732dbb3SVikram Hegde #define	AMD_IOMMU_EVENTTAILPTR		(18 << 16 | 4)
1396732dbb3SVikram Hegde 
1406732dbb3SVikram Hegde /* Status Register bits */
1416732dbb3SVikram Hegde #define	AMD_IOMMU_CMDBUF_RUN		(4 << 16 | 4)
1426732dbb3SVikram Hegde #define	AMD_IOMMU_EVENT_LOG_RUN		(3 << 16 | 3)
1436732dbb3SVikram Hegde #define	AMD_IOMMU_COMWAIT_INT		(2 << 16 | 2)
1446732dbb3SVikram Hegde #define	AMD_IOMMU_EVENT_LOG_INT		(1 << 16 | 1)
1456732dbb3SVikram Hegde #define	AMD_IOMMU_EVENT_OVERFLOW_INT	(0 << 16 | 0)
1466732dbb3SVikram Hegde 
1476732dbb3SVikram Hegde /* Device Table Bits */
1486732dbb3SVikram Hegde 
1496732dbb3SVikram Hegde /* size in bytes of each device table entry */
1506732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_ENTRY_SZ	(32)
1516732dbb3SVikram Hegde 
1526732dbb3SVikram Hegde /* Interrupt Remapping related Device Table bits */
1536732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_LINT1PASS	((191-128) << 16 | (191-128))
1546732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_LINT0PASS	((190-128) << 16 | (190-128))
1556732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_INTCTL		((189-128) << 16 | (188-128))
1566732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_NMIPASS	((186-128) << 16 | (186-128))
1576732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_EXTINTPAS	((185-128) << 16 | (185-128))
1586732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_INITPASS	((184-128) << 16 | (184-128))
1596732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_INTR_ROOT	((179-128) << 16 | (134-128))
1606732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_IG		((133-128) << 16 | (133-128))
1616732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_INTTABLEN	((132-128) << 16 | (129-128))
1626732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_IV		((128-128) << 16 | (128-128))
1636732dbb3SVikram Hegde 
1646732dbb3SVikram Hegde /* DMA Remapping related Device Table Bits */
1656732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_SYSMGT		((105-64) << 16 | (104-64))
1666732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_EX		((103-64) << 16 | (103-64))
1676732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_SD		((102-64) << 16 | (102-64))
1686732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_CACHE		((101-64) << 16 | (101-64))
1696732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_IOCTL		((100-64) << 16 | (99-64))
1706732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_SA		((98-64) << 16 | (98-64))
1716732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_SE		((97-64) << 16 | (97-64))
1726732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_IOTLB		((96-64) << 16 | (96-64))
1736732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_DOMAINID	((79-64) << 16 | (64-64))
1746732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_IW		(62 << 16 | 62)
1756732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_IR		(61 << 16 | 61)
1766732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_ROOT_PGTBL	(51 << 16 | 12)
1776732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_PG_MODE	(11 << 16 | 9)
1786732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_TV		(1 << 16 | 1)
1796732dbb3SVikram Hegde #define	AMD_IOMMU_DEVTBL_V		(0 << 16 | 0)
1806732dbb3SVikram Hegde 
1816732dbb3SVikram Hegde #define	BUS_DEVFN_TO_BDF(b, devfn)	(devfn)
1826732dbb3SVikram Hegde #define	AMD_IOMMU_ALIAS_HASH_SZ		(256)
1836732dbb3SVikram Hegde 
1846732dbb3SVikram Hegde #define	AMD_IOMMU_REG_ADDR_LOCKED	(0x1)
1856732dbb3SVikram Hegde 
1866732dbb3SVikram Hegde /*
1876732dbb3SVikram Hegde  * IOMMU Command bits
1886732dbb3SVikram Hegde  */
1896732dbb3SVikram Hegde 
1906732dbb3SVikram Hegde typedef enum {
1916732dbb3SVikram Hegde 	AMD_IOMMU_CMD_INVAL = 0,
1926732dbb3SVikram Hegde 	AMD_IOMMU_CMD_COMPL_WAIT,
1936732dbb3SVikram Hegde 	AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
1946732dbb3SVikram Hegde 	AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
1956732dbb3SVikram Hegde 	AMD_IOMMU_CMD_INVAL_IOTLB_PAGES,
1966732dbb3SVikram Hegde 	AMD_IOMMU_CMD_INVAL_INTR_TABLE,
1976732dbb3SVikram Hegde } amd_iommu_cmd_t;
1986732dbb3SVikram Hegde 
1996732dbb3SVikram Hegde typedef enum {
2006732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_NONE = 0,
2016732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT = 1,
2026732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F = 2,
2036732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S = 4,
2046732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL = 8,
2056732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S = 16,
2066732dbb3SVikram Hegde 	AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S = 32
2076732dbb3SVikram Hegde } amd_iommu_cmd_flags_t;
2086732dbb3SVikram Hegde 
2096732dbb3SVikram Hegde /* Common command bits */
2106732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_OPCODE		(31 << 16 | 28)
2116732dbb3SVikram Hegde 
2126732dbb3SVikram Hegde /* Completion Wait command bits */
2136732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_S		(0 << 16 | 0)
2146732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_I		(1 << 16 | 1)
2156732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_F		(2 << 16 | 2)
2166732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO	(31 << 16 | 3)
2176732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI	(19 << 16 | 0)
2186732dbb3SVikram Hegde 
2196732dbb3SVikram Hegde /* Invalidate Device Table entry command bits */
2206732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID		(15 << 16 | 0)
2216732dbb3SVikram Hegde 
2226732dbb3SVikram Hegde /* Invalidate IOMMU Pages command bits */
2236732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID		(15 << 16 | 0)
2246732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_S			(0 << 16 | 0)
2256732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_PDE			(1 << 16 | 1)
2266732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO		(31 << 16 | 12)
2276732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI		(63 << 16 | 32)
2286732dbb3SVikram Hegde 
2296732dbb3SVikram Hegde 
2306732dbb3SVikram Hegde /* Invalidate IOTLB command bits */
2316732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID		(15 << 16 | 0)
2326732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND		(31 << 16 | 24)
2336732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID		(15 << 16 | 0)
2346732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_S			(0 << 16 | 0)
2356732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO		(31 << 16 | 12)
2366732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI		(31 << 16 | 0)
2376732dbb3SVikram Hegde 
2386732dbb3SVikram Hegde #define	AMD_IOMMU_DEFAULT_MAXPEND			(10)
2396732dbb3SVikram Hegde 
2406732dbb3SVikram Hegde /* Invalidate Interrupt Table bits */
2416732dbb3SVikram Hegde #define	AMD_IOMMU_CMD_INVAL_INTR_DEVICEID		(15 << 16 | 0)
2426732dbb3SVikram Hegde 
2436732dbb3SVikram Hegde #if defined(__amd64)
2446732dbb3SVikram Hegde #define	dmac_cookie_addr	dmac_laddress
2456732dbb3SVikram Hegde #else
2466732dbb3SVikram Hegde #define	dmac_cookie_addr	dmac_address
2476732dbb3SVikram Hegde #endif
2486732dbb3SVikram Hegde 
2496732dbb3SVikram Hegde #define	AMD_IOMMU_TABLE_ALIGN	((1ULL << 12) - 1)
2506732dbb3SVikram Hegde 
2516732dbb3SVikram Hegde #define	AMD_IOMMU_MAX_DEVICEID	(0xFFFF)
2526732dbb3SVikram Hegde 
2536732dbb3SVikram Hegde /*
2546732dbb3SVikram Hegde  * DMA sync macros
2556732dbb3SVikram Hegde  * TODO: optimize sync only small ranges
2566732dbb3SVikram Hegde  */
2576732dbb3SVikram Hegde #define	SYNC_FORDEV(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORDEV)
2586732dbb3SVikram Hegde #define	SYNC_FORKERN(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORKERNEL)
2596732dbb3SVikram Hegde 
2606732dbb3SVikram Hegde #define	WAIT_SEC(s)	drv_usecwait(1000000*(s))
2616732dbb3SVikram Hegde 
2626732dbb3SVikram Hegde #define	CMD2OFF(c)	((c) << 4)
2636732dbb3SVikram Hegde #define	OFF2CMD(o)	((o) >> 4)
2646732dbb3SVikram Hegde 
2656732dbb3SVikram Hegde typedef union split {
2666732dbb3SVikram Hegde 	uint64_t u64;
2676732dbb3SVikram Hegde 	uint32_t u32[2];
2686732dbb3SVikram Hegde } split_t;
2696732dbb3SVikram Hegde 
2706732dbb3SVikram Hegde #define	BITPOS_START(b)	((b) >> 16)
2716732dbb3SVikram Hegde #define	BITPOS_END(b)	((b) & 0xFFFF)
2726732dbb3SVikram Hegde 
2736732dbb3SVikram Hegde #define	START_MASK64(s)	(((s) == 63) ? ~((uint64_t)0) : \
2746732dbb3SVikram Hegde 	(uint64_t)((1ULL << ((s)+1)) - 1))
2756732dbb3SVikram Hegde #define	START_MASK32(s)	(((s) == 31) ? ~((uint32_t)0) : \
2766732dbb3SVikram Hegde 	(uint32_t)((1ULL << ((s)+1)) - 1))
2776732dbb3SVikram Hegde #define	START_MASK16(s)	(((s) == 15) ? ~((uint16_t)0) : \
2786732dbb3SVikram Hegde 	(uint16_t)((1ULL << ((s)+1)) - 1))
2796732dbb3SVikram Hegde #define	START_MASK8(s)	(((s) == 7) ? ~((uint8_t)0) : \
2806732dbb3SVikram Hegde 	(uint8_t)((1ULL << ((s)+1)) - 1))
2816732dbb3SVikram Hegde 
2826732dbb3SVikram Hegde #define	END_MASK(e)	((1ULL << (e)) - 1)
2836732dbb3SVikram Hegde 
2846732dbb3SVikram Hegde #define	BIT_MASK64(s, e)	(uint64_t)(START_MASK64(s) & ~END_MASK(e))
2856732dbb3SVikram Hegde #define	BIT_MASK32(s, e)	(uint32_t)(START_MASK32(s) & ~END_MASK(e))
2866732dbb3SVikram Hegde #define	BIT_MASK16(s, e)	(uint16_t)(START_MASK16(s) & ~END_MASK(e))
2876732dbb3SVikram Hegde #define	BIT_MASK8(s, e)		(uint8_t)(START_MASK8(s) & ~END_MASK(e))
2886732dbb3SVikram Hegde 
2896732dbb3SVikram Hegde #define	AMD_IOMMU_REG_GET64_IMPL(rp, b) \
2906732dbb3SVikram Hegde 	(((*(rp)) & (START_MASK64(BITPOS_START(b)))) >> BITPOS_END(b))
2916732dbb3SVikram Hegde #define	AMD_IOMMU_REG_GET64(rp, b) 					 \
2926732dbb3SVikram Hegde 	((amd_iommu_64bit_bug) ? amd_iommu_reg_get64_workaround(rp, b) : \
2936732dbb3SVikram Hegde 	AMD_IOMMU_REG_GET64_IMPL(rp, b))
2946732dbb3SVikram Hegde #define	AMD_IOMMU_REG_GET32(rp, b) \
2956732dbb3SVikram Hegde 	(((*(rp)) & (START_MASK32(BITPOS_START(b)))) >> BITPOS_END(b))
2966732dbb3SVikram Hegde #define	AMD_IOMMU_REG_GET16(rp, b) \
2976732dbb3SVikram Hegde 	(((*(rp)) & (START_MASK16(BITPOS_START(b)))) >> BITPOS_END(b))
2986732dbb3SVikram Hegde #define	AMD_IOMMU_REG_GET8(rp, b) \
2996732dbb3SVikram Hegde 	(((*(rp)) & (START_MASK8(BITPOS_START(b)))) >> BITPOS_END(b))
3006732dbb3SVikram Hegde 
3016732dbb3SVikram Hegde #define	AMD_IOMMU_REG_SET64_IMPL(rp, b, v) \
3026732dbb3SVikram Hegde 	((*(rp)) = \
3036732dbb3SVikram Hegde 	(((uint64_t)(*(rp)) & ~(BIT_MASK64(BITPOS_START(b), BITPOS_END(b)))) \
3046732dbb3SVikram Hegde 	| ((uint64_t)(v) << BITPOS_END(b))))
3056732dbb3SVikram Hegde 
3066732dbb3SVikram Hegde #define	AMD_IOMMU_REG_SET64(rp, b, v) 			\
3076732dbb3SVikram Hegde 	(void) ((amd_iommu_64bit_bug) ?			\
3086732dbb3SVikram Hegde 	amd_iommu_reg_set64_workaround(rp, b, v) : 	\
3096732dbb3SVikram Hegde 	AMD_IOMMU_REG_SET64_IMPL(rp, b, v))
3106732dbb3SVikram Hegde 
3116732dbb3SVikram Hegde #define	AMD_IOMMU_REG_SET32(rp, b, v) \
3126732dbb3SVikram Hegde 	((*(rp)) = \
3136732dbb3SVikram Hegde 	(((uint32_t)(*(rp)) & ~(BIT_MASK32(BITPOS_START(b), BITPOS_END(b)))) \
3146732dbb3SVikram Hegde 	| ((uint32_t)(v) << BITPOS_END(b))))
3156732dbb3SVikram Hegde 
3166732dbb3SVikram Hegde #define	AMD_IOMMU_REG_SET16(rp, b, v) \
3176732dbb3SVikram Hegde 	((*(rp)) = \
3186732dbb3SVikram Hegde 	(((uint16_t)(*(rp)) & ~(BIT_MASK16(BITPOS_START(b), BITPOS_END(b)))) \
3196732dbb3SVikram Hegde 	| ((uint16_t)(v) << BITPOS_END(b))))
3206732dbb3SVikram Hegde 
3216732dbb3SVikram Hegde #define	AMD_IOMMU_REG_SET8(rp, b, v) \
3226732dbb3SVikram Hegde 	((*(rp)) = \
3236732dbb3SVikram Hegde 	(((uint8_t)(*(rp)) & ~(BIT_MASK8(BITPOS_START(b), BITPOS_END(b)))) \
3246732dbb3SVikram Hegde 	| ((uint8_t)(v) << BITPOS_END(b))))
3256732dbb3SVikram Hegde 
3266732dbb3SVikram Hegde /*
3276732dbb3SVikram Hegde  * Cast a 64 bit pointer to a uint64_t *
3286732dbb3SVikram Hegde  */
3296732dbb3SVikram Hegde #define	REGADDR64(a)	((uint64_t *)(uintptr_t)(a))
3306732dbb3SVikram Hegde 
3316732dbb3SVikram Hegde typedef enum {
3326732dbb3SVikram Hegde 	AMD_IOMMU_INTR_INVALID = 0,
3336732dbb3SVikram Hegde 	AMD_IOMMU_INTR_TABLE,
3346732dbb3SVikram Hegde 	AMD_IOMMU_INTR_ALLOCED,
3356732dbb3SVikram Hegde 	AMD_IOMMU_INTR_HANDLER,
3366732dbb3SVikram Hegde 	AMD_IOMMU_INTR_ENABLED
3376732dbb3SVikram Hegde } amd_iommu_intr_state_t;
3386732dbb3SVikram Hegde 
3396732dbb3SVikram Hegde 
3406732dbb3SVikram Hegde typedef struct amd_iommu {
3416732dbb3SVikram Hegde 	kmutex_t aiomt_mutex;
3426732dbb3SVikram Hegde 	kmutex_t aiomt_eventlock;
3436732dbb3SVikram Hegde 	kmutex_t aiomt_cmdlock;
3446732dbb3SVikram Hegde 	dev_info_t *aiomt_dip;
345*ba758cf1SJerry Gilliam 	uint16_t aiomt_bdf;
3466732dbb3SVikram Hegde 	int aiomt_idx;
3476732dbb3SVikram Hegde 	iommulib_handle_t aiomt_iommulib_handle;
3486732dbb3SVikram Hegde 	iommulib_ops_t *aiomt_iommulib_ops;
3496732dbb3SVikram Hegde 	uint32_t aiomt_cap_hdr;
3506732dbb3SVikram Hegde 	uint8_t aiomt_npcache;
3516732dbb3SVikram Hegde 	uint8_t aiomt_httun;
3526732dbb3SVikram Hegde 	uint8_t aiomt_iotlb;
3536732dbb3SVikram Hegde 	uint8_t aiomt_captype;
3546732dbb3SVikram Hegde 	uint8_t aiomt_capid;
3556732dbb3SVikram Hegde 	uint32_t aiomt_low_addr32;
3566732dbb3SVikram Hegde 	uint32_t aiomt_hi_addr32;
3576732dbb3SVikram Hegde 	uint64_t aiomt_reg_pa;
3586732dbb3SVikram Hegde 	uint64_t aiomt_va;
3596732dbb3SVikram Hegde 	uint64_t aiomt_reg_va;
3606732dbb3SVikram Hegde 	uint32_t aiomt_range;
3616732dbb3SVikram Hegde 	uint8_t aiomt_rng_bus;
3626732dbb3SVikram Hegde 	uint8_t aiomt_first_devfn;
3636732dbb3SVikram Hegde 	uint8_t aiomt_last_devfn;
3646732dbb3SVikram Hegde 	uint8_t aiomt_rng_valid;
3656732dbb3SVikram Hegde 	uint8_t aiomt_ht_unitid;
3666732dbb3SVikram Hegde 	uint32_t aiomt_misc;
3676732dbb3SVikram Hegde 	uint8_t aiomt_htatsresv;
3686732dbb3SVikram Hegde 	uint8_t aiomt_vasize;
3696732dbb3SVikram Hegde 	uint8_t aiomt_pasize;
3706732dbb3SVikram Hegde 	uint8_t aiomt_msinum;
3716732dbb3SVikram Hegde 	uint8_t aiomt_reg_pages;
3726732dbb3SVikram Hegde 	uint32_t aiomt_reg_size;
3736732dbb3SVikram Hegde 	uint32_t aiomt_devtbl_sz;
3746732dbb3SVikram Hegde 	uint32_t aiomt_cmdbuf_sz;
3756732dbb3SVikram Hegde 	uint32_t aiomt_eventlog_sz;
3766732dbb3SVikram Hegde 	caddr_t aiomt_devtbl;
3776732dbb3SVikram Hegde 	caddr_t aiomt_cmdbuf;
3786732dbb3SVikram Hegde 	caddr_t aiomt_eventlog;
3796732dbb3SVikram Hegde 	uint32_t *aiomt_cmd_tail;
3806732dbb3SVikram Hegde 	uint32_t *aiomt_event_head;
3816732dbb3SVikram Hegde 	ddi_dma_handle_t aiomt_dmahdl;
3826732dbb3SVikram Hegde 	void *aiomt_dma_bufva;
3836732dbb3SVikram Hegde 	uint64_t aiomt_dma_mem_realsz;
3846732dbb3SVikram Hegde 	ddi_acc_handle_t aiomt_dma_mem_hdl;
3856732dbb3SVikram Hegde 	ddi_dma_cookie_t aiomt_buf_dma_cookie;
3866732dbb3SVikram Hegde 	uint_t aiomt_buf_dma_ncookie;
3876732dbb3SVikram Hegde 	amd_iommu_intr_state_t aiomt_intr_state;
3886732dbb3SVikram Hegde 	ddi_intr_handle_t *aiomt_intr_htable;
3896732dbb3SVikram Hegde 	uint32_t aiomt_intr_htable_sz;
3906732dbb3SVikram Hegde 	uint32_t aiomt_actual_intrs;
3916732dbb3SVikram Hegde 	uint32_t aiomt_intr_cap;
3926732dbb3SVikram Hegde 	uint64_t aiomt_reg_devtbl_va;
3936732dbb3SVikram Hegde 	uint64_t aiomt_reg_cmdbuf_va;
3946732dbb3SVikram Hegde 	uint64_t aiomt_reg_eventlog_va;
3956732dbb3SVikram Hegde 	uint64_t aiomt_reg_ctrl_va;
3966732dbb3SVikram Hegde 	uint64_t aiomt_reg_excl_base_va;
3976732dbb3SVikram Hegde 	uint64_t aiomt_reg_excl_lim_va;
3986732dbb3SVikram Hegde 	uint64_t aiomt_reg_cmdbuf_head_va;
3996732dbb3SVikram Hegde 	uint64_t aiomt_reg_cmdbuf_tail_va;
4006732dbb3SVikram Hegde 	uint64_t aiomt_reg_eventlog_head_va;
4016732dbb3SVikram Hegde 	uint64_t aiomt_reg_eventlog_tail_va;
4026732dbb3SVikram Hegde 	uint64_t aiomt_reg_status_va;
4036732dbb3SVikram Hegde 	struct amd_iommu *aiomt_next;
4046732dbb3SVikram Hegde } amd_iommu_t;
4056732dbb3SVikram Hegde 
4066732dbb3SVikram Hegde typedef struct amd_iommu_dma_devtbl_ent {
4076732dbb3SVikram Hegde 	uint16_t de_domainid;
4086732dbb3SVikram Hegde 	uint8_t de_R;
4096732dbb3SVikram Hegde 	uint8_t de_W;
4106732dbb3SVikram Hegde 	caddr_t de_root_pgtbl;
4116732dbb3SVikram Hegde 	uint8_t de_pgmode;
4126732dbb3SVikram Hegde } amd_iommu_dma_devtbl_entry_t;
4136732dbb3SVikram Hegde 
4146732dbb3SVikram Hegde typedef struct amd_iommu_alias {
4156732dbb3SVikram Hegde 	uint16_t al_bdf;
4166732dbb3SVikram Hegde 	uint16_t al_src_bdf;
4176732dbb3SVikram Hegde 	struct amd_iommu_alias *al_next;
4186732dbb3SVikram Hegde } amd_iommu_alias_t;
4196732dbb3SVikram Hegde 
4206732dbb3SVikram Hegde typedef struct amd_iommu_cmdargs {
4216732dbb3SVikram Hegde 	uint64_t ca_addr;
4226732dbb3SVikram Hegde 	uint16_t ca_domainid;
4236732dbb3SVikram Hegde 	uint16_t ca_deviceid;
4246732dbb3SVikram Hegde } amd_iommu_cmdargs_t;
4256732dbb3SVikram Hegde 
4266732dbb3SVikram Hegde struct amd_iommu_page_table;
4276732dbb3SVikram Hegde 
4286732dbb3SVikram Hegde typedef struct amd_iommu_page_table_hash {
4296732dbb3SVikram Hegde 	kmutex_t ampt_lock;
4306732dbb3SVikram Hegde 	struct amd_iommu_page_table **ampt_hash;
4316732dbb3SVikram Hegde } amd_iommu_page_table_hash_t;
4326732dbb3SVikram Hegde 
4336732dbb3SVikram Hegde typedef enum {
4346732dbb3SVikram Hegde 	AMD_IOMMU_LOG_INVALID_OP = 0,
4356732dbb3SVikram Hegde 	AMD_IOMMU_LOG_DISPLAY,
4366732dbb3SVikram Hegde 	AMD_IOMMU_LOG_DISCARD
4376732dbb3SVikram Hegde } amd_iommu_log_op_t;
4386732dbb3SVikram Hegde 
4396732dbb3SVikram Hegde typedef enum {
4406732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_NONE = 0,
4416732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_ALLOCHDL = 0x1,
4426732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_FREEHDL = 0x2,
4436732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_BIND = 0x4,
4446732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_UNBIND = 0x8,
4456732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_WIN = 0x10,
4466732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_PAGE_TABLES = 0x20,
4476732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_DEVTBL = 0x40,
4486732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_CMDBUF = 0x80,
4496732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_EVENTLOG = 0x100,
4506732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_ACPI = 0x200,
4516732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_PA2VA = 0x400,
4526732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_TABLES = 0x800,
4536732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_EXCL = 0x1000,
4546732dbb3SVikram Hegde 	AMD_IOMMU_DEBUG_INTR = 0x2000
4556732dbb3SVikram Hegde } amd_iommu_debug_t;
4566732dbb3SVikram Hegde 
4576732dbb3SVikram Hegde extern const char *amd_iommu_modname;
4586732dbb3SVikram Hegde extern kmutex_t amd_iommu_global_lock;
4596732dbb3SVikram Hegde extern amd_iommu_alias_t **amd_iommu_alias;
4606732dbb3SVikram Hegde extern amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
4616732dbb3SVikram Hegde extern ddi_device_acc_attr_t amd_iommu_devacc;
4626732dbb3SVikram Hegde extern amd_iommu_debug_t amd_iommu_debug;
4636732dbb3SVikram Hegde 
4646732dbb3SVikram Hegde extern uint8_t amd_iommu_htatsresv;
4656732dbb3SVikram Hegde extern uint8_t amd_iommu_vasize;
4666732dbb3SVikram Hegde extern uint8_t amd_iommu_pasize;
4676732dbb3SVikram Hegde extern int amd_iommu_64bit_bug;
4686732dbb3SVikram Hegde extern int amd_iommu_unity_map;
4696732dbb3SVikram Hegde extern int amd_iommu_no_RW_perms;
4706732dbb3SVikram Hegde extern int amd_iommu_no_unmap;
4716732dbb3SVikram Hegde extern int amd_iommu_pageva_inval_all;
4726732dbb3SVikram Hegde extern int amd_iommu_disable;
4736732dbb3SVikram Hegde extern char *amd_iommu_disable_list;
4746732dbb3SVikram Hegde 
4756732dbb3SVikram Hegde extern uint64_t amd_iommu_reg_get64_workaround(uint64_t *regp, uint32_t bits);
4766732dbb3SVikram Hegde extern uint64_t amd_iommu_reg_set64_workaround(uint64_t *regp, uint32_t bits,
4776732dbb3SVikram Hegde     uint64_t value);
478*ba758cf1SJerry Gilliam extern dev_info_t *amd_iommu_pci_dip(dev_info_t *rdip, const char *path);
4796732dbb3SVikram Hegde 
4806732dbb3SVikram Hegde int amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
4816732dbb3SVikram Hegde     amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held);
4826732dbb3SVikram Hegde int amd_iommu_page_table_hash_init(amd_iommu_page_table_hash_t *ampt);
4836732dbb3SVikram Hegde void amd_iommu_page_table_hash_fini(amd_iommu_page_table_hash_t *ampt);
4846732dbb3SVikram Hegde 
4856732dbb3SVikram Hegde int amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op);
4866732dbb3SVikram Hegde void amd_iommu_read_boot_props(void);
4876732dbb3SVikram Hegde void amd_iommu_lookup_conf_props(dev_info_t *dip);
4886732dbb3SVikram Hegde 
4896732dbb3SVikram Hegde #endif	/* _KERNEL */
4906732dbb3SVikram Hegde 
4916732dbb3SVikram Hegde #ifdef	__cplusplus
4926732dbb3SVikram Hegde }
4936732dbb3SVikram Hegde #endif
4946732dbb3SVikram Hegde 
4956732dbb3SVikram Hegde #endif	/* _AMD_IOMMU_IMPL_H */
496