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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #ifndef _SYS_IOMMULIB_H 26 #define _SYS_IOMMULIB_H 27 28 #pragma ident "@(#)iommulib.h 1.3 08/08/31 SMI" 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #include <sys/ddi_impldefs.h> 35 #include <sys/smbios.h> 36 37 #ifdef _KERNEL 38 39 typedef enum { 40 INVALID_VENDOR = 0, 41 AMD_IOMMU, 42 INTEL_IOMMU 43 } iommulib_vendor_t; 44 45 typedef enum { 46 IOMMU_OPS_VERSION_INVALID = 0, 47 IOMMU_OPS_VERSION_1 = 1, 48 IOMMU_OPS_VERSION_2 = 2 49 } iommulib_opsversion_t; 50 51 #define IOMMU_OPS_VERSION IOMMU_OPS_VERSION_2 52 53 typedef struct iommulib_ops { 54 iommulib_opsversion_t ilops_vers; 55 iommulib_vendor_t ilops_vendor; 56 char *ilops_id; 57 void *ilops_data; 58 59 int (*ilops_probe)(iommulib_handle_t handle, dev_info_t *rdip); 60 61 int (*ilops_dma_allochdl)(iommulib_handle_t handle, 62 dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 63 int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *dma_handlep); 64 65 int (*ilops_dma_freehdl)(iommulib_handle_t handle, 66 dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle); 67 68 int (*ilops_dma_bindhdl)(iommulib_handle_t handle, dev_info_t *dip, 69 dev_info_t *rdip, ddi_dma_handle_t dma_handle, 70 struct ddi_dma_req *dmareq, ddi_dma_cookie_t *cookiep, 71 uint_t *ccountp); 72 73 int (*ilops_dma_unbindhdl)(iommulib_handle_t handle, 74 dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle); 75 76 int (*ilops_dma_sync)(iommulib_handle_t handle, dev_info_t *dip, 77 dev_info_t *rdip, ddi_dma_handle_t dma_handle, off_t off, 78 size_t len, uint_t cache_flags); 79 80 int (*ilops_dma_win)(iommulib_handle_t handle, dev_info_t *dip, 81 dev_info_t *rdip, ddi_dma_handle_t dma_handle, uint_t win, 82 off_t *offp, size_t *lenp, ddi_dma_cookie_t *cookiep, 83 uint_t *ccountp); 84 85 int (*ilops_dma_mapobject)(iommulib_handle_t handle, 86 dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle, 87 struct ddi_dma_req *dmareq, ddi_dma_obj_t *dmao); 88 89 int (*ilops_dma_unmapobject)(iommulib_handle_t handle, 90 dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle, 91 ddi_dma_obj_t *dmao); 92 93 /* Obsolete DMA routines */ 94 95 int (*ilops_dma_map)(iommulib_handle_t handle, dev_info_t *dip, 96 dev_info_t *rdip, struct ddi_dma_req *dmareq, 97 ddi_dma_handle_t *dma_handle); 98 99 int (*ilops_dma_mctl)(iommulib_handle_t handle, dev_info_t *dip, 100 dev_info_t *rdip, ddi_dma_handle_t dma_handle, 101 enum ddi_dma_ctlops request, off_t *offp, size_t *lenp, 102 caddr_t *objpp, uint_t cache_flags); 103 104 } iommulib_ops_t; 105 106 /* 107 * Fake pointer value to indicate that a device will not use an IOMMU 108 * for DMA (it's either set up for passthrough or uses a unity mapping). 109 */ 110 #define IOMMU_HANDLE_UNUSED (void *)-1 111 112 /* 113 * IOMMU_UNITIALIZED() is true if it has not been determined whether 114 * a device uses an IOMMU for DMA or not. After it has been determined, 115 * the USED and UNUSED macros may be used to see if an IOMMU is being 116 * used or not. 117 * 118 * IOMMU_USED() is true if a device uses an IOMMU for DMA 119 * 120 * IOMMU_UNUSED() is true if a device does not use an IOMMU for DMA 121 */ 122 #define IOMMU_USED(dip) \ 123 (DEVI(dip)->devi_iommulib_handle != NULL && \ 124 DEVI(dip)->devi_iommulib_handle != IOMMU_HANDLE_UNUSED) 125 #define IOMMU_UNUSED(dip) \ 126 (DEVI(dip)->devi_iommulib_handle == IOMMU_HANDLE_UNUSED) 127 #define IOMMU_UNITIALIZED(dip) \ 128 (DEVI(dip)->devi_iommulib_handle == NULL) 129 130 typedef enum { 131 IOMMU_NEXOPS_VERSION_INVALID = 0, 132 IOMMU_NEXOPS_VERSION_1 = 1, 133 IOMMU_NEXOPS_VERSION_2 = 2 134 } iommulib_nexops_version_t; 135 136 #define IOMMU_NEXOPS_VERSION IOMMU_NEXOPS_VERSION_2 137 138 typedef struct iommulib_nexops { 139 iommulib_nexops_version_t nops_vers; 140 char *nops_id; 141 void *nops_data; 142 143 int (*nops_dma_allochdl)(dev_info_t *dip, dev_info_t *rdip, 144 ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 145 ddi_dma_handle_t *handlep); 146 147 int (*nops_dma_freehdl)(dev_info_t *dip, dev_info_t *rdip, 148 ddi_dma_handle_t handle); 149 150 int (*nops_dma_bindhdl)(dev_info_t *dip, dev_info_t *rdip, 151 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 152 ddi_dma_cookie_t *cookiep, uint_t *ccountp); 153 154 int (*nops_dma_unbindhdl)(dev_info_t *dip, dev_info_t *rdip, 155 ddi_dma_handle_t handle); 156 157 void (*nops_dma_reset_cookies)(dev_info_t *dip, 158 ddi_dma_handle_t handle); 159 160 int (*nops_dma_get_cookies)(dev_info_t *dip, ddi_dma_handle_t handle, 161 ddi_dma_cookie_t **cookiepp, uint_t *ccountp); 162 163 int (*nops_dma_set_cookies)(dev_info_t *dip, ddi_dma_handle_t handle, 164 ddi_dma_cookie_t *cookiep, uint_t ccount); 165 166 int (*nops_dma_clear_cookies)(dev_info_t *dip, ddi_dma_handle_t handle); 167 168 int (*nops_dma_get_sleep_flags)(ddi_dma_handle_t handle); 169 170 int (*nops_dma_sync)(dev_info_t *dip, dev_info_t *rdip, 171 ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags); 172 173 int (*nops_dma_win)(dev_info_t *dip, dev_info_t *rdip, 174 ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 175 ddi_dma_cookie_t *cookiep, uint_t *ccountp); 176 177 int (*nops_dma_map)(dev_info_t *dip, dev_info_t *rdip, 178 struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep); 179 180 int (*nops_dma_mctl)(dev_info_t *dip, dev_info_t *rdip, 181 ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 182 size_t *lenp, caddr_t *objpp, uint_t cache_flags); 183 184 int (*nops_dmahdl_setprivate)(dev_info_t *dip, dev_info_t *rdip, 185 ddi_dma_handle_t handle, void *priv); 186 187 void * (*nops_dmahdl_getprivate)(dev_info_t *dip, dev_info_t *rdip, 188 ddi_dma_handle_t handle); 189 } iommulib_nexops_t; 190 191 /* 192 * struct iommu_dip_private 193 * private iommu structure hook on dev_info 194 */ 195 typedef struct iommu_private { 196 /* pci seg, bus, dev, func */ 197 int idp_seg; 198 int idp_bus; 199 int idp_devfn; 200 201 /* ppb information */ 202 boolean_t idp_is_bridge; 203 int idp_bbp_type; 204 int idp_sec; 205 int idp_sub; 206 207 /* identifier for special devices */ 208 boolean_t idp_is_display; 209 boolean_t idp_is_lpc; 210 211 /* domain ptr */ 212 void *idp_intel_domain; 213 } iommu_private_t; 214 215 #define INTEL_IOMMU_PRIVATE(i) (dmar_domain_state_t *)(i) 216 217 typedef struct gfx_entry { 218 int g_ref; 219 dev_info_t *g_dip; 220 struct gfx_entry *g_prev; 221 struct gfx_entry *g_next; 222 } gfx_entry_t; 223 224 /* 225 * Interfaces for nexus drivers - typically rootnex 226 */ 227 228 int iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops, 229 iommulib_nexhandle_t *handle); 230 231 int iommulib_nexus_unregister(iommulib_nexhandle_t handle); 232 233 int iommulib_nex_open(dev_info_t *dip, dev_info_t *rdip); 234 void iommulib_nex_close(dev_info_t *rdip); 235 236 int iommulib_nexdma_allochdl(dev_info_t *dip, dev_info_t *rdip, 237 ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), 238 caddr_t arg, ddi_dma_handle_t *dma_handlep); 239 240 int iommulib_nexdma_freehdl(dev_info_t *dip, dev_info_t *rdip, 241 ddi_dma_handle_t dma_handle); 242 243 int iommulib_nexdma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 244 ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 245 ddi_dma_cookie_t *cookiep, uint_t *ccountp); 246 247 int iommulib_nexdma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 248 ddi_dma_handle_t dma_handle); 249 250 int iommulib_nexdma_sync(dev_info_t *dip, dev_info_t *rdip, 251 ddi_dma_handle_t dma_handle, off_t off, size_t len, 252 uint_t cache_flags); 253 254 int iommulib_nexdma_win(dev_info_t *dip, dev_info_t *rdip, 255 ddi_dma_handle_t dma_handle, uint_t win, off_t *offp, size_t *lenp, 256 ddi_dma_cookie_t *cookiep, uint_t *ccountp); 257 258 int iommulib_nexdma_map(dev_info_t *dip, dev_info_t *rdip, 259 struct ddi_dma_req *dmareq, ddi_dma_handle_t *dma_handle); 260 261 int iommulib_nexdma_mctl(dev_info_t *dip, dev_info_t *rdip, 262 ddi_dma_handle_t dma_handle, enum ddi_dma_ctlops request, 263 off_t *offp, size_t *lenp, caddr_t *objpp, uint_t cache_flags); 264 265 int iommulib_nexdma_mapobject(dev_info_t *dip, dev_info_t *rdip, 266 ddi_dma_handle_t dma_handle, struct ddi_dma_req *dmareq, 267 ddi_dma_obj_t *dmao); 268 int iommulib_nexdma_unmapobject(dev_info_t *dip, dev_info_t *rdip, 269 ddi_dma_handle_t dma_handle, ddi_dma_obj_t *dmao); 270 271 /* 272 * Interfaces for IOMMU drivers provided by IOMMULIB 273 */ 274 275 int iommulib_iommu_register(dev_info_t *dip, iommulib_ops_t *ops, 276 iommulib_handle_t *handle); 277 278 int iommulib_iommu_unregister(iommulib_handle_t handle); 279 280 int iommulib_iommu_getunitid(iommulib_handle_t handle, uint64_t *unitidp); 281 282 dev_info_t *iommulib_iommu_getdip(iommulib_handle_t handle); 283 284 iommulib_ops_t *iommulib_iommu_getops(iommulib_handle_t handle); 285 286 void *iommulib_iommu_getdata(iommulib_handle_t handle); 287 288 289 /* Interfaces for IOMMU drivers provided by NEXUS drivers (typically rootnex) */ 290 291 int iommulib_iommu_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 292 ddi_dma_attr_t *attr, int (*waitfp)(caddr_t), caddr_t arg, 293 ddi_dma_handle_t *handlep); 294 295 int iommulib_iommu_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, 296 ddi_dma_handle_t handle); 297 298 int iommulib_iommu_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 299 ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 300 ddi_dma_cookie_t *cookiep, uint_t *ccountp); 301 302 int iommulib_iommu_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 303 ddi_dma_handle_t handle); 304 305 void iommulib_iommu_dma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle); 306 307 int iommulib_iommu_dma_get_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 308 ddi_dma_cookie_t **cookiepp, uint_t *ccountp); 309 310 int iommulib_iommu_dma_set_cookies(dev_info_t *dip, ddi_dma_handle_t handle, 311 ddi_dma_cookie_t *cookiep, uint_t ccount); 312 313 int iommulib_iommu_dma_clear_cookies(dev_info_t *dip, ddi_dma_handle_t handle); 314 315 int iommulib_iommu_dma_get_sleep_flags(dev_info_t *dip, 316 ddi_dma_handle_t handle); 317 318 int iommulib_iommu_dma_sync(dev_info_t *dip, dev_info_t *rdip, 319 ddi_dma_handle_t handle, off_t off, size_t len, uint_t cache_flags); 320 321 int iommulib_iommu_dma_win(dev_info_t *dip, dev_info_t *rdip, 322 ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, 323 ddi_dma_cookie_t *cookiep, uint_t *ccountp); 324 325 int iommulib_iommu_dma_map(dev_info_t *dip, dev_info_t *rdip, 326 struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep); 327 328 int iommulib_iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 329 ddi_dma_handle_t handle, enum ddi_dma_ctlops request, off_t *offp, 330 size_t *lenp, caddr_t *objpp, uint_t cache_flags); 331 332 int iommulib_iommu_dmahdl_setprivate(dev_info_t *dip, dev_info_t *rdip, 333 ddi_dma_handle_t handle, void *priv); 334 335 void *iommulib_iommu_dmahdl_getprivate(dev_info_t *dip, dev_info_t *rdip, 336 ddi_dma_handle_t handle); 337 338 339 /* 340 * For SMBIOS access from IOMMU drivers 341 */ 342 extern smbios_hdl_t *iommulib_smbios; 343 344 #endif /* _KERNEL */ 345 346 #ifdef __cplusplus 347 } 348 #endif 349 350 #endif /* _SYS_IOMMULIB_H */ 351