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