xref: /titanic_50/usr/src/uts/i86pc/sys/immu.h (revision 3a634bfc9a31448c742688c603d3e76b83b041a0)
1*3a634bfcSVikram Hegde /*
2*3a634bfcSVikram Hegde  * CDDL HEADER START
3*3a634bfcSVikram Hegde  *
4*3a634bfcSVikram Hegde  * The contents of this file are subject to the terms of the
5*3a634bfcSVikram Hegde  * Common Development and Distribution License (the "License").
6*3a634bfcSVikram Hegde  * You may not use this file except in compliance with the License.
7*3a634bfcSVikram Hegde  *
8*3a634bfcSVikram Hegde  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3a634bfcSVikram Hegde  * or http://www.opensolaris.org/os/licensing.
10*3a634bfcSVikram Hegde  * See the License for the specific language governing permissions
11*3a634bfcSVikram Hegde  * and limitations under the License.
12*3a634bfcSVikram Hegde  *
13*3a634bfcSVikram Hegde  * When distributing Covered Code, include this CDDL HEADER in each
14*3a634bfcSVikram Hegde  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3a634bfcSVikram Hegde  * If applicable, add the following below this CDDL HEADER, with the
16*3a634bfcSVikram Hegde  * fields enclosed by brackets "[]" replaced with your own identifying
17*3a634bfcSVikram Hegde  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3a634bfcSVikram Hegde  *
19*3a634bfcSVikram Hegde  * CDDL HEADER END
20*3a634bfcSVikram Hegde  */
21*3a634bfcSVikram Hegde /*
22*3a634bfcSVikram Hegde  * Portions Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*3a634bfcSVikram Hegde  * Use is subject to license terms.
24*3a634bfcSVikram Hegde  */
25*3a634bfcSVikram Hegde 
26*3a634bfcSVikram Hegde /*
27*3a634bfcSVikram Hegde  * Copyright (c) 2008, Intel Corporation.
28*3a634bfcSVikram Hegde  * All rights reserved.
29*3a634bfcSVikram Hegde  */
30*3a634bfcSVikram Hegde 
31*3a634bfcSVikram Hegde #ifndef	_SYS_INTEL_IOMMU_H
32*3a634bfcSVikram Hegde #define	_SYS_INTEL_IOMMU_H
33*3a634bfcSVikram Hegde 
34*3a634bfcSVikram Hegde /*
35*3a634bfcSVikram Hegde  * Intel IOMMU implementation specific state
36*3a634bfcSVikram Hegde  */
37*3a634bfcSVikram Hegde 
38*3a634bfcSVikram Hegde #ifdef	__cplusplus
39*3a634bfcSVikram Hegde extern "C" {
40*3a634bfcSVikram Hegde #endif
41*3a634bfcSVikram Hegde 
42*3a634bfcSVikram Hegde #include <sys/types.h>
43*3a634bfcSVikram Hegde #include <sys/bitset.h>
44*3a634bfcSVikram Hegde #include <sys/kstat.h>
45*3a634bfcSVikram Hegde #include <sys/vmem.h>
46*3a634bfcSVikram Hegde #include <sys/rootnex.h>
47*3a634bfcSVikram Hegde 
48*3a634bfcSVikram Hegde /*
49*3a634bfcSVikram Hegde  * Some ON drivers have bugs. Keep this define until all such drivers
50*3a634bfcSVikram Hegde  * have been fixed
51*3a634bfcSVikram Hegde  */
52*3a634bfcSVikram Hegde #define	BUGGY_DRIVERS 1
53*3a634bfcSVikram Hegde 
54*3a634bfcSVikram Hegde /* PD(T)E entries */
55*3a634bfcSVikram Hegde typedef uint64_t hw_pdte_t;
56*3a634bfcSVikram Hegde 
57*3a634bfcSVikram Hegde #define	IMMU_MAXNAMELEN (64)
58*3a634bfcSVikram Hegde #define	IMMU_MAXSEG	(1)
59*3a634bfcSVikram Hegde #define	IMMU_REGSZ	(1UL << 12)
60*3a634bfcSVikram Hegde #define	IMMU_PAGESIZE   (4096)
61*3a634bfcSVikram Hegde #define	IMMU_PAGESHIFT	(12)
62*3a634bfcSVikram Hegde #define	IMMU_PAGEOFFSET	(IMMU_PAGESIZE - 1)
63*3a634bfcSVikram Hegde #define	IMMU_PAGEMASK	(~IMMU_PAGEOFFSET)
64*3a634bfcSVikram Hegde #define	IMMU_BTOP(b)	(((uint64_t)b) >> IMMU_PAGESHIFT)
65*3a634bfcSVikram Hegde #define	IMMU_PTOB(p)	(((uint64_t)p) << IMMU_PAGESHIFT)
66*3a634bfcSVikram Hegde #define	IMMU_PGTABLE_MAX_LEVELS	(6)
67*3a634bfcSVikram Hegde #define	IMMU_ROUNDUP(size) (((size) + IMMU_PAGEOFFSET) & ~IMMU_PAGEOFFSET)
68*3a634bfcSVikram Hegde #define	IMMU_ROUNDOWN(addr) ((addr) & ~IMMU_PAGEOFFSET)
69*3a634bfcSVikram Hegde #define	IMMU_PGTABLE_LEVEL_STRIDE	(9)
70*3a634bfcSVikram Hegde #define	IMMU_PGTABLE_LEVEL_MASK	((1<<IMMU_PGTABLE_LEVEL_STRIDE) - 1)
71*3a634bfcSVikram Hegde #define	IMMU_PGTABLE_OFFSHIFT  (IMMU_PAGESHIFT - IMMU_PGTABLE_LEVEL_STRIDE)
72*3a634bfcSVikram Hegde #define	IMMU_PGTABLE_MAXIDX  ((IMMU_PAGESIZE / sizeof (hw_pdte_t)) - 1)
73*3a634bfcSVikram Hegde 
74*3a634bfcSVikram Hegde #define	IMMU_ROUNDUP(size) (((size) + IMMU_PAGEOFFSET) & ~IMMU_PAGEOFFSET)
75*3a634bfcSVikram Hegde #define	IMMU_ROUNDOWN(addr) ((addr) & ~IMMU_PAGEOFFSET)
76*3a634bfcSVikram Hegde 
77*3a634bfcSVikram Hegde /*
78*3a634bfcSVikram Hegde  * DMAR global defines
79*3a634bfcSVikram Hegde  */
80*3a634bfcSVikram Hegde #define	DMAR_TABLE	"dmar-table"
81*3a634bfcSVikram Hegde #define	DMAR_INTRMAP_SUPPORT	(0x01)
82*3a634bfcSVikram Hegde 
83*3a634bfcSVikram Hegde /* DMAR unit types */
84*3a634bfcSVikram Hegde #define	DMAR_DRHD	0
85*3a634bfcSVikram Hegde #define	DMAR_RMRR	1
86*3a634bfcSVikram Hegde #define	DMAR_ATSR	2
87*3a634bfcSVikram Hegde #define	DMAR_RHSA	3
88*3a634bfcSVikram Hegde 
89*3a634bfcSVikram Hegde /* DRHD flag values */
90*3a634bfcSVikram Hegde #define	DMAR_INCLUDE_ALL	(0x01)
91*3a634bfcSVikram Hegde 
92*3a634bfcSVikram Hegde /* Device scope types */
93*3a634bfcSVikram Hegde #define	DMAR_ENDPOINT	1
94*3a634bfcSVikram Hegde #define	DMAR_SUBTREE	2
95*3a634bfcSVikram Hegde #define	DMAR_IOAPIC	3
96*3a634bfcSVikram Hegde #define	DMAR_HPET	4
97*3a634bfcSVikram Hegde 
98*3a634bfcSVikram Hegde 
99*3a634bfcSVikram Hegde /* Forward declarations for IOMMU state structure and DVMA domain struct */
100*3a634bfcSVikram Hegde struct immu;
101*3a634bfcSVikram Hegde struct domain;
102*3a634bfcSVikram Hegde 
103*3a634bfcSVikram Hegde /*
104*3a634bfcSVikram Hegde  * The following structure describes the formate of DMAR ACPI table format.
105*3a634bfcSVikram Hegde  * They are used to parse DMAR ACPI table. Read the spec for the meaning
106*3a634bfcSVikram Hegde  * of each member.
107*3a634bfcSVikram Hegde  */
108*3a634bfcSVikram Hegde 
109*3a634bfcSVikram Hegde /* lengths of various strings */
110*3a634bfcSVikram Hegde #define	DMAR_SIG_LEN    (4)	/* table signature */
111*3a634bfcSVikram Hegde #define	DMAR_OEMID_LEN  (6)	/* OEM ID */
112*3a634bfcSVikram Hegde #define	DMAR_TBLID_LEN  (8)	/* OEM table ID */
113*3a634bfcSVikram Hegde #define	DMAR_ASL_LEN    (4)	/* ASL len */
114*3a634bfcSVikram Hegde 
115*3a634bfcSVikram Hegde typedef struct dmar_table {
116*3a634bfcSVikram Hegde 	kmutex_t	tbl_lock;
117*3a634bfcSVikram Hegde 	uint8_t		tbl_haw;
118*3a634bfcSVikram Hegde 	boolean_t	tbl_intrmap;
119*3a634bfcSVikram Hegde 	list_t		tbl_drhd_list[IMMU_MAXSEG];
120*3a634bfcSVikram Hegde 	list_t		tbl_rmrr_list[IMMU_MAXSEG];
121*3a634bfcSVikram Hegde 	char		*tbl_oem_id;
122*3a634bfcSVikram Hegde 	char		*tbl_oem_tblid;
123*3a634bfcSVikram Hegde 	uint32_t	tbl_oem_rev;
124*3a634bfcSVikram Hegde 	caddr_t		tbl_raw;
125*3a634bfcSVikram Hegde 	int		tbl_rawlen;
126*3a634bfcSVikram Hegde } dmar_table_t;
127*3a634bfcSVikram Hegde 
128*3a634bfcSVikram Hegde typedef struct drhd {
129*3a634bfcSVikram Hegde 	kmutex_t	dr_lock;   /* protects the dmar field */
130*3a634bfcSVikram Hegde 	struct immu	*dr_immu;
131*3a634bfcSVikram Hegde 	dev_info_t	*dr_dip;
132*3a634bfcSVikram Hegde 	uint16_t 	dr_seg;
133*3a634bfcSVikram Hegde 	uint64_t 	dr_regs;
134*3a634bfcSVikram Hegde 	boolean_t	dr_include_all;
135*3a634bfcSVikram Hegde 	list_t 		dr_scope_list;
136*3a634bfcSVikram Hegde 	list_node_t 	dr_node;
137*3a634bfcSVikram Hegde } drhd_t;
138*3a634bfcSVikram Hegde 
139*3a634bfcSVikram Hegde typedef struct rmrr {
140*3a634bfcSVikram Hegde 	kmutex_t	rm_lock;
141*3a634bfcSVikram Hegde 	uint16_t	rm_seg;
142*3a634bfcSVikram Hegde 	uint64_t	rm_base;
143*3a634bfcSVikram Hegde 	uint64_t	rm_limit;
144*3a634bfcSVikram Hegde 	list_t		rm_scope_list;
145*3a634bfcSVikram Hegde 	list_node_t	rm_node;
146*3a634bfcSVikram Hegde } rmrr_t;
147*3a634bfcSVikram Hegde 
148*3a634bfcSVikram Hegde /*
149*3a634bfcSVikram Hegde  * Macros based on PCI spec
150*3a634bfcSVikram Hegde  */
151*3a634bfcSVikram Hegde #define	IMMU_PCI_DEV(devfunc)    ((uint64_t)devfunc >> 3) /* from devfunc  */
152*3a634bfcSVikram Hegde #define	IMMU_PCI_FUNC(devfunc)   (devfunc & 7)  /* get func from devfunc */
153*3a634bfcSVikram Hegde #define	IMMU_PCI_DEVFUNC(d, f)   (((d) << 3) | (f))  /* create devfunc */
154*3a634bfcSVikram Hegde 
155*3a634bfcSVikram Hegde typedef struct scope {
156*3a634bfcSVikram Hegde 	uint8_t scp_type;
157*3a634bfcSVikram Hegde 	uint8_t scp_enumid;
158*3a634bfcSVikram Hegde 	uint8_t scp_bus;
159*3a634bfcSVikram Hegde 	uint8_t scp_dev;
160*3a634bfcSVikram Hegde 	uint8_t scp_func;
161*3a634bfcSVikram Hegde 	list_node_t scp_node;
162*3a634bfcSVikram Hegde } scope_t;
163*3a634bfcSVikram Hegde 
164*3a634bfcSVikram Hegde /*
165*3a634bfcSVikram Hegde  * interrupt source id and drhd info for ioapic
166*3a634bfcSVikram Hegde  */
167*3a634bfcSVikram Hegde typedef struct ioapic_drhd {
168*3a634bfcSVikram Hegde 	uchar_t		ioapic_ioapicid;
169*3a634bfcSVikram Hegde 	uint16_t	ioapic_sid;	/* ioapic source id */
170*3a634bfcSVikram Hegde 	drhd_t		*ioapic_drhd;
171*3a634bfcSVikram Hegde 	list_node_t	ioapic_node;
172*3a634bfcSVikram Hegde } ioapic_drhd_t;
173*3a634bfcSVikram Hegde 
174*3a634bfcSVikram Hegde typedef struct memrng {
175*3a634bfcSVikram Hegde 	uint64_t mrng_start;
176*3a634bfcSVikram Hegde 	uint64_t mrng_npages;
177*3a634bfcSVikram Hegde } memrng_t;
178*3a634bfcSVikram Hegde 
179*3a634bfcSVikram Hegde typedef enum immu_flags {
180*3a634bfcSVikram Hegde 	IMMU_FLAGS_NONE = 0x1,
181*3a634bfcSVikram Hegde 	IMMU_FLAGS_SLEEP = 0x1,
182*3a634bfcSVikram Hegde 	IMMU_FLAGS_NOSLEEP = 0x2,
183*3a634bfcSVikram Hegde 	IMMU_FLAGS_READ = 0x4,
184*3a634bfcSVikram Hegde 	IMMU_FLAGS_WRITE = 0x8,
185*3a634bfcSVikram Hegde 	IMMU_FLAGS_DONTPASS = 0x10,
186*3a634bfcSVikram Hegde 	IMMU_FLAGS_ALLOC = 0x20,
187*3a634bfcSVikram Hegde 	IMMU_FLAGS_MUST_MATCH = 0x40,
188*3a634bfcSVikram Hegde 	IMMU_FLAGS_PAGE1 = 0x80,
189*3a634bfcSVikram Hegde 	IMMU_FLAGS_UNITY = 0x100,
190*3a634bfcSVikram Hegde 	IMMU_FLAGS_DMAHDL = 0x200,
191*3a634bfcSVikram Hegde 	IMMU_FLAGS_MEMRNG = 0x400
192*3a634bfcSVikram Hegde } immu_flags_t;
193*3a634bfcSVikram Hegde 
194*3a634bfcSVikram Hegde typedef enum cont_avail {
195*3a634bfcSVikram Hegde 	IMMU_CONT_BAD = 0x0,
196*3a634bfcSVikram Hegde 	IMMU_CONT_UNINITED = 0x1,
197*3a634bfcSVikram Hegde 	IMMU_CONT_INITED = 0x2
198*3a634bfcSVikram Hegde } cont_avail_t;
199*3a634bfcSVikram Hegde 
200*3a634bfcSVikram Hegde /* Size of root and context tables and their entries */
201*3a634bfcSVikram Hegde #define	IMMU_ROOT_TBLSZ		(4096)
202*3a634bfcSVikram Hegde #define	IMMU_CONT_TBLSZ		(4096)
203*3a634bfcSVikram Hegde #define	IMMU_ROOT_NUM		(256)
204*3a634bfcSVikram Hegde #define	IMMU_CONT_NUM		(256)
205*3a634bfcSVikram Hegde 
206*3a634bfcSVikram Hegde /* register offset */
207*3a634bfcSVikram Hegde #define	IMMU_REG_VERSION	(0x00)  /* Version Rigister, 32 bit */
208*3a634bfcSVikram Hegde #define	IMMU_REG_CAP		(0x08)  /* Capability Register, 64 bit */
209*3a634bfcSVikram Hegde #define	IMMU_REG_EXCAP		(0x10)  /* Extended Capability Reg, 64 bit */
210*3a634bfcSVikram Hegde #define	IMMU_REG_GLOBAL_CMD	(0x18)  /* Global Command Register, 32 bit */
211*3a634bfcSVikram Hegde #define	IMMU_REG_GLOBAL_STS	(0x1C)  /* Global Status Register, 32 bit */
212*3a634bfcSVikram Hegde #define	IMMU_REG_ROOTENTRY	(0x20)  /* Root-Entry Table Addr Reg, 64 bit */
213*3a634bfcSVikram Hegde #define	IMMU_REG_CONTEXT_CMD	(0x28)  /* Context Comand Register, 64 bit */
214*3a634bfcSVikram Hegde #define	IMMU_REG_FAULT_STS	(0x34)  /* Fault Status Register, 32 bit */
215*3a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_CON	(0x38)  /* Fault Event Control Reg, 32 bit */
216*3a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_DATA	(0x3C)  /* Fault Event Data Register, 32 bit */
217*3a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_ADDR	(0x40)  /* Fault Event Address Reg, 32 bit */
218*3a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_UADDR	(0x44)  /* Fault Event Upper Addr Reg, 32 bit */
219*3a634bfcSVikram Hegde #define	IMMU_REG_AFAULT_LOG	(0x58)  /* Advanced Fault Log Reg, 64 bit */
220*3a634bfcSVikram Hegde #define	IMMU_REG_PMER		(0x64)  /* Protected Memory Enble Reg, 32 bit */
221*3a634bfcSVikram Hegde #define	IMMU_REG_PLMBR		(0x68)  /* Protected Low Mem Base Reg, 32 bit */
222*3a634bfcSVikram Hegde #define	IMMU_REG_PLMLR		(0x6C)  /* Protected Low Mem Lim Reg, 32 bit */
223*3a634bfcSVikram Hegde #define	IMMU_REG_PHMBR		(0X70)  /* Protectd High Mem Base Reg, 64 bit */
224*3a634bfcSVikram Hegde #define	IMMU_REG_PHMLR		(0x78)  /* Protected High Mem Lim Reg, 64 bit */
225*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_QH	(0x80)  /* Invalidation Queue Head, 64 bit */
226*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_QT	(0x88)  /* Invalidation Queue Tail, 64 bit */
227*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_QAR	(0x90)  /* Invalidtion Queue Addr Reg, 64 bit */
228*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CSR	(0x9C)  /* Inval Compl Status Reg, 32 bit */
229*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CECR	(0xA0)  /* Inval Compl Evnt Ctrl Reg, 32 bit */
230*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CEDR	(0xA4)  /* Inval Compl Evnt Data Reg, 32 bit */
231*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CEAR	(0xA8)  /* Inval Compl Event Addr Reg, 32 bit */
232*3a634bfcSVikram Hegde #define	IMMU_REG_INVAL_CEUAR	(0xAC)  /* Inval Comp Evnt Up Addr reg, 32bit */
233*3a634bfcSVikram Hegde #define	IMMU_REG_IRTAR		(0xB8)  /* INTR Remap Tbl Addr Reg, 64 bit */
234*3a634bfcSVikram Hegde 
235*3a634bfcSVikram Hegde /* ioapic memory region */
236*3a634bfcSVikram Hegde #define	IOAPIC_REGION_START	(0xfee00000)
237*3a634bfcSVikram Hegde #define	IOAPIC_REGION_END	(0xfeefffff)
238*3a634bfcSVikram Hegde 
239*3a634bfcSVikram Hegde /* fault register */
240*3a634bfcSVikram Hegde #define	IMMU_FAULT_STS_PPF		(2)
241*3a634bfcSVikram Hegde #define	IMMU_FAULT_STS_PFO		(1)
242*3a634bfcSVikram Hegde #define	IMMU_FAULT_STS_ITE		(1 << 6)
243*3a634bfcSVikram Hegde #define	IMMU_FAULT_STS_ICE		(1 << 5)
244*3a634bfcSVikram Hegde #define	IMMU_FAULT_STS_IQE		(1 << 4)
245*3a634bfcSVikram Hegde #define	IMMU_FAULT_GET_INDEX(x)		((((uint64_t)x) >> 8) & 0xff)
246*3a634bfcSVikram Hegde #define	IMMU_FRR_GET_F(x)		(((uint64_t)x) >> 63)
247*3a634bfcSVikram Hegde #define	IMMU_FRR_GET_FR(x)		((((uint64_t)x) >> 32) & 0xff)
248*3a634bfcSVikram Hegde #define	IMMU_FRR_GET_FT(x)		((((uint64_t)x) >> 62) & 0x1)
249*3a634bfcSVikram Hegde #define	IMMU_FRR_GET_SID(x)		((x) & 0xffff)
250*3a634bfcSVikram Hegde 
251*3a634bfcSVikram Hegde /* (ex)capability register */
252*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_NFR(x)		(((((uint64_t)x) >> 40) & 0xff) + 1)
253*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_DWD(x)		((((uint64_t)x) >> 54) & 1)
254*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_DRD(x)		((((uint64_t)x) >> 55) & 1)
255*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_PSI(x)		((((uint64_t)x) >> 39) & 1)
256*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_SPS(x)		((((uint64_t)x) >> 34) & 0xf)
257*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_ISOCH(x)		((((uint64_t)x) >> 23) & 1)
258*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_ZLR(x)		((((uint64_t)x) >> 22) & 1)
259*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_MAMV(x)		((((uint64_t)x) >> 48) & 0x3f)
260*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_CM(x)		((((uint64_t)x) >> 7) & 1)
261*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_PHMR(x)		((((uint64_t)x) >> 6) & 1)
262*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_PLMR(x)		((((uint64_t)x) >> 5) & 1)
263*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_RWBF(x)		((((uint64_t)x) >> 4) & 1)
264*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_AFL(x)		((((uint64_t)x) >> 3) & 1)
265*3a634bfcSVikram Hegde #define	IMMU_CAP_GET_FRO(x)		(((((uint64_t)x) >> 24) & 0x3ff) * 16)
266*3a634bfcSVikram Hegde #define	IMMU_CAP_MGAW(x)		(((((uint64_t)x) >> 16) & 0x3f) + 1)
267*3a634bfcSVikram Hegde #define	IMMU_CAP_SAGAW(x)		((((uint64_t)x) >> 8) & 0x1f)
268*3a634bfcSVikram Hegde #define	IMMU_CAP_ND(x)			(1 << (((x) & 0x7) *2 + 4)) -1
269*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_IRO(x)		(((((uint64_t)x) >> 8) & 0x3ff) << 4)
270*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_MHMV(x)		(((uint64_t)x >> 20) & 0xf)
271*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_SC(x)		((x) & 0x80)
272*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_PT(x)		((x) & 0x40)
273*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_CH(x)		((x) & 0x20)
274*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_EIM(x)		((x) & 0x10)
275*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_IR(x)		((x) & 0x8)
276*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_DI(x)		((x) & 0x4)
277*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_QI(x)		((x) & 0x2)
278*3a634bfcSVikram Hegde #define	IMMU_ECAP_GET_C(x)		((x) & 0x1)
279*3a634bfcSVikram Hegde 
280*3a634bfcSVikram Hegde #define	IMMU_CAP_SET_RWBF(x)		((x) |= (1 << 4))
281*3a634bfcSVikram Hegde 
282*3a634bfcSVikram Hegde 
283*3a634bfcSVikram Hegde /* iotlb invalidation */
284*3a634bfcSVikram Hegde #define	TLB_INV_GLOBAL		(((uint64_t)1) << 60)
285*3a634bfcSVikram Hegde #define	TLB_INV_DOMAIN		(((uint64_t)2) << 60)
286*3a634bfcSVikram Hegde #define	TLB_INV_PAGE		(((uint64_t)3) << 60)
287*3a634bfcSVikram Hegde #define	TLB_INV_GET_IAIG(x)	((((uint64_t)x) >> 57) & 7)
288*3a634bfcSVikram Hegde #define	TLB_INV_DRAIN_READ	(((uint64_t)1) << 49)
289*3a634bfcSVikram Hegde #define	TLB_INV_DRAIN_WRITE	(((uint64_t)1) << 48)
290*3a634bfcSVikram Hegde #define	TLB_INV_DID(x)		(((uint64_t)((x) & 0xffff)) << 32)
291*3a634bfcSVikram Hegde #define	TLB_INV_IVT		(((uint64_t)1) << 63)
292*3a634bfcSVikram Hegde #define	TLB_IVA_HINT(x)		(((x) & 0x1) << 6)
293*3a634bfcSVikram Hegde #define	TLB_IVA_LEAF		1
294*3a634bfcSVikram Hegde #define	TLB_IVA_WHOLE		0
295*3a634bfcSVikram Hegde 
296*3a634bfcSVikram Hegde /* dont use value 0 for  enums - to catch unit 8 */
297*3a634bfcSVikram Hegde typedef enum iotlb_inv {
298*3a634bfcSVikram Hegde 	IOTLB_PSI = 1,
299*3a634bfcSVikram Hegde 	IOTLB_DSI,
300*3a634bfcSVikram Hegde 	IOTLB_GLOBAL
301*3a634bfcSVikram Hegde } immu_iotlb_inv_t;
302*3a634bfcSVikram Hegde 
303*3a634bfcSVikram Hegde typedef enum context_inv {
304*3a634bfcSVikram Hegde 	CONTEXT_FSI = 1,
305*3a634bfcSVikram Hegde 	CONTEXT_DSI,
306*3a634bfcSVikram Hegde 	CONTEXT_GLOBAL
307*3a634bfcSVikram Hegde } immu_context_inv_t;
308*3a634bfcSVikram Hegde 
309*3a634bfcSVikram Hegde /* context invalidation */
310*3a634bfcSVikram Hegde #define	CCMD_INV_ICC		(((uint64_t)1) << 63)
311*3a634bfcSVikram Hegde #define	CCMD_INV_GLOBAL		(((uint64_t)1) << 61)
312*3a634bfcSVikram Hegde #define	CCMD_INV_DOMAIN		(((uint64_t)2) << 61)
313*3a634bfcSVikram Hegde #define	CCMD_INV_DEVICE		(((uint64_t)3) << 61)
314*3a634bfcSVikram Hegde #define	CCMD_INV_DID(x)		((uint64_t)((x) & 0xffff))
315*3a634bfcSVikram Hegde #define	CCMD_INV_SID(x)		(((uint64_t)((x) & 0xffff)) << 16)
316*3a634bfcSVikram Hegde #define	CCMD_INV_FM(x)		(((uint64_t)((x) & 0x3)) << 32)
317*3a634bfcSVikram Hegde 
318*3a634bfcSVikram Hegde /* global command register */
319*3a634bfcSVikram Hegde #define	IMMU_GCMD_TE		(((uint32_t)1) << 31)
320*3a634bfcSVikram Hegde #define	IMMU_GCMD_SRTP		(((uint32_t)1) << 30)
321*3a634bfcSVikram Hegde #define	IMMU_GCMD_SFL		(((uint32_t)1) << 29)
322*3a634bfcSVikram Hegde #define	IMMU_GCMD_EAFL		(((uint32_t)1) << 28)
323*3a634bfcSVikram Hegde #define	IMMU_GCMD_WBF		(((uint32_t)1) << 27)
324*3a634bfcSVikram Hegde #define	IMMU_GCMD_QIE		(((uint32_t)1) << 26)
325*3a634bfcSVikram Hegde #define	IMMU_GCMD_IRE		(((uint32_t)1) << 25)
326*3a634bfcSVikram Hegde #define	IMMU_GCMD_SIRTP	(((uint32_t)1) << 24)
327*3a634bfcSVikram Hegde #define	IMMU_GCMD_CFI		(((uint32_t)1) << 23)
328*3a634bfcSVikram Hegde 
329*3a634bfcSVikram Hegde /* global status register */
330*3a634bfcSVikram Hegde #define	IMMU_GSTS_TES		(((uint32_t)1) << 31)
331*3a634bfcSVikram Hegde #define	IMMU_GSTS_RTPS		(((uint32_t)1) << 30)
332*3a634bfcSVikram Hegde #define	IMMU_GSTS_FLS		(((uint32_t)1) << 29)
333*3a634bfcSVikram Hegde #define	IMMU_GSTS_AFLS		(((uint32_t)1) << 28)
334*3a634bfcSVikram Hegde #define	IMMU_GSTS_WBFS		(((uint32_t)1) << 27)
335*3a634bfcSVikram Hegde #define	IMMU_GSTS_QIES		(((uint32_t)1) << 26)
336*3a634bfcSVikram Hegde #define	IMMU_GSTS_IRES		(((uint32_t)1) << 25)
337*3a634bfcSVikram Hegde #define	IMMU_GSTS_IRTPS	(((uint32_t)1) << 24)
338*3a634bfcSVikram Hegde #define	IMMU_GSTS_CFIS		(((uint32_t)1) << 23)
339*3a634bfcSVikram Hegde 
340*3a634bfcSVikram Hegde /* psi address mask */
341*3a634bfcSVikram Hegde #define	ADDR_AM_MAX(m)		(((uint_t)1) << (m))
342*3a634bfcSVikram Hegde #define	ADDR_AM_OFFSET(n, m)	((n) & (ADDR_AM_MAX(m) - 1))
343*3a634bfcSVikram Hegde 
344*3a634bfcSVikram Hegde /* dmar fault event */
345*3a634bfcSVikram Hegde #define	IMMU_INTR_IPL			(8)
346*3a634bfcSVikram Hegde #define	IMMU_REG_FEVNT_CON_IM_SHIFT	(31)
347*3a634bfcSVikram Hegde 
348*3a634bfcSVikram Hegde #define	IMMU_ALLOC_RESOURCE_DELAY    (drv_usectohz(5000))
349*3a634bfcSVikram Hegde 
350*3a634bfcSVikram Hegde /* max value of Size field of Interrupt Remapping Table Address Register */
351*3a634bfcSVikram Hegde #define	INTRMAP_MAX_IRTA_SIZE	0xf
352*3a634bfcSVikram Hegde 
353*3a634bfcSVikram Hegde /* interrupt remapping table entry size */
354*3a634bfcSVikram Hegde #define	INTRMAP_RTE_SIZE		0x10
355*3a634bfcSVikram Hegde 
356*3a634bfcSVikram Hegde /* ioapic redirection table entry related shift of remappable interrupt */
357*3a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_IDX_SHIFT		17
358*3a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_FORMAT_SHIFT	16
359*3a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_TM_SHIFT		15
360*3a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_POL_SHIFT		13
361*3a634bfcSVikram Hegde #define	INTRMAP_IOAPIC_IDX15_SHIFT	11
362*3a634bfcSVikram Hegde 
363*3a634bfcSVikram Hegde /* msi intr entry related shift of remappable interrupt */
364*3a634bfcSVikram Hegde #define	INTRMAP_MSI_IDX_SHIFT	5
365*3a634bfcSVikram Hegde #define	INTRMAP_MSI_FORMAT_SHIFT	4
366*3a634bfcSVikram Hegde #define	INTRMAP_MSI_SHV_SHIFT	3
367*3a634bfcSVikram Hegde #define	INTRMAP_MSI_IDX15_SHIFT	2
368*3a634bfcSVikram Hegde 
369*3a634bfcSVikram Hegde #define	INTRMAP_IDX_FULL		(uint_t)-1
370*3a634bfcSVikram Hegde 
371*3a634bfcSVikram Hegde #define	RDT_DLM(rdt)	BITX((rdt), 10, 8)
372*3a634bfcSVikram Hegde #define	RDT_DM(rdt)	BT_TEST(&(rdt), 11)
373*3a634bfcSVikram Hegde #define	RDT_POL(rdt)	BT_TEST(&(rdt), 13)
374*3a634bfcSVikram Hegde #define	RDT_TM(rdt)	BT_TEST(&(rdt), 15)
375*3a634bfcSVikram Hegde 
376*3a634bfcSVikram Hegde #define	INTRMAP_DISABLE	(void *)-1
377*3a634bfcSVikram Hegde 
378*3a634bfcSVikram Hegde /*
379*3a634bfcSVikram Hegde  * invalidation granularity
380*3a634bfcSVikram Hegde  */
381*3a634bfcSVikram Hegde typedef enum {
382*3a634bfcSVikram Hegde 	TLB_INV_G_GLOBAL = 1,
383*3a634bfcSVikram Hegde 	TLB_INV_G_DOMAIN,
384*3a634bfcSVikram Hegde 	TLB_INV_G_PAGE
385*3a634bfcSVikram Hegde } tlb_inv_g_t;
386*3a634bfcSVikram Hegde 
387*3a634bfcSVikram Hegde typedef enum {
388*3a634bfcSVikram Hegde 	CTT_INV_G_GLOBAL = 1,
389*3a634bfcSVikram Hegde 	CTT_INV_G_DOMAIN,
390*3a634bfcSVikram Hegde 	CTT_INV_G_DEVICE
391*3a634bfcSVikram Hegde } ctt_inv_g_t;
392*3a634bfcSVikram Hegde 
393*3a634bfcSVikram Hegde typedef enum {
394*3a634bfcSVikram Hegde 	IEC_INV_GLOBAL = 0,
395*3a634bfcSVikram Hegde 	IEC_INV_INDEX
396*3a634bfcSVikram Hegde } iec_inv_g_t;
397*3a634bfcSVikram Hegde 
398*3a634bfcSVikram Hegde 
399*3a634bfcSVikram Hegde struct inv_queue_state;
400*3a634bfcSVikram Hegde struct intrmap_tbl_state;
401*3a634bfcSVikram Hegde 
402*3a634bfcSVikram Hegde /* A software page table structure */
403*3a634bfcSVikram Hegde typedef struct pgtable {
404*3a634bfcSVikram Hegde 	krwlock_t swpg_rwlock;
405*3a634bfcSVikram Hegde 	caddr_t hwpg_vaddr;   /* HW pgtable VA */
406*3a634bfcSVikram Hegde 	paddr_t hwpg_paddr;   /* HW pgtable PA */
407*3a634bfcSVikram Hegde 	ddi_dma_handle_t hwpg_dmahdl;
408*3a634bfcSVikram Hegde 	ddi_acc_handle_t hwpg_memhdl;
409*3a634bfcSVikram Hegde 	struct pgtable **swpg_next_array;
410*3a634bfcSVikram Hegde 	list_node_t swpg_domain_node;  /* domain list of pgtables */
411*3a634bfcSVikram Hegde } pgtable_t;
412*3a634bfcSVikram Hegde 
413*3a634bfcSVikram Hegde /* interrupt remapping table state info */
414*3a634bfcSVikram Hegde typedef struct intrmap {
415*3a634bfcSVikram Hegde 	kmutex_t		intrmap_lock;
416*3a634bfcSVikram Hegde 	ddi_dma_handle_t	intrmap_dma_hdl;
417*3a634bfcSVikram Hegde 	ddi_acc_handle_t	intrmap_acc_hdl;
418*3a634bfcSVikram Hegde 	caddr_t			intrmap_vaddr;
419*3a634bfcSVikram Hegde 	paddr_t			intrmap_paddr;
420*3a634bfcSVikram Hegde 	uint_t			intrmap_size;
421*3a634bfcSVikram Hegde 	bitset_t		intrmap_map;
422*3a634bfcSVikram Hegde 	uint_t			intrmap_free;
423*3a634bfcSVikram Hegde } intrmap_t;
424*3a634bfcSVikram Hegde 
425*3a634bfcSVikram Hegde typedef struct hw_rce {
426*3a634bfcSVikram Hegde 	uint64_t lo;
427*3a634bfcSVikram Hegde 	uint64_t hi;
428*3a634bfcSVikram Hegde } hw_rce_t;
429*3a634bfcSVikram Hegde 
430*3a634bfcSVikram Hegde 
431*3a634bfcSVikram Hegde #define	ROOT_GET_P(hrent) ((hrent)->lo & 0x1)
432*3a634bfcSVikram Hegde #define	ROOT_SET_P(hrent) ((hrent)->lo |= 0x1)
433*3a634bfcSVikram Hegde 
434*3a634bfcSVikram Hegde #define	ROOT_GET_CONT(hrent) ((hrent)->lo & ~(0xFFF))
435*3a634bfcSVikram Hegde #define	ROOT_SET_CONT(hrent, paddr) ((hrent)->lo |= (paddr & (~0xFFF)))
436*3a634bfcSVikram Hegde 
437*3a634bfcSVikram Hegde #define	TTYPE_XLATE_ONLY  (0x0)
438*3a634bfcSVikram Hegde #define	TTYPE_XLATE_IOTLB (0x1)
439*3a634bfcSVikram Hegde #define	TTYPE_PASSTHRU    (0x2)
440*3a634bfcSVikram Hegde #define	TTYPE_RESERVED    (0x3)
441*3a634bfcSVikram Hegde 
442*3a634bfcSVikram Hegde #define	CONT_GET_DID(hcent) ((((uint64_t)(hcent)->hi) >> 8) & 0xFFFF)
443*3a634bfcSVikram Hegde #define	CONT_SET_DID(hcent, did) ((hcent)->hi |= ((0xFFFF & (did)) << 8))
444*3a634bfcSVikram Hegde 
445*3a634bfcSVikram Hegde #define	CONT_GET_AVAIL(hcent) ((((uint64_t)((hcent)->hi)) >> 0x3) & 0xF)
446*3a634bfcSVikram Hegde #define	CONT_SET_AVAIL(hcent, av) ((hcent)->hi |= ((0xF & (av)) << 0x3))
447*3a634bfcSVikram Hegde 
448*3a634bfcSVikram Hegde #define	CONT_GET_LO_AW(hcent) (30 + 9 *((hcent)->hi & 0x7))
449*3a634bfcSVikram Hegde #define	CONT_GET_AW(hcent) \
450*3a634bfcSVikram Hegde 	((CONT_GET_LO_AW(hcent) == 66) ? 64 : CONT_GET_LO_AW(hcent))
451*3a634bfcSVikram Hegde #define	CONT_SET_AW(hcent, aw) \
452*3a634bfcSVikram Hegde 	((hcent)->hi |= (((((aw) + 2) - 30) / 9) & 0x7))
453*3a634bfcSVikram Hegde 
454*3a634bfcSVikram Hegde #define	CONT_GET_ASR(hcent) ((hcent)->lo & ~(0xFFF))
455*3a634bfcSVikram Hegde #define	CONT_SET_ASR(hcent, paddr) ((hcent)->lo |= (paddr & (~0xFFF)))
456*3a634bfcSVikram Hegde 
457*3a634bfcSVikram Hegde #define	CONT_GET_TTYPE(hcent) ((((uint64_t)(hcent)->lo) >> 0x2) & 0x3)
458*3a634bfcSVikram Hegde #define	CONT_SET_TTYPE(hcent, ttype) ((hcent)->lo |= (((ttype) & 0x3) << 0x2))
459*3a634bfcSVikram Hegde 
460*3a634bfcSVikram Hegde #define	CONT_GET_P(hcent) ((hcent)->lo & 0x1)
461*3a634bfcSVikram Hegde #define	CONT_SET_P(hcent) ((hcent)->lo |= 0x1)
462*3a634bfcSVikram Hegde 
463*3a634bfcSVikram Hegde 
464*3a634bfcSVikram Hegde /* we use the bit 63 (available for system SW) as a present bit */
465*3a634bfcSVikram Hegde #define	PDTE_SW4(hw_pdte) ((hw_pdte) & ((uint64_t)1<<63))
466*3a634bfcSVikram Hegde #define	PDTE_CLEAR_SW4(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<63))
467*3a634bfcSVikram Hegde 
468*3a634bfcSVikram Hegde #define	PDTE_P(hw_pdte) ((hw_pdte) & ((uint64_t)1<<63))
469*3a634bfcSVikram Hegde #define	PDTE_CLEAR_P(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<63))
470*3a634bfcSVikram Hegde #define	PDTE_SET_P(hw_pdte) ((hw_pdte) |= ((uint64_t)1<<63))
471*3a634bfcSVikram Hegde 
472*3a634bfcSVikram Hegde #define	PDTE_TM(hw_pdte) ((hw_pdte) & ((uint64_t)1<<62))
473*3a634bfcSVikram Hegde #define	PDTE_CLEAR_TM(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<62))
474*3a634bfcSVikram Hegde 
475*3a634bfcSVikram Hegde #define	PDTE_SW3(hw_pdte) \
476*3a634bfcSVikram Hegde 	(((hw_pdte) & ~(((uint64_t)0x3<<62)|(((uint64_t)1<<52)-1))) >> 52)
477*3a634bfcSVikram Hegde #define	PDTE_SW3_OVERFLOW(hw_pdte) \
478*3a634bfcSVikram Hegde 	(PDTE_SW3(hw_pdte) == 0x3FF)
479*3a634bfcSVikram Hegde #define	PDTE_CLEAR_SW3(hw_pdte) \
480*3a634bfcSVikram Hegde 	((hw_pdte) &= (((uint64_t)0x3<<62)|(((uint64_t)1<<52)-1)))
481*3a634bfcSVikram Hegde #define	PDTE_SET_SW3(hw_pdte, ref) \
482*3a634bfcSVikram Hegde 	((hw_pdte) |= ((((uint64_t)(ref)) & 0x3FF) << 52))
483*3a634bfcSVikram Hegde 
484*3a634bfcSVikram Hegde #define	PDTE_PADDR(hw_pdte) ((hw_pdte) & ~(((uint64_t)0xFFF<<52)|((1<<12)-1)))
485*3a634bfcSVikram Hegde #define	PDTE_CLEAR_PADDR(hw_pdte) \
486*3a634bfcSVikram Hegde 		((hw_pdte) &= (((uint64_t)0xFFF<<52)|((1<<12)-1)))
487*3a634bfcSVikram Hegde #define	PDTE_SET_PADDR(hw_pdte, paddr) ((hw_pdte) |= PDTE_PADDR(paddr))
488*3a634bfcSVikram Hegde 
489*3a634bfcSVikram Hegde #define	PDTE_SNP(hw_pdte) ((hw_pdte) & (1<<11))
490*3a634bfcSVikram Hegde #define	PDTE_CLEAR_SNP(hw_pdte) ((hw_pdte) &= ~(1<<11))
491*3a634bfcSVikram Hegde #define	PDTE_SET_SNP(hw_pdte) ((hw_pdte) |= (1<<11))
492*3a634bfcSVikram Hegde 
493*3a634bfcSVikram Hegde #define	PDTE_SW2(hw_pdte) ((hw_pdte) & (0x700))
494*3a634bfcSVikram Hegde #define	PDTE_CLEAR_SW2(hw_pdte) ((hw_pdte) &= ~(0x700))
495*3a634bfcSVikram Hegde 
496*3a634bfcSVikram Hegde #define	PDTE_SP(hw_pdte) ((hw_pdte) & (0x80))
497*3a634bfcSVikram Hegde #define	PDTE_CLEAR_SP(hw_pdte) ((hw_pdte) &= ~(0x80))
498*3a634bfcSVikram Hegde 
499*3a634bfcSVikram Hegde #define	PDTE_SW1(hw_pdte) ((hw_pdte) & (0x7C))
500*3a634bfcSVikram Hegde #define	PDTE_CLEAR_SW1(hw_pdte) ((hw_pdte) &= ~(0x7C))
501*3a634bfcSVikram Hegde 
502*3a634bfcSVikram Hegde #define	PDTE_WRITE(hw_pdte) ((hw_pdte) & (0x2))
503*3a634bfcSVikram Hegde #define	PDTE_CLEAR_WRITE(hw_pdte) ((hw_pdte) &= ~(0x2))
504*3a634bfcSVikram Hegde #define	PDTE_SET_WRITE(hw_pdte) ((hw_pdte) |= (0x2))
505*3a634bfcSVikram Hegde 
506*3a634bfcSVikram Hegde #define	PDTE_READ(hw_pdte) ((hw_pdte) & (0x1))
507*3a634bfcSVikram Hegde #define	PDTE_CLEAR_READ(hw_pdte) ((hw_pdte) &= ~(0x1))
508*3a634bfcSVikram Hegde #define	PDTE_SET_READ(hw_pdte) ((hw_pdte) |= (0x1))
509*3a634bfcSVikram Hegde 
510*3a634bfcSVikram Hegde typedef struct immu {
511*3a634bfcSVikram Hegde 	kmutex_t		immu_lock;
512*3a634bfcSVikram Hegde 	char			*immu_name;
513*3a634bfcSVikram Hegde 
514*3a634bfcSVikram Hegde 	/* lock grabbed by interrupt handler */
515*3a634bfcSVikram Hegde 	kmutex_t		immu_intr_lock;
516*3a634bfcSVikram Hegde 
517*3a634bfcSVikram Hegde 	/* ACPI/DMAR table related */
518*3a634bfcSVikram Hegde 	void			*immu_dmar_unit;
519*3a634bfcSVikram Hegde 	dev_info_t		*immu_dip;
520*3a634bfcSVikram Hegde 	struct domain		*immu_unity_domain;
521*3a634bfcSVikram Hegde 
522*3a634bfcSVikram Hegde 	/* IOMMU register related */
523*3a634bfcSVikram Hegde 	kmutex_t		immu_regs_lock;
524*3a634bfcSVikram Hegde 	boolean_t		immu_regs_setup;
525*3a634bfcSVikram Hegde 	boolean_t		immu_regs_running;
526*3a634bfcSVikram Hegde 	boolean_t		immu_regs_quiesced;
527*3a634bfcSVikram Hegde 	ddi_acc_handle_t	immu_regs_handle;
528*3a634bfcSVikram Hegde 	caddr_t			immu_regs_addr;
529*3a634bfcSVikram Hegde 	uint64_t		immu_regs_cap;
530*3a634bfcSVikram Hegde 	uint64_t		immu_regs_excap;
531*3a634bfcSVikram Hegde 	uint32_t		immu_regs_cmdval;
532*3a634bfcSVikram Hegde 	uint32_t		immu_regs_intr_msi_addr;
533*3a634bfcSVikram Hegde 	uint32_t		immu_regs_intr_msi_data;
534*3a634bfcSVikram Hegde 	uint32_t		immu_regs_intr_uaddr;
535*3a634bfcSVikram Hegde 
536*3a634bfcSVikram Hegde 	/* DVMA related */
537*3a634bfcSVikram Hegde 	kmutex_t		immu_dvma_lock;
538*3a634bfcSVikram Hegde 	boolean_t		immu_dvma_setup;
539*3a634bfcSVikram Hegde 	boolean_t		immu_dvma_running;
540*3a634bfcSVikram Hegde 	int			immu_dvma_gaw;
541*3a634bfcSVikram Hegde 	int			immu_dvma_agaw;
542*3a634bfcSVikram Hegde 	int			immu_dvma_nlevels;
543*3a634bfcSVikram Hegde 	boolean_t		immu_dvma_coherent;
544*3a634bfcSVikram Hegde 
545*3a634bfcSVikram Hegde 	/* DVMA context related */
546*3a634bfcSVikram Hegde 	krwlock_t		immu_ctx_rwlock;
547*3a634bfcSVikram Hegde 	pgtable_t		*immu_ctx_root;
548*3a634bfcSVikram Hegde 
549*3a634bfcSVikram Hegde 	/* DVMA domain related */
550*3a634bfcSVikram Hegde 	int			immu_max_domains;
551*3a634bfcSVikram Hegde 	vmem_t			*immu_did_arena;
552*3a634bfcSVikram Hegde 	char			immu_did_arena_name[IMMU_MAXNAMELEN];
553*3a634bfcSVikram Hegde 	list_t			immu_domain_list;
554*3a634bfcSVikram Hegde 
555*3a634bfcSVikram Hegde 	/* DVMA special devices */
556*3a634bfcSVikram Hegde 	boolean_t		immu_dvma_gfx_only;
557*3a634bfcSVikram Hegde 	list_t			immu_dvma_lpc_list;
558*3a634bfcSVikram Hegde 	list_t			immu_dvma_gfx_list;
559*3a634bfcSVikram Hegde 
560*3a634bfcSVikram Hegde 	/* interrupt remapping related */
561*3a634bfcSVikram Hegde 	kmutex_t		immu_intrmap_lock;
562*3a634bfcSVikram Hegde 	boolean_t		immu_intrmap_setup;
563*3a634bfcSVikram Hegde 	boolean_t		immu_intrmap_running;
564*3a634bfcSVikram Hegde 	intrmap_t		*immu_intrmap;
565*3a634bfcSVikram Hegde 	uint64_t		immu_intrmap_irta_reg;
566*3a634bfcSVikram Hegde 
567*3a634bfcSVikram Hegde 	/* queued invalidation related */
568*3a634bfcSVikram Hegde 	kmutex_t		immu_qinv_lock;
569*3a634bfcSVikram Hegde 	boolean_t		immu_qinv_setup;
570*3a634bfcSVikram Hegde 	boolean_t		immu_qinv_running;
571*3a634bfcSVikram Hegde 	boolean_t		immu_qinv_enabled;
572*3a634bfcSVikram Hegde 	void			*immu_qinv;
573*3a634bfcSVikram Hegde 	uint64_t		immu_qinv_reg_value;
574*3a634bfcSVikram Hegde 
575*3a634bfcSVikram Hegde 	/* list_node for system-wide list of DMAR units */
576*3a634bfcSVikram Hegde 	list_node_t		immu_node;
577*3a634bfcSVikram Hegde } immu_t;
578*3a634bfcSVikram Hegde 
579*3a634bfcSVikram Hegde /* properties that control DVMA */
580*3a634bfcSVikram Hegde #define	DDI_DVMA_MAPTYPE_PROP	"ddi-dvma-mapping"
581*3a634bfcSVikram Hegde 
582*3a634bfcSVikram Hegde /* property values */
583*3a634bfcSVikram Hegde #define	DDI_DVMA_MAPTYPE_UNITY	"unity"
584*3a634bfcSVikram Hegde 
585*3a634bfcSVikram Hegde typedef enum immu_maptype {
586*3a634bfcSVikram Hegde 	IMMU_MAPTYPE_BAD = 0,    /* 0 is always bad */
587*3a634bfcSVikram Hegde 	IMMU_MAPTYPE_UNITY = 1,
588*3a634bfcSVikram Hegde 	IMMU_MAPTYPE_XLATE
589*3a634bfcSVikram Hegde } immu_maptype_t;
590*3a634bfcSVikram Hegde 
591*3a634bfcSVikram Hegde /*
592*3a634bfcSVikram Hegde  * domain_t
593*3a634bfcSVikram Hegde  *
594*3a634bfcSVikram Hegde  */
595*3a634bfcSVikram Hegde typedef struct domain {
596*3a634bfcSVikram Hegde 	/* the basics */
597*3a634bfcSVikram Hegde 	uint_t			dom_did;
598*3a634bfcSVikram Hegde 	immu_t			*dom_immu;
599*3a634bfcSVikram Hegde 
600*3a634bfcSVikram Hegde 	/* mapping related */
601*3a634bfcSVikram Hegde 	immu_maptype_t		dom_maptype;
602*3a634bfcSVikram Hegde 	vmem_t			*dom_dvma_arena;
603*3a634bfcSVikram Hegde 	char			dom_dvma_arena_name[IMMU_MAXNAMELEN];
604*3a634bfcSVikram Hegde 
605*3a634bfcSVikram Hegde 	/* pgtables */
606*3a634bfcSVikram Hegde 	pgtable_t		*dom_pgtable_root;
607*3a634bfcSVikram Hegde 	krwlock_t		dom_pgtable_rwlock;
608*3a634bfcSVikram Hegde 
609*3a634bfcSVikram Hegde 	/* list of pgtables for this domain */
610*3a634bfcSVikram Hegde 	list_t			dom_pglist;
611*3a634bfcSVikram Hegde 
612*3a634bfcSVikram Hegde 	/* list node for list of domains (unity or xlate) */
613*3a634bfcSVikram Hegde 	list_node_t		dom_maptype_node;
614*3a634bfcSVikram Hegde 	/* list node for list of domains off immu */
615*3a634bfcSVikram Hegde 	list_node_t		dom_immu_node;
616*3a634bfcSVikram Hegde } domain_t;
617*3a634bfcSVikram Hegde 
618*3a634bfcSVikram Hegde typedef enum immu_pcib {
619*3a634bfcSVikram Hegde 	IMMU_PCIB_BAD = 0,
620*3a634bfcSVikram Hegde 	IMMU_PCIB_NOBDF,
621*3a634bfcSVikram Hegde 	IMMU_PCIB_PCIE_PCIE,
622*3a634bfcSVikram Hegde 	IMMU_PCIB_PCIE_PCI,
623*3a634bfcSVikram Hegde 	IMMU_PCIB_PCI_PCI,
624*3a634bfcSVikram Hegde 	IMMU_PCIB_ENDPOINT
625*3a634bfcSVikram Hegde } immu_pcib_t;
626*3a634bfcSVikram Hegde 
627*3a634bfcSVikram Hegde /*
628*3a634bfcSVikram Hegde  *  immu_devi_t
629*3a634bfcSVikram Hegde  *      Intel IOMMU in devinfo node
630*3a634bfcSVikram Hegde  */
631*3a634bfcSVikram Hegde typedef struct immu_devi {
632*3a634bfcSVikram Hegde 	/* pci seg, bus, dev, func */
633*3a634bfcSVikram Hegde 	int		imd_seg;
634*3a634bfcSVikram Hegde 	int		imd_bus;
635*3a634bfcSVikram Hegde 	int		imd_devfunc;
636*3a634bfcSVikram Hegde 
637*3a634bfcSVikram Hegde 	/* ppb information */
638*3a634bfcSVikram Hegde 	immu_pcib_t	imd_pcib_type;
639*3a634bfcSVikram Hegde 	int		imd_sec;
640*3a634bfcSVikram Hegde 	int		imd_sub;
641*3a634bfcSVikram Hegde 
642*3a634bfcSVikram Hegde 	/* identifier for special devices */
643*3a634bfcSVikram Hegde 	boolean_t	imd_display;
644*3a634bfcSVikram Hegde 	boolean_t	imd_lpc;
645*3a634bfcSVikram Hegde 
646*3a634bfcSVikram Hegde 	/* dmar unit to which this dip belongs */
647*3a634bfcSVikram Hegde 	immu_t		*imd_immu;
648*3a634bfcSVikram Hegde 
649*3a634bfcSVikram Hegde 	/* domain ptr */
650*3a634bfcSVikram Hegde 	domain_t	*imd_domain;
651*3a634bfcSVikram Hegde 	dev_info_t	*imd_ddip;
652*3a634bfcSVikram Hegde 
653*3a634bfcSVikram Hegde 	/* my devinfo */
654*3a634bfcSVikram Hegde 	dev_info_t	*imd_dip;
655*3a634bfcSVikram Hegde 
656*3a634bfcSVikram Hegde 	/*
657*3a634bfcSVikram Hegde 	 * if we are a "special" devinfo
658*3a634bfcSVikram Hegde 	 * the node for the special linked list
659*3a634bfcSVikram Hegde 	 * off the DMAR unit structure
660*3a634bfcSVikram Hegde 	 */
661*3a634bfcSVikram Hegde 	list_node_t	imd_spc_node;
662*3a634bfcSVikram Hegde } immu_devi_t;
663*3a634bfcSVikram Hegde 
664*3a634bfcSVikram Hegde #define	IMMU_DEVI(dip)		((immu_devi_t *)(DEVI(dip)->devi_iommu))
665*3a634bfcSVikram Hegde #define	IMMU_DEVI_SET(dip, imd)	(DEVI(dip)->devi_iommu = (void *)imd)
666*3a634bfcSVikram Hegde 
667*3a634bfcSVikram Hegde /*
668*3a634bfcSVikram Hegde  * struct dmar_arg
669*3a634bfcSVikram Hegde  */
670*3a634bfcSVikram Hegde typedef struct immu_arg {
671*3a634bfcSVikram Hegde 	int		ima_seg;
672*3a634bfcSVikram Hegde 	int		ima_bus;
673*3a634bfcSVikram Hegde 	int		ima_devfunc;
674*3a634bfcSVikram Hegde 	dev_info_t	*ima_rdip;
675*3a634bfcSVikram Hegde 	dev_info_t	*ima_ddip;
676*3a634bfcSVikram Hegde } immu_arg_t;
677*3a634bfcSVikram Hegde 
678*3a634bfcSVikram Hegde /*
679*3a634bfcSVikram Hegde  * Globals used by IOMMU code
680*3a634bfcSVikram Hegde  */
681*3a634bfcSVikram Hegde /* shared between IOMMU files */
682*3a634bfcSVikram Hegde extern dev_info_t *root_devinfo;
683*3a634bfcSVikram Hegde extern kmutex_t immu_lock;
684*3a634bfcSVikram Hegde extern list_t immu_list;
685*3a634bfcSVikram Hegde extern boolean_t immu_setup;
686*3a634bfcSVikram Hegde extern boolean_t immu_running;
687*3a634bfcSVikram Hegde extern kmutex_t ioapic_drhd_lock;
688*3a634bfcSVikram Hegde extern list_t ioapic_drhd_list;
689*3a634bfcSVikram Hegde 
690*3a634bfcSVikram Hegde /* switches */
691*3a634bfcSVikram Hegde 
692*3a634bfcSVikram Hegde /* Various features */
693*3a634bfcSVikram Hegde extern boolean_t immu_enable;
694*3a634bfcSVikram Hegde extern boolean_t immu_dvma_enable;
695*3a634bfcSVikram Hegde extern boolean_t immu_gfxdvma_enable;
696*3a634bfcSVikram Hegde extern boolean_t immu_intrmap_enable;
697*3a634bfcSVikram Hegde extern boolean_t immu_qinv_enable;
698*3a634bfcSVikram Hegde extern boolean_t immu_mmio_safe;
699*3a634bfcSVikram Hegde 
700*3a634bfcSVikram Hegde /* various quirks that need working around */
701*3a634bfcSVikram Hegde extern boolean_t immu_quirk_usbpage0;
702*3a634bfcSVikram Hegde extern boolean_t immu_quirk_usbfullpa;
703*3a634bfcSVikram Hegde extern boolean_t immu_quirk_usbrmrr;
704*3a634bfcSVikram Hegde extern boolean_t immu_quirk_mobile4;
705*3a634bfcSVikram Hegde 
706*3a634bfcSVikram Hegde /* debug messages */
707*3a634bfcSVikram Hegde extern boolean_t immu_dmar_print;
708*3a634bfcSVikram Hegde 
709*3a634bfcSVikram Hegde /* ################### Interfaces exported outside IOMMU code ############## */
710*3a634bfcSVikram Hegde void immu_init(void);
711*3a634bfcSVikram Hegde void immu_startup(void);
712*3a634bfcSVikram Hegde void immu_shutdown(void);
713*3a634bfcSVikram Hegde void immu_destroy(void);
714*3a634bfcSVikram Hegde int immu_map_sgl(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq,
715*3a634bfcSVikram Hegde     int prealloc_count, dev_info_t *rdip);
716*3a634bfcSVikram Hegde int immu_unmap_sgl(ddi_dma_impl_t *hp, dev_info_t *rdip);
717*3a634bfcSVikram Hegde void immu_device_tree_changed(void);
718*3a634bfcSVikram Hegde void immu_physmem_update(uint64_t addr, uint64_t size);
719*3a634bfcSVikram Hegde int immu_quiesce(void);
720*3a634bfcSVikram Hegde int immu_unquiesce(void);
721*3a634bfcSVikram Hegde /* ######################################################################### */
722*3a634bfcSVikram Hegde 
723*3a634bfcSVikram Hegde /* ################# Interfaces used within IOMMU code #################### */
724*3a634bfcSVikram Hegde 
725*3a634bfcSVikram Hegde /* functions in rootnex.c */
726*3a634bfcSVikram Hegde int rootnex_dvcookies_alloc(ddi_dma_impl_t *hp,
727*3a634bfcSVikram Hegde     struct ddi_dma_req *dmareq, dev_info_t *rdip, void *arg);
728*3a634bfcSVikram Hegde void rootnex_dvcookies_free(dvcookie_t *dvcookies, void *arg);
729*3a634bfcSVikram Hegde 
730*3a634bfcSVikram Hegde /* immu_dmar.c interfaces */
731*3a634bfcSVikram Hegde int immu_dmar_setup(void);
732*3a634bfcSVikram Hegde int immu_dmar_parse(void);
733*3a634bfcSVikram Hegde void immu_dmar_startup(void);
734*3a634bfcSVikram Hegde void immu_dmar_shutdown(void);
735*3a634bfcSVikram Hegde void immu_dmar_destroy(void);
736*3a634bfcSVikram Hegde boolean_t immu_dmar_blacklisted(char **strings_array, uint_t nstrings);
737*3a634bfcSVikram Hegde immu_t *immu_dmar_get_immu(dev_info_t *rdip);
738*3a634bfcSVikram Hegde char *immu_dmar_unit_name(void *dmar_unit);
739*3a634bfcSVikram Hegde dev_info_t *immu_dmar_unit_dip(void *dmar_unit);
740*3a634bfcSVikram Hegde void immu_dmar_set_immu(void *dmar_unit, immu_t *immu);
741*3a634bfcSVikram Hegde void *immu_dmar_walk_units(int seg, void *dmar_unit);
742*3a634bfcSVikram Hegde boolean_t immu_dmar_intrmap_supported(void);
743*3a634bfcSVikram Hegde uint16_t immu_dmar_ioapic_sid(int ioapicid);
744*3a634bfcSVikram Hegde immu_t *immu_dmar_ioapic_immu(int ioapicid);
745*3a634bfcSVikram Hegde void immu_dmar_rmrr_map(void);
746*3a634bfcSVikram Hegde 
747*3a634bfcSVikram Hegde /* immu.c interfaces */
748*3a634bfcSVikram Hegde int immu_walk_ancestor(dev_info_t *rdip, dev_info_t *ddip,
749*3a634bfcSVikram Hegde     int (*func)(dev_info_t *, void *arg), void *arg,
750*3a634bfcSVikram Hegde     int *level, immu_flags_t immu_flags);
751*3a634bfcSVikram Hegde 
752*3a634bfcSVikram Hegde /* immu_regs.c interfaces */
753*3a634bfcSVikram Hegde void immu_regs_setup(list_t *immu_list);
754*3a634bfcSVikram Hegde void immu_regs_startup(immu_t *immu);
755*3a634bfcSVikram Hegde int immu_regs_resume(immu_t *immu);
756*3a634bfcSVikram Hegde void immu_regs_suspend(immu_t *immu);
757*3a634bfcSVikram Hegde void immu_regs_shutdown(immu_t *immu);
758*3a634bfcSVikram Hegde void immu_regs_destroy(list_t *immu_list);
759*3a634bfcSVikram Hegde 
760*3a634bfcSVikram Hegde void immu_regs_intr(immu_t *immu, uint32_t msi_addr, uint32_t msi_data,
761*3a634bfcSVikram Hegde     uint32_t uaddr);
762*3a634bfcSVikram Hegde 
763*3a634bfcSVikram Hegde boolean_t immu_regs_passthru_supported(immu_t *immu);
764*3a634bfcSVikram Hegde boolean_t immu_regs_is_TM_reserved(immu_t *immu);
765*3a634bfcSVikram Hegde boolean_t immu_regs_is_SNP_reserved(immu_t *immu);
766*3a634bfcSVikram Hegde 
767*3a634bfcSVikram Hegde void immu_regs_wbf_flush(immu_t *immu);
768*3a634bfcSVikram Hegde void immu_regs_cpu_flush(immu_t *immu, caddr_t addr, uint_t size);
769*3a634bfcSVikram Hegde void immu_regs_iotlb_flush(immu_t *immu, uint_t domainid, uint64_t dvma,
770*3a634bfcSVikram Hegde     uint64_t count, uint_t hint, immu_iotlb_inv_t type);
771*3a634bfcSVikram Hegde void immu_regs_context_flush(immu_t *immu, uint8_t function_mask,
772*3a634bfcSVikram Hegde     uint16_t source_id, uint_t did, immu_context_inv_t type);
773*3a634bfcSVikram Hegde void immu_regs_set_root_table(immu_t *immu);
774*3a634bfcSVikram Hegde void immu_regs_qinv_enable(immu_t *immu, uint64_t qinv_reg_value);
775*3a634bfcSVikram Hegde void immu_regs_intr_enable(immu_t *immu, uint32_t msi_addr, uint32_t msi_data,
776*3a634bfcSVikram Hegde     uint32_t uaddr);
777*3a634bfcSVikram Hegde void immu_regs_intrmap_enable(immu_t *immu, uint64_t irta_reg);
778*3a634bfcSVikram Hegde uint64_t immu_regs_get64(immu_t *immu, uint_t reg);
779*3a634bfcSVikram Hegde void immu_regs_put64(immu_t *immu, uint_t reg, uint64_t val);
780*3a634bfcSVikram Hegde uint32_t immu_regs_get32(immu_t *immu, uint_t reg);
781*3a634bfcSVikram Hegde void immu_regs_put32(immu_t *immu, uint_t reg, uint32_t val);
782*3a634bfcSVikram Hegde 
783*3a634bfcSVikram Hegde /* immu_dvma.c interfaces */
784*3a634bfcSVikram Hegde void immu_dvma_setup(list_t *immu_list);
785*3a634bfcSVikram Hegde void immu_dvma_startup(immu_t *immu);
786*3a634bfcSVikram Hegde void immu_dvma_shutdown(immu_t *immu);
787*3a634bfcSVikram Hegde void immu_dvma_destroy(list_t *immu_list);
788*3a634bfcSVikram Hegde 
789*3a634bfcSVikram Hegde void immu_dvma_physmem_update(uint64_t addr, uint64_t size);
790*3a634bfcSVikram Hegde int immu_dvma_map(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq, memrng_t *,
791*3a634bfcSVikram Hegde     uint_t prealloc_count, dev_info_t *rdip, immu_flags_t immu_flags);
792*3a634bfcSVikram Hegde int immu_dvma_unmap(ddi_dma_impl_t *hp, dev_info_t *rdip);
793*3a634bfcSVikram Hegde int immu_dvma_alloc(dvcookie_t *first_dvcookie, void *arg);
794*3a634bfcSVikram Hegde void immu_dvma_free(dvcookie_t *first_dvcookie, void *arg);
795*3a634bfcSVikram Hegde int immu_devi_set(dev_info_t *dip, immu_flags_t immu_flags);
796*3a634bfcSVikram Hegde immu_devi_t *immu_devi_get(dev_info_t *dip);
797*3a634bfcSVikram Hegde immu_t *immu_dvma_get_immu(dev_info_t *dip, immu_flags_t immu_flags);
798*3a634bfcSVikram Hegde 
799*3a634bfcSVikram Hegde 
800*3a634bfcSVikram Hegde /* immu_intrmap.c interfaces */
801*3a634bfcSVikram Hegde void immu_intrmap_setup(list_t *immu_list);
802*3a634bfcSVikram Hegde void immu_intrmap_startup(immu_t *immu);
803*3a634bfcSVikram Hegde void immu_intrmap_shutdown(immu_t *immu);
804*3a634bfcSVikram Hegde void immu_intrmap_destroy(list_t *immu_list);
805*3a634bfcSVikram Hegde 
806*3a634bfcSVikram Hegde /* registers interrupt handler for IOMMU unit */
807*3a634bfcSVikram Hegde void immu_intr_register(immu_t *immu);
808*3a634bfcSVikram Hegde int immu_intr_handler(immu_t *immu);
809*3a634bfcSVikram Hegde 
810*3a634bfcSVikram Hegde 
811*3a634bfcSVikram Hegde /* immu_qinv.c interfaces */
812*3a634bfcSVikram Hegde void immu_qinv_setup(list_t *immu_list);
813*3a634bfcSVikram Hegde void immu_qinv_startup(immu_t *immu);
814*3a634bfcSVikram Hegde void immu_qinv_shutdown(immu_t *immu);
815*3a634bfcSVikram Hegde void immu_qinv_destroy(list_t *immu_list);
816*3a634bfcSVikram Hegde 
817*3a634bfcSVikram Hegde void immu_qinv_context_fsi(immu_t *immu, uint8_t function_mask,
818*3a634bfcSVikram Hegde     uint16_t source_id, uint_t domain_id);
819*3a634bfcSVikram Hegde void immu_qinv_context_dsi(immu_t *immu, uint_t domain_id);
820*3a634bfcSVikram Hegde void immu_qinv_context_gbl(immu_t *immu);
821*3a634bfcSVikram Hegde void immu_qinv_iotlb_psi(immu_t *immu, uint_t domain_id,
822*3a634bfcSVikram Hegde     uint64_t dvma, uint_t count, uint_t hint);
823*3a634bfcSVikram Hegde void immu_qinv_iotlb_dsi(immu_t *immu, uint_t domain_id);
824*3a634bfcSVikram Hegde void immu_qinv_iotlb_gbl(immu_t *immu);
825*3a634bfcSVikram Hegde void immu_qinv_intr_global(immu_t *immu);
826*3a634bfcSVikram Hegde void immu_qinv_intr_one_cache(immu_t *immu, uint_t idx);
827*3a634bfcSVikram Hegde void immu_qinv_intr_caches(immu_t *immu, uint_t idx, uint_t cnt);
828*3a634bfcSVikram Hegde void immu_qinv_report_fault(immu_t *immu);
829*3a634bfcSVikram Hegde 
830*3a634bfcSVikram Hegde 
831*3a634bfcSVikram Hegde #ifdef	__cplusplus
832*3a634bfcSVikram Hegde }
833*3a634bfcSVikram Hegde #endif
834*3a634bfcSVikram Hegde 
835*3a634bfcSVikram Hegde #endif	/* _SYS_INTEL_IOMMU_H */
836