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 */