17125fcbdSVikram Hegde /*
27125fcbdSVikram Hegde  * CDDL HEADER START
37125fcbdSVikram Hegde  *
47125fcbdSVikram Hegde  * The contents of this file are subject to the terms of the
57125fcbdSVikram Hegde  * Common Development and Distribution License (the "License").
67125fcbdSVikram Hegde  * You may not use this file except in compliance with the License.
77125fcbdSVikram Hegde  *
87125fcbdSVikram Hegde  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97125fcbdSVikram Hegde  * or http://www.opensolaris.org/os/licensing.
107125fcbdSVikram Hegde  * See the License for the specific language governing permissions
117125fcbdSVikram Hegde  * and limitations under the License.
127125fcbdSVikram Hegde  *
137125fcbdSVikram Hegde  * When distributing Covered Code, include this CDDL HEADER in each
147125fcbdSVikram Hegde  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157125fcbdSVikram Hegde  * If applicable, add the following below this CDDL HEADER, with the
167125fcbdSVikram Hegde  * fields enclosed by brackets "[]" replaced with your own identifying
177125fcbdSVikram Hegde  * information: Portions Copyright [yyyy] [name of copyright owner]
187125fcbdSVikram Hegde  *
197125fcbdSVikram Hegde  * CDDL HEADER END
207125fcbdSVikram Hegde  */
217125fcbdSVikram Hegde /*
22*ba758cf1SJerry Gilliam  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
237125fcbdSVikram Hegde  */
247125fcbdSVikram Hegde 
257125fcbdSVikram Hegde #ifndef	_AMD_IOMMU_IMPL_H
267125fcbdSVikram Hegde #define	_AMD_IOMMU_IMPL_H
277125fcbdSVikram Hegde 
287125fcbdSVikram Hegde #ifdef	__cplusplus
297125fcbdSVikram Hegde extern "C" {
307125fcbdSVikram Hegde #endif
317125fcbdSVikram Hegde 
327125fcbdSVikram Hegde #include <sys/pci.h>
337125fcbdSVikram Hegde 
347125fcbdSVikram Hegde #ifdef	_KERNEL
357125fcbdSVikram Hegde 
367125fcbdSVikram Hegde #define	AMD_IOMMU_PCI_PROG_IF	(0x0)
377125fcbdSVikram Hegde 
387125fcbdSVikram Hegde #define	AMD_IOMMU_CAP		(0x3)
397125fcbdSVikram Hegde 
407125fcbdSVikram Hegde #define	AMD_IOMMU_REG_SIZE	(0x2028)
417125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_SZ	(16)
427125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_SZ	(15)
437125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_SZ	(15)
447125fcbdSVikram Hegde #define	AMD_IOMMU_DEVENT_SZ	(32)
457125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_SZ	(16)
467125fcbdSVikram Hegde #define	AMD_IOMMU_EVENT_SZ	(16)
477125fcbdSVikram Hegde 
487125fcbdSVikram Hegde /* Capability Register offsets */
497125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_HDR_OFF		(0x00)
507125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_ADDR_LOW_OFF	(0x04)
517125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_ADDR_HI_OFF	(0x08)
527125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_RANGE_OFF		(0x0C)
537125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_MISC_OFF		(0x10)
547125fcbdSVikram Hegde 
557125fcbdSVikram Hegde /* ControL Registers offsets */
567125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_REG_OFF	(0x00)
577125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_REG_OFF	(0x08)
587125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_REG_OFF	(0x10)
597125fcbdSVikram Hegde #define	AMD_IOMMU_CTRL_REG_OFF		(0x18)
607125fcbdSVikram Hegde #define	AMD_IOMMU_EXCL_BASE_REG_OFF	(0x20)
617125fcbdSVikram Hegde #define	AMD_IOMMU_EXCL_LIM_REG_OFF	(0x28)
627125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_HEAD_REG_OFF	(0x2000)
637125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_TAIL_REG_OFF	(0x2008)
647125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_HEAD_REG_OFF	(0x2010)
657125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_TAIL_REG_OFF	(0x2018)
667125fcbdSVikram Hegde #define	AMD_IOMMU_STATUS_REG_OFF	(0x2020)
677125fcbdSVikram Hegde 
687125fcbdSVikram Hegde /* Capability Header Register Bits */
697125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_NPCACHE	(26 << 16 | 26)
707125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_HTTUN	(25 << 16 | 25)
717125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_IOTLB	(24 << 16 | 24)
727125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_TYPE	(18 << 16 | 16)
737125fcbdSVikram Hegde #define	AMD_IOMMU_CAP_ID	(7 << 16 | 0)
747125fcbdSVikram Hegde 
757125fcbdSVikram Hegde /* Capability Range Register bits */
767125fcbdSVikram Hegde #define	AMD_IOMMU_LAST_DEVFN	(31 << 16 | 24)
777125fcbdSVikram Hegde #define	AMD_IOMMU_FIRST_DEVFN	(23 << 16 | 16)
787125fcbdSVikram Hegde #define	AMD_IOMMU_RNG_BUS	(15 << 16 | 8)
797125fcbdSVikram Hegde #define	AMD_IOMMU_RNG_VALID	(7 << 16 | 7)
807125fcbdSVikram Hegde #define	AMD_IOMMU_HT_UNITID	(4 << 16 | 0)
817125fcbdSVikram Hegde 
827125fcbdSVikram Hegde 
837125fcbdSVikram Hegde /* Capability Misc Register bits */
847125fcbdSVikram Hegde #define	AMD_IOMMU_HT_ATSRSV	(22 << 16 | 22)
857125fcbdSVikram Hegde #define	AMD_IOMMU_VA_SIZE	(21 << 16 | 15)
867125fcbdSVikram Hegde #define	AMD_IOMMU_PA_SIZE	(14 << 16 | 8)
877125fcbdSVikram Hegde #define	AMD_IOMMU_MSINUM	(4 << 16 | 0)
887125fcbdSVikram Hegde 
897125fcbdSVikram Hegde /* Device Table Base Address register bits */
907125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTABBASE	(51 << 16 | 12)
917125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTABSIZE	(8 << 16 | 0)
927125fcbdSVikram Hegde 
937125fcbdSVikram Hegde /* Command Buffer Base Address register bits */
947125fcbdSVikram Hegde #define	AMD_IOMMU_COMLEN	(59 << 16 | 56)
957125fcbdSVikram Hegde #define	AMD_IOMMU_COMBASE	(51 << 16 | 12)
967125fcbdSVikram Hegde 
977125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_MINSZ	(8)
987125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_MAXSZ	(15)
997125fcbdSVikram Hegde 
1007125fcbdSVikram Hegde /* Event Log Base Address register bits */
1017125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLEN	(59 << 16 | 56)
1027125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTBASE	(51 << 16 | 12)
1037125fcbdSVikram Hegde 
1047125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_MINSZ	(8)
1057125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_MAXSZ	(15)
1067125fcbdSVikram Hegde 
1077125fcbdSVikram Hegde /* Control register bits */
1087125fcbdSVikram Hegde #define	AMD_IOMMU_CMDBUF_ENABLE		(12 << 16 | 12)
10994f1124eSVikram Hegde #define	AMD_IOMMU_ISOC			(11 << 16 | 11)
11094f1124eSVikram Hegde #define	AMD_IOMMU_COHERENT		(10 << 16 | 10)
11194f1124eSVikram Hegde #define	AMD_IOMMU_RESPASSPW		(9 << 16 | 9)
11294f1124eSVikram Hegde #define	AMD_IOMMU_PASSPW		(8 << 16 | 8)
11394f1124eSVikram Hegde #define	AMD_IOMMU_INVTO			(7 << 16 | 5)
1147125fcbdSVikram Hegde #define	AMD_IOMMU_COMWAITINT_ENABLE	(4 << 16 | 4)
1157125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTINT_ENABLE	(3 << 16 | 3)
1167125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTLOG_ENABLE	(2 << 16 | 2)
1177125fcbdSVikram Hegde #define	AMD_IOMMU_HT_TUN_ENABLE		(1 << 16 | 1)
1187125fcbdSVikram Hegde #define	AMD_IOMMU_ENABLE		(0 << 16 | 0)
1197125fcbdSVikram Hegde 
1207125fcbdSVikram Hegde /* Exclusion Base Register bits */
1217125fcbdSVikram Hegde #define	AMD_IOMMU_EXCL_BASE_ADDR	(51 << 16 | 12)
1227125fcbdSVikram Hegde #define	AMD_IOMMU_EXCL_BASE_ALLOW	(1 << 16 | 1)
1237125fcbdSVikram Hegde #define	AMD_IOMMU_EXCL_BASE_EXEN	(0 << 16 | 0)
1247125fcbdSVikram Hegde 
1257125fcbdSVikram Hegde /* Exclusion Limit Register bits */
1267125fcbdSVikram Hegde #define	AMD_IOMMU_EXCL_LIM		(51 << 16 | 12)
1277125fcbdSVikram Hegde 
1287125fcbdSVikram Hegde /* Command Buffer Head Pointer Register bits */
1297125fcbdSVikram Hegde #define	AMD_IOMMU_CMDHEADPTR		(18 << 16 | 4)
1307125fcbdSVikram Hegde 
1317125fcbdSVikram Hegde /* Command Buffer Tail Pointer Register bits */
1327125fcbdSVikram Hegde #define	AMD_IOMMU_CMDTAILPTR		(18 << 16 | 4)
1337125fcbdSVikram Hegde 
1347125fcbdSVikram Hegde /* Event Log Head Pointer Register bits */
1357125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTHEADPTR		(18 << 16 | 4)
1367125fcbdSVikram Hegde 
1377125fcbdSVikram Hegde /* Event Log Tail Pointer Register bits */
1387125fcbdSVikram Hegde #define	AMD_IOMMU_EVENTTAILPTR		(18 << 16 | 4)
1397125fcbdSVikram Hegde 
1407125fcbdSVikram Hegde /* Status Register bits */
14194f1124eSVikram Hegde #define	AMD_IOMMU_CMDBUF_RUN		(4 << 16 | 4)
14294f1124eSVikram Hegde #define	AMD_IOMMU_EVENT_LOG_RUN		(3 << 16 | 3)
1437125fcbdSVikram Hegde #define	AMD_IOMMU_COMWAIT_INT		(2 << 16 | 2)
1447125fcbdSVikram Hegde #define	AMD_IOMMU_EVENT_LOG_INT		(1 << 16 | 1)
1457125fcbdSVikram Hegde #define	AMD_IOMMU_EVENT_OVERFLOW_INT	(0 << 16 | 0)
1467125fcbdSVikram Hegde 
1477125fcbdSVikram Hegde /* Device Table Bits */
1487125fcbdSVikram Hegde 
1497125fcbdSVikram Hegde /* size in bytes of each device table entry */
1507125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_ENTRY_SZ	(32)
1517125fcbdSVikram Hegde 
1527125fcbdSVikram Hegde /* Interrupt Remapping related Device Table bits */
1537125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_LINT1PASS	((191-128) << 16 | (191-128))
1547125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_LINT0PASS	((190-128) << 16 | (190-128))
1557125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_INTCTL		((189-128) << 16 | (188-128))
1567125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_NMIPASS	((186-128) << 16 | (186-128))
1577125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_EXTINTPAS	((185-128) << 16 | (185-128))
1587125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_INITPASS	((184-128) << 16 | (184-128))
1597125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_INTR_ROOT	((179-128) << 16 | (134-128))
1607125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_IG		((133-128) << 16 | (133-128))
1617125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_INTTABLEN	((132-128) << 16 | (129-128))
1627125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_IV		((128-128) << 16 | (128-128))
1637125fcbdSVikram Hegde 
1647125fcbdSVikram Hegde /* DMA Remapping related Device Table Bits */
1657125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_SYSMGT		((105-64) << 16 | (104-64))
1667125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_EX		((103-64) << 16 | (103-64))
1677125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_SD		((102-64) << 16 | (102-64))
1687125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_CACHE		((101-64) << 16 | (101-64))
1697125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_IOCTL		((100-64) << 16 | (99-64))
1707125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_SA		((98-64) << 16 | (98-64))
1717125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_SE		((97-64) << 16 | (97-64))
1727125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_IOTLB		((96-64) << 16 | (96-64))
1737125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_DOMAINID	((79-64) << 16 | (64-64))
1747125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_IW		(62 << 16 | 62)
1757125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_IR		(61 << 16 | 61)
1767125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_ROOT_PGTBL	(51 << 16 | 12)
1777125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_PG_MODE	(11 << 16 | 9)
1787125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_TV		(1 << 16 | 1)
1797125fcbdSVikram Hegde #define	AMD_IOMMU_DEVTBL_V		(0 << 16 | 0)
1807125fcbdSVikram Hegde 
1817125fcbdSVikram Hegde #define	BUS_DEVFN_TO_BDF(b, devfn)	(devfn)
1827125fcbdSVikram Hegde #define	AMD_IOMMU_ALIAS_HASH_SZ		(256)
1837125fcbdSVikram Hegde 
1847125fcbdSVikram Hegde #define	AMD_IOMMU_REG_ADDR_LOCKED	(0x1)
1857125fcbdSVikram Hegde 
1867125fcbdSVikram Hegde /*
1877125fcbdSVikram Hegde  * IOMMU Command bits
1887125fcbdSVikram Hegde  */
1897125fcbdSVikram Hegde 
1907125fcbdSVikram Hegde typedef enum {
1917125fcbdSVikram Hegde 	AMD_IOMMU_CMD_INVAL = 0,
1927125fcbdSVikram Hegde 	AMD_IOMMU_CMD_COMPL_WAIT,
1937125fcbdSVikram Hegde 	AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
1947125fcbdSVikram Hegde 	AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
1957125fcbdSVikram Hegde 	AMD_IOMMU_CMD_INVAL_IOTLB_PAGES,
1967125fcbdSVikram Hegde 	AMD_IOMMU_CMD_INVAL_INTR_TABLE,
1977125fcbdSVikram Hegde } amd_iommu_cmd_t;
1987125fcbdSVikram Hegde 
1997125fcbdSVikram Hegde typedef enum {
2007125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_NONE = 0,
2017125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT = 1,
2027125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F = 2,
2037125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S = 4,
2047125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL = 8,
2057125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S = 16,
2067125fcbdSVikram Hegde 	AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S = 32
2077125fcbdSVikram Hegde } amd_iommu_cmd_flags_t;
2087125fcbdSVikram Hegde 
2097125fcbdSVikram Hegde /* Common command bits */
2107125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_OPCODE		(31 << 16 | 28)
2117125fcbdSVikram Hegde 
2127125fcbdSVikram Hegde /* Completion Wait command bits */
21394f1124eSVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_S		(0 << 16 | 0)
2147125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_I		(1 << 16 | 1)
2157125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_F		(2 << 16 | 2)
2167125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO	(31 << 16 | 3)
2177125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI	(19 << 16 | 0)
2187125fcbdSVikram Hegde 
2197125fcbdSVikram Hegde /* Invalidate Device Table entry command bits */
2207125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID		(15 << 16 | 0)
2217125fcbdSVikram Hegde 
2227125fcbdSVikram Hegde /* Invalidate IOMMU Pages command bits */
2237125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID		(15 << 16 | 0)
2247125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_S			(0 << 16 | 0)
22594f1124eSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_PDE			(1 << 16 | 1)
2267125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO		(31 << 16 | 12)
2277125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI		(63 << 16 | 32)
2287125fcbdSVikram Hegde 
2297125fcbdSVikram Hegde 
2307125fcbdSVikram Hegde /* Invalidate IOTLB command bits */
2317125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID		(15 << 16 | 0)
2327125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND		(31 << 16 | 24)
2337125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID		(15 << 16 | 0)
2347125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_S			(0 << 16 | 0)
2357125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO		(31 << 16 | 12)
23694f1124eSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI		(31 << 16 | 0)
2377125fcbdSVikram Hegde 
2387125fcbdSVikram Hegde #define	AMD_IOMMU_DEFAULT_MAXPEND			(10)
2397125fcbdSVikram Hegde 
2407125fcbdSVikram Hegde /* Invalidate Interrupt Table bits */
2417125fcbdSVikram Hegde #define	AMD_IOMMU_CMD_INVAL_INTR_DEVICEID		(15 << 16 | 0)
2427125fcbdSVikram Hegde 
2430412ba67SVikram Hegde #if defined(__amd64)
2447125fcbdSVikram Hegde #define	dmac_cookie_addr	dmac_laddress
2457125fcbdSVikram Hegde #else
2467125fcbdSVikram Hegde #define	dmac_cookie_addr	dmac_address
2477125fcbdSVikram Hegde #endif
2487125fcbdSVikram Hegde 
2497125fcbdSVikram Hegde #define	AMD_IOMMU_TABLE_ALIGN	((1ULL << 12) - 1)
2507125fcbdSVikram Hegde 
25194f1124eSVikram Hegde #define	AMD_IOMMU_MAX_DEVICEID	(0xFFFF)
25294f1124eSVikram Hegde 
2537125fcbdSVikram Hegde /*
2547125fcbdSVikram Hegde  * DMA sync macros
25594f1124eSVikram Hegde  * TODO: optimize sync only small ranges
2567125fcbdSVikram Hegde  */
2577125fcbdSVikram Hegde #define	SYNC_FORDEV(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORDEV)
2587125fcbdSVikram Hegde #define	SYNC_FORKERN(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORKERNEL)
2597125fcbdSVikram Hegde 
2607125fcbdSVikram Hegde #define	WAIT_SEC(s)	drv_usecwait(1000000*(s))
2617125fcbdSVikram Hegde 
2627125fcbdSVikram Hegde #define	CMD2OFF(c)	((c) << 4)
2637125fcbdSVikram Hegde #define	OFF2CMD(o)	((o) >> 4)
2647125fcbdSVikram Hegde 
26594f1124eSVikram Hegde typedef union split {
26694f1124eSVikram Hegde 	uint64_t u64;
26794f1124eSVikram Hegde 	uint32_t u32[2];
26894f1124eSVikram Hegde } split_t;
26994f1124eSVikram Hegde 
27094f1124eSVikram Hegde #define	BITPOS_START(b)	((b) >> 16)
27194f1124eSVikram Hegde #define	BITPOS_END(b)	((b) & 0xFFFF)
27294f1124eSVikram Hegde 
27394f1124eSVikram Hegde #define	START_MASK64(s)	(((s) == 63) ? ~((uint64_t)0) : \
27494f1124eSVikram Hegde 	(uint64_t)((1ULL << ((s)+1)) - 1))
27594f1124eSVikram Hegde #define	START_MASK32(s)	(((s) == 31) ? ~((uint32_t)0) : \
27694f1124eSVikram Hegde 	(uint32_t)((1ULL << ((s)+1)) - 1))
27794f1124eSVikram Hegde #define	START_MASK16(s)	(((s) == 15) ? ~((uint16_t)0) : \
27894f1124eSVikram Hegde 	(uint16_t)((1ULL << ((s)+1)) - 1))
27994f1124eSVikram Hegde #define	START_MASK8(s)	(((s) == 7) ? ~((uint8_t)0) : \
28094f1124eSVikram Hegde 	(uint8_t)((1ULL << ((s)+1)) - 1))
28194f1124eSVikram Hegde 
28294f1124eSVikram Hegde #define	END_MASK(e)	((1ULL << (e)) - 1)
28394f1124eSVikram Hegde 
28494f1124eSVikram Hegde #define	BIT_MASK64(s, e)	(uint64_t)(START_MASK64(s) & ~END_MASK(e))
28594f1124eSVikram Hegde #define	BIT_MASK32(s, e)	(uint32_t)(START_MASK32(s) & ~END_MASK(e))
28694f1124eSVikram Hegde #define	BIT_MASK16(s, e)	(uint16_t)(START_MASK16(s) & ~END_MASK(e))
28794f1124eSVikram Hegde #define	BIT_MASK8(s, e)		(uint8_t)(START_MASK8(s) & ~END_MASK(e))
28894f1124eSVikram Hegde 
28994f1124eSVikram Hegde #define	AMD_IOMMU_REG_GET64_IMPL(rp, b) \
29094f1124eSVikram Hegde 	(((*(rp)) & (START_MASK64(BITPOS_START(b)))) >> BITPOS_END(b))
29194f1124eSVikram Hegde #define	AMD_IOMMU_REG_GET64(rp, b) 					 \
29294f1124eSVikram Hegde 	((amd_iommu_64bit_bug) ? amd_iommu_reg_get64_workaround(rp, b) : \
29394f1124eSVikram Hegde 	AMD_IOMMU_REG_GET64_IMPL(rp, b))
29494f1124eSVikram Hegde #define	AMD_IOMMU_REG_GET32(rp, b) \
29594f1124eSVikram Hegde 	(((*(rp)) & (START_MASK32(BITPOS_START(b)))) >> BITPOS_END(b))
29694f1124eSVikram Hegde #define	AMD_IOMMU_REG_GET16(rp, b) \
29794f1124eSVikram Hegde 	(((*(rp)) & (START_MASK16(BITPOS_START(b)))) >> BITPOS_END(b))
29894f1124eSVikram Hegde #define	AMD_IOMMU_REG_GET8(rp, b) \
29994f1124eSVikram Hegde 	(((*(rp)) & (START_MASK8(BITPOS_START(b)))) >> BITPOS_END(b))
30094f1124eSVikram Hegde 
30194f1124eSVikram Hegde #define	AMD_IOMMU_REG_SET64_IMPL(rp, b, v) \
30294f1124eSVikram Hegde 	((*(rp)) = \
30394f1124eSVikram Hegde 	(((uint64_t)(*(rp)) & ~(BIT_MASK64(BITPOS_START(b), BITPOS_END(b)))) \
30494f1124eSVikram Hegde 	| ((uint64_t)(v) << BITPOS_END(b))))
30594f1124eSVikram Hegde 
30694f1124eSVikram Hegde #define	AMD_IOMMU_REG_SET64(rp, b, v) 			\
30794f1124eSVikram Hegde 	(void) ((amd_iommu_64bit_bug) ?			\
30894f1124eSVikram Hegde 	amd_iommu_reg_set64_workaround(rp, b, v) : 	\
30994f1124eSVikram Hegde 	AMD_IOMMU_REG_SET64_IMPL(rp, b, v))
31094f1124eSVikram Hegde 
31194f1124eSVikram Hegde #define	AMD_IOMMU_REG_SET32(rp, b, v) \
31294f1124eSVikram Hegde 	((*(rp)) = \
31394f1124eSVikram Hegde 	(((uint32_t)(*(rp)) & ~(BIT_MASK32(BITPOS_START(b), BITPOS_END(b)))) \
31494f1124eSVikram Hegde 	| ((uint32_t)(v) << BITPOS_END(b))))
31594f1124eSVikram Hegde 
31694f1124eSVikram Hegde #define	AMD_IOMMU_REG_SET16(rp, b, v) \
31794f1124eSVikram Hegde 	((*(rp)) = \
31894f1124eSVikram Hegde 	(((uint16_t)(*(rp)) & ~(BIT_MASK16(BITPOS_START(b), BITPOS_END(b)))) \
31994f1124eSVikram Hegde 	| ((uint16_t)(v) << BITPOS_END(b))))
32094f1124eSVikram Hegde 
32194f1124eSVikram Hegde #define	AMD_IOMMU_REG_SET8(rp, b, v) \
32294f1124eSVikram Hegde 	((*(rp)) = \
32394f1124eSVikram Hegde 	(((uint8_t)(*(rp)) & ~(BIT_MASK8(BITPOS_START(b), BITPOS_END(b)))) \
32494f1124eSVikram Hegde 	| ((uint8_t)(v) << BITPOS_END(b))))
32594f1124eSVikram Hegde 
3267125fcbdSVikram Hegde /*
32794f1124eSVikram Hegde  * Cast a 64 bit pointer to a uint64_t *
3287125fcbdSVikram Hegde  */
32994f1124eSVikram Hegde #define	REGADDR64(a)	((uint64_t *)(uintptr_t)(a))
33094f1124eSVikram Hegde 
33194f1124eSVikram Hegde typedef enum {
33294f1124eSVikram Hegde 	AMD_IOMMU_INTR_INVALID = 0,
33394f1124eSVikram Hegde 	AMD_IOMMU_INTR_TABLE,
33494f1124eSVikram Hegde 	AMD_IOMMU_INTR_ALLOCED,
33594f1124eSVikram Hegde 	AMD_IOMMU_INTR_HANDLER,
33694f1124eSVikram Hegde 	AMD_IOMMU_INTR_ENABLED
33794f1124eSVikram Hegde } amd_iommu_intr_state_t;
33894f1124eSVikram Hegde 
3397125fcbdSVikram Hegde 
3407125fcbdSVikram Hegde typedef struct amd_iommu {
3417125fcbdSVikram Hegde 	kmutex_t aiomt_mutex;
3427125fcbdSVikram Hegde 	kmutex_t aiomt_eventlock;
34394f1124eSVikram Hegde 	kmutex_t aiomt_cmdlock;
3447125fcbdSVikram Hegde 	dev_info_t *aiomt_dip;
345*ba758cf1SJerry Gilliam 	uint16_t aiomt_bdf;
3467125fcbdSVikram Hegde 	int aiomt_idx;
3477125fcbdSVikram Hegde 	iommulib_handle_t aiomt_iommulib_handle;
3487125fcbdSVikram Hegde 	iommulib_ops_t *aiomt_iommulib_ops;
3497125fcbdSVikram Hegde 	uint32_t aiomt_cap_hdr;
3507125fcbdSVikram Hegde 	uint8_t aiomt_npcache;
3517125fcbdSVikram Hegde 	uint8_t aiomt_httun;
3527125fcbdSVikram Hegde 	uint8_t aiomt_iotlb;
3537125fcbdSVikram Hegde 	uint8_t aiomt_captype;
3547125fcbdSVikram Hegde 	uint8_t aiomt_capid;
3557125fcbdSVikram Hegde 	uint32_t aiomt_low_addr32;
3567125fcbdSVikram Hegde 	uint32_t aiomt_hi_addr32;
3577125fcbdSVikram Hegde 	uint64_t aiomt_reg_pa;
35894f1124eSVikram Hegde 	uint64_t aiomt_va;
3597125fcbdSVikram Hegde 	uint64_t aiomt_reg_va;
3607125fcbdSVikram Hegde 	uint32_t aiomt_range;
3617125fcbdSVikram Hegde 	uint8_t aiomt_rng_bus;
3627125fcbdSVikram Hegde 	uint8_t aiomt_first_devfn;
3637125fcbdSVikram Hegde 	uint8_t aiomt_last_devfn;
3647125fcbdSVikram Hegde 	uint8_t aiomt_rng_valid;
3657125fcbdSVikram Hegde 	uint8_t aiomt_ht_unitid;
3667125fcbdSVikram Hegde 	uint32_t aiomt_misc;
3677125fcbdSVikram Hegde 	uint8_t aiomt_htatsresv;
3687125fcbdSVikram Hegde 	uint8_t aiomt_vasize;
3697125fcbdSVikram Hegde 	uint8_t aiomt_pasize;
3707125fcbdSVikram Hegde 	uint8_t aiomt_msinum;
3717125fcbdSVikram Hegde 	uint8_t aiomt_reg_pages;
3727125fcbdSVikram Hegde 	uint32_t aiomt_reg_size;
3737125fcbdSVikram Hegde 	uint32_t aiomt_devtbl_sz;
3747125fcbdSVikram Hegde 	uint32_t aiomt_cmdbuf_sz;
3757125fcbdSVikram Hegde 	uint32_t aiomt_eventlog_sz;
3767125fcbdSVikram Hegde 	caddr_t aiomt_devtbl;
3777125fcbdSVikram Hegde 	caddr_t aiomt_cmdbuf;
3787125fcbdSVikram Hegde 	caddr_t aiomt_eventlog;
3797125fcbdSVikram Hegde 	uint32_t *aiomt_cmd_tail;
3807125fcbdSVikram Hegde 	uint32_t *aiomt_event_head;
3817125fcbdSVikram Hegde 	ddi_dma_handle_t aiomt_dmahdl;
3827125fcbdSVikram Hegde 	void *aiomt_dma_bufva;
3837125fcbdSVikram Hegde 	uint64_t aiomt_dma_mem_realsz;
3847125fcbdSVikram Hegde 	ddi_acc_handle_t aiomt_dma_mem_hdl;
3857125fcbdSVikram Hegde 	ddi_dma_cookie_t aiomt_buf_dma_cookie;
3867125fcbdSVikram Hegde 	uint_t aiomt_buf_dma_ncookie;
3877125fcbdSVikram Hegde 	amd_iommu_intr_state_t aiomt_intr_state;
3887125fcbdSVikram Hegde 	ddi_intr_handle_t *aiomt_intr_htable;
3897125fcbdSVikram Hegde 	uint32_t aiomt_intr_htable_sz;
3907125fcbdSVikram Hegde 	uint32_t aiomt_actual_intrs;
3917125fcbdSVikram Hegde 	uint32_t aiomt_intr_cap;
3927125fcbdSVikram Hegde 	uint64_t aiomt_reg_devtbl_va;
3937125fcbdSVikram Hegde 	uint64_t aiomt_reg_cmdbuf_va;
3947125fcbdSVikram Hegde 	uint64_t aiomt_reg_eventlog_va;
3957125fcbdSVikram Hegde 	uint64_t aiomt_reg_ctrl_va;
3967125fcbdSVikram Hegde 	uint64_t aiomt_reg_excl_base_va;
3977125fcbdSVikram Hegde 	uint64_t aiomt_reg_excl_lim_va;
3987125fcbdSVikram Hegde 	uint64_t aiomt_reg_cmdbuf_head_va;
3997125fcbdSVikram Hegde 	uint64_t aiomt_reg_cmdbuf_tail_va;
4007125fcbdSVikram Hegde 	uint64_t aiomt_reg_eventlog_head_va;
4017125fcbdSVikram Hegde 	uint64_t aiomt_reg_eventlog_tail_va;
4027125fcbdSVikram Hegde 	uint64_t aiomt_reg_status_va;
4037125fcbdSVikram Hegde 	struct amd_iommu *aiomt_next;
4047125fcbdSVikram Hegde } amd_iommu_t;
4057125fcbdSVikram Hegde 
4067125fcbdSVikram Hegde typedef struct amd_iommu_dma_devtbl_ent {
4077125fcbdSVikram Hegde 	uint16_t de_domainid;
4087125fcbdSVikram Hegde 	uint8_t de_R;
4097125fcbdSVikram Hegde 	uint8_t de_W;
4107125fcbdSVikram Hegde 	caddr_t de_root_pgtbl;
4117125fcbdSVikram Hegde 	uint8_t de_pgmode;
4127125fcbdSVikram Hegde } amd_iommu_dma_devtbl_entry_t;
4137125fcbdSVikram Hegde 
4147125fcbdSVikram Hegde typedef struct amd_iommu_alias {
4157125fcbdSVikram Hegde 	uint16_t al_bdf;
4167125fcbdSVikram Hegde 	uint16_t al_src_bdf;
4177125fcbdSVikram Hegde 	struct amd_iommu_alias *al_next;
4187125fcbdSVikram Hegde } amd_iommu_alias_t;
4197125fcbdSVikram Hegde 
4207125fcbdSVikram Hegde typedef struct amd_iommu_cmdargs {
42194f1124eSVikram Hegde 	uint64_t ca_addr;
4227125fcbdSVikram Hegde 	uint16_t ca_domainid;
4237125fcbdSVikram Hegde 	uint16_t ca_deviceid;
4247125fcbdSVikram Hegde } amd_iommu_cmdargs_t;
4257125fcbdSVikram Hegde 
4267125fcbdSVikram Hegde struct amd_iommu_page_table;
4277125fcbdSVikram Hegde 
4287125fcbdSVikram Hegde typedef struct amd_iommu_page_table_hash {
4297125fcbdSVikram Hegde 	kmutex_t ampt_lock;
4307125fcbdSVikram Hegde 	struct amd_iommu_page_table **ampt_hash;
4317125fcbdSVikram Hegde } amd_iommu_page_table_hash_t;
4327125fcbdSVikram Hegde 
43394f1124eSVikram Hegde typedef enum {
43494f1124eSVikram Hegde 	AMD_IOMMU_LOG_INVALID_OP = 0,
43594f1124eSVikram Hegde 	AMD_IOMMU_LOG_DISPLAY,
43694f1124eSVikram Hegde 	AMD_IOMMU_LOG_DISCARD
43794f1124eSVikram Hegde } amd_iommu_log_op_t;
43894f1124eSVikram Hegde 
4397125fcbdSVikram Hegde typedef enum {
4407125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_NONE = 0,
4417125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_ALLOCHDL = 0x1,
4427125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_FREEHDL = 0x2,
4437125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_BIND = 0x4,
4447125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_UNBIND = 0x8,
4457125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_WIN = 0x10,
4467125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_PAGE_TABLES = 0x20,
4477125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_DEVTBL = 0x40,
4487125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_CMDBUF = 0x80,
4497125fcbdSVikram Hegde 	AMD_IOMMU_DEBUG_EVENTLOG = 0x100,
45094f1124eSVikram Hegde 	AMD_IOMMU_DEBUG_ACPI = 0x200,
45194f1124eSVikram Hegde 	AMD_IOMMU_DEBUG_PA2VA = 0x400,
45294f1124eSVikram Hegde 	AMD_IOMMU_DEBUG_TABLES = 0x800,
45394f1124eSVikram Hegde 	AMD_IOMMU_DEBUG_EXCL = 0x1000,
45494f1124eSVikram Hegde 	AMD_IOMMU_DEBUG_INTR = 0x2000
4557125fcbdSVikram Hegde } amd_iommu_debug_t;
4567125fcbdSVikram Hegde 
4577125fcbdSVikram Hegde extern const char *amd_iommu_modname;
4587125fcbdSVikram Hegde extern kmutex_t amd_iommu_global_lock;
4597125fcbdSVikram Hegde extern amd_iommu_alias_t **amd_iommu_alias;
4607125fcbdSVikram Hegde extern amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
4617125fcbdSVikram Hegde extern ddi_device_acc_attr_t amd_iommu_devacc;
4627125fcbdSVikram Hegde extern amd_iommu_debug_t amd_iommu_debug;
4637125fcbdSVikram Hegde 
4647125fcbdSVikram Hegde extern uint8_t amd_iommu_htatsresv;
4657125fcbdSVikram Hegde extern uint8_t amd_iommu_vasize;
4667125fcbdSVikram Hegde extern uint8_t amd_iommu_pasize;
46794f1124eSVikram Hegde extern int amd_iommu_64bit_bug;
46894f1124eSVikram Hegde extern int amd_iommu_unity_map;
46994f1124eSVikram Hegde extern int amd_iommu_no_RW_perms;
47094f1124eSVikram Hegde extern int amd_iommu_no_unmap;
47194f1124eSVikram Hegde extern int amd_iommu_pageva_inval_all;
47294f1124eSVikram Hegde extern int amd_iommu_disable;
47394f1124eSVikram Hegde extern char *amd_iommu_disable_list;
47494f1124eSVikram Hegde 
47594f1124eSVikram Hegde extern uint64_t amd_iommu_reg_get64_workaround(uint64_t *regp, uint32_t bits);
47694f1124eSVikram Hegde extern uint64_t amd_iommu_reg_set64_workaround(uint64_t *regp, uint32_t bits,
47794f1124eSVikram Hegde     uint64_t value);
478*ba758cf1SJerry Gilliam extern dev_info_t *amd_iommu_pci_dip(dev_info_t *rdip, const char *path);
4797125fcbdSVikram Hegde 
4807125fcbdSVikram Hegde int amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
4817125fcbdSVikram Hegde     amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held);
4827125fcbdSVikram Hegde int amd_iommu_page_table_hash_init(amd_iommu_page_table_hash_t *ampt);
4837125fcbdSVikram Hegde void amd_iommu_page_table_hash_fini(amd_iommu_page_table_hash_t *ampt);
4847125fcbdSVikram Hegde 
48594f1124eSVikram Hegde int amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op);
48694f1124eSVikram Hegde void amd_iommu_read_boot_props(void);
48794f1124eSVikram Hegde void amd_iommu_lookup_conf_props(dev_info_t *dip);
4887125fcbdSVikram Hegde 
4897125fcbdSVikram Hegde #endif	/* _KERNEL */
4907125fcbdSVikram Hegde 
4917125fcbdSVikram Hegde #ifdef	__cplusplus
4927125fcbdSVikram Hegde }
4937125fcbdSVikram Hegde #endif
4947125fcbdSVikram Hegde 
4957125fcbdSVikram Hegde #endif	/* _AMD_IOMMU_IMPL_H */
496