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