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_EPH_EN 0x0000200000000000ull /* Enh PPR Handling En */ 190 #define AMDIOMMU_CTRL_HADUP_MASK 0x0000c00000000000ull /* Access and Dirty in host PT */ 191 #define AMDIOMMU_CTRL_GDUP_DIS 0x0001000000000000ull /* Dis Dirty in guest PT */ 192 #define AMDIOMMU_CTRL_XT_EN 0x0004000000000000ull /* x2APIC mode */ 193 #define AMDIOMMU_CTRL_INTCAPXT_EN 0x0008000000000000ull /* x2APIC mode for IOMMU intrs */ 194 #define AMDIOMMU_CTRL_vCMD_EN 0x0010000000000000ull /* vCMD buffer proc En */ 195 #define AMDIOMMU_CTRL_vIOMMU_EN 0x0020000000000000ull /* vIOMMU En */ 196 #define AMDIOMMU_CTRL_GAUP_DIS 0x0040000000000000ull /* Dis Access in guest PT */ 197 #define AMDIOMMU_CTRL_GAPPI_EN 0x0080000000000000ull /* Guest APIC phys proc intr En */ 198 #define AMDIOMMU_CTRL_TMPM_EN 0x0100000000000000ull /* Tiered Mem Page Migration En */ 199 #define AMDIOMMU_CTRL_GGCR3TRP_PHYS 0x0400000000000000ull /* GCR3 is GPA (otherwise SPA) */ 200 #define AMDIOMMU_CTRL_IRTCACHE_DIS 0x0800000000000000ull /* IRT Caching Dis */ 201 #define AMDIOMMU_CTRL_GSTBUFTRP_MODE 0x1000000000000000ull /* See spec */ 202 #define AMDIOMMU_CTRL_SNPAVIC_MASK 0xe000000000000000ull /* MBZ */ 203 204 /* 205 * IOMMU Extended Feature Register AMDIOMMU_EFR fields 206 */ 207 #define AMDIOMMU_EFR_XT_SUP 0x0000000000000004ull /* x2APIC */ 208 #define AMDIOMMU_EFR_HWEV_SUP 0x0000000000000100ull /* HW Event regs */ 209 #define AMDIOMMU_EFR_PC_SUP 0x0000000000000200ull /* Perf counters */ 210 #define AMDIOMMU_EFR_HATS_MASK 0x0000000000000c00ull /* Host Addr Trans Size */ 211 #define AMDIOMMU_EFR_HATS_4LVL 0x0000000000000000ull 212 #define AMDIOMMU_EFR_HATS_5LVL 0x0000000000000400ull 213 #define AMDIOMMU_EFR_HATS_6LVL 0x0000000000000800ull 214 #define AMDIOMMU_EFR_DEVTBLSEG_MASK 0x000000c000000000ull /* DevTbl segmentation */ 215 #define AMDIOMMU_EFR_DEVTBLSEG_SHIFT 38 216 217 /* IOMMU Command Pointers (Head/Tail) registers fields */ 218 #define AMDIOMMU_CMDPTR_MASK 0x000000000007fff0ull 219 220 /* IOMMU Command Buffer Base fields */ 221 #define AMDIOMMU_CMDBUF_BASE_SZSHIFT 56 /* Shift for size */ 222 #define AMDIOMMU_CMDBUF_MAX (512 * 1024) 223 224 /* IOMMU Event Log Base register fields */ 225 #define AMDIOMMU_EVNTLOG_BASE_SZSHIFT 56 /* Shift for size */ 226 #define AMDIOMMU_EVNTLOG_MIN 256 227 #define AMDIOMMU_EVNTLOG_MAX 32768 228 229 /* IOMMU Hardware Event Status register fields */ 230 #define AMDIOMMU_HWEVS_HEV 0x00000001 /* HW Ev Valid */ 231 #define AMDIOMMU_HWEVS_HEO 0x00000002 /* HW Ev Overfl */ 232 233 /* 234 * IOMMU Command and Event Status register fields. 235 * From the spec, all defined bits are either RO or RW1C. As a consequence, 236 * single bit can be safely written to the register to clean a specific 237 * condition. 238 */ 239 #define AMDIOMMU_CMDEVS_EVOVRFLW 0x00000001 240 #define AMDIOMMU_CMDEVS_EVLOGINT 0x00000002 241 #define AMDIOMMU_CMDEVS_COMWAITINT 0x00000004 242 #define AMDIOMMU_CMDEVS_EVLOGRUN 0x00000008 243 #define AMDIOMMU_CMDEVS_CMDBUFRUN 0x00000010 244 #define AMDIOMMU_CMDEVS_PPROVRFLW 0x00000020 245 #define AMDIOMMU_CMDEVS_PPRINT 0x00000040 246 #define AMDIOMMU_CMDEVS_PPRLOGRUN 0x00000080 247 #define AMDIOMMU_CMDEVS_GALOGRUN 0x00000100 248 #define AMDIOMMU_CMDEVS_GALOVRFLW 0x00000200 249 #define AMDIOMMU_CMDEVS_GAINT 0x00000400 250 #define AMDIOMMU_CMDEVS_PPROVRFLWB 0x00000800 251 #define AMDIOMMU_CMDEVS_PPRLOGACTIVE 0x00001000 252 #define AMDIOMMU_CMDEVS_RESV1 0x00002000 253 #define AMDIOMMU_CMDEVS_RESV2 0x00004000 254 #define AMDIOMMU_CMDEVS_EVOVRFLWB 0x00008000 255 #define AMDIOMMU_CMDEVS_EVLOGACTIVE 0x00010000 256 #define AMDIOMMU_CMDEVS_PPROVRFLWEB 0x00020000 257 #define AMDIOMMU_CMDEVS_PPROVRFLWE 0x00040000 258 259 /* 260 * Device Table Entry (DTE) 261 */ 262 struct amdiommu_dte { 263 u_int v:1; /* Valid */ 264 u_int tv:1; /* Translation Valid */ 265 u_int rsrv0:5; 266 u_int had:2; /* Host Access Dirty */ 267 u_int pgmode:3; /* Paging Mode */ 268 uint64_t ptroot:40; /* Page Table Root */ 269 u_int ppr:1; /* PPR En */ 270 u_int gprp:1; /* Guest PPR Resp with PASID */ 271 u_int giov:1; /* Guest IO Prot Valid */ 272 u_int gv:1; /* Guest Translation Valid */ 273 u_int glx:2; /* Guest Levels Translated */ 274 u_int gcr3root0:3; /* GCR3 root pointer part */ 275 u_int ir:1; /* Read Perm */ 276 u_int iw:1; /* Write Perm */ 277 u_int rsrv1:1; 278 u_int domainid:16; /* domain tag */ 279 u_int gcr3root1:16; /* GCR3 root pointer part */ 280 u_int i:1; /* IOTLB En */ 281 u_int se:1; /* Suppress IO Fault Events */ 282 u_int sa:1; /* Suppress All IO Fault Events */ 283 u_int pioctl:2; /* Port IO Control */ 284 u_int cache:1; /* IOTLB Cache Hint */ 285 u_int sd:1; /* Snoop Disable */ 286 u_int ex:1; /* Allow Exclusion */ 287 u_int sysmgt:2; /* System Management Msg Handling */ 288 u_int sats:1; /* Secure/Non-secure ATS */ 289 u_int gcr3root2:21; /* GCR3 root pointer part */ 290 u_int iv:1; /* Intr Map Valid */ 291 u_int inttablen:4; /* log2 Intr Table Len */ 292 u_int ig:1; /* Ignore Unmapped Interrupts */ 293 uint64_t intrroot:46; /* Interrupt Table Root (-low 6bits) */ 294 u_int rsrv2:2; 295 u_int gpm:2; /* Guest Paging Mode */ 296 u_int initpass:1; /* INIT pass-through */ 297 u_int eintpass:1; /* ExtInt pass-through */ 298 u_int nmipass:1; /* NMI pass-through */ 299 u_int hptmode:1; /* Host Page Table Mode Hint */ 300 u_int intctl:2; /* Interrupt Control */ 301 u_int lint0pass:1; /* LINT0 pass-through */ 302 u_int lint1pass:1; /* LINT1 pass-through */ 303 u_int rsrv3:15; 304 u_int vimu:1; /* Virtualize IOMMU En */ 305 u_int gdevid:16; /* Guest Dev Id */ 306 u_int gid:16; /* Guest Id */ 307 u_int rsrv4:5; 308 u_int rsrv5:1; /* Not Checked, sw avail */ 309 u_int attrv:1; /* Attr Override Valid */ 310 u_int mode0fc:1; /* Replace for PTE.FC */ 311 u_int snoopattr:8; /* GuestPTE.PAT -> ATS.N xlat */ 312 } __packed; 313 _Static_assert(sizeof(struct amdiommu_dte) == 8 * sizeof(uint32_t), "DTE"); 314 315 #define AMDIOMMU_DTE_HAD_NAND 0x0 /* No Access, No Dirty */ 316 #define AMDIOMMU_DTE_HAD_AND 0x1 /* Access, No Dirty */ 317 #define AMDIOMMU_DTE_HAD_RSRV 0x2 318 #define AMDIOMMU_DTE_HAD_AD 0x3 /* Access, Dirty */ 319 320 #define AMDIOMMU_DTE_PGMODE_1T1 0x0 /* SPA = GPA */ 321 #define AMDIOMMU_DTE_PGMODE_1LV 0x1 /* 1 Level PT */ 322 #define AMDIOMMU_DTE_PGMODE_2LV 0x2 /* 2 Level PT */ 323 #define AMDIOMMU_DTE_PGMODE_3LV 0x3 /* 3 Level PT */ 324 #define AMDIOMMU_DTE_PGMODE_4LV 0x4 /* 4 Level PT */ 325 #define AMDIOMMU_DTE_PGMODE_5LV 0x5 /* 5 Level PT */ 326 #define AMDIOMMU_DTE_PGMODE_6LV 0x6 /* 6 Level PT */ 327 #define AMDIOMMU_DTE_PGMODE_RSRV 0x7 328 329 #define AMDIOMMU_DTE_GLX_1LV 0x0 /* 1 Level GCR3 */ 330 #define AMDIOMMU_DTE_GLX_2LV 0x1 /* 2 Level GCR3 */ 331 #define AMDIOMMU_DTE_GLX_3LV 0x2 /* 3 Level GCR3 */ 332 #define AMDIOMMU_DTE_GLX_RSRV 0x3 333 334 #define AMDIOMMU_DTE_PIOCTL_DIS 0x0 335 #define AMDIOMMU_DTE_PIOCTL_EN 0x1 336 #define AMDIOMMU_DTE_PIOCTL_MAP 0x2 337 #define AMDIOMMU_DTE_PIOCTL_RSRV 0x3 338 339 #define AMDIOMMU_DTE_SYSMGT_DIS 0x0 /* Target Abort */ 340 #define AMDIOMMU_DTE_SYSMGT_FW 0x0 /* Forwarded All */ 341 #define AMDIOMMU_DTE_SYSMGT_FWI 0x0 /* Forwarded INT */ 342 #define AMDIOMMU_DTE_SYSMGT_T 0x0 /* Translated */ 343 344 #define AMDIOMMU_DTE_GPM_4LV 0x0 /* 4 Level */ 345 #define AMDIOMMU_DTE_GPM_5LV 0x1 /* 5 Level */ 346 #define AMDIOMMU_DTE_GPM_RSRV1 0x2 347 #define AMDIOMMU_DTE_GPM_RSRV2 0x3 348 349 #define AMDIOMMU_DTE_INTCTL_DIS 0x0 /* Target Abort */ 350 #define AMDIOMMU_DTE_INTCTL_FW 0x1 /* Forward Unmapped */ 351 #define AMDIOMMU_DTE_INTCTL_MAP 0x2 /* Forward Remapped */ 352 #define AMDIOMMU_DTE_INTCTL_RSRV 0x3 353 354 #define AMDIOMMU_PGTBL_MAXLVL 6 355 356 /* 357 * Page Table Entry (PTE/PDE) 358 */ 359 #define AMDIOMMU_PTE_PR 0x0001 /* Present, AKA V */ 360 #define AMDIOMMU_IGN1 0x0002 361 #define AMDIOMMU_IGN2 0x0004 362 #define AMDIOMMU_IGN3 0x0008 363 #define AMDIOMMU_IGN4 0x0010 364 #define AMDIOMMU_PTE_A 0x0020 /* Accessed */ 365 #define AMDIOMMU_PTE_D 0x0040 /* Dirty */ 366 #define AMDIOMMU_IGN5 0x0080 367 #define AMDIOMMU_IGN6 0x0100 368 #define AMDIOMMU_PTE_NLVL_MASK 0x0e00 /* Next Level */ 369 #define AMDIOMMU_PTE_NLVL_SHIFT 9 370 #define AMDIOMMU_PTE_NLVL_7h 0x0e00 /* Magic Next Level */ 371 #define AMDIOMMU_PTE_PA_MASK 0x000ffffffffff000ull 372 #define AMDIOMMU_PTE_PA_SHIFT 12 373 #define AMDIOMMU_PTE_PMC_MASK 0x0600000000000000ull /* Page Migr */ 374 #define AMDIOMMU_PTE_U 0x0800000000000000ull /* ATS.U */ 375 #define AMDIOMMU_PTE_FC 0x1000000000000000ull /* Force Coh */ 376 #define AMDIOMMU_PTE_IR 0x2000000000000000ull /* Read Perm */ 377 #define AMDIOMMU_PTE_IW 0x4000000000000000ull /* Write Perm */ 378 #define AMDIOMMU_PTE_IGN7 0x8000000000000000ull 379 380 /* 381 * IRTEs 382 */ 383 384 /* vAPIC is not enabled, guestmode = 0 */ 385 struct amdiommu_irte_basic_novapic { 386 u_int remapen:1; /* 0 - Target Abort */ 387 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 388 u_int inttype:3; 389 u_int rqeoi:1; /* Request EOI */ 390 u_int dm:1; /* Dest Mode */ 391 u_int guestmode:1; /* MBZ */ 392 u_int dest:8; /* Destination APIC */ 393 u_int vector:8; 394 u_int rsrv:8; 395 } __packed; 396 _Static_assert(sizeof(struct amdiommu_irte_basic_novapic) == 397 1 * sizeof(uint32_t), "IRTE 1"); 398 399 /* vAPIC is enabled, guestmode = 0 */ 400 struct amdiommu_irte_basic_vapic { 401 u_int remapen:1; /* 0 - Target Abort */ 402 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 403 u_int inttype:3; 404 u_int rqeoi:1; /* Request EOI */ 405 u_int dm:1; /* Dest Mode */ 406 u_int guestmode:1; /* MBZ */ 407 u_int dest:8; /* Destination APIC */ 408 u_int rsrv0:16; 409 u_int rsrv1:32; 410 u_int vector:8; 411 u_int rsrv2:24; 412 u_int rsrv3:32; 413 } __packed; 414 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic) == 415 4 * sizeof(uint32_t), "IRTE 2"); 416 417 /* vAPIC is enabled, guestmode = 1 */ 418 struct amdiommu_irte_guest_vapic { 419 u_int remapen:1; /* 0 - Target Abort */ 420 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 421 u_int galogintr:1; 422 u_int rsrv0:2; 423 u_int gappidis:1; /* supress GAPPI */ 424 u_int isrun:1; /* Guest Running hint */ 425 u_int guestmode:1; /* MB1 */ 426 u_int dest:8; /* Destination APIC for dorbell */ 427 u_int rsrv1:16; 428 u_int gatag:32; 429 u_int vector:8; 430 u_int rsrv2:4; 431 uint64_t vapicrp:40; /* 51:12 bits of SPA for APIC backing page */ 432 u_int rsrv3:12; 433 } __packed; 434 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic) == 435 4 * sizeof(uint32_t), "IRTE 3"); 436 437 /* vAPIC is enabled, guestmode = 0, x2APIC */ 438 struct amdiommu_irte_basic_vapic_x2 { 439 u_int remapen:1; /* 0 - Target Abort */ 440 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 441 u_int inttype:3; 442 u_int rqeoi:1; /* Request EOI */ 443 u_int dm:1; /* Dest Mode */ 444 u_int guestmode:1; /* MBZ */ 445 u_int dest0:24; /* Destination APIC 23:0 */ 446 u_int rsrv0:32; 447 u_int vector:8; 448 u_int rsrv1:24; 449 u_int rsrv2:24; 450 u_int dest1:8; /* Destination APIC 31:24 */ 451 } __packed; 452 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic_x2) == 453 4 * sizeof(uint32_t), "IRTE 4"); 454 455 /* vAPIC is enabled, guestmode = 1, x2APIC */ 456 struct amdiommu_irte_guest_vapic_x2 { 457 u_int remapen:1; /* 0 - Target Abort */ 458 u_int supiopf:1; /* Supress IO_PAGE_FAULT events */ 459 u_int galogintr:1; 460 u_int rsrv0:2; 461 u_int gappidis:1; /* supress GAPPI */ 462 u_int isrun:1; /* Guest Running hint */ 463 u_int guestmode:1; /* MB1 */ 464 u_int dest0:24; /* Destination APIC for dorbell 23:0 */ 465 u_int gatag:32; 466 u_int vector:8; 467 u_int rsrv2:4; 468 uint64_t vapicrp:40; /* 51:12 bits of SPA for APIC backing page */ 469 u_int rsrv3:4; 470 u_int dest1:8; /* Destination APIC 31:24 */ 471 } __packed; 472 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic_x2) == 473 4 * sizeof(uint32_t), "IRTE 5"); 474 475 #define AMDIOMMU_IRTE_INTTYPE_FIXED 0 476 #define AMDIOMMU_IRTE_INTTYPE_ARBITR 1 477 478 #define AMDIOMMU_IRTE_DM_LOGICAL 1 479 #define AMDIOMMU_IRTE_DM_PHYSICAL 1 480 481 /* 482 * Commands 483 */ 484 485 struct amdiommu_cmd_generic { 486 u_int w0:32; 487 union { 488 u_int ww1:32; 489 struct { 490 u_int w1:28; 491 u_int op:4; 492 }; 493 }; 494 u_int w2:32; 495 u_int w3:32; 496 } __packed; 497 _Static_assert(sizeof(struct amdiommu_cmd_generic) == 498 4 * sizeof(uint32_t), "CMD_GENERIC"); 499 500 #define AMDIOMMU_CMD_SZ_SHIFT 4 /* Shift for cmd count 501 to ring offset */ 502 #define AMDIOMMU_CMD_SZ sizeof(struct amdiommu_cmd_generic) 503 /* Command size */ 504 _Static_assert((1 << AMDIOMMU_CMD_SZ_SHIFT) == AMDIOMMU_CMD_SZ, 505 "CMD size shift"); 506 507 struct amdiommu_cmd_completion_wait { 508 u_int s:1; 509 u_int i:1; 510 u_int f:1; 511 u_int address0:29; /* Store Address 31:3 */ 512 u_int address1:20; /* Store Address 51:32 */ 513 u_int rsrv:8; 514 u_int op:4; 515 u_int data0:32; 516 u_int data1:32; 517 } __packed; 518 _Static_assert(sizeof(struct amdiommu_cmd_completion_wait) == 519 4 * sizeof(uint32_t), "CMD_COMPLETION_WAIT"); 520 521 struct amdiommu_cmd_invalidate_devtab_entry { 522 u_int devid:16; 523 u_int rsrv0:16; 524 u_int rsrv1:28; 525 u_int op:4; 526 u_int rsrv2:32; 527 u_int rsrv3:32; 528 } __packed; 529 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_devtab_entry) == 530 4 * sizeof(uint32_t), "CMD_INVALIDATE_DEVTAB_ENTRY"); 531 532 struct amdiommu_cmd_invalidate_iommu_pages { 533 u_int pasid:20; 534 u_int rsrv0:12; 535 u_int domainid:16; 536 u_int rsrv1:12; 537 u_int op:4; 538 u_int s:1; 539 u_int pde:1; 540 u_int gn:1; 541 u_int rsrv2:9; 542 uint64_t address:52; /* Address 63:12 */ 543 } __packed; 544 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_pages) == 545 4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_PAGES"); 546 547 struct amdiommu_cmd_invalidate_iotlb_pages { 548 u_int devid:16; 549 u_int pasid1:8; 550 u_int maxpend0:8; 551 u_int queueid:16; 552 u_int pasid0:8; 553 u_int pasid2:4; 554 u_int op:4; 555 u_int s:1; 556 u_int rsrv0:1; 557 u_int gn:1; 558 u_int rsrv1:1; 559 u_int type:2; 560 u_int rsrv2:6; 561 uint64_t address:52; /* Address 63:12 */ 562 } __packed; 563 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iotlb_pages) == 564 4 * sizeof(uint32_t), "CMD_INVALIDATE_IOTLB_PAGES"); 565 566 struct amdiommu_cmd_invalidate_interrupt_table { 567 u_int devid:16; 568 u_int rsrv0:16; 569 u_int rsrv1:28; 570 u_int op:4; 571 u_int rsrv2:32; 572 u_int rsrv3:32; 573 } __packed; 574 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_interrupt_table) == 575 4 * sizeof(uint32_t), "CMD_INVALIDATE_INTERRUPT_TABLE"); 576 577 struct amdiommu_cmd_prefetch_iommu_pages { 578 u_int devid:16; 579 u_int rsrv0:8; 580 u_int pfcount:8; 581 u_int pasid:20; 582 u_int rsrv1:8; 583 u_int op:4; 584 u_int s:1; 585 u_int rsrv2:1; 586 u_int gn:1; 587 u_int rsrv3:1; 588 u_int inval:1; /* Invalidate First */ 589 u_int rsrv4:7; 590 uint64_t address:52; /* Address 63:12 */ 591 } __packed; 592 _Static_assert(sizeof(struct amdiommu_cmd_prefetch_iommu_pages) == 593 4 * sizeof(uint32_t), "CMD_PREFETCH_IOMMU_PAGES"); 594 595 struct amdiommu_cmd_complete_ppr_request { 596 u_int devid:16; 597 u_int rsrv0:16; 598 u_int pasid:20; 599 u_int rsrv1:8; 600 u_int op:4; 601 u_int rsrv2:2; 602 u_int gn:1; 603 u_int rsrv3:29; 604 u_int compltag:16; 605 u_int rsrv4:16; 606 } __packed; 607 _Static_assert(sizeof(struct amdiommu_cmd_complete_ppr_request) == 608 4 * sizeof(uint32_t), "CMD_COMPLETE_PPR_REQUEST"); 609 610 struct amdiommu_cmd_invalidate_iommu_all { 611 u_int rsrv0:32; 612 u_int op:4; 613 u_int rsrv1:28; 614 u_int rsrv2:32; 615 u_int rsrv3:32; 616 } __packed; 617 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_all) == 618 4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_ALL"); 619 620 struct amdiommu_cmd_insert_guest_event { 621 u_int rsrv0:32; 622 u_int guestid:16; 623 u_int rsrv1:12; 624 u_int op:4; 625 u_int rsrv2:32; 626 u_int rsrv3:32; 627 } __packed; 628 _Static_assert(sizeof(struct amdiommu_cmd_insert_guest_event) == 629 4 * sizeof(uint32_t), "CMD_INSERT_GUEST_EVENT"); 630 631 struct amdiommu_cmd_reset_vmmio { 632 u_int guestid:16; 633 u_int rsrv0:11; 634 u_int all:1; 635 u_int rsrv1:3; 636 u_int vcmd:1; 637 u_int rsrv2:27; 638 u_int op:4; 639 u_int rsrv3:32; 640 u_int rsrv4:32; 641 } __packed; 642 _Static_assert(sizeof(struct amdiommu_cmd_reset_vmmio) == 643 4 * sizeof(uint32_t), "CMD_RESET_VMMIO"); 644 645 #define AMDIOMMU_CMD_COMPLETION_WAIT 0x1 646 #define AMDIOMMU_CMD_INVALIDATE_DEVTAB_ENTRY 0x2 647 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_PAGES 0x3 648 #define AMDIOMMU_CMD_INVALIDATE_IOTLB_PAGES 0x4 649 #define AMDIOMMU_CMD_INVALIDATE_INTERRUPT_TABLE 0x5 650 #define AMDIOMMU_CMD_PREFETCH_IOMMU_PAGES 0x6 651 #define AMDIOMMU_CMD_COMPLETE_PPR_REQUEST 0x7 652 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_ALL 0x8 653 #define AMDIOMMU_CMD_INSERT_GUEST_EVENT 0x9 654 #define AMDIOMMU_CMD_RESET_VMMIO 0xa 655 656 /* 657 * Logging 658 */ 659 struct amdiommu_event_generic { 660 u_int w0:32; 661 union { 662 u_int ww1:32; 663 struct { 664 u_int w1:28; 665 u_int code:4; 666 }; 667 }; 668 u_int w2:32; 669 u_int w3:32; 670 } __packed; 671 _Static_assert(sizeof(struct amdiommu_event_generic) == 672 4 * sizeof(uint32_t), "EVENT_GENERIC"); 673 674 #define AMDIOMMU_EV_SZ_SHIFT 4 /* Shift for event count 675 to ring offset */ 676 #define AMDIOMMU_EV_SZ sizeof(struct amdiommu_event_generic) 677 /* Event size */ 678 _Static_assert((1 << AMDIOMMU_EV_SZ_SHIFT) == AMDIOMMU_EV_SZ, 679 "Event size shift"); 680 681 struct amdiommu_event_ill_dev_table_entry { 682 u_int devid:16; 683 u_int pasid1:4; 684 u_int rsrv0:7; 685 u_int vnr:1; 686 u_int rsrv1:1; 687 u_int vevent:1; 688 u_int vptr:1; 689 u_int vcmd:1; 690 u_int pasid:16; 691 u_int gn:1; 692 u_int rsrv2:2; 693 u_int i:1; 694 u_int rsrv3:1; 695 u_int rw:1; 696 u_int rsrv4:1; 697 u_int rz:1; 698 u_int tr:1; 699 u_int rsrv5:3; 700 u_int code:4; 701 u_int rsrv6:2; 702 u_int addr1:30; 703 u_int addr2:32; 704 } __packed; 705 _Static_assert(sizeof(struct amdiommu_event_ill_dev_table_entry) == 706 4 * sizeof(uint32_t), "EVENT_ILLEGAL_DEV_TABLE_ENTRY"); 707 708 struct amdiommu_event_io_page_fault_entry { 709 u_int devid:16; 710 u_int pasid1:4; 711 u_int rsrv0:7; 712 u_int vnr:1; 713 u_int rsrv1:1; 714 u_int vevent:1; 715 u_int vptr:1; 716 u_int vcmd:1; 717 u_int pasid:16; /* also domain id */ 718 u_int gn:1; 719 u_int nx:1; 720 u_int us:1; 721 u_int i:1; 722 u_int pr:1; 723 u_int rw:1; 724 u_int pe:1; 725 u_int rz:1; 726 u_int tr:1; 727 u_int rsrv2:3; 728 u_int code:4; 729 u_int addr1:32; 730 u_int addr2:32; 731 } __packed; 732 _Static_assert(sizeof(struct amdiommu_event_io_page_fault_entry) == 733 4 * sizeof(uint32_t), "EVENT_IO_PAGE_FAULT_ENTRY"); 734 735 #define AMDIOMMU_EV_ILL_DEV_TABLE_ENTRY 0x1 736 #define AMDIOMMU_EV_IO_PAGE_FAULT 0x2 737 #define AMDIOMMU_EV_DEV_TAB_HW_ERROR 0x3 738 #define AMDIOMMU_EV_PAGE_TAB_HW_ERROR 0x4 739 #define AMDIOMMU_EV_ILL_CMD_ERROR 0x5 740 #define AMDIOMMU_EV_CMD_HW_ERROR 0x6 741 #define AMDIOMMU_EV_IOTLB_INV_TIMEOUT 0x7 742 #define AMDIOMMU_EV_INVALID_DEV_REQ 0x8 743 #define AMDIOMMU_EV_INVALID_PPR_REQ 0x9 744 #define AMDIOMMU_EV_COUNTER_ZERO 0xa /* Typo in table 42? */ 745 746 #endif /* __X86_IOMMU_AMD_REG_H */ 747