xref: /illumos-gate/usr/src/uts/i86pc/sys/immu.h (revision 9e986f0e)
13a634bfcSVikram Hegde /*
23a634bfcSVikram Hegde  * CDDL HEADER START
33a634bfcSVikram Hegde  *
43a634bfcSVikram Hegde  * The contents of this file are subject to the terms of the
53a634bfcSVikram Hegde  * Common Development and Distribution License (the "License").
63a634bfcSVikram Hegde  * You may not use this file except in compliance with the License.
73a634bfcSVikram Hegde  *
83a634bfcSVikram Hegde  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93a634bfcSVikram Hegde  * or http://www.opensolaris.org/os/licensing.
103a634bfcSVikram Hegde  * See the License for the specific language governing permissions
113a634bfcSVikram Hegde  * and limitations under the License.
123a634bfcSVikram Hegde  *
133a634bfcSVikram Hegde  * When distributing Covered Code, include this CDDL HEADER in each
143a634bfcSVikram Hegde  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153a634bfcSVikram Hegde  * If applicable, add the following below this CDDL HEADER, with the
163a634bfcSVikram Hegde  * fields enclosed by brackets "[]" replaced with your own identifying
173a634bfcSVikram Hegde  * information: Portions Copyright [yyyy] [name of copyright owner]
183a634bfcSVikram Hegde  *
193a634bfcSVikram Hegde  * CDDL HEADER END
203a634bfcSVikram Hegde  */
213a634bfcSVikram Hegde /*
22*9e986f0eSFrank Van Der Linden  * Portions Copyright (c) 2010, Oracle and/or its affiliates.
23*9e986f0eSFrank Van Der Linden  * All rights reserved.
243a634bfcSVikram Hegde  */
253a634bfcSVikram Hegde 
263a634bfcSVikram Hegde /*
273a634bfcSVikram Hegde  * Copyright (c) 2008, Intel Corporation.
283a634bfcSVikram Hegde  * All rights reserved.
293a634bfcSVikram Hegde  */
303a634bfcSVikram Hegde 
313a634bfcSVikram Hegde #ifndef	_SYS_INTEL_IOMMU_H
323a634bfcSVikram Hegde #define	_SYS_INTEL_IOMMU_H
333a634bfcSVikram Hegde 
343a634bfcSVikram Hegde /*
353a634bfcSVikram Hegde  * Intel IOMMU implementation specific state
363a634bfcSVikram Hegde  */
373a634bfcSVikram Hegde 
383a634bfcSVikram Hegde #ifdef	__cplusplus
393a634bfcSVikram Hegde extern "C" {
403a634bfcSVikram Hegde #endif
413a634bfcSVikram Hegde 
423a634bfcSVikram Hegde #include <sys/types.h>
433a634bfcSVikram Hegde #include <sys/bitset.h>
443a634bfcSVikram Hegde #include <sys/kstat.h>
453a634bfcSVikram Hegde #include <sys/vmem.h>
463a634bfcSVikram Hegde #include <sys/rootnex.h>
473a634bfcSVikram Hegde 
483a634bfcSVikram Hegde /*
493a634bfcSVikram Hegde  * Some ON drivers have bugs. Keep this define until all such drivers
503a634bfcSVikram Hegde  * have been fixed
513a634bfcSVikram Hegde  */
523a634bfcSVikram Hegde #define	BUGGY_DRIVERS 1
533a634bfcSVikram Hegde 
543a634bfcSVikram Hegde /* PD(T)E entries */
553a634bfcSVikram Hegde typedef uint64_t hw_pdte_t;
563a634bfcSVikram Hegde 
573a634bfcSVikram Hegde #define	IMMU_MAXNAMELEN (64)
583a634bfcSVikram Hegde #define	IMMU_MAXSEG	(1)
593a634bfcSVikram Hegde #define	IMMU_REGSZ	(1UL << 12)
603a634bfcSVikram Hegde #define	IMMU_PAGESIZE   (4096)
613a634bfcSVikram Hegde #define	IMMU_PAGESHIFT	(12)
623a634bfcSVikram Hegde #define	IMMU_PAGEOFFSET	(IMMU_PAGESIZE - 1)
633a634bfcSVikram Hegde #define	IMMU_PAGEMASK	(~IMMU_PAGEOFFSET)
643a634bfcSVikram Hegde #define	IMMU_BTOP(b)	(((uint64_t)b) >> IMMU_PAGESHIFT)
653a634bfcSVikram Hegde #define	IMMU_PTOB(p)	(((uint64_t)p) << IMMU_PAGESHIFT)
663a634bfcSVikram Hegde #define	IMMU_PGTABLE_MAX_LEVELS	(6)
673a634bfcSVikram Hegde #define	IMMU_ROUNDUP(size) (((size) + IMMU_PAGEOFFSET) & ~IMMU_PAGEOFFSET)
683a634bfcSVikram Hegde #define	IMMU_ROUNDOWN(addr) ((addr) & ~IMMU_PAGEOFFSET)
693a634bfcSVikram Hegde #define	IMMU_PGTABLE_LEVEL_STRIDE	(9)
703a634bfcSVikram Hegde #define	IMMU_PGTABLE_LEVEL_MASK	((1<<IMMU_PGTABLE_LEVEL_STRIDE) - 1)
713a634bfcSVikram Hegde #define	IMMU_PGTABLE_OFFSHIFT  (IMMU_PAGESHIFT - IMMU_PGTABLE_LEVEL_STRIDE)
723a634bfcSVikram Hegde #define	IMMU_PGTABLE_MAXIDX  ((IMMU_PAGESIZE / sizeof (hw_pdte_t)) - 1)
733a634bfcSVikram Hegde 
743a634bfcSVikram Hegde #define	IMMU_ROUNDUP(size) (((size) + IMMU_PAGEOFFSET) & ~IMMU_PAGEOFFSET)
753a634bfcSVikram Hegde #define	IMMU_ROUNDOWN(addr) ((addr) & ~IMMU_PAGEOFFSET)
763a634bfcSVikram Hegde 
773a634bfcSVikram Hegde /*
783a634bfcSVikram Hegde  * DMAR global defines
793a634bfcSVikram Hegde  */
803a634bfcSVikram Hegde #define	DMAR_TABLE	"dmar-table"
813a634bfcSVikram Hegde #define	DMAR_INTRMAP_SUPPORT	(0x01)
823a634bfcSVikram Hegde 
833a634bfcSVikram Hegde /* DMAR unit types */
843a634bfcSVikram Hegde #define	DMAR_DRHD	0
853a634bfcSVikram Hegde #define	DMAR_RMRR	1
863a634bfcSVikram Hegde #define	DMAR_ATSR	2
873a634bfcSVikram Hegde #define	DMAR_RHSA	3
883a634bfcSVikram Hegde 
893a634bfcSVikram Hegde /* DRHD flag values */
903a634bfcSVikram Hegde #define	DMAR_INCLUDE_ALL	(0x01)
913a634bfcSVikram Hegde 
923a634bfcSVikram Hegde /* Device scope types */
933a634bfcSVikram Hegde #define	DMAR_ENDPOINT	1
943a634bfcSVikram Hegde #define	DMAR_SUBTREE	2
953a634bfcSVikram Hegde #define	DMAR_IOAPIC	3
963a634bfcSVikram Hegde #define	DMAR_HPET	4
973a634bfcSVikram Hegde 
983a634bfcSVikram Hegde 
993a634bfcSVikram Hegde /* Forward declarations for IOMMU state structure and DVMA domain struct */
1003a634bfcSVikram Hegde struct immu;
1013a634bfcSVikram Hegde struct domain;
1023a634bfcSVikram Hegde 
1033a634bfcSVikram Hegde /*
1043a634bfcSVikram Hegde  * The following structure describes the formate of DMAR ACPI table format.
1053a634bfcSVikram Hegde  * They are used to parse DMAR ACPI table. Read the spec for the meaning
1063a634bfcSVikram Hegde  * of each member.
1073a634bfcSVikram Hegde  */
1083a634bfcSVikram Hegde 
1093a634bfcSVikram Hegde /* lengths of various strings */
1103a634bfcSVikram Hegde #define	DMAR_SIG_LEN    (4)	/* table signature */
1113a634bfcSVikram Hegde #define	DMAR_OEMID_LEN  (6)	/* OEM ID */
1123a634bfcSVikram Hegde #define	DMAR_TBLID_LEN  (8)	/* OEM table ID */
1133a634bfcSVikram Hegde #define	DMAR_ASL_LEN    (4)	/* ASL len */
1143a634bfcSVikram Hegde 
1153a634bfcSVikram Hegde typedef struct dmar_table {
1163a634bfcSVikram Hegde 	kmutex_t	tbl_lock;
1173a634bfcSVikram Hegde 	uint8_t		tbl_haw;
1183a634bfcSVikram Hegde 	boolean_t	tbl_intrmap;
1193a634bfcSVikram Hegde 	list_t		tbl_drhd_list[IMMU_MAXSEG];
1203a634bfcSVikram Hegde 	list_t		tbl_rmrr_list[IMMU_MAXSEG];
1213a634bfcSVikram Hegde 	char		*tbl_oem_id;
1223a634bfcSVikram Hegde 	char		*tbl_oem_tblid;
1233a634bfcSVikram Hegde 	uint32_t	tbl_oem_rev;
1243a634bfcSVikram Hegde 	caddr_t		tbl_raw;
1253a634bfcSVikram Hegde 	int		tbl_rawlen;
1263a634bfcSVikram Hegde } dmar_table_t;
1273a634bfcSVikram Hegde 
1283a634bfcSVikram Hegde typedef struct drhd {
1293a634bfcSVikram Hegde 	kmutex_t	dr_lock;   /* protects the dmar field */
1303a634bfcSVikram Hegde 	struct immu	*dr_immu;
1313a634bfcSVikram Hegde 	dev_info_t	*dr_dip;
1323a634bfcSVikram Hegde 	uint16_t 	dr_seg;
1333a634bfcSVikram Hegde 	uint64_t 	dr_regs;
1343a634bfcSVikram Hegde 	boolean_t	dr_include_all;
1353a634bfcSVikram Hegde 	list_t 		dr_scope_list;
1363a634bfcSVikram Hegde 	list_node_t 	dr_node;
1373a634bfcSVikram Hegde } drhd_t;
1383a634bfcSVikram Hegde 
1393a634bfcSVikram Hegde typedef struct rmrr {
1403a634bfcSVikram Hegde 	kmutex_t	rm_lock;
1413a634bfcSVikram Hegde 	uint16_t	rm_seg;
1423a634bfcSVikram Hegde 	uint64_t	rm_base;
1433a634bfcSVikram Hegde 	uint64_t	rm_limit;
1443a634bfcSVikram Hegde 	list_t		rm_scope_list;
1453a634bfcSVikram Hegde 	list_node_t	rm_node;
1463a634bfcSVikram Hegde } rmrr_t;
1473a634bfcSVikram Hegde 
1483a634bfcSVikram Hegde /*
1493a634bfcSVikram Hegde  * Macros based on PCI spec
1503a634bfcSVikram Hegde  */
1513a634bfcSVikram Hegde #define	IMMU_PCI_DEV(devfunc)    ((uint64_t)devfunc >> 3) /* from devfunc  */
1523a634bfcSVikram Hegde #define	IMMU_PCI_FUNC(devfunc)   (devfunc & 7)  /* get func from devfunc */
1533a634bfcSVikram Hegde #define	IMMU_PCI_DEVFUNC(d, f)   (((d) << 3) | (f))  /* create devfunc */
1543a634bfcSVikram Hegde 
1553a634bfcSVikram Hegde typedef struct scope {
1563a634bfcSVikram Hegde 	uint8_t scp_type;
1573a634bfcSVikram Hegde 	uint8_t scp_enumid;
1583a634bfcSVikram Hegde 	uint8_t scp_bus;
1593a634bfcSVikram Hegde 	uint8_t scp_dev;
1603a634bfcSVikram Hegde 	uint8_t scp_func;
1613a634bfcSVikram Hegde 	list_node_t scp_node;
1623a634bfcSVikram Hegde } scope_t;
1633a634bfcSVikram Hegde 
1643a634bfcSVikram Hegde /*
1653a634bfcSVikram Hegde  * interrupt source id and drhd info for ioapic
1663a634bfcSVikram Hegde  */
1673a634bfcSVikram Hegde typedef struct ioapic_drhd {
1683a634bfcSVikram Hegde 	uchar_t		ioapic_ioapicid;
1693a634bfcSVikram Hegde 	uint16_t	ioapic_sid;	/* ioapic source id */
1703a634bfcSVikram Hegde 	drhd_t		*ioapic_drhd;
1713a634bfcSVikram Hegde 	list_node_t	ioapic_node;
1723a634bfcSVikram Hegde } ioapic_drhd_t;
1733a634bfcSVikram Hegde 
1743a634bfcSVikram Hegde typedef struct memrng {
1753a634bfcSVikram Hegde 	uint64_t mrng_start;
1763a634bfcSVikram Hegde 	uint64_t mrng_npages;
1773a634bfcSVikram Hegde } memrng_t;
1783a634bfcSVikram Hegde 
1793a634bfcSVikram Hegde typedef enum immu_flags {
1803a634bfcSVikram Hegde 	IMMU_FLAGS_NONE = 0x1,
1813a634bfcSVikram Hegde 	IMMU_FLAGS_SLEEP = 0x1,
1823a634bfcSVikram Hegde 	IMMU_FLAGS_NOSLEEP = 0x2,
1833a634bfcSVikram Hegde 	IMMU_FLAGS_READ = 0x4,
1843a634bfcSVikram Hegde 	IMMU_FLAGS_WRITE = 0x8,
1853a634bfcSVikram Hegde 	IMMU_FLAGS_DONTPASS = 0x10,
1863a634bfcSVikram Hegde 	IMMU_FLAGS_ALLOC = 0x20,
1873a634bfcSVikram Hegde 	IMMU_FLAGS_MUST_MATCH = 0x40,
1883a634bfcSVikram Hegde 	IMMU_FLAGS_PAGE1 = 0x80,
1893a634bfcSVikram Hegde 	IMMU_FLAGS_UNITY = 0x100,
1903a634bfcSVikram Hegde 	IMMU_FLAGS_DMAHDL = 0x200,
1913a634bfcSVikram Hegde 	IMMU_FLAGS_MEMRNG = 0x400
1923a634bfcSVikram Hegde } immu_flags_t;
1933a634bfcSVikram Hegde 
1943a634bfcSVikram Hegde typedef enum cont_avail {
1953a634bfcSVikram Hegde 	IMMU_CONT_BAD = 0x0,
1963a634bfcSVikram Hegde 	IMMU_CONT_UNINITED = 0x1,
1973a634bfcSVikram Hegde 	IMMU_CONT_INITED = 0x2
1983a634bfcSVikram Hegde } cont_avail_t;
1993a634bfcSVikram Hegde 
2003a634bfcSVikram Hegde /* Size of root and context tables and their entries */
2013a634bfcSVikram Hegde #define	IMMU_ROOT_TBLSZ		(4096)
2023a634bfcSVikram Hegde #define	IMMU_CONT_TBLSZ		(4096)
2033a634bfcSVikram Hegde #define	IMMU_ROOT_NUM		(256)
2043a634bfcSVikram Hegde #define	IMMU_CONT_NUM		(256)
2053a634bfcSVikram Hegde 
2063a634bfcSVikram Hegde /* register offset */
2073a634bfcSVikram Hegde #define	IMMU_REG_VERSION	(0x00)  /* Version Rigister, 32 bit */
2083a634bfcSVikram Hegde #define	IMMU_REG_CAP		(0x08)  /* Capability Register, 64 bit */
2093a634bfcSVikram Hegde #define	IMMU_REG_EXCAP		(0x10)  /* Extended Capability Reg, 64 bit */
2103a634bfcSVikram Hegde #define	IMMU_REG_GLOBAL_CMD	(0x18)  /* Global Command Register, 32 bit */
2113a634bfcSVikram Hegde #define	IMMU_REG_GLOBAL_STS	(0x1C)  /* Global Status Register, 32 bit */
2123a634bfcSVikram Hegde #define	IMMU_REG_ROOTENTRY	(0x20)  /* Root-Entry Table Addr Reg, 64 bit */
2133a634bfcSVikram Hegde #define	IMMU_REG_CONTEXT_CMD	(0x28)  /* Context Comand Register, 64 bit */
2143a634bfcSVikram Hegde #define	IMMU_REG_FAULT_STS	(0x34)  /* Fault Status Register, 32 bit */
2153a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_CON	(0x38)  /* Fault Event Control Reg, 32 bit */
2163a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_DATA	(0x3C)  /* Fault Event Data Register, 32 bit */
2173a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_ADDR	(0x40)  /* Fault Event Address Reg, 32 bit */
2183a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_UADDR	(0x44)  /* Fault Event Upper Addr Reg, 32 bit */
2193a634bfcSVikram Hegde #define	IMMU_REG_AFAULT_LOG	(0x58)  /* Advanced Fault Log Reg, 64 bit */
2203a634bfcSVikram Hegde #define	IMMU_REG_PMER		(0x64)  /* Protected Memory Enble Reg, 32 bit */
2213a634bfcSVikram Hegde #define	IMMU_REG_PLMBR		(0x68)  /* Protected Low Mem Base Reg, 32 bit */
2223a634bfcSVikram Hegde #define	IMMU_REG_PLMLR		(0x6C)  /* Protected Low Mem Lim Reg, 32 bit */
2233a634bfcSVikram Hegde #define	IMMU_REG_PHMBR		(0X70)  /* Protectd High Mem Base Reg, 64 bit */
2243a634bfcSVikram Hegde #define	IMMU_REG_PHMLR		(0x78)  /* Protected High Mem Lim Reg, 64 bit */
2253a634bfcSVikram Hegde #define	IMMU_REG_INVAL_QH	(0x80)  /* Invalidation Queue Head, 64 bit */
2263a634bfcSVikram Hegde #define	IMMU_REG_INVAL_QT	(0x88)  /* Invalidation Queue Tail, 64 bit */
2273a634bfcSVikram Hegde #define	IMMU_REG_INVAL_QAR	(0x90)  /* Invalidtion Queue Addr Reg, 64 bit */
2283a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CSR	(0x9C)  /* Inval Compl Status Reg, 32 bit */
2293a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CECR	(0xA0)  /* Inval Compl Evnt Ctrl Reg, 32 bit */
2303a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CEDR	(0xA4)  /* Inval Compl Evnt Data Reg, 32 bit */
2313a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CEAR	(0xA8)  /* Inval Compl Event Addr Reg, 32 bit */
2323a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CEUAR	(0xAC)  /* Inval Comp Evnt Up Addr reg, 32bit */
2333a634bfcSVikram Hegde #define	IMMU_REG_IRTAR		(0xB8)  /* INTR Remap Tbl Addr Reg, 64 bit */
2343a634bfcSVikram Hegde 
2353a634bfcSVikram Hegde /* ioapic memory region */
2363a634bfcSVikram Hegde #define	IOAPIC_REGION_START	(0xfee00000)
2373a634bfcSVikram Hegde #define	IOAPIC_REGION_END	(0xfeefffff)
2383a634bfcSVikram Hegde 
2393a634bfcSVikram Hegde /* fault register */
2403a634bfcSVikram Hegde #define	IMMU_FAULT_STS_PPF		(2)
2413a634bfcSVikram Hegde #define	IMMU_FAULT_STS_PFO		(1)
2423a634bfcSVikram Hegde #define	IMMU_FAULT_STS_ITE		(1 << 6)
2433a634bfcSVikram Hegde #define	IMMU_FAULT_STS_ICE		(1 << 5)
2443a634bfcSVikram Hegde #define	IMMU_FAULT_STS_IQE		(1 << 4)
2453a634bfcSVikram Hegde #define	IMMU_FAULT_GET_INDEX(x)		((((uint64_t)x) >> 8) & 0xff)
2463a634bfcSVikram Hegde #define	IMMU_FRR_GET_F(x)		(((uint64_t)x) >> 63)
2473a634bfcSVikram Hegde #define	IMMU_FRR_GET_FR(x)		((((uint64_t)x) >> 32) & 0xff)
2483a634bfcSVikram Hegde #define	IMMU_FRR_GET_FT(x)		((((uint64_t)x) >> 62) & 0x1)
2493a634bfcSVikram Hegde #define	IMMU_FRR_GET_SID(x)		((x) & 0xffff)
2503a634bfcSVikram Hegde 
2513a634bfcSVikram Hegde /* (ex)capability register */
2523a634bfcSVikram Hegde #define	IMMU_CAP_GET_NFR(x)		(((((uint64_t)x) >> 40) & 0xff) + 1)
2533a634bfcSVikram Hegde #define	IMMU_CAP_GET_DWD(x)		((((uint64_t)x) >> 54) & 1)
2543a634bfcSVikram Hegde #define	IMMU_CAP_GET_DRD(x)		((((uint64_t)x) >> 55) & 1)
2553a634bfcSVikram Hegde #define	IMMU_CAP_GET_PSI(x)		((((uint64_t)x) >> 39) & 1)
2563a634bfcSVikram Hegde #define	IMMU_CAP_GET_SPS(x)		((((uint64_t)x) >> 34) & 0xf)
2573a634bfcSVikram Hegde #define	IMMU_CAP_GET_ISOCH(x)		((((uint64_t)x) >> 23) & 1)
2583a634bfcSVikram Hegde #define	IMMU_CAP_GET_ZLR(x)		((((uint64_t)x) >> 22) & 1)
2593a634bfcSVikram Hegde #define	IMMU_CAP_GET_MAMV(x)		((((uint64_t)x) >> 48) & 0x3f)
2603a634bfcSVikram Hegde #define	IMMU_CAP_GET_CM(x)		((((uint64_t)x) >> 7) & 1)
2613a634bfcSVikram Hegde #define	IMMU_CAP_GET_PHMR(x)		((((uint64_t)x) >> 6) & 1)
2623a634bfcSVikram Hegde #define	IMMU_CAP_GET_PLMR(x)		((((uint64_t)x) >> 5) & 1)
2633a634bfcSVikram Hegde #define	IMMU_CAP_GET_RWBF(x)		((((uint64_t)x) >> 4) & 1)
2643a634bfcSVikram Hegde #define	IMMU_CAP_GET_AFL(x)		((((uint64_t)x) >> 3) & 1)
2653a634bfcSVikram Hegde #define	IMMU_CAP_GET_FRO(x)		(((((uint64_t)x) >> 24) & 0x3ff) * 16)
2663a634bfcSVikram Hegde #define	IMMU_CAP_MGAW(x)		(((((uint64_t)x) >> 16) & 0x3f) + 1)
2673a634bfcSVikram Hegde #define	IMMU_CAP_SAGAW(x)		((((uint64_t)x) >> 8) & 0x1f)
2683a634bfcSVikram Hegde #define	IMMU_CAP_ND(x)			(1 << (((x) & 0x7) *2 + 4)) -1
2693a634bfcSVikram Hegde #define	IMMU_ECAP_GET_IRO(x)		(((((uint64_t)x) >> 8) & 0x3ff) << 4)
2703a634bfcSVikram Hegde #define	IMMU_ECAP_GET_MHMV(x)		(((uint64_t)x >> 20) & 0xf)
2713a634bfcSVikram Hegde #define	IMMU_ECAP_GET_SC(x)		((x) & 0x80)
2723a634bfcSVikram Hegde #define	IMMU_ECAP_GET_PT(x)		((x) & 0x40)
2733a634bfcSVikram Hegde #define	IMMU_ECAP_GET_CH(x)		((x) & 0x20)
2743a634bfcSVikram Hegde #define	IMMU_ECAP_GET_EIM(x)		((x) & 0x10)
2753a634bfcSVikram Hegde #define	IMMU_ECAP_GET_IR(x)		((x) & 0x8)
2763a634bfcSVikram Hegde #define	IMMU_ECAP_GET_DI(x)		((x) & 0x4)
2773a634bfcSVikram Hegde #define	IMMU_ECAP_GET_QI(x)		((x) & 0x2)
2783a634bfcSVikram Hegde #define	IMMU_ECAP_GET_C(x)		((x) & 0x1)
2793a634bfcSVikram Hegde 
2803a634bfcSVikram Hegde #define	IMMU_CAP_SET_RWBF(x)		((x) |= (1 << 4))
2813a634bfcSVikram Hegde 
2823a634bfcSVikram Hegde 
2833a634bfcSVikram Hegde /* iotlb invalidation */
2843a634bfcSVikram Hegde #define	TLB_INV_GLOBAL		(((uint64_t)1) << 60)
2853a634bfcSVikram Hegde #define	TLB_INV_DOMAIN		(((uint64_t)2) << 60)
2863a634bfcSVikram Hegde #define	TLB_INV_PAGE		(((uint64_t)3) << 60)
2873a634bfcSVikram Hegde #define	TLB_INV_GET_IAIG(x)	((((uint64_t)x) >> 57) & 7)
2883a634bfcSVikram Hegde #define	TLB_INV_DRAIN_READ	(((uint64_t)1) << 49)
2893a634bfcSVikram Hegde #define	TLB_INV_DRAIN_WRITE	(((uint64_t)1) << 48)
2903a634bfcSVikram Hegde #define	TLB_INV_DID(x)		(((uint64_t)((x) & 0xffff)) << 32)
2913a634bfcSVikram Hegde #define	TLB_INV_IVT		(((uint64_t)1) << 63)
2923a634bfcSVikram Hegde #define	TLB_IVA_HINT(x)		(((x) & 0x1) << 6)
2933a634bfcSVikram Hegde #define	TLB_IVA_LEAF		1
2943a634bfcSVikram Hegde #define	TLB_IVA_WHOLE		0
2953a634bfcSVikram Hegde 
2963a634bfcSVikram Hegde /* dont use value 0 for  enums - to catch unit 8 */
2973a634bfcSVikram Hegde typedef enum iotlb_inv {
2983a634bfcSVikram Hegde 	IOTLB_PSI = 1,
2993a634bfcSVikram Hegde 	IOTLB_DSI,
3003a634bfcSVikram Hegde 	IOTLB_GLOBAL
3013a634bfcSVikram Hegde } immu_iotlb_inv_t;
3023a634bfcSVikram Hegde 
3033a634bfcSVikram Hegde typedef enum context_inv {
3043a634bfcSVikram Hegde 	CONTEXT_FSI = 1,
3053a634bfcSVikram Hegde 	CONTEXT_DSI,
3063a634bfcSVikram Hegde 	CONTEXT_GLOBAL
3073a634bfcSVikram Hegde } immu_context_inv_t;
3083a634bfcSVikram Hegde 
3093a634bfcSVikram Hegde /* context invalidation */
3103a634bfcSVikram Hegde #define	CCMD_INV_ICC		(((uint64_t)1) << 63)
3113a634bfcSVikram Hegde #define	CCMD_INV_GLOBAL		(((uint64_t)1) << 61)
3123a634bfcSVikram Hegde #define	CCMD_INV_DOMAIN		(((uint64_t)2) << 61)
3133a634bfcSVikram Hegde #define	CCMD_INV_DEVICE		(((uint64_t)3) << 61)
3143a634bfcSVikram Hegde #define	CCMD_INV_DID(x)		((uint64_t)((x) & 0xffff))
3153a634bfcSVikram Hegde #define	CCMD_INV_SID(x)		(((uint64_t)((x) & 0xffff)) << 16)
3163a634bfcSVikram Hegde #define	CCMD_INV_FM(x)		(((uint64_t)((x) & 0x3)) << 32)
3173a634bfcSVikram Hegde 
3183a634bfcSVikram Hegde /* global command register */
3193a634bfcSVikram Hegde #define	IMMU_GCMD_TE		(((uint32_t)1) << 31)
3203a634bfcSVikram Hegde #define	IMMU_GCMD_SRTP		(((uint32_t)1) << 30)
3213a634bfcSVikram Hegde #define	IMMU_GCMD_SFL		(((uint32_t)1) << 29)
3223a634bfcSVikram Hegde #define	IMMU_GCMD_EAFL		(((uint32_t)1) << 28)
3233a634bfcSVikram Hegde #define	IMMU_GCMD_WBF		(((uint32_t)1) << 27)
3243a634bfcSVikram Hegde #define	IMMU_GCMD_QIE		(((uint32_t)1) << 26)
3253a634bfcSVikram Hegde #define	IMMU_GCMD_IRE		(((uint32_t)1) << 25)
3263a634bfcSVikram Hegde #define	IMMU_GCMD_SIRTP	(((uint32_t)1) << 24)
3273a634bfcSVikram Hegde #define	IMMU_GCMD_CFI		(((uint32_t)1) << 23)
3283a634bfcSVikram Hegde 
3293a634bfcSVikram Hegde /* global status register */
3303a634bfcSVikram Hegde #define	IMMU_GSTS_TES		(((uint32_t)1) << 31)
3313a634bfcSVikram Hegde #define	IMMU_GSTS_RTPS		(((uint32_t)1) << 30)
3323a634bfcSVikram Hegde #define	IMMU_GSTS_FLS		(((uint32_t)1) << 29)
3333a634bfcSVikram Hegde #define	IMMU_GSTS_AFLS		(((uint32_t)1) << 28)
3343a634bfcSVikram Hegde #define	IMMU_GSTS_WBFS		(((uint32_t)1) << 27)
3353a634bfcSVikram Hegde #define	IMMU_GSTS_QIES		(((uint32_t)1) << 26)
3363a634bfcSVikram Hegde #define	IMMU_GSTS_IRES		(((uint32_t)1) << 25)
3373a634bfcSVikram Hegde #define	IMMU_GSTS_IRTPS	(((uint32_t)1) << 24)
3383a634bfcSVikram Hegde #define	IMMU_GSTS_CFIS		(((uint32_t)1) << 23)
3393a634bfcSVikram Hegde 
3403a634bfcSVikram Hegde /* psi address mask */
3413a634bfcSVikram Hegde #define	ADDR_AM_MAX(m)		(((uint_t)1) << (m))
3423a634bfcSVikram Hegde #define	ADDR_AM_OFFSET(n, m)	((n) & (ADDR_AM_MAX(m) - 1))
3433a634bfcSVikram Hegde 
3443a634bfcSVikram Hegde /* dmar fault event */
345e03dceedSVikram Hegde #define	IMMU_INTR_IPL			(4)
3463a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_CON_IM_SHIFT	(31)
3473a634bfcSVikram Hegde 
3483a634bfcSVikram Hegde #define	IMMU_ALLOC_RESOURCE_DELAY    (drv_usectohz(5000))
3493a634bfcSVikram Hegde 
3503a634bfcSVikram Hegde /* max value of Size field of Interrupt Remapping Table Address Register */
3513a634bfcSVikram Hegde #define	INTRMAP_MAX_IRTA_SIZE	0xf
3523a634bfcSVikram Hegde 
3533a634bfcSVikram Hegde /* interrupt remapping table entry size */
3543a634bfcSVikram Hegde #define	INTRMAP_RTE_SIZE		0x10
3553a634bfcSVikram Hegde 
3563a634bfcSVikram Hegde /* ioapic redirection table entry related shift of remappable interrupt */
3573a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_IDX_SHIFT		17
3583a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_FORMAT_SHIFT	16
3593a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_TM_SHIFT		15
3603a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_POL_SHIFT		13
3613a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_IDX15_SHIFT	11
3623a634bfcSVikram Hegde 
3633a634bfcSVikram Hegde /* msi intr entry related shift of remappable interrupt */
3643a634bfcSVikram Hegde #define	INTRMAP_MSI_IDX_SHIFT	5
3653a634bfcSVikram Hegde #define	INTRMAP_MSI_FORMAT_SHIFT	4
3663a634bfcSVikram Hegde #define	INTRMAP_MSI_SHV_SHIFT	3
3673a634bfcSVikram Hegde #define	INTRMAP_MSI_IDX15_SHIFT	2
3683a634bfcSVikram Hegde 
3693a634bfcSVikram Hegde #define	INTRMAP_IDX_FULL		(uint_t)-1
3703a634bfcSVikram Hegde 
3713a634bfcSVikram Hegde #define	RDT_DLM(rdt)	BITX((rdt), 10, 8)
3723a634bfcSVikram Hegde #define	RDT_DM(rdt)	BT_TEST(&(rdt), 11)
3733a634bfcSVikram Hegde #define	RDT_POL(rdt)	BT_TEST(&(rdt), 13)
3743a634bfcSVikram Hegde #define	RDT_TM(rdt)	BT_TEST(&(rdt), 15)
3753a634bfcSVikram Hegde 
3763a634bfcSVikram Hegde #define	INTRMAP_DISABLE	(void *)-1
3773a634bfcSVikram Hegde 
3783a634bfcSVikram Hegde /*
3793a634bfcSVikram Hegde  * invalidation granularity
3803a634bfcSVikram Hegde  */
3813a634bfcSVikram Hegde typedef enum {
3823a634bfcSVikram Hegde 	TLB_INV_G_GLOBAL = 1,
3833a634bfcSVikram Hegde 	TLB_INV_G_DOMAIN,
3843a634bfcSVikram Hegde 	TLB_INV_G_PAGE
3853a634bfcSVikram Hegde } tlb_inv_g_t;
3863a634bfcSVikram Hegde 
3873a634bfcSVikram Hegde typedef enum {
3883a634bfcSVikram Hegde 	CTT_INV_G_GLOBAL = 1,
3893a634bfcSVikram Hegde 	CTT_INV_G_DOMAIN,
3903a634bfcSVikram Hegde 	CTT_INV_G_DEVICE
3913a634bfcSVikram Hegde } ctt_inv_g_t;
3923a634bfcSVikram Hegde 
3933a634bfcSVikram Hegde typedef enum {
3943a634bfcSVikram Hegde 	IEC_INV_GLOBAL = 0,
3953a634bfcSVikram Hegde 	IEC_INV_INDEX
3963a634bfcSVikram Hegde } iec_inv_g_t;
3973a634bfcSVikram Hegde 
3983a634bfcSVikram Hegde 
3993a634bfcSVikram Hegde struct inv_queue_state;
4003a634bfcSVikram Hegde struct intrmap_tbl_state;
4013a634bfcSVikram Hegde 
4023a634bfcSVikram Hegde /* A software page table structure */
4033a634bfcSVikram Hegde typedef struct pgtable {
4043a634bfcSVikram Hegde 	krwlock_t swpg_rwlock;
4053a634bfcSVikram Hegde 	caddr_t hwpg_vaddr;   /* HW pgtable VA */
4063a634bfcSVikram Hegde 	paddr_t hwpg_paddr;   /* HW pgtable PA */
4073a634bfcSVikram Hegde 	ddi_dma_handle_t hwpg_dmahdl;
4083a634bfcSVikram Hegde 	ddi_acc_handle_t hwpg_memhdl;
4093a634bfcSVikram Hegde 	struct pgtable **swpg_next_array;
4103a634bfcSVikram Hegde 	list_node_t swpg_domain_node;  /* domain list of pgtables */
4113a634bfcSVikram Hegde } pgtable_t;
4123a634bfcSVikram Hegde 
4133a634bfcSVikram Hegde /* interrupt remapping table state info */
4143a634bfcSVikram Hegde typedef struct intrmap {
4153a634bfcSVikram Hegde 	kmutex_t		intrmap_lock;
4163a634bfcSVikram Hegde 	ddi_dma_handle_t	intrmap_dma_hdl;
4173a634bfcSVikram Hegde 	ddi_acc_handle_t	intrmap_acc_hdl;
4183a634bfcSVikram Hegde 	caddr_t			intrmap_vaddr;
4193a634bfcSVikram Hegde 	paddr_t			intrmap_paddr;
4203a634bfcSVikram Hegde 	uint_t			intrmap_size;
4213a634bfcSVikram Hegde 	bitset_t		intrmap_map;
4223a634bfcSVikram Hegde 	uint_t			intrmap_free;
4233a634bfcSVikram Hegde } intrmap_t;
4243a634bfcSVikram Hegde 
4253a634bfcSVikram Hegde typedef struct hw_rce {
4263a634bfcSVikram Hegde 	uint64_t lo;
4273a634bfcSVikram Hegde 	uint64_t hi;
4283a634bfcSVikram Hegde } hw_rce_t;
4293a634bfcSVikram Hegde 
4303a634bfcSVikram Hegde 
4313a634bfcSVikram Hegde #define	ROOT_GET_P(hrent) ((hrent)->lo & 0x1)
4323a634bfcSVikram Hegde #define	ROOT_SET_P(hrent) ((hrent)->lo |= 0x1)
4333a634bfcSVikram Hegde 
4343a634bfcSVikram Hegde #define	ROOT_GET_CONT(hrent) ((hrent)->lo & ~(0xFFF))
4353a634bfcSVikram Hegde #define	ROOT_SET_CONT(hrent, paddr) ((hrent)->lo |= (paddr & (~0xFFF)))
4363a634bfcSVikram Hegde 
4373a634bfcSVikram Hegde #define	TTYPE_XLATE_ONLY  (0x0)
4383a634bfcSVikram Hegde #define	TTYPE_XLATE_IOTLB (0x1)
4393a634bfcSVikram Hegde #define	TTYPE_PASSTHRU    (0x2)
4403a634bfcSVikram Hegde #define	TTYPE_RESERVED    (0x3)
4413a634bfcSVikram Hegde 
4423a634bfcSVikram Hegde #define	CONT_GET_DID(hcent) ((((uint64_t)(hcent)->hi) >> 8) & 0xFFFF)
4433a634bfcSVikram Hegde #define	CONT_SET_DID(hcent, did) ((hcent)->hi |= ((0xFFFF & (did)) << 8))
4443a634bfcSVikram Hegde 
4453a634bfcSVikram Hegde #define	CONT_GET_AVAIL(hcent) ((((uint64_t)((hcent)->hi)) >> 0x3) & 0xF)
4463a634bfcSVikram Hegde #define	CONT_SET_AVAIL(hcent, av) ((hcent)->hi |= ((0xF & (av)) << 0x3))
4473a634bfcSVikram Hegde 
4483a634bfcSVikram Hegde #define	CONT_GET_LO_AW(hcent) (30 + 9 *((hcent)->hi & 0x7))
4493a634bfcSVikram Hegde #define	CONT_GET_AW(hcent) \
4503a634bfcSVikram Hegde 	((CONT_GET_LO_AW(hcent) == 66) ? 64 : CONT_GET_LO_AW(hcent))
4513a634bfcSVikram Hegde #define	CONT_SET_AW(hcent, aw) \
4523a634bfcSVikram Hegde 	((hcent)->hi |= (((((aw) + 2) - 30) / 9) & 0x7))
4533a634bfcSVikram Hegde 
4543a634bfcSVikram Hegde #define	CONT_GET_ASR(hcent) ((hcent)->lo & ~(0xFFF))
4553a634bfcSVikram Hegde #define	CONT_SET_ASR(hcent, paddr) ((hcent)->lo |= (paddr & (~0xFFF)))
4563a634bfcSVikram Hegde 
4573a634bfcSVikram Hegde #define	CONT_GET_TTYPE(hcent) ((((uint64_t)(hcent)->lo) >> 0x2) & 0x3)
4583a634bfcSVikram Hegde #define	CONT_SET_TTYPE(hcent, ttype) ((hcent)->lo |= (((ttype) & 0x3) << 0x2))
4593a634bfcSVikram Hegde 
4603a634bfcSVikram Hegde #define	CONT_GET_P(hcent) ((hcent)->lo & 0x1)
4613a634bfcSVikram Hegde #define	CONT_SET_P(hcent) ((hcent)->lo |= 0x1)
4623a634bfcSVikram Hegde 
4633a634bfcSVikram Hegde 
4643a634bfcSVikram Hegde /* we use the bit 63 (available for system SW) as a present bit */
4653a634bfcSVikram Hegde #define	PDTE_SW4(hw_pdte) ((hw_pdte) & ((uint64_t)1<<63))
4663a634bfcSVikram Hegde #define	PDTE_CLEAR_SW4(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<63))
4673a634bfcSVikram Hegde 
4683a634bfcSVikram Hegde #define	PDTE_P(hw_pdte) ((hw_pdte) & ((uint64_t)1<<63))
4693a634bfcSVikram Hegde #define	PDTE_CLEAR_P(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<63))
4703a634bfcSVikram Hegde #define	PDTE_SET_P(hw_pdte) ((hw_pdte) |= ((uint64_t)1<<63))
4713a634bfcSVikram Hegde 
4723a634bfcSVikram Hegde #define	PDTE_TM(hw_pdte) ((hw_pdte) & ((uint64_t)1<<62))
4733a634bfcSVikram Hegde #define	PDTE_CLEAR_TM(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<62))
4743a634bfcSVikram Hegde 
4753a634bfcSVikram Hegde #define	PDTE_SW3(hw_pdte) \
4763a634bfcSVikram Hegde 	(((hw_pdte) & ~(((uint64_t)0x3<<62)|(((uint64_t)1<<52)-1))) >> 52)
4773a634bfcSVikram Hegde #define	PDTE_SW3_OVERFLOW(hw_pdte) \
4783a634bfcSVikram Hegde 	(PDTE_SW3(hw_pdte) == 0x3FF)
4793a634bfcSVikram Hegde #define	PDTE_CLEAR_SW3(hw_pdte) \
4803a634bfcSVikram Hegde 	((hw_pdte) &= (((uint64_t)0x3<<62)|(((uint64_t)1<<52)-1)))
4813a634bfcSVikram Hegde #define	PDTE_SET_SW3(hw_pdte, ref) \
4823a634bfcSVikram Hegde 	((hw_pdte) |= ((((uint64_t)(ref)) & 0x3FF) << 52))
4833a634bfcSVikram Hegde 
4843a634bfcSVikram Hegde #define	PDTE_PADDR(hw_pdte) ((hw_pdte) & ~(((uint64_t)0xFFF<<52)|((1<<12)-1)))
4853a634bfcSVikram Hegde #define	PDTE_CLEAR_PADDR(hw_pdte) \
4863a634bfcSVikram Hegde 		((hw_pdte) &= (((uint64_t)0xFFF<<52)|((1<<12)-1)))
4873a634bfcSVikram Hegde #define	PDTE_SET_PADDR(hw_pdte, paddr) ((hw_pdte) |= PDTE_PADDR(paddr))
4883a634bfcSVikram Hegde 
4893a634bfcSVikram Hegde #define	PDTE_SNP(hw_pdte) ((hw_pdte) & (1<<11))
4903a634bfcSVikram Hegde #define	PDTE_CLEAR_SNP(hw_pdte) ((hw_pdte) &= ~(1<<11))
4913a634bfcSVikram Hegde #define	PDTE_SET_SNP(hw_pdte) ((hw_pdte) |= (1<<11))
4923a634bfcSVikram Hegde 
4933a634bfcSVikram Hegde #define	PDTE_SW2(hw_pdte) ((hw_pdte) & (0x700))
4943a634bfcSVikram Hegde #define	PDTE_CLEAR_SW2(hw_pdte) ((hw_pdte) &= ~(0x700))
4953a634bfcSVikram Hegde 
4963a634bfcSVikram Hegde #define	PDTE_SP(hw_pdte) ((hw_pdte) & (0x80))
4973a634bfcSVikram Hegde #define	PDTE_CLEAR_SP(hw_pdte) ((hw_pdte) &= ~(0x80))
4983a634bfcSVikram Hegde 
4993a634bfcSVikram Hegde #define	PDTE_SW1(hw_pdte) ((hw_pdte) & (0x7C))
5003a634bfcSVikram Hegde #define	PDTE_CLEAR_SW1(hw_pdte) ((hw_pdte) &= ~(0x7C))
5013a634bfcSVikram Hegde 
5023a634bfcSVikram Hegde #define	PDTE_WRITE(hw_pdte) ((hw_pdte) & (0x2))
5033a634bfcSVikram Hegde #define	PDTE_CLEAR_WRITE(hw_pdte) ((hw_pdte) &= ~(0x2))
5043a634bfcSVikram Hegde #define	PDTE_SET_WRITE(hw_pdte) ((hw_pdte) |= (0x2))
5053a634bfcSVikram Hegde 
5063a634bfcSVikram Hegde #define	PDTE_READ(hw_pdte) ((hw_pdte) & (0x1))
5073a634bfcSVikram Hegde #define	PDTE_CLEAR_READ(hw_pdte) ((hw_pdte) &= ~(0x1))
5083a634bfcSVikram Hegde #define	PDTE_SET_READ(hw_pdte) ((hw_pdte) |= (0x1))
5093a634bfcSVikram Hegde 
5103a634bfcSVikram Hegde typedef struct immu {
5113a634bfcSVikram Hegde 	kmutex_t		immu_lock;
5123a634bfcSVikram Hegde 	char			*immu_name;
5133a634bfcSVikram Hegde 
5143a634bfcSVikram Hegde 	/* lock grabbed by interrupt handler */
5153a634bfcSVikram Hegde 	kmutex_t		immu_intr_lock;
5163a634bfcSVikram Hegde 
5173a634bfcSVikram Hegde 	/* ACPI/DMAR table related */
5183a634bfcSVikram Hegde 	void			*immu_dmar_unit;
5193a634bfcSVikram Hegde 	dev_info_t		*immu_dip;
5203a634bfcSVikram Hegde 	struct domain		*immu_unity_domain;
5213a634bfcSVikram Hegde 
5223a634bfcSVikram Hegde 	/* IOMMU register related */
5233a634bfcSVikram Hegde 	kmutex_t		immu_regs_lock;
524e03dceedSVikram Hegde 	kcondvar_t		immu_regs_cv;
525e03dceedSVikram Hegde 	boolean_t		immu_regs_busy;
5263a634bfcSVikram Hegde 	boolean_t		immu_regs_setup;
5273a634bfcSVikram Hegde 	boolean_t		immu_regs_running;
5283a634bfcSVikram Hegde 	boolean_t		immu_regs_quiesced;
5293a634bfcSVikram Hegde 	ddi_acc_handle_t	immu_regs_handle;
5303a634bfcSVikram Hegde 	caddr_t			immu_regs_addr;
5313a634bfcSVikram Hegde 	uint64_t		immu_regs_cap;
5323a634bfcSVikram Hegde 	uint64_t		immu_regs_excap;
5333a634bfcSVikram Hegde 	uint32_t		immu_regs_cmdval;
5343a634bfcSVikram Hegde 	uint32_t		immu_regs_intr_msi_addr;
5353a634bfcSVikram Hegde 	uint32_t		immu_regs_intr_msi_data;
5363a634bfcSVikram Hegde 	uint32_t		immu_regs_intr_uaddr;
5373a634bfcSVikram Hegde 
5383a634bfcSVikram Hegde 	/* DVMA related */
5393a634bfcSVikram Hegde 	kmutex_t		immu_dvma_lock;
5403a634bfcSVikram Hegde 	boolean_t		immu_dvma_setup;
5413a634bfcSVikram Hegde 	boolean_t		immu_dvma_running;
5423a634bfcSVikram Hegde 	int			immu_dvma_gaw;
5433a634bfcSVikram Hegde 	int			immu_dvma_agaw;
5443a634bfcSVikram Hegde 	int			immu_dvma_nlevels;
5453a634bfcSVikram Hegde 	boolean_t		immu_dvma_coherent;
546e03dceedSVikram Hegde 	boolean_t		immu_TM_reserved;
547e03dceedSVikram Hegde 	boolean_t		immu_SNP_reserved;
5483a634bfcSVikram Hegde 
5493a634bfcSVikram Hegde 	/* DVMA context related */
5503a634bfcSVikram Hegde 	krwlock_t		immu_ctx_rwlock;
5513a634bfcSVikram Hegde 	pgtable_t		*immu_ctx_root;
5523a634bfcSVikram Hegde 
5533a634bfcSVikram Hegde 	/* DVMA domain related */
5543a634bfcSVikram Hegde 	int			immu_max_domains;
5553a634bfcSVikram Hegde 	vmem_t			*immu_did_arena;
5563a634bfcSVikram Hegde 	char			immu_did_arena_name[IMMU_MAXNAMELEN];
5573a634bfcSVikram Hegde 	list_t			immu_domain_list;
5583a634bfcSVikram Hegde 
5593a634bfcSVikram Hegde 	/* DVMA special devices */
5603a634bfcSVikram Hegde 	boolean_t		immu_dvma_gfx_only;
5613a634bfcSVikram Hegde 	list_t			immu_dvma_lpc_list;
5623a634bfcSVikram Hegde 	list_t			immu_dvma_gfx_list;
5633a634bfcSVikram Hegde 
5643a634bfcSVikram Hegde 	/* interrupt remapping related */
5653a634bfcSVikram Hegde 	kmutex_t		immu_intrmap_lock;
5663a634bfcSVikram Hegde 	boolean_t		immu_intrmap_setup;
5673a634bfcSVikram Hegde 	boolean_t		immu_intrmap_running;
5683a634bfcSVikram Hegde 	intrmap_t		*immu_intrmap;
5693a634bfcSVikram Hegde 	uint64_t		immu_intrmap_irta_reg;
5703a634bfcSVikram Hegde 
5713a634bfcSVikram Hegde 	/* queued invalidation related */
5723a634bfcSVikram Hegde 	kmutex_t		immu_qinv_lock;
5733a634bfcSVikram Hegde 	boolean_t		immu_qinv_setup;
5743a634bfcSVikram Hegde 	boolean_t		immu_qinv_running;
5753a634bfcSVikram Hegde 	boolean_t		immu_qinv_enabled;
5763a634bfcSVikram Hegde 	void			*immu_qinv;
5773a634bfcSVikram Hegde 	uint64_t		immu_qinv_reg_value;
5783a634bfcSVikram Hegde 
5793a634bfcSVikram Hegde 	/* list_node for system-wide list of DMAR units */
5803a634bfcSVikram Hegde 	list_node_t		immu_node;
5813a634bfcSVikram Hegde } immu_t;
5823a634bfcSVikram Hegde 
5833a634bfcSVikram Hegde /* properties that control DVMA */
584*9e986f0eSFrank Van Der Linden #define	DDI_DVMA_MAPTYPE_ROOTNEX_PROP	"immu-dvma-mapping"
5853a634bfcSVikram Hegde 
586*9e986f0eSFrank Van Der Linden #define	DDI_DVMA_MAPTYPE_UNITY		"unity"
587*9e986f0eSFrank Van Der Linden #define	DDI_DVMA_MAPTYPE_XLATE		"xlate"
5883a634bfcSVikram Hegde 
5893a634bfcSVikram Hegde typedef enum immu_maptype {
5903a634bfcSVikram Hegde 	IMMU_MAPTYPE_BAD = 0,    /* 0 is always bad */
5913a634bfcSVikram Hegde 	IMMU_MAPTYPE_UNITY = 1,
5923a634bfcSVikram Hegde 	IMMU_MAPTYPE_XLATE
5933a634bfcSVikram Hegde } immu_maptype_t;
5943a634bfcSVikram Hegde 
595e03dceedSVikram Hegde #define	IMMU_COOKIE_HASHSZ	(512)
596e03dceedSVikram Hegde 
5973a634bfcSVikram Hegde /*
5983a634bfcSVikram Hegde  * domain_t
5993a634bfcSVikram Hegde  *
6003a634bfcSVikram Hegde  */
6013a634bfcSVikram Hegde typedef struct domain {
6023a634bfcSVikram Hegde 	/* the basics */
6033a634bfcSVikram Hegde 	uint_t			dom_did;
6043a634bfcSVikram Hegde 	immu_t			*dom_immu;
6053a634bfcSVikram Hegde 
6063a634bfcSVikram Hegde 	/* mapping related */
6073a634bfcSVikram Hegde 	immu_maptype_t		dom_maptype;
6083a634bfcSVikram Hegde 	vmem_t			*dom_dvma_arena;
6093a634bfcSVikram Hegde 	char			dom_dvma_arena_name[IMMU_MAXNAMELEN];
6103a634bfcSVikram Hegde 
6113a634bfcSVikram Hegde 	/* pgtables */
6123a634bfcSVikram Hegde 	pgtable_t		*dom_pgtable_root;
6133a634bfcSVikram Hegde 	krwlock_t		dom_pgtable_rwlock;
6143a634bfcSVikram Hegde 
6153a634bfcSVikram Hegde 	/* list node for list of domains (unity or xlate) */
6163a634bfcSVikram Hegde 	list_node_t		dom_maptype_node;
6173a634bfcSVikram Hegde 	/* list node for list of domains off immu */
6183a634bfcSVikram Hegde 	list_node_t		dom_immu_node;
619e03dceedSVikram Hegde 
620e03dceedSVikram Hegde 	mod_hash_t 		*dom_cookie_hash;
6213a634bfcSVikram Hegde } domain_t;
6223a634bfcSVikram Hegde 
6233a634bfcSVikram Hegde typedef enum immu_pcib {
6243a634bfcSVikram Hegde 	IMMU_PCIB_BAD = 0,
6253a634bfcSVikram Hegde 	IMMU_PCIB_NOBDF,
6263a634bfcSVikram Hegde 	IMMU_PCIB_PCIE_PCIE,
6273a634bfcSVikram Hegde 	IMMU_PCIB_PCIE_PCI,
6283a634bfcSVikram Hegde 	IMMU_PCIB_PCI_PCI,
6293a634bfcSVikram Hegde 	IMMU_PCIB_ENDPOINT
6303a634bfcSVikram Hegde } immu_pcib_t;
6313a634bfcSVikram Hegde 
6323a634bfcSVikram Hegde /*
6333a634bfcSVikram Hegde  *  immu_devi_t
6343a634bfcSVikram Hegde  *      Intel IOMMU in devinfo node
6353a634bfcSVikram Hegde  */
6363a634bfcSVikram Hegde typedef struct immu_devi {
6373a634bfcSVikram Hegde 	/* pci seg, bus, dev, func */
6383a634bfcSVikram Hegde 	int		imd_seg;
6393a634bfcSVikram Hegde 	int		imd_bus;
6403a634bfcSVikram Hegde 	int		imd_devfunc;
6413a634bfcSVikram Hegde 
6423a634bfcSVikram Hegde 	/* ppb information */
6433a634bfcSVikram Hegde 	immu_pcib_t	imd_pcib_type;
6443a634bfcSVikram Hegde 	int		imd_sec;
6453a634bfcSVikram Hegde 	int		imd_sub;
6463a634bfcSVikram Hegde 
6473a634bfcSVikram Hegde 	/* identifier for special devices */
6483a634bfcSVikram Hegde 	boolean_t	imd_display;
6493a634bfcSVikram Hegde 	boolean_t	imd_lpc;
6503a634bfcSVikram Hegde 
6513a634bfcSVikram Hegde 	/* dmar unit to which this dip belongs */
6523a634bfcSVikram Hegde 	immu_t		*imd_immu;
6533a634bfcSVikram Hegde 
654*9e986f0eSFrank Van Der Linden 	immu_flags_t	imd_dvma_flags;
655*9e986f0eSFrank Van Der Linden 
6563a634bfcSVikram Hegde 	/* domain ptr */
6573a634bfcSVikram Hegde 	domain_t	*imd_domain;
6583a634bfcSVikram Hegde 	dev_info_t	*imd_ddip;
6593a634bfcSVikram Hegde 
6603a634bfcSVikram Hegde 	/* my devinfo */
6613a634bfcSVikram Hegde 	dev_info_t	*imd_dip;
6623a634bfcSVikram Hegde 
6633a634bfcSVikram Hegde 	/*
6643a634bfcSVikram Hegde 	 * if we are a "special" devinfo
6653a634bfcSVikram Hegde 	 * the node for the special linked list
6663a634bfcSVikram Hegde 	 * off the DMAR unit structure
6673a634bfcSVikram Hegde 	 */
6683a634bfcSVikram Hegde 	list_node_t	imd_spc_node;
6693a634bfcSVikram Hegde } immu_devi_t;
6703a634bfcSVikram Hegde 
6713a634bfcSVikram Hegde #define	IMMU_DEVI(dip)		((immu_devi_t *)(DEVI(dip)->devi_iommu))
6723a634bfcSVikram Hegde #define	IMMU_DEVI_SET(dip, imd)	(DEVI(dip)->devi_iommu = (void *)imd)
6733a634bfcSVikram Hegde 
6743a634bfcSVikram Hegde /*
6753a634bfcSVikram Hegde  * struct dmar_arg
6763a634bfcSVikram Hegde  */
6773a634bfcSVikram Hegde typedef struct immu_arg {
6783a634bfcSVikram Hegde 	int		ima_seg;
6793a634bfcSVikram Hegde 	int		ima_bus;
6803a634bfcSVikram Hegde 	int		ima_devfunc;
6813a634bfcSVikram Hegde 	dev_info_t	*ima_rdip;
6823a634bfcSVikram Hegde 	dev_info_t	*ima_ddip;
6833a634bfcSVikram Hegde } immu_arg_t;
6843a634bfcSVikram Hegde 
6853a634bfcSVikram Hegde /*
6863a634bfcSVikram Hegde  * Globals used by IOMMU code
6873a634bfcSVikram Hegde  */
6883a634bfcSVikram Hegde /* shared between IOMMU files */
6893a634bfcSVikram Hegde extern dev_info_t *root_devinfo;
6903a634bfcSVikram Hegde extern kmutex_t immu_lock;
6913a634bfcSVikram Hegde extern list_t immu_list;
692e03dceedSVikram Hegde extern void *immu_pgtable_cache;
6933a634bfcSVikram Hegde extern boolean_t immu_setup;
6943a634bfcSVikram Hegde extern boolean_t immu_running;
6953a634bfcSVikram Hegde extern kmutex_t ioapic_drhd_lock;
6963a634bfcSVikram Hegde extern list_t ioapic_drhd_list;
6973a634bfcSVikram Hegde 
6983a634bfcSVikram Hegde /* switches */
6993a634bfcSVikram Hegde 
7003a634bfcSVikram Hegde /* Various features */
7013a634bfcSVikram Hegde extern boolean_t immu_enable;
7023a634bfcSVikram Hegde extern boolean_t immu_gfxdvma_enable;
7033a634bfcSVikram Hegde extern boolean_t immu_intrmap_enable;
7043a634bfcSVikram Hegde extern boolean_t immu_qinv_enable;
7053a634bfcSVikram Hegde 
7063a634bfcSVikram Hegde /* various quirks that need working around */
7073a634bfcSVikram Hegde extern boolean_t immu_quirk_usbpage0;
7083a634bfcSVikram Hegde extern boolean_t immu_quirk_usbfullpa;
7093a634bfcSVikram Hegde extern boolean_t immu_quirk_usbrmrr;
7103a634bfcSVikram Hegde extern boolean_t immu_quirk_mobile4;
7113a634bfcSVikram Hegde 
7123a634bfcSVikram Hegde /* debug messages */
7133a634bfcSVikram Hegde extern boolean_t immu_dmar_print;
7143a634bfcSVikram Hegde 
715e03dceedSVikram Hegde /* tunables */
716e03dceedSVikram Hegde extern int64_t immu_flush_gran;
717e03dceedSVikram Hegde 
718*9e986f0eSFrank Van Der Linden extern immu_flags_t immu_global_dvma_flags;
719*9e986f0eSFrank Van Der Linden 
7203a634bfcSVikram Hegde /* ################### Interfaces exported outside IOMMU code ############## */
7213a634bfcSVikram Hegde void immu_init(void);
7223a634bfcSVikram Hegde void immu_startup(void);
7233a634bfcSVikram Hegde void immu_shutdown(void);
7243a634bfcSVikram Hegde void immu_destroy(void);
7253a634bfcSVikram Hegde int immu_map_sgl(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq,
7263a634bfcSVikram Hegde     int prealloc_count, dev_info_t *rdip);
7273a634bfcSVikram Hegde int immu_unmap_sgl(ddi_dma_impl_t *hp, dev_info_t *rdip);
7283a634bfcSVikram Hegde void immu_device_tree_changed(void);
7293a634bfcSVikram Hegde void immu_physmem_update(uint64_t addr, uint64_t size);
7303a634bfcSVikram Hegde int immu_quiesce(void);
7313a634bfcSVikram Hegde int immu_unquiesce(void);
7323a634bfcSVikram Hegde /* ######################################################################### */
7333a634bfcSVikram Hegde 
7343a634bfcSVikram Hegde /* ################# Interfaces used within IOMMU code #################### */
7353a634bfcSVikram Hegde 
7363a634bfcSVikram Hegde /* functions in rootnex.c */
7373a634bfcSVikram Hegde int rootnex_dvcookies_alloc(ddi_dma_impl_t *hp,
7383a634bfcSVikram Hegde     struct ddi_dma_req *dmareq, dev_info_t *rdip, void *arg);
7393a634bfcSVikram Hegde void rootnex_dvcookies_free(dvcookie_t *dvcookies, void *arg);
7403a634bfcSVikram Hegde 
7413a634bfcSVikram Hegde /* immu_dmar.c interfaces */
7423a634bfcSVikram Hegde int immu_dmar_setup(void);
7433a634bfcSVikram Hegde int immu_dmar_parse(void);
7443a634bfcSVikram Hegde void immu_dmar_startup(void);
7453a634bfcSVikram Hegde void immu_dmar_shutdown(void);
7463a634bfcSVikram Hegde void immu_dmar_destroy(void);
7473a634bfcSVikram Hegde boolean_t immu_dmar_blacklisted(char **strings_array, uint_t nstrings);
7483a634bfcSVikram Hegde immu_t *immu_dmar_get_immu(dev_info_t *rdip);
7493a634bfcSVikram Hegde char *immu_dmar_unit_name(void *dmar_unit);
7503a634bfcSVikram Hegde dev_info_t *immu_dmar_unit_dip(void *dmar_unit);
7513a634bfcSVikram Hegde void immu_dmar_set_immu(void *dmar_unit, immu_t *immu);
7523a634bfcSVikram Hegde void *immu_dmar_walk_units(int seg, void *dmar_unit);
7533a634bfcSVikram Hegde boolean_t immu_dmar_intrmap_supported(void);
7543a634bfcSVikram Hegde uint16_t immu_dmar_ioapic_sid(int ioapicid);
7553a634bfcSVikram Hegde immu_t *immu_dmar_ioapic_immu(int ioapicid);
7563a634bfcSVikram Hegde void immu_dmar_rmrr_map(void);
7573a634bfcSVikram Hegde 
7583a634bfcSVikram Hegde /* immu.c interfaces */
7593a634bfcSVikram Hegde int immu_walk_ancestor(dev_info_t *rdip, dev_info_t *ddip,
7603a634bfcSVikram Hegde     int (*func)(dev_info_t *, void *arg), void *arg,
7613a634bfcSVikram Hegde     int *level, immu_flags_t immu_flags);
7623a634bfcSVikram Hegde 
7633a634bfcSVikram Hegde /* immu_regs.c interfaces */
7643a634bfcSVikram Hegde void immu_regs_setup(list_t *immu_list);
7653a634bfcSVikram Hegde void immu_regs_startup(immu_t *immu);
7663a634bfcSVikram Hegde int immu_regs_resume(immu_t *immu);
7673a634bfcSVikram Hegde void immu_regs_suspend(immu_t *immu);
7683a634bfcSVikram Hegde void immu_regs_shutdown(immu_t *immu);
7693a634bfcSVikram Hegde void immu_regs_destroy(list_t *immu_list);
7703a634bfcSVikram Hegde 
7713a634bfcSVikram Hegde void immu_regs_intr(immu_t *immu, uint32_t msi_addr, uint32_t msi_data,
7723a634bfcSVikram Hegde     uint32_t uaddr);
7733a634bfcSVikram Hegde 
7743a634bfcSVikram Hegde boolean_t immu_regs_passthru_supported(immu_t *immu);
7753a634bfcSVikram Hegde boolean_t immu_regs_is_TM_reserved(immu_t *immu);
7763a634bfcSVikram Hegde boolean_t immu_regs_is_SNP_reserved(immu_t *immu);
7773a634bfcSVikram Hegde 
7783a634bfcSVikram Hegde void immu_regs_wbf_flush(immu_t *immu);
7793a634bfcSVikram Hegde void immu_regs_cpu_flush(immu_t *immu, caddr_t addr, uint_t size);
7803a634bfcSVikram Hegde void immu_regs_iotlb_flush(immu_t *immu, uint_t domainid, uint64_t dvma,
7813a634bfcSVikram Hegde     uint64_t count, uint_t hint, immu_iotlb_inv_t type);
7823a634bfcSVikram Hegde void immu_regs_context_flush(immu_t *immu, uint8_t function_mask,
7833a634bfcSVikram Hegde     uint16_t source_id, uint_t did, immu_context_inv_t type);
7843a634bfcSVikram Hegde void immu_regs_set_root_table(immu_t *immu);
7853a634bfcSVikram Hegde void immu_regs_qinv_enable(immu_t *immu, uint64_t qinv_reg_value);
7863a634bfcSVikram Hegde void immu_regs_intr_enable(immu_t *immu, uint32_t msi_addr, uint32_t msi_data,
7873a634bfcSVikram Hegde     uint32_t uaddr);
7883a634bfcSVikram Hegde void immu_regs_intrmap_enable(immu_t *immu, uint64_t irta_reg);
7893a634bfcSVikram Hegde uint64_t immu_regs_get64(immu_t *immu, uint_t reg);
7903a634bfcSVikram Hegde void immu_regs_put64(immu_t *immu, uint_t reg, uint64_t val);
7913a634bfcSVikram Hegde uint32_t immu_regs_get32(immu_t *immu, uint_t reg);
7923a634bfcSVikram Hegde void immu_regs_put32(immu_t *immu, uint_t reg, uint32_t val);
7933a634bfcSVikram Hegde 
7943a634bfcSVikram Hegde /* immu_dvma.c interfaces */
7953a634bfcSVikram Hegde void immu_dvma_setup(list_t *immu_list);
7963a634bfcSVikram Hegde void immu_dvma_startup(immu_t *immu);
7973a634bfcSVikram Hegde void immu_dvma_shutdown(immu_t *immu);
7983a634bfcSVikram Hegde void immu_dvma_destroy(list_t *immu_list);
7993a634bfcSVikram Hegde 
8003a634bfcSVikram Hegde void immu_dvma_physmem_update(uint64_t addr, uint64_t size);
8013a634bfcSVikram Hegde int immu_dvma_map(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq, memrng_t *,
8023a634bfcSVikram Hegde     uint_t prealloc_count, dev_info_t *rdip, immu_flags_t immu_flags);
8033a634bfcSVikram Hegde int immu_dvma_unmap(ddi_dma_impl_t *hp, dev_info_t *rdip);
8043a634bfcSVikram Hegde int immu_dvma_alloc(dvcookie_t *first_dvcookie, void *arg);
8053a634bfcSVikram Hegde void immu_dvma_free(dvcookie_t *first_dvcookie, void *arg);
8063a634bfcSVikram Hegde int immu_devi_set(dev_info_t *dip, immu_flags_t immu_flags);
8073a634bfcSVikram Hegde immu_devi_t *immu_devi_get(dev_info_t *dip);
8083a634bfcSVikram Hegde immu_t *immu_dvma_get_immu(dev_info_t *dip, immu_flags_t immu_flags);
809e03dceedSVikram Hegde int pgtable_ctor(void *buf, void *arg, int kmflag);
810e03dceedSVikram Hegde void pgtable_dtor(void *buf, void *arg);
8113a634bfcSVikram Hegde 
8123a634bfcSVikram Hegde /* immu_intrmap.c interfaces */
8133a634bfcSVikram Hegde void immu_intrmap_setup(list_t *immu_list);
8143a634bfcSVikram Hegde void immu_intrmap_startup(immu_t *immu);
8153a634bfcSVikram Hegde void immu_intrmap_shutdown(immu_t *immu);
8163a634bfcSVikram Hegde void immu_intrmap_destroy(list_t *immu_list);
8173a634bfcSVikram Hegde 
8183a634bfcSVikram Hegde /* registers interrupt handler for IOMMU unit */
8193a634bfcSVikram Hegde void immu_intr_register(immu_t *immu);
8203a634bfcSVikram Hegde int immu_intr_handler(immu_t *immu);
8213a634bfcSVikram Hegde 
8223a634bfcSVikram Hegde 
8233a634bfcSVikram Hegde /* immu_qinv.c interfaces */
8243a634bfcSVikram Hegde void immu_qinv_setup(list_t *immu_list);
8253a634bfcSVikram Hegde void immu_qinv_startup(immu_t *immu);
8263a634bfcSVikram Hegde void immu_qinv_shutdown(immu_t *immu);
8273a634bfcSVikram Hegde void immu_qinv_destroy(list_t *immu_list);
8283a634bfcSVikram Hegde 
8293a634bfcSVikram Hegde void immu_qinv_context_fsi(immu_t *immu, uint8_t function_mask,
8303a634bfcSVikram Hegde     uint16_t source_id, uint_t domain_id);
8313a634bfcSVikram Hegde void immu_qinv_context_dsi(immu_t *immu, uint_t domain_id);
8323a634bfcSVikram Hegde void immu_qinv_context_gbl(immu_t *immu);
8333a634bfcSVikram Hegde void immu_qinv_iotlb_psi(immu_t *immu, uint_t domain_id,
8343a634bfcSVikram Hegde     uint64_t dvma, uint_t count, uint_t hint);
8353a634bfcSVikram Hegde void immu_qinv_iotlb_dsi(immu_t *immu, uint_t domain_id);
8363a634bfcSVikram Hegde void immu_qinv_iotlb_gbl(immu_t *immu);
8373a634bfcSVikram Hegde void immu_qinv_intr_global(immu_t *immu);
8383a634bfcSVikram Hegde void immu_qinv_intr_one_cache(immu_t *immu, uint_t idx);
8393a634bfcSVikram Hegde void immu_qinv_intr_caches(immu_t *immu, uint_t idx, uint_t cnt);
8403a634bfcSVikram Hegde void immu_qinv_report_fault(immu_t *immu);
8413a634bfcSVikram Hegde 
8423a634bfcSVikram Hegde 
8433a634bfcSVikram Hegde #ifdef	__cplusplus
8443a634bfcSVikram Hegde }
8453a634bfcSVikram Hegde #endif
8463a634bfcSVikram Hegde 
8473a634bfcSVikram Hegde #endif	/* _SYS_INTEL_IOMMU_H */
848