1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024 The FreeBSD Foundation 5 * 6 * This software was developed by Konstantin Belousov <kib@FreeBSD.org> 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #ifndef __X86_IOMMU_AMD_REG_H 32 #define __X86_IOMMU_AMD_REG_H 33 34 /* 35 * MMIO Registers. Offsets and bits definitions. 36 */ 37 38 #define AMDIOMMU_DEVTAB_BASE 0x0000 39 #define AMDIOMMU_CMDBUF_BASE 0x0008 40 #define AMDIOMMU_EVNTLOG_BASE 0x0010 41 #define AMDIOMMU_CTRL 0x0018 42 #define AMDIOMMU_EXCL_BASE 0x0020 43 #define AMDIOMMU_EXCL_RANGE 0x0028 44 #define AMDIOMMU_EFR 0x0030 45 #define AMDIOMMU_PPRLOG_BASE 0x0038 46 #define AMDIOMMU_HWEV_UPPER 0x0040 47 #define AMDIOMMU_HWEV_LOWER 0x0048 48 #define AMDIOMMU_HWEV_STATUS 0x0050 49 50 #define AMDIOMMU_SMIF_0 0x0060 51 #define AMDIOMMU_SMIF_1 0x0068 52 #define AMDIOMMU_SMIF_2 0x0070 53 #define AMDIOMMU_SMIF_3 0x0078 54 #define AMDIOMMU_SMIF_4 0x0080 55 #define AMDIOMMU_SMIF_5 0x0088 56 #define AMDIOMMU_SMIF_6 0x0090 57 #define AMDIOMMU_SMIF_7 0x0098 58 #define AMDIOMMU_SMIF_8 0x00a0 59 #define AMDIOMMU_SMIF_9 0x00a8 60 #define AMDIOMMU_SMIF_10 0x00b0 61 #define AMDIOMMU_SMIF_11 0x00b8 62 #define AMDIOMMU_SMIF_12 0x00c0 63 #define AMDIOMMU_SMIF_13 0x00c8 64 #define AMDIOMMU_SMIF_14 0x00d0 65 #define AMDIOMMU_SMIF_15 0x00d8 66 67 #define AMDIOMMU_VAPIC_LOG_BASE 0x00e0 68 #define AMDIOMMU_VAPIC_LOG_TAIL 0x00e8 69 #define AMDIOMMU_PPRLOGB_BASE 0x00f0 70 #define AMDIOMMU_EVNTLOGB_BASE 0x00f0 71 72 #define AMDIOMMU_DEVTAB_S1_BASE 0x0100 73 #define AMDIOMMU_DEVTAB_S2_BASE 0x0108 74 #define AMDIOMMU_DEVTAB_S3_BASE 0x0110 75 #define AMDIOMMU_DEVTAB_S4_BASE 0x0118 76 #define AMDIOMMU_DEVTAB_S5_BASE 0x0120 77 #define AMDIOMMU_DEVTAB_S6_BASE 0x0128 78 #define AMDIOMMU_DEVTAB_S7_BASE 0x0130 79 80 #define AMDIOMMU_DSFX 0x0138 81 #define AMDIOMMU_DSCX 0x0140 82 #define AMDIOMMU_DSSX 0x0148 83 84 #define AMDIOMMU_MSI_VEC0 0x0150 85 #define AMDIOMMU_MSI_VEC1 0x0154 86 #define AMDIOMMU_MSI_CAP_H 0x0158 87 #define AMDIOMMU_MSI_ADDR_LOW 0x015c 88 #define AMDIOMMU_MSI_ADDR_HIGH 0x0160 89 #define AMDIOMMU_MSI_DATA 0x0164 90 #define AMDIOMMU_MSI_MAPCAP 0x0168 91 92 #define AMDIOMMU_PERFOPT 0x016c 93 94 #define AMDIOMMU_x2APIC_CTRL 0x0170 95 #define AMDIOMMU_PPRI_CTRL 0x0178 96 #define AMDIOMMU_GALOGI_CTRL 0x0180 97 98 #define AMDIOMMU_vIOMMU_STATUS 0x0190 99 100 #define AMDIOMMU_MARC0_BASE 0x0200 101 #define AMDIOMMU_MARC0_RELOC 0x0208 102 #define AMDIOMMU_MARC0_LEN 0x0210 103 #define AMDIOMMU_MARC1_BASE 0x0218 104 #define AMDIOMMU_MARC1_RELOC 0x0220 105 #define AMDIOMMU_MARC1_LEN 0x0228 106 #define AMDIOMMU_MARC2_BASE 0x0230 107 #define AMDIOMMU_MARC2_RELOC 0x0238 108 #define AMDIOMMU_MARC2_LEN 0x0240 109 #define AMDIOMMU_MARC3_BASE 0x0248 110 #define AMDIOMMU_MARC3_RELOC 0x0250 111 #define AMDIOMMU_MARC3_LEN 0x0258 112 113 #define AMDIOMMU_EFR2 0x01a0 114 115 #define AMDIOMMU_CMDBUF_HEAD 0x2000 116 #define AMDIOMMU_CMDBUF_TAIL 0x2008 117 #define AMDIOMMU_EVNTLOG_HEAD 0x2010 118 #define AMDIOMMU_EVNTLOG_TAIL 0x2018 119 #define AMDIOMMU_CMDEV_STATUS 0x2020 120 #define AMDIOMMU_PPRLOG_HEAD 0x2030 121 #define AMDIOMMU_PPRLOG_TAIL 0x2038 122 #define AMDIOMMU_vAPICLOG_HEAD 0x2040 123 #define AMDIOMMU_vAPICLOG_TAIL 0x2048 124 #define AMDIOMMU_PPRLOGB_HEAD 0x2050 125 #define AMDIOMMU_PPRLOGB_TAIL 0x2058 126 #define AMDIOMMU_EVNTLOGB_HEAD 0x2070 127 #define AMDIOMMU_EVNTLOGB_TAIL 0x2078 128 #define AMDIOMMU_PPRLOG_AUR 0x2080 129 #define AMDIOMMU_PPRLOG_EAI 0x2088 130 #define AMDIOMMU_PPRLOGB_AUR 0x2090 131 132 /* 133 * IOMMU Control Register AMDIOMMU_CTRL fields 134 */ 135 #define AMDIOMMU_CTRL_EN 0x0000000000000001ull /* IOMMU En */ 136 #define AMDIOMMU_CTRL_HTTUN_EN 0x0000000000000002ull /* HT Tun Trans En */ 137 #define AMDIOMMU_CTRL_EVNTLOG_EN 0x0000000000000004ull /* Event Log En */ 138 #define AMDIOMMU_CTRL_EVENTINT_EN 0x0000000000000008ull /* Event Log Intr En */ 139 #define AMDIOMMU_CTRL_COMWINT_EN 0x0000000000000010ull /* Compl Wait Intr En */ 140 #define AMDIOMMU_CTRL_INVTOUT_MASK 0x00000000000000e0ull /* IOTLB Inv Timeout*/ 141 #define AMDIOMMU_CTRL_INVTOUT_NO 0x0000000000000000ull 142 #define AMDIOMMU_CTRL_INVTOUT_1MS 0x0000000000000020ull 143 #define AMDIOMMU_CTRL_INVTOUT_10MS 0x0000000000000040ull 144 #define AMDIOMMU_CTRL_INVTOUT_100MS 0x0000000000000060ull 145 #define AMDIOMMU_CTRL_INVTOUT_1S 0x0000000000000080ull 146 #define AMDIOMMU_CTRL_INVTOUT_10S 0x00000000000000a0ull 147 #define AMDIOMMU_CTRL_INVTOUT_100S 0x00000000000000b0ull 148 #define AMDIOMMU_CTRL_INVTOUT_RSRV 0x00000000000000e0ull 149 #define AMDIOMMU_CTRL_PASSPW 0x0000000000000100ull /* HT Pass Posted Wr */ 150 #define AMDIOMMU_CTRL_REPASSPW 0x0000000000000200ull /* HT Resp Pass Posted Wr */ 151 #define AMDIOMMU_CTRL_COHERENT 0x0000000000000400ull /* HT Coherent Reads */ 152 #define AMDIOMMU_CTRL_ISOC 0x0000000000000800ull /* HT Isoc Reads */ 153 #define AMDIOMMU_CTRL_CMDBUF_EN 0x0000000000001000ull /* Start CMD proc En */ 154 #define AMDIOMMU_CTRL_PPRLOG_EN 0x0000000000002000ull /* Periph Page Req Log En */ 155 #define AMDIOMMU_CTRL_PPRINT_EN 0x0000000000004000ull /* Periph Page Req Intr En */ 156 #define AMDIOMMU_CTRL_PPR_EN 0x0000000000008000ull /* Periph Page Req En */ 157 #define AMDIOMMU_CTRL_GT_EN 0x0000000000010000ull /* Guest En */ 158 #define AMDIOMMU_CTRL_GA_EN 0x0000000000020000ull /* Guest vAPIC En */ 159 #define AMDIOMMU_CTRL_SMIF_EN 0x0000000000400000ull /* SMI Filter En */ 160 #define AMDIOMMU_CTRL_SLFWB_DIS 0x0000000000800000ull /* Self WriteBack Dis */ 161 #define AMDIOMMU_CTRL_SMIFLOG_EN 0x0000000001000000ull /* SMI Filter Log En */ 162 #define AMDIOMMU_CTRL_GAM_EN_MASK 0x000000000e000000ull /* Guest vAPIC Mode En */ 163 #define AMDIOMMU_CTRL_GAM_EN_vAPIC_GM0 0x0000000000000000ull /* IRTE.GM = 0 */ 164 #define AMDIOMMU_CTRL_GAM_EN_vAPIC_GM1 0x0000000002000000ull /* IRTE.GM = 1 */ 165 #define AMDIOMMU_CTRL_GALOG_EN 0x0000000010000000ull /* Guest vAPIC GA Log En */ 166 #define AMDIOMMU_CTRL_GAINT_EN 0x0000000020000000ull /* Guest vAPIC GA Intr En */ 167 #define AMDIOMMU_CTRL_DUALPPRLOG_MASK 0x00000000c0000000ull /* Dual Periph Page Req Log En */ 168 #define AMDIOMMU_CTRL_DUALPPRLOG_A 0x0000000000000000ull /* Use Log A */ 169 #define AMDIOMMU_CTRL_DUALPPRLOG_B 0x0000000040000000ull /* Use Log B */ 170 #define AMDIOMMU_CTRL_DUALPPRLOG_SWAP 0x0000000080000000ull /* Auto-swap on full */ 171 #define AMDIOMMU_CTRL_DUALPPRLOG_RSRV 0x00000000c0000000ull 172 #define AMDIOMMU_CTRL_DUALEVNTLOG_MASK 0x0000000300000000ull /* Dual Event Log En */ 173 #define AMDIOMMU_CTRL_DUALEVNTLOG_A 0x0000000000000000ull /* Use Log A Buf */ 174 #define AMDIOMMU_CTRL_DUALEVNTLOG_B 0x0000000100000000ull /* Use Log B Buf */ 175 #define AMDIOMMU_CTRL_DUALEVNTLOG_SWAP 0x0000000200000000ull /* Auto-swap on full */ 176 #define AMDIOMMU_CTRL_DUALEVNTLOG_RSRV 0x0000000300000000ull 177 #define AMDIOMMU_CTRL_DEVTABSEG_MASK 0x0000001c00000000ull /* Dev Table Segm */ 178 #define AMDIOMMU_CTRL_DEVTABSEG_1 0x0000000000000000ull /* 1 Segment */ 179 #define AMDIOMMU_CTRL_DEVTABSEG_2 0x0000000400000000ull /* 2 Segments */ 180 #define AMDIOMMU_CTRL_DEVTABSEG_4 0x0000000800000000ull /* 4 Segments */ 181 #define AMDIOMMU_CTRL_DEVTABSEG_8 0x0000000c00000000ull /* 8 Segments */ 182 #define AMDIOMMU_CTRL_PRIVABRT_MASK 0x0000006000000000ull /* Privilege Abort En */ 183 #define AMDIOMMU_CTRL_PRIVABRT_USR 0x0000000000000000ull /* Privilege Abort User */ 184 #define AMDIOMMU_CTRL_PRIVABRT_ALL 0x0000002000000000ull /* Privilege Abort Always */ 185 #define AMDIOMMU_CTRL_PPRAUTORSP_EN 0x0000008000000000ull /* PPR Auto Resp En */ 186 #define AMDIOMMU_CTRL_MARC_EN 0x0000010000000000ull /* Memory Addr Routing En */ 187 #define AMDIOMMU_CTRL_BLKSTOPMRK_EN 0x0000020000000000ull /* Block StopMark En */ 188 #define AMDIOMMU_CTRL_PPRAUTORESPA_EN 0x0000040000000000ull /* PPR Auto Resp Always En */ 189 #define AMDIOMMU_CTRL_NUMINTRREMAP_MASK 0x0000180000000000ull /* Remapping MSI mode */ 190 #define AMDIOMMU_CTRL_NUMINTRREMAP_512 0x0000000000000000ull /* 512 max */ 191 #define AMDIOMMU_CTRL_NUMINTRREMAP_2048 0x0000080000000000ull /* 2048 max */ 192 #define AMDIOMMU_CTRL_EPH_EN 0x0000200000000000ull /* Enh PPR Handling En */ 193 #define AMDIOMMU_CTRL_HADUP_MASK 0x0000c00000000000ull /* Access and Dirty in host PT */ 194 #define AMDIOMMU_CTRL_GDUP_DIS 0x0001000000000000ull /* Dis Dirty in guest PT */ 195 #define AMDIOMMU_CTRL_XT_EN 0x0004000000000000ull /* x2APIC mode */ 196 #define AMDIOMMU_CTRL_INTCAPXT_EN 0x0008000000000000ull /* x2APIC mode for IOMMU intrs */ 197 #define AMDIOMMU_CTRL_vCMD_EN 0x0010000000000000ull /* vCMD buffer proc En */ 198 #define AMDIOMMU_CTRL_vIOMMU_EN 0x0020000000000000ull /* vIOMMU En */ 199 #define AMDIOMMU_CTRL_GAUP_DIS 0x0040000000000000ull /* Dis Access in guest PT */ 200 #define AMDIOMMU_CTRL_GAPPI_EN 0x0080000000000000ull /* Guest APIC phys proc intr En */ 201 #define AMDIOMMU_CTRL_TMPM_EN 0x0100000000000000ull /* Tiered Mem Page Migration En */ 202 #define AMDIOMMU_CTRL_GGCR3TRP_PHYS 0x0400000000000000ull /* GCR3 is GPA (otherwise SPA) */ 203 #define AMDIOMMU_CTRL_IRTCACHE_DIS 0x0800000000000000ull /* IRT Caching Dis */ 204 #define AMDIOMMU_CTRL_GSTBUFTRP_MODE 0x1000000000000000ull /* See spec */ 205 #define AMDIOMMU_CTRL_SNPAVIC_MASK 0xe000000000000000ull /* MBZ */ 206 207 /* 208 * IOMMU Extended Feature Register AMDIOMMU_EFR fields 209 */ 210 #define AMDIOMMU_EFR_XT_SUP 0x0000000000000004ull /* x2APIC */ 211 #define AMDIOMMU_EFR_HWEV_SUP 0x0000000000000100ull /* HW Event regs */ 212 #define AMDIOMMU_EFR_PC_SUP 0x0000000000000200ull /* Perf counters */ 213 #define AMDIOMMU_EFR_HATS_MASK 0x0000000000000c00ull /* Host Addr Trans Size */ 214 #define AMDIOMMU_EFR_HATS_4LVL 0x0000000000000000ull 215 #define AMDIOMMU_EFR_HATS_5LVL 0x0000000000000400ull 216 #define AMDIOMMU_EFR_HATS_6LVL 0x0000000000000800ull 217 #define AMDIOMMU_EFR_DEVTBLSEG_MASK 0x000000c000000000ull /* DevTbl segmentation */ 218 #define AMDIOMMU_EFR_DEVTBLSEG_SHIFT 38 219 220 /* IOMMU Command Pointers (Head/Tail) registers fields */ 221 #define AMDIOMMU_CMDPTR_MASK 0x000000000007fff0ull 222 223 /* IOMMU Command Buffer Base fields */ 224 #define AMDIOMMU_CMDBUF_BASE_SZSHIFT 56 /* Shift for size */ 225 #define AMDIOMMU_CMDBUF_MAX (512 * 1024) 226 227 /* IOMMU Event Log Base register fields */ 228 #define AMDIOMMU_EVNTLOG_BASE_SZSHIFT 56 /* Shift for size */ 229 #define AMDIOMMU_EVNTLOG_MIN 256 230 #define AMDIOMMU_EVNTLOG_MAX 32768 231 232 /* IOMMU Hardware Event Status register fields */ 233 #define AMDIOMMU_HWEVS_HEV 0x00000001 /* HW Ev Valid */ 234 #define AMDIOMMU_HWEVS_HEO 0x00000002 /* HW Ev Overfl */ 235 236 /* 237 * IOMMU Command and Event Status register fields. 238 * From the spec, all defined bits are either RO or RW1C. As a consequence, 239 * single bit can be safely written to the register to clean a specific 240 * condition. 241 */ 242 #define AMDIOMMU_CMDEVS_EVOVRFLW 0x00000001 243 #define AMDIOMMU_CMDEVS_EVLOGINT 0x00000002 244 #define AMDIOMMU_CMDEVS_COMWAITINT 0x00000004 245 #define AMDIOMMU_CMDEVS_EVLOGRUN 0x00000008 246 #define AMDIOMMU_CMDEVS_CMDBUFRUN 0x00000010 247 #define AMDIOMMU_CMDEVS_PPROVRFLW 0x00000020 248 #define AMDIOMMU_CMDEVS_PPRINT 0x00000040 249 #define AMDIOMMU_CMDEVS_PPRLOGRUN 0x00000080 250 #define AMDIOMMU_CMDEVS_GALOGRUN 0x00000100 251 #define AMDIOMMU_CMDEVS_GALOVRFLW 0x00000200 252 #define AMDIOMMU_CMDEVS_GAINT 0x00000400 253 #define AMDIOMMU_CMDEVS_PPROVRFLWB 0x00000800 254 #define AMDIOMMU_CMDEVS_PPRLOGACTIVE 0x00001000 255 #define AMDIOMMU_CMDEVS_RESV1 0x00002000 256 #define AMDIOMMU_CMDEVS_RESV2 0x00004000 257 #define AMDIOMMU_CMDEVS_EVOVRFLWB 0x00008000 258 #define AMDIOMMU_CMDEVS_EVLOGACTIVE 0x00010000 259 #define AMDIOMMU_CMDEVS_PPROVRFLWEB 0x00020000 260 #define AMDIOMMU_CMDEVS_PPROVRFLWE 0x00040000 261 262 /* 263 * IOMMU Extended Feature2 register fields. 264 * All currently defined bits are RO. 265 */ 266 #define AMDIOMMU_EFR2_TMPMSUP 0x0000000000000004ull /* Tiered Mem Migration */ 267 #define AMDIOMMU_EFR2_GCR3TRPM 0x0000000000000008ull /* GPA based GCR3 pointer in DTE */ 268 #define AMDIOMMU_EFR2_GAPPID 0x0000000000000010ull /* masking of GAPIC PPI */ 269 #define AMDIOMMU_EFR2_SNPAVIC_MASK 0x00000000000000e0ull /* SNP-enabled Adv intr features */ 270 #define AMDIOMMU_EFR2_SNPAVIC_NO 0x0000000000000000ull /* No features supported */ 271 #define AMDIOMMU_EFR2_SNPAVIC_REMAPV 0x0000000000000020ull /* Intr remapping with GVAPIC */ 272 #define AMDIOMMU_EFR2_NUMINTRREMAP_MASK 0x0000000000000300ull /* Number of remapped intr per dev */ 273 #define AMDIOMMU_EFR2_NUMINTRREMAP_512 0x0000000000000000ull /* 512 */ 274 #define AMDIOMMU_EFR2_NUMINTRREMAP_2048 0x0000000000000100ull /* 2048 */ 275 #define AMDIOMMU_EFR2_HTRANGEIGN 0x0000000000000800ull /* HT range is regular GPA */ 276 277 /* 278 * Device Table Entry (DTE) 279 */ 280 struct amdiommu_dte { 281 u_int v:1; /* Valid */ 282 u_int tv:1; /* Translation Valid */ 283 u_int rsrv0:5; 284 u_int had:2; /* Host Access Dirty */ 285 u_int pgmode:3; /* Paging Mode */ 286 uint64_t ptroot:40; /* Page Table Root */ 287 u_int ppr:1; /* PPR En */ 288 u_int gprp:1; /* Guest PPR Resp with PASID */ 289 u_int giov:1; /* Guest IO Prot Valid */ 290 u_int gv:1; /* Guest Translation Valid */ 291 u_int glx:2; /* Guest Levels Translated */ 292 u_int gcr3root0:3; /* GCR3 root pointer part */ 293 u_int ir:1; /* Read Perm */ 294 u_int iw:1; /* Write Perm */ 295 u_int rsrv1:1; 296 u_int domainid:16; /* domain tag */ 297 u_int gcr3root1:16; /* GCR3 root pointer part */ 298 u_int i:1; /* IOTLB En */ 299 u_int se:1; /* Suppress IO Fault Events */ 300 u_int sa:1; /* Suppress All IO Fault Events */ 301 u_int pioctl:2; /* Port IO Control */ 302 u_int cache:1; /* IOTLB Cache Hint */ 303 u_int sd:1; /* Snoop Disable */ 304 u_int ex:1; /* Allow Exclusion */ 305 u_int sysmgt:2; /* System Management Msg Handling */ 306 u_int sats:1; /* Secure/Non-secure ATS */ 307 u_int gcr3root2:21; /* GCR3 root pointer part */ 308 u_int iv:1; /* Intr Map Valid */ 309 u_int inttablen:4; /* log2 Intr Table Len */ 310 u_int ig:1; /* Ignore Unmapped Interrupts */ 311 uint64_t intrroot:46; /* Interrupt Table Root (-low 6bits) */ 312 u_int rsrv2:2; 313 u_int gpm:2; /* Guest Paging Mode */ 314 u_int initpass:1; /* INIT pass-through */ 315 u_int eintpass:1; /* ExtInt pass-through */ 316 u_int nmipass:1; /* NMI pass-through */ 317 u_int hptmode:1; /* Host Page Table Mode Hint */ 318 u_int intctl:2; /* Interrupt Control */ 319 u_int lint0pass:1; /* LINT0 pass-through */ 320 u_int lint1pass:1; /* LINT1 pass-through */ 321 u_int rsrv3:15; 322 u_int vimu:1; /* Virtualize IOMMU En */ 323 u_int gdevid:16; /* Guest Dev Id */ 324 u_int gid:16; /* Guest Id */ 325 u_int rsrv4:5; 326 u_int rsrv5:1; /* Not Checked, sw avail */ 327 u_int attrv:1; /* Attr Override Valid */ 328 u_int mode0fc:1; /* Replace for PTE.FC */ 329 u_int snoopattr:8; /* GuestPTE.PAT -> ATS.N xlat */ 330 } __packed; 331 _Static_assert(sizeof(struct amdiommu_dte) == 8 * sizeof(uint32_t), "DTE"); 332 333 #define AMDIOMMU_DTE_HAD_NAND 0x0 /* No Access, No Dirty */ 334 #define AMDIOMMU_DTE_HAD_AND 0x1 /* Access, No Dirty */ 335 #define AMDIOMMU_DTE_HAD_RSRV 0x2 336 #define AMDIOMMU_DTE_HAD_AD 0x3 /* Access, Dirty */ 337 338 #define AMDIOMMU_DTE_PGMODE_1T1 0x0 /* SPA = GPA */ 339 #define AMDIOMMU_DTE_PGMODE_1LV 0x1 /* 1 Level PT */ 340 #define AMDIOMMU_DTE_PGMODE_2LV 0x2 /* 2 Level PT */ 341 #define AMDIOMMU_DTE_PGMODE_3LV 0x3 /* 3 Level PT */ 342 #define AMDIOMMU_DTE_PGMODE_4LV 0x4 /* 4 Level PT */ 343 #define AMDIOMMU_DTE_PGMODE_5LV 0x5 /* 5 Level PT */ 344 #define AMDIOMMU_DTE_PGMODE_6LV 0x6 /* 6 Level PT */ 345 #define AMDIOMMU_DTE_PGMODE_RSRV 0x7 346 347 #define AMDIOMMU_DTE_GLX_1LV 0x0 /* 1 Level GCR3 */ 348 #define AMDIOMMU_DTE_GLX_2LV 0x1 /* 2 Level GCR3 */ 349 #define AMDIOMMU_DTE_GLX_3LV 0x2 /* 3 Level GCR3 */ 350 #define AMDIOMMU_DTE_GLX_RSRV 0x3 351 352 #define AMDIOMMU_DTE_PIOCTL_DIS 0x0 353 #define AMDIOMMU_DTE_PIOCTL_EN 0x1 354 #define AMDIOMMU_DTE_PIOCTL_MAP 0x2 355 #define AMDIOMMU_DTE_PIOCTL_RSRV 0x3 356 357 #define AMDIOMMU_DTE_SYSMGT_DIS 0x0 /* Target Abort */ 358 #define AMDIOMMU_DTE_SYSMGT_FW 0x0 /* Forwarded All */ 359 #define AMDIOMMU_DTE_SYSMGT_FWI 0x0 /* Forwarded INT */ 360 #define AMDIOMMU_DTE_SYSMGT_T 0x0 /* Translated */ 361 362 #define AMDIOMMU_DTE_GPM_4LV 0x0 /* 4 Level */ 363 #define AMDIOMMU_DTE_GPM_5LV 0x1 /* 5 Level */ 364 #define AMDIOMMU_DTE_GPM_RSRV1 0x2 365 #define AMDIOMMU_DTE_GPM_RSRV2 0x3 366 367 #define AMDIOMMU_DTE_INTCTL_DIS 0x0 /* Target Abort */ 368 #define AMDIOMMU_DTE_INTCTL_FW 0x1 /* Forward Unmapped */ 369 #define AMDIOMMU_DTE_INTCTL_MAP 0x2 /* Forward Remapped */ 370 #define AMDIOMMU_DTE_INTCTL_RSRV 0x3 371 372 #define AMDIOMMU_PGTBL_MAXLVL 6 373 374 /* 375 * Page Table Entry (PTE/PDE) 376 */ 377 #define AMDIOMMU_PTE_PR 0x0001 /* Present, AKA V */ 378 #define AMDIOMMU_IGN1 0x0002 379 #define AMDIOMMU_IGN2 0x0004 380 #define AMDIOMMU_IGN3 0x0008 381 #define AMDIOMMU_IGN4 0x0010 382 #define AMDIOMMU_PTE_A 0x0020 /* Accessed */ 383 #define AMDIOMMU_PTE_D 0x0040 /* Dirty */ 384 #define AMDIOMMU_IGN5 0x0080 385 #define AMDIOMMU_IGN6 0x0100 386 #define AMDIOMMU_PTE_NLVL_MASK 0x0e00 /* Next Level */ 387 #define AMDIOMMU_PTE_NLVL_SHIFT 9 388 #define AMDIOMMU_PTE_NLVL_7h 0x0e00 /* Magic Next Level */ 389 #define AMDIOMMU_PTE_PA_MASK 0x000ffffffffff000ull 390 #define AMDIOMMU_PTE_PA_SHIFT 12 391 #define AMDIOMMU_PTE_PMC_MASK 0x0600000000000000ull /* Page Migr */ 392 #define AMDIOMMU_PTE_U 0x0800000000000000ull /* ATS.U */ 393 #define AMDIOMMU_PTE_FC 0x1000000000000000ull /* Force Coh */ 394 #define AMDIOMMU_PTE_IR 0x2000000000000000ull /* Read Perm */ 395 #define AMDIOMMU_PTE_IW 0x4000000000000000ull /* Write Perm */ 396 #define AMDIOMMU_PTE_IGN7 0x8000000000000000ull 397 398 /* 399 * IRTEs 400 */ 401 402 /* vAPIC is not enabled, guestmode = 0 */ 403 struct amdiommu_irte_basic_novapic { 404 u_int remapen:1; /* 0 - Target Abort */ 405 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 406 u_int inttype:3; 407 u_int rqeoi:1; /* Request EOI */ 408 u_int dm:1; /* Dest Mode */ 409 u_int guestmode:1; /* MBZ */ 410 u_int dest:8; /* Destination APIC */ 411 u_int vector:8; 412 u_int rsrv:8; 413 } __packed; 414 _Static_assert(sizeof(struct amdiommu_irte_basic_novapic) == 415 1 * sizeof(uint32_t), "IRTE 1"); 416 417 /* vAPIC is enabled, guestmode = 0 */ 418 struct amdiommu_irte_basic_vapic { 419 u_int remapen:1; /* 0 - Target Abort */ 420 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 421 u_int inttype:3; 422 u_int rqeoi:1; /* Request EOI */ 423 u_int dm:1; /* Dest Mode */ 424 u_int guestmode:1; /* MBZ */ 425 u_int dest:8; /* Destination APIC */ 426 u_int rsrv0:16; 427 u_int rsrv1:32; 428 u_int vector:8; 429 u_int rsrv2:24; 430 u_int rsrv3:32; 431 } __packed; 432 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic) == 433 4 * sizeof(uint32_t), "IRTE 2"); 434 435 /* vAPIC is enabled, guestmode = 1 */ 436 struct amdiommu_irte_guest_vapic { 437 u_int remapen:1; /* 0 - Target Abort */ 438 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 439 u_int galogintr:1; 440 u_int rsrv0:2; 441 u_int gappidis:1; /* supress GAPPI */ 442 u_int isrun:1; /* Guest Running hint */ 443 u_int guestmode:1; /* MB1 */ 444 u_int dest:8; /* Destination APIC for dorbell */ 445 u_int rsrv1:16; 446 u_int gatag:32; 447 u_int vector:8; 448 u_int rsrv2:4; 449 uint64_t vapicrp:40; /* 51:12 bits of SPA for APIC backing page */ 450 u_int rsrv3:12; 451 } __packed; 452 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic) == 453 4 * sizeof(uint32_t), "IRTE 3"); 454 455 /* vAPIC is enabled, guestmode = 0, x2APIC */ 456 struct amdiommu_irte_basic_vapic_x2 { 457 u_int remapen:1; /* 0 - Target Abort */ 458 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 459 u_int inttype:3; 460 u_int rqeoi:1; /* Request EOI */ 461 u_int dm:1; /* Dest Mode */ 462 u_int guestmode:1; /* MBZ */ 463 u_int dest0:24; /* Destination APIC 23:0 */ 464 u_int rsrv0:32; 465 u_int vector:8; 466 u_int rsrv1:24; 467 u_int rsrv2:24; 468 u_int dest1:8; /* Destination APIC 31:24 */ 469 } __packed; 470 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic_x2) == 471 4 * sizeof(uint32_t), "IRTE 4"); 472 473 /* vAPIC is enabled, guestmode = 1, x2APIC */ 474 struct amdiommu_irte_guest_vapic_x2 { 475 u_int remapen:1; /* 0 - Target Abort */ 476 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 477 u_int galogintr:1; 478 u_int rsrv0:2; 479 u_int gappidis:1; /* supress GAPPI */ 480 u_int isrun:1; /* Guest Running hint */ 481 u_int guestmode:1; /* MB1 */ 482 u_int dest0:24; /* Destination APIC for dorbell 23:0 */ 483 u_int gatag:32; 484 u_int vector:8; 485 u_int rsrv2:4; 486 uint64_t vapicrp:40; /* 51:12 bits of SPA for APIC backing page */ 487 u_int rsrv3:4; 488 u_int dest1:8; /* Destination APIC 31:24 */ 489 } __packed; 490 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic_x2) == 491 4 * sizeof(uint32_t), "IRTE 5"); 492 493 #define AMDIOMMU_IRTE_INTTYPE_FIXED 0 494 #define AMDIOMMU_IRTE_INTTYPE_ARBITR 1 495 496 #define AMDIOMMU_IRTE_DM_LOGICAL 1 497 #define AMDIOMMU_IRTE_DM_PHYSICAL 1 498 499 /* 500 * Commands 501 */ 502 503 struct amdiommu_cmd_generic { 504 u_int w0:32; 505 union { 506 u_int ww1:32; 507 struct { 508 u_int w1:28; 509 u_int op:4; 510 }; 511 }; 512 u_int w2:32; 513 u_int w3:32; 514 } __packed; 515 _Static_assert(sizeof(struct amdiommu_cmd_generic) == 516 4 * sizeof(uint32_t), "CMD_GENERIC"); 517 518 #define AMDIOMMU_CMD_SZ_SHIFT 4 /* Shift for cmd count 519 to ring offset */ 520 #define AMDIOMMU_CMD_SZ sizeof(struct amdiommu_cmd_generic) 521 /* Command size */ 522 _Static_assert((1 << AMDIOMMU_CMD_SZ_SHIFT) == AMDIOMMU_CMD_SZ, 523 "CMD size shift"); 524 525 struct amdiommu_cmd_completion_wait { 526 u_int s:1; 527 u_int i:1; 528 u_int f:1; 529 u_int address0:29; /* Store Address 31:3 */ 530 u_int address1:20; /* Store Address 51:32 */ 531 u_int rsrv:8; 532 u_int op:4; 533 u_int data0:32; 534 u_int data1:32; 535 } __packed; 536 _Static_assert(sizeof(struct amdiommu_cmd_completion_wait) == 537 4 * sizeof(uint32_t), "CMD_COMPLETION_WAIT"); 538 539 struct amdiommu_cmd_invalidate_devtab_entry { 540 u_int devid:16; 541 u_int rsrv0:16; 542 u_int rsrv1:28; 543 u_int op:4; 544 u_int rsrv2:32; 545 u_int rsrv3:32; 546 } __packed; 547 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_devtab_entry) == 548 4 * sizeof(uint32_t), "CMD_INVALIDATE_DEVTAB_ENTRY"); 549 550 struct amdiommu_cmd_invalidate_iommu_pages { 551 u_int pasid:20; 552 u_int rsrv0:12; 553 u_int domainid:16; 554 u_int rsrv1:12; 555 u_int op:4; 556 u_int s:1; 557 u_int pde:1; 558 u_int gn:1; 559 u_int rsrv2:9; 560 uint64_t address:52; /* Address 63:12 */ 561 } __packed; 562 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_pages) == 563 4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_PAGES"); 564 565 struct amdiommu_cmd_invalidate_iotlb_pages { 566 u_int devid:16; 567 u_int pasid1:8; 568 u_int maxpend0:8; 569 u_int queueid:16; 570 u_int pasid0:8; 571 u_int pasid2:4; 572 u_int op:4; 573 u_int s:1; 574 u_int rsrv0:1; 575 u_int gn:1; 576 u_int rsrv1:1; 577 u_int type:2; 578 u_int rsrv2:6; 579 uint64_t address:52; /* Address 63:12 */ 580 } __packed; 581 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iotlb_pages) == 582 4 * sizeof(uint32_t), "CMD_INVALIDATE_IOTLB_PAGES"); 583 584 struct amdiommu_cmd_invalidate_interrupt_table { 585 u_int devid:16; 586 u_int rsrv0:16; 587 u_int rsrv1:28; 588 u_int op:4; 589 u_int rsrv2:32; 590 u_int rsrv3:32; 591 } __packed; 592 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_interrupt_table) == 593 4 * sizeof(uint32_t), "CMD_INVALIDATE_INTERRUPT_TABLE"); 594 595 struct amdiommu_cmd_prefetch_iommu_pages { 596 u_int devid:16; 597 u_int rsrv0:8; 598 u_int pfcount:8; 599 u_int pasid:20; 600 u_int rsrv1:8; 601 u_int op:4; 602 u_int s:1; 603 u_int rsrv2:1; 604 u_int gn:1; 605 u_int rsrv3:1; 606 u_int inval:1; /* Invalidate First */ 607 u_int rsrv4:7; 608 uint64_t address:52; /* Address 63:12 */ 609 } __packed; 610 _Static_assert(sizeof(struct amdiommu_cmd_prefetch_iommu_pages) == 611 4 * sizeof(uint32_t), "CMD_PREFETCH_IOMMU_PAGES"); 612 613 struct amdiommu_cmd_complete_ppr_request { 614 u_int devid:16; 615 u_int rsrv0:16; 616 u_int pasid:20; 617 u_int rsrv1:8; 618 u_int op:4; 619 u_int rsrv2:2; 620 u_int gn:1; 621 u_int rsrv3:29; 622 u_int compltag:16; 623 u_int rsrv4:16; 624 } __packed; 625 _Static_assert(sizeof(struct amdiommu_cmd_complete_ppr_request) == 626 4 * sizeof(uint32_t), "CMD_COMPLETE_PPR_REQUEST"); 627 628 struct amdiommu_cmd_invalidate_iommu_all { 629 u_int rsrv0:32; 630 u_int op:4; 631 u_int rsrv1:28; 632 u_int rsrv2:32; 633 u_int rsrv3:32; 634 } __packed; 635 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_all) == 636 4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_ALL"); 637 638 struct amdiommu_cmd_insert_guest_event { 639 u_int rsrv0:32; 640 u_int guestid:16; 641 u_int rsrv1:12; 642 u_int op:4; 643 u_int rsrv2:32; 644 u_int rsrv3:32; 645 } __packed; 646 _Static_assert(sizeof(struct amdiommu_cmd_insert_guest_event) == 647 4 * sizeof(uint32_t), "CMD_INSERT_GUEST_EVENT"); 648 649 struct amdiommu_cmd_reset_vmmio { 650 u_int guestid:16; 651 u_int rsrv0:11; 652 u_int all:1; 653 u_int rsrv1:3; 654 u_int vcmd:1; 655 u_int rsrv2:27; 656 u_int op:4; 657 u_int rsrv3:32; 658 u_int rsrv4:32; 659 } __packed; 660 _Static_assert(sizeof(struct amdiommu_cmd_reset_vmmio) == 661 4 * sizeof(uint32_t), "CMD_RESET_VMMIO"); 662 663 #define AMDIOMMU_CMD_COMPLETION_WAIT 0x1 664 #define AMDIOMMU_CMD_INVALIDATE_DEVTAB_ENTRY 0x2 665 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_PAGES 0x3 666 #define AMDIOMMU_CMD_INVALIDATE_IOTLB_PAGES 0x4 667 #define AMDIOMMU_CMD_INVALIDATE_INTERRUPT_TABLE 0x5 668 #define AMDIOMMU_CMD_PREFETCH_IOMMU_PAGES 0x6 669 #define AMDIOMMU_CMD_COMPLETE_PPR_REQUEST 0x7 670 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_ALL 0x8 671 #define AMDIOMMU_CMD_INSERT_GUEST_EVENT 0x9 672 #define AMDIOMMU_CMD_RESET_VMMIO 0xa 673 674 /* 675 * Logging 676 */ 677 struct amdiommu_event_generic { 678 u_int w0:32; 679 union { 680 u_int ww1:32; 681 struct { 682 u_int w1:28; 683 u_int code:4; 684 }; 685 }; 686 u_int w2:32; 687 u_int w3:32; 688 } __packed; 689 _Static_assert(sizeof(struct amdiommu_event_generic) == 690 4 * sizeof(uint32_t), "EVENT_GENERIC"); 691 692 #define AMDIOMMU_EV_SZ_SHIFT 4 /* Shift for event count 693 to ring offset */ 694 #define AMDIOMMU_EV_SZ sizeof(struct amdiommu_event_generic) 695 /* Event size */ 696 _Static_assert((1 << AMDIOMMU_EV_SZ_SHIFT) == AMDIOMMU_EV_SZ, 697 "Event size shift"); 698 699 struct amdiommu_event_ill_dev_table_entry { 700 u_int devid:16; 701 u_int pasid1:4; 702 u_int rsrv0:7; 703 u_int vnr:1; 704 u_int rsrv1:1; 705 u_int vevent:1; 706 u_int vptr:1; 707 u_int vcmd:1; 708 u_int pasid:16; 709 u_int gn:1; 710 u_int rsrv2:2; 711 u_int i:1; 712 u_int rsrv3:1; 713 u_int rw:1; 714 u_int rsrv4:1; 715 u_int rz:1; 716 u_int tr:1; 717 u_int rsrv5:3; 718 u_int code:4; 719 u_int rsrv6:2; 720 u_int addr1:30; 721 u_int addr2:32; 722 } __packed; 723 _Static_assert(sizeof(struct amdiommu_event_ill_dev_table_entry) == 724 4 * sizeof(uint32_t), "EVENT_ILLEGAL_DEV_TABLE_ENTRY"); 725 726 struct amdiommu_event_io_page_fault_entry { 727 u_int devid:16; 728 u_int pasid1:4; 729 u_int rsrv0:7; 730 u_int vnr:1; 731 u_int rsrv1:1; 732 u_int vevent:1; 733 u_int vptr:1; 734 u_int vcmd:1; 735 u_int pasid:16; /* also domain id */ 736 u_int gn:1; 737 u_int nx:1; 738 u_int us:1; 739 u_int i:1; 740 u_int pr:1; 741 u_int rw:1; 742 u_int pe:1; 743 u_int rz:1; 744 u_int tr:1; 745 u_int rsrv2:3; 746 u_int code:4; 747 u_int addr1:32; 748 u_int addr2:32; 749 } __packed; 750 _Static_assert(sizeof(struct amdiommu_event_io_page_fault_entry) == 751 4 * sizeof(uint32_t), "EVENT_IO_PAGE_FAULT_ENTRY"); 752 753 #define AMDIOMMU_EV_ILL_DEV_TABLE_ENTRY 0x1 754 #define AMDIOMMU_EV_IO_PAGE_FAULT 0x2 755 #define AMDIOMMU_EV_DEV_TAB_HW_ERROR 0x3 756 #define AMDIOMMU_EV_PAGE_TAB_HW_ERROR 0x4 757 #define AMDIOMMU_EV_ILL_CMD_ERROR 0x5 758 #define AMDIOMMU_EV_CMD_HW_ERROR 0x6 759 #define AMDIOMMU_EV_IOTLB_INV_TIMEOUT 0x7 760 #define AMDIOMMU_EV_INVALID_DEV_REQ 0x8 761 #define AMDIOMMU_EV_INVALID_PPR_REQ 0x9 762 #define AMDIOMMU_EV_COUNTER_ZERO 0xa /* Typo in table 42? */ 763 764 #endif /* __X86_IOMMU_AMD_REG_H */ 765