1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2017 Gary Mills
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #ifndef _AMD_IOMMU_ACPI_H
27 #define	_AMD_IOMMU_ACPI_H
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 #include <sys/sunddi.h>
34 #include <sys/acpi/acpi.h>
35 #include <sys/acpica.h>
36 #include <sys/amd_iommu.h>
37 #include "amd_iommu_impl.h"
38 
39 #ifdef _KERNEL
40 
41 #define	IVRS_SIG	"IVRS"
42 
43 /*
44  * IVINFO bit fields
45  * Documented at: http://support.amd.com/TechDocs/48882_IOMMU.pdf
46  */
47 #define	AMD_IOMMU_ACPI_IVINFO_RSV1	(31 << 16 | 23)
48 #define	AMD_IOMMU_ACPI_HT_ATSRSV	(22 << 16 | 22)
49 #define	AMD_IOMMU_ACPI_VA_SIZE		(21 << 16 | 15)
50 #define	AMD_IOMMU_ACPI_PA_SIZE		(14 << 16 | 8)
51 #define	AMD_IOMMU_ACPI_GVA_SIZE		(7 << 16 | 5)
52 #define	AMD_IOMMU_ACPI_IVINFO_RSV2	(4 << 16 | 1)
53 #define	AMD_IOMMU_ACPI_IVINFO_EFRSUP	(0 << 16 | 0)
54 
55 /*
56  * IVHD Device entry len field
57  */
58 #define	AMD_IOMMU_ACPI_DEVENTRY_LEN	(7 << 16 | 6)
59 
60 /*
61  * IVHD flag fields definition
62  */
63 #define	AMD_IOMMU_ACPI_IVHD_FLAGS_RSV		(7 << 16 | 5)
64 #define	AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP	(4 << 16 | 4)
65 #define	AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC		(3 << 16 | 3)
66 #define	AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW	(2 << 16 | 2)
67 #define	AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW	(1 << 16 | 1)
68 #define	AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN	(0 << 16 | 0)
69 
70 /*
71  * IVHD IOMMU info fields
72  */
73 #define	AMD_IOMMU_ACPI_IOMMU_INFO_RSV1		(15 << 16 | 13)
74 #define	AMD_IOMMU_ACPI_IOMMU_INFO_UNITID	(12 << 16 | 8)
75 #define	AMD_IOMMU_ACPI_IOMMU_INFO_RSV2		(7 << 16 | 5)
76 #define	AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM	(4 << 16 | 0)
77 
78 /*
79  * IVHD deventry data settings
80  */
81 #define	AMD_IOMMU_ACPI_LINT1PASS	(7 << 16 | 7)
82 #define	AMD_IOMMU_ACPI_LINT0PASS	(6 << 16 | 6)
83 #define	AMD_IOMMU_ACPI_SYSMGT		(5 << 16 | 4)
84 #define	AMD_IOMMU_ACPI_DATRSV		(3 << 16 | 3)
85 #define	AMD_IOMMU_ACPI_NMIPASS		(2 << 16 | 2)
86 #define	AMD_IOMMU_ACPI_EXTINTPASS	(1 << 16 | 1)
87 #define	AMD_IOMMU_ACPI_INITPASS		(0 << 16 | 0)
88 
89 /*
90  * IVHD deventry extended data settings
91  */
92 #define	AMD_IOMMU_ACPI_ATSDISABLED	(31 << 16 | 31)
93 #define	AMD_IOMMU_ACPI_EXTDATRSV	(30 << 16 | 0)
94 
95 /*
96  * IVMD flags fields settings
97  */
98 #define	AMD_IOMMU_ACPI_IVMD_RSV		(7 << 16 | 4)
99 #define	AMD_IOMMU_ACPI_IVMD_EXCL_RANGE	(3 << 16 | 3)
100 #define	AMD_IOMMU_ACPI_IVMD_IW		(2 << 16 | 2)
101 #define	AMD_IOMMU_ACPI_IVMD_IR		(1 << 16 | 1)
102 #define	AMD_IOMMU_ACPI_IVMD_UNITY	(0 << 16 | 0)
103 
104 #define	AMD_IOMMU_ACPI_INFO_HASH_SZ	(256)
105 
106 /*
107  * Deventry special device "variety"
108  */
109 #define	AMD_IOMMU_ACPI_SPECIAL_APIC	0x1
110 #define	AMD_IOMMU_ACPI_SPECIAL_HPET	0x2
111 
112 typedef enum {
113 	DEVENTRY_INVALID = 0,
114 	DEVENTRY_ALL = 1,
115 	DEVENTRY_SELECT,
116 	DEVENTRY_RANGE,
117 	DEVENTRY_RANGE_END,
118 	DEVENTRY_ALIAS_SELECT,
119 	DEVENTRY_ALIAS_RANGE,
120 	DEVENTRY_EXTENDED_SELECT,
121 	DEVENTRY_EXTENDED_RANGE,
122 	DEVENTRY_SPECIAL_DEVICE
123 } ivhd_deventry_type_t;
124 
125 typedef enum {
126 	IVMD_DEVICE_INVALID = 0,
127 	IVMD_DEVICEID_ALL,
128 	IVMD_DEVICEID_SELECT,
129 	IVMD_DEVICEID_RANGE
130 } ivmd_deviceid_type_t;
131 
132 typedef struct ivhd_deventry {
133 	uint8_t idev_len;
134 	ivhd_deventry_type_t  idev_type;
135 	int32_t idev_deviceid;
136 	int32_t idev_src_deviceid;
137 	uint8_t idev_handle;
138 	uint8_t idev_variety;
139 	uint8_t idev_Lint1Pass;
140 	uint8_t idev_Lint0Pass;
141 	uint8_t idev_SysMgt;
142 	uint8_t idev_NMIPass;
143 	uint8_t idev_ExtIntPass;
144 	uint8_t idev_INITPass;
145 	uint8_t idev_AtsDisabled;
146 	struct ivhd_deventry *idev_next;
147 } ivhd_deventry_t;
148 
149 typedef struct ivhd {
150 	uint8_t ivhd_type;
151 	uint8_t ivhd_flags;
152 	uint16_t ivhd_len;
153 	uint16_t ivhd_deviceid;
154 	uint16_t ivhd_cap_off;
155 	uint64_t ivhd_reg_base;
156 	uint16_t ivhd_pci_seg;
157 	uint16_t ivhd_iommu_info;
158 	uint32_t ivhd_resv;
159 } ivhd_t;
160 
161 typedef struct ivhd_container {
162 	ivhd_t *ivhdc_ivhd;
163 	ivhd_deventry_t *ivhdc_first_deventry;
164 	ivhd_deventry_t *ivhdc_last_deventry;
165 	struct ivhd_container *ivhdc_next;
166 } ivhd_container_t;
167 
168 typedef struct ivmd {
169 	uint8_t ivmd_type;
170 	uint8_t ivmd_flags;
171 	uint16_t ivmd_len;
172 	uint16_t ivmd_deviceid;
173 	uint16_t ivmd_auxdata;
174 	uint64_t ivmd_resv;
175 	uint64_t ivmd_phys_start;
176 	uint64_t ivmd_phys_len;
177 } ivmd_t;
178 
179 typedef struct ivmd_container {
180 	ivmd_t *ivmdc_ivmd;
181 	struct ivmd_container *ivmdc_next;
182 } ivmd_container_t;
183 
184 typedef struct ivrs {
185 	struct acpi_table_header ivrs_hdr;
186 	uint32_t ivrs_ivinfo;
187 	uint64_t ivrs_resv;
188 } ivrs_t;
189 
190 typedef struct amd_iommu_acpi {
191 	struct ivrs *acp_ivrs;
192 	ivhd_container_t *acp_first_ivhdc;
193 	ivhd_container_t *acp_last_ivhdc;
194 	ivmd_container_t *acp_first_ivmdc;
195 	ivmd_container_t *acp_last_ivmdc;
196 } amd_iommu_acpi_t;
197 
198 
199 /* Global IVINFo fields */
200 typedef struct amd_iommu_acpi_global {
201 	uint8_t acg_HtAtsResv;
202 	uint8_t acg_VAsize;
203 	uint8_t acg_PAsize;
204 } amd_iommu_acpi_global_t;
205 
206 typedef struct amd_iommu_acpi_ivhd {
207 	int32_t ach_deviceid_start;
208 	int32_t ach_deviceid_end;
209 
210 	/* IVHD deventry type */
211 	ivhd_deventry_type_t ach_dev_type;
212 
213 	/* IVHD flag fields */
214 	uint8_t ach_IotlbSup;
215 	uint8_t ach_Isoc;
216 	uint8_t ach_ResPassPW;
217 	uint8_t ach_PassPW;
218 	uint8_t ach_HtTunEn;
219 
220 	/* IVHD fields */
221 	uint16_t ach_IOMMU_deviceid;
222 	uint16_t ach_IOMMU_cap_off;
223 	uint64_t ach_IOMMU_reg_base;
224 	uint16_t ach_IOMMU_pci_seg;
225 
226 	/* IVHD IOMMU info fields */
227 	uint8_t ach_IOMMU_UnitID;
228 	uint8_t ach_IOMMU_MSInum;
229 
230 	/* IVHD deventry data settings */
231 	uint8_t ach_Lint1Pass;
232 	uint8_t ach_Lint0Pass;
233 	uint8_t ach_SysMgt;
234 	uint8_t ach_NMIPass;
235 	uint8_t ach_ExtIntPass;
236 	uint8_t ach_INITPass;
237 
238 	/* alias */
239 	int32_t ach_src_deviceid;
240 
241 	/* IVHD deventry extended data settings */
242 	uint8_t ach_AtsDisabled;
243 
244 	/* IVHD deventry special device */
245 	uint8_t ach_special_handle;
246 	uint8_t ach_special_variety;
247 
248 	struct amd_iommu_acpi_ivhd *ach_next;
249 } amd_iommu_acpi_ivhd_t;
250 
251 typedef struct amd_iommu_acpi_ivmd {
252 	int32_t acm_deviceid_start;
253 	int32_t acm_deviceid_end;
254 
255 	/* IVMD type */
256 	ivmd_deviceid_type_t acm_dev_type;
257 
258 	/* IVMD flags */
259 	uint8_t acm_ExclRange;
260 	uint8_t acm_IW;
261 	uint8_t acm_IR;
262 	uint8_t acm_Unity;
263 
264 	/* IVMD mem block */
265 	uint64_t acm_ivmd_phys_start;
266 	uint64_t acm_ivmd_phys_len;
267 
268 	struct amd_iommu_acpi_ivmd *acm_next;
269 } amd_iommu_acpi_ivmd_t;
270 
271 typedef union {
272 	uint16_t   ent16;
273 	uint8_t	   ent8[2];
274 } align_16_t;
275 
276 typedef union {
277 	uint32_t   ent32;
278 	uint8_t	   ent8[4];
279 } align_32_t;
280 
281 typedef union {
282 	ivhd_t *ivhdp;
283 	char   *cp;
284 } align_ivhd_t;
285 
286 typedef union {
287 	ivmd_t *ivmdp;
288 	char   *cp;
289 } align_ivmd_t;
290 
291 #pragma pack()
292 
293 int amd_iommu_acpi_init(void);
294 void amd_iommu_acpi_fini(void);
295 amd_iommu_acpi_ivhd_t *amd_iommu_lookup_all_ivhd(void);
296 amd_iommu_acpi_ivmd_t *amd_iommu_lookup_all_ivmd(void);
297 amd_iommu_acpi_ivhd_t *amd_iommu_lookup_any_ivhd(amd_iommu_t *);
298 amd_iommu_acpi_ivmd_t *amd_iommu_lookup_any_ivmd(void);
299 amd_iommu_acpi_global_t *amd_iommu_lookup_acpi_global(void);
300 amd_iommu_acpi_ivhd_t *amd_iommu_lookup_ivhd(int32_t deviceid);
301 amd_iommu_acpi_ivmd_t *amd_iommu_lookup_ivmd(int32_t deviceid);
302 int amd_iommu_acpi_init_devtbl(amd_iommu_t *iommu);
303 
304 #endif /* _KERNEL */
305 
306 #ifdef __cplusplus
307 }
308 #endif
309 
310 #endif	/* _AMD_IOMMU_ACPI_H */
311