1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2016 Anish Gupta (anish@freebsd.org) 5 * Copyright (c) 2021 The FreeBSD Foundation 6 * 7 * Portions of this software were developed by Ka Ho Ng 8 * under sponsorship from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice unmodified, this list of conditions, and the following 15 * disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 #ifndef _AMDVI_PRIV_H_ 35 #define _AMDVI_PRIV_H_ 36 37 #include <contrib/dev/acpica/include/acpi.h> 38 39 #define BIT(n) (1ULL << (n)) 40 /* Return value of bits[n:m] where n and (n >= ) m are bit positions. */ 41 #define REG_BITS(x, n, m) (((x) >> (m)) & \ 42 ((1 << (((n) - (m)) + 1)) - 1)) 43 44 /* 45 * IOMMU PCI capability. 46 */ 47 #define AMDVI_PCI_CAP_IOTLB BIT(0) /* IOTLB is supported. */ 48 #define AMDVI_PCI_CAP_HT BIT(1) /* HyperTransport tunnel support. */ 49 #define AMDVI_PCI_CAP_NPCACHE BIT(2) /* Not present page cached. */ 50 #define AMDVI_PCI_CAP_EFR BIT(3) /* Extended features. */ 51 #define AMDVI_PCI_CAP_EXT BIT(4) /* Miscellaneous information reg. */ 52 53 /* 54 * IOMMU extended features. 55 */ 56 #define AMDVI_EX_FEA_PREFSUP BIT(0) /* Prefetch command support. */ 57 #define AMDVI_EX_FEA_PPRSUP BIT(1) /* PPR support */ 58 #define AMDVI_EX_FEA_XTSUP BIT(2) /* Reserved */ 59 #define AMDVI_EX_FEA_NXSUP BIT(3) /* No-execute. */ 60 #define AMDVI_EX_FEA_GTSUP BIT(4) /* Guest translation support. */ 61 #define AMDVI_EX_FEA_EFRW BIT(5) /* Reserved */ 62 #define AMDVI_EX_FEA_IASUP BIT(6) /* Invalidate all command supp. */ 63 #define AMDVI_EX_FEA_GASUP BIT(7) /* Guest APIC or AVIC support. */ 64 #define AMDVI_EX_FEA_HESUP BIT(8) /* Hardware Error. */ 65 #define AMDVI_EX_FEA_PCSUP BIT(9) /* Performance counters support. */ 66 /* XXX: add more EFER bits. */ 67 68 /* 69 * Device table entry or DTE 70 * NOTE: Must be 256-bits/32 bytes aligned. 71 */ 72 struct amdvi_dte { 73 uint32_t dt_valid:1; /* Device Table valid. */ 74 uint32_t pt_valid:1; /* Page translation valid. */ 75 uint16_t :7; /* Reserved[8:2] */ 76 uint8_t pt_level:3; /* Paging level, 0 to disable. */ 77 uint64_t pt_base:40; /* Page table root pointer. */ 78 uint8_t :3; /* Reserved[54:52] */ 79 uint8_t gv_valid:1; /* Revision 2, GVA to SPA. */ 80 uint8_t gv_level:2; /* Revision 2, GLX level. */ 81 uint8_t gv_cr3_lsb:3; /* Revision 2, GCR3[14:12] */ 82 uint8_t read_allow:1; /* I/O read enabled. */ 83 uint8_t write_allow:1; /* I/O write enabled. */ 84 uint8_t :1; /* Reserved[63] */ 85 uint16_t domain_id:16; /* Domain ID */ 86 uint16_t gv_cr3_lsb2:16; /* Revision 2, GCR3[30:15] */ 87 uint8_t iotlb_enable:1; /* Device support IOTLB */ 88 uint8_t sup_second_io_fault:1; /* Suppress subsequent I/O faults. */ 89 uint8_t sup_all_io_fault:1; /* Suppress all I/O page faults. */ 90 uint8_t IOctl:2; /* Port I/O control. */ 91 uint8_t iotlb_cache_disable:1; /* IOTLB cache hints. */ 92 uint8_t snoop_disable:1; /* Snoop disable. */ 93 uint8_t allow_ex:1; /* Allow exclusion. */ 94 uint8_t sysmgmt:2; /* System management message.*/ 95 uint8_t :1; /* Reserved[106] */ 96 uint32_t gv_cr3_msb:21; /* Revision 2, GCR3[51:31] */ 97 uint8_t intmap_valid:1; /* Interrupt map valid. */ 98 uint8_t intmap_len:4; /* Interrupt map table length. */ 99 uint8_t intmap_ign:1; /* Ignore unmapped interrupts. */ 100 uint64_t intmap_base:46; /* IntMap base. */ 101 uint8_t :4; /* Reserved[183:180] */ 102 uint8_t init_pass:1; /* INIT pass through or PT */ 103 uint8_t extintr_pass:1; /* External Interrupt PT */ 104 uint8_t nmi_pass:1; /* NMI PT */ 105 uint8_t :1; /* Reserved[187] */ 106 uint8_t intr_ctrl:2; /* Interrupt control */ 107 uint8_t lint0_pass:1; /* LINT0 PT */ 108 uint8_t lint1_pass:1; /* LINT1 PT */ 109 uint64_t :64; /* Reserved[255:192] */ 110 } __attribute__((__packed__)); 111 CTASSERT(sizeof(struct amdvi_dte) == 32); 112 113 /* 114 * IOMMU command entry. 115 */ 116 struct amdvi_cmd { 117 uint32_t word0; 118 uint32_t word1:28; 119 uint8_t opcode:4; 120 uint64_t addr; 121 } __attribute__((__packed__)); 122 123 /* Command opcodes. */ 124 #define AMDVI_CMP_WAIT_OPCODE 0x1 /* Completion wait. */ 125 #define AMDVI_INVD_DTE_OPCODE 0x2 /* Invalidate device table entry. */ 126 #define AMDVI_INVD_PAGE_OPCODE 0x3 /* Invalidate pages. */ 127 #define AMDVI_INVD_IOTLB_OPCODE 0x4 /* Invalidate IOTLB pages. */ 128 #define AMDVI_INVD_INTR_OPCODE 0x5 /* Invalidate Interrupt table. */ 129 #define AMDVI_PREFETCH_PAGES_OPCODE 0x6 /* Prefetch IOMMU pages. */ 130 #define AMDVI_COMP_PPR_OPCODE 0x7 /* Complete PPR request. */ 131 #define AMDVI_INV_ALL_OPCODE 0x8 /* Invalidate all. */ 132 133 /* Completion wait attributes. */ 134 #define AMDVI_CMP_WAIT_STORE BIT(0) /* Write back data. */ 135 #define AMDVI_CMP_WAIT_INTR BIT(1) /* Completion wait interrupt. */ 136 #define AMDVI_CMP_WAIT_FLUSH BIT(2) /* Flush queue. */ 137 138 /* Invalidate page. */ 139 #define AMDVI_INVD_PAGE_S BIT(0) /* Invalidation size. */ 140 #define AMDVI_INVD_PAGE_PDE BIT(1) /* Invalidate PDE. */ 141 #define AMDVI_INVD_PAGE_GN_GVA BIT(2) /* GPA or GVA. */ 142 143 #define AMDVI_INVD_PAGE_ALL_ADDR (0x7FFFFFFFFFFFFULL << 12) 144 145 /* Invalidate IOTLB. */ 146 #define AMDVI_INVD_IOTLB_S BIT(0) /* Invalidation size 4k or addr */ 147 #define AMDVI_INVD_IOTLB_GN_GVA BIT(2) /* GPA or GVA. */ 148 149 #define AMDVI_INVD_IOTLB_ALL_ADDR (0x7FFFFFFFFFFFFULL << 12) 150 /* XXX: add more command entries. */ 151 152 /* 153 * IOMMU event entry. 154 */ 155 struct amdvi_event { 156 uint16_t devid; 157 uint16_t pasid_hi; 158 uint16_t pasid_domid; /* PASID low or DomainID */ 159 uint16_t flag:12; 160 uint8_t opcode:4; 161 uint64_t addr; 162 } __attribute__((__packed__)); 163 CTASSERT(sizeof(struct amdvi_event) == 16); 164 165 /* Various event types. */ 166 #define AMDVI_EVENT_INVALID_DTE 0x1 167 #define AMDVI_EVENT_PFAULT 0x2 168 #define AMDVI_EVENT_DTE_HW_ERROR 0x3 169 #define AMDVI_EVENT_PAGE_HW_ERROR 0x4 170 #define AMDVI_EVENT_ILLEGAL_CMD 0x5 171 #define AMDVI_EVENT_CMD_HW_ERROR 0x6 172 #define AMDVI_EVENT_IOTLB_TIMEOUT 0x7 173 #define AMDVI_EVENT_INVALID_DTE_REQ 0x8 174 #define AMDVI_EVENT_INVALID_PPR_REQ 0x9 175 #define AMDVI_EVENT_COUNTER_ZERO 0xA 176 177 #define AMDVI_EVENT_FLAG_MASK 0x1FF /* Mask for event flags. */ 178 #define AMDVI_EVENT_FLAG_TYPE(x) (((x) >> 9) & 0x3) 179 180 /* 181 * IOMMU control block. 182 */ 183 struct amdvi_ctrl { 184 struct { 185 uint16_t size:9; 186 uint16_t :3; 187 uint64_t base:40; /* Devtable register base. */ 188 uint16_t :12; 189 } dte; 190 struct { 191 uint16_t :12; 192 uint64_t base:40; 193 uint8_t :4; 194 uint8_t len:4; 195 uint8_t :4; 196 } cmd; 197 struct { 198 uint16_t :12; 199 uint64_t base:40; 200 uint8_t :4; 201 uint8_t len:4; 202 uint8_t :4; 203 } event; 204 uint16_t control :13; 205 uint64_t :51; 206 struct { 207 uint8_t enable:1; 208 uint8_t allow:1; 209 uint16_t :10; 210 uint64_t base:40; 211 uint16_t :12; 212 uint16_t :12; 213 uint64_t limit:40; 214 uint16_t :12; 215 } excl; 216 /* 217 * Revision 2 only. 218 */ 219 uint64_t ex_feature; 220 struct { 221 uint16_t :12; 222 uint64_t base:40; 223 uint8_t :4; 224 uint8_t len:4; 225 uint8_t :4; 226 } ppr; 227 uint64_t first_event; 228 uint64_t second_event; 229 uint64_t event_status; 230 /* Revision 2 only, end. */ 231 uint8_t pad1[0x1FA8]; /* Padding. */ 232 uint32_t cmd_head:19; 233 uint64_t :45; 234 uint32_t cmd_tail:19; 235 uint64_t :45; 236 uint32_t evt_head:19; 237 uint64_t :45; 238 uint32_t evt_tail:19; 239 uint64_t :45; 240 uint32_t status:19; 241 uint64_t :45; 242 uint64_t pad2; 243 uint8_t :4; 244 uint16_t ppr_head:15; 245 uint64_t :45; 246 uint8_t :4; 247 uint16_t ppr_tail:15; 248 uint64_t :45; 249 uint8_t pad3[0x1FC0]; /* Padding. */ 250 251 /* XXX: More for rev2. */ 252 } __attribute__((__packed__)); 253 CTASSERT(offsetof(struct amdvi_ctrl, pad1)== 0x58); 254 CTASSERT(offsetof(struct amdvi_ctrl, pad2)== 0x2028); 255 CTASSERT(offsetof(struct amdvi_ctrl, pad3)== 0x2040); 256 257 #define AMDVI_MMIO_V1_SIZE (4 * PAGE_SIZE) /* v1 size */ 258 /* 259 * AMF IOMMU v2 size including event counters 260 */ 261 #define AMDVI_MMIO_V2_SIZE (8 * PAGE_SIZE) 262 263 CTASSERT(sizeof(struct amdvi_ctrl) == 0x4000); 264 CTASSERT(sizeof(struct amdvi_ctrl) == AMDVI_MMIO_V1_SIZE); 265 266 /* IVHD flag */ 267 #define IVHD_FLAG_HTT BIT(0) /* Hypertransport Tunnel. */ 268 #define IVHD_FLAG_PPW BIT(1) /* Pass posted write. */ 269 #define IVHD_FLAG_RPPW BIT(2) /* Response pass posted write. */ 270 #define IVHD_FLAG_ISOC BIT(3) /* Isoc support. */ 271 #define IVHD_FLAG_IOTLB BIT(4) /* IOTLB support. */ 272 #define IVHD_FLAG_COH BIT(5) /* Coherent control, default 1 */ 273 #define IVHD_FLAG_PFS BIT(6) /* Prefetch IOMMU pages. */ 274 #define IVHD_FLAG_PPRS BIT(7) /* Peripheral page support. */ 275 276 /* IVHD device entry data setting. */ 277 #define IVHD_DEV_LINT0_PASS BIT(6) /* LINT0 interrupts. */ 278 #define IVHD_DEV_LINT1_PASS BIT(7) /* LINT1 interrupts. */ 279 280 /* Bit[5:4] for System Mgmt. Bit3 is reserved. */ 281 #define IVHD_DEV_INIT_PASS BIT(0) /* INIT */ 282 #define IVHD_DEV_EXTINTR_PASS BIT(1) /* ExtInt */ 283 #define IVHD_DEV_NMI_PASS BIT(2) /* NMI */ 284 285 /* IVHD 8-byte extended data settings. */ 286 #define IVHD_DEV_EXT_ATS_DISABLE BIT(31) /* Disable ATS */ 287 288 /* IOMMU control register. */ 289 #define AMDVI_CTRL_EN BIT(0) /* IOMMU enable. */ 290 #define AMDVI_CTRL_HTT BIT(1) /* Hypertransport tunnel enable. */ 291 #define AMDVI_CTRL_ELOG BIT(2) /* Event log enable. */ 292 #define AMDVI_CTRL_ELOGINT BIT(3) /* Event log interrupt. */ 293 #define AMDVI_CTRL_COMINT BIT(4) /* Completion wait interrupt. */ 294 #define AMDVI_CTRL_PPW BIT(8) 295 #define AMDVI_CTRL_RPPW BIT(9) 296 #define AMDVI_CTRL_COH BIT(10) 297 #define AMDVI_CTRL_ISOC BIT(11) 298 #define AMDVI_CTRL_CMD BIT(12) /* Command buffer enable. */ 299 #define AMDVI_CTRL_PPRLOG BIT(13) 300 #define AMDVI_CTRL_PPRINT BIT(14) 301 #define AMDVI_CTRL_PPREN BIT(15) 302 #define AMDVI_CTRL_GTE BIT(16) /* Guest translation enable. */ 303 #define AMDVI_CTRL_GAE BIT(17) /* Guest APIC enable. */ 304 305 /* Invalidation timeout. */ 306 #define AMDVI_CTRL_INV_NO_TO 0 /* No timeout. */ 307 #define AMDVI_CTRL_INV_TO_1ms 1 /* 1 ms */ 308 #define AMDVI_CTRL_INV_TO_10ms 2 /* 10 ms */ 309 #define AMDVI_CTRL_INV_TO_100ms 3 /* 100 ms */ 310 #define AMDVI_CTRL_INV_TO_1S 4 /* 1 second */ 311 #define AMDVI_CTRL_INV_TO_10S 5 /* 10 second */ 312 #define AMDVI_CTRL_INV_TO_100S 6 /* 100 second */ 313 314 /* 315 * Max number of PCI devices. 316 * 256 bus x 32 slot/devices x 8 functions. 317 */ 318 #define PCI_NUM_DEV_MAX 0x10000 319 320 /* Maximum number of domains supported by IOMMU. */ 321 #define AMDVI_MAX_DOMAIN (BIT(16) - 1) 322 323 /* 324 * IOMMU Page Table attributes. 325 */ 326 #define AMDVI_PT_PRESENT BIT(0) 327 #define AMDVI_PT_COHERENT BIT(60) 328 #define AMDVI_PT_READ BIT(61) 329 #define AMDVI_PT_WRITE BIT(62) 330 331 #define AMDVI_PT_RW (AMDVI_PT_READ | AMDVI_PT_WRITE) 332 #define AMDVI_PT_MASK 0xFFFFFFFFFF000UL /* Only [51:12] for PA */ 333 334 #define AMDVI_PD_LEVEL_SHIFT 9 335 #define AMDVI_PD_SUPER(x) (((x) >> AMDVI_PD_LEVEL_SHIFT) == 7) 336 /* 337 * IOMMU Status, offset 0x2020 338 */ 339 #define AMDVI_STATUS_EV_OF BIT(0) /* Event overflow. */ 340 #define AMDVI_STATUS_EV_INTR BIT(1) /* Event interrupt. */ 341 /* Completion wait command completed. */ 342 #define AMDVI_STATUS_CMP BIT(2) 343 344 #define IVRS_CTRL_RID 1 /* MMIO RID */ 345 346 /* ACPI IVHD */ 347 struct ivhd_dev_cfg { 348 uint32_t start_id; 349 uint32_t end_id; 350 uint8_t data; /* Device configuration. */ 351 bool enable_ats; /* ATS enabled for the device. */ 352 int ats_qlen; /* ATS invalidation queue depth. */ 353 }; 354 355 struct amdvi_domain { 356 uint64_t *ptp; /* Highest level page table */ 357 int ptp_level; /* Level of page tables */ 358 u_int id; /* Domain id */ 359 SLIST_ENTRY (amdvi_domain) next; 360 }; 361 362 /* 363 * Different type of IVHD. 364 * XXX: Use AcpiIvrsType once new IVHD types are available. 365 */ 366 enum IvrsType 367 { 368 IVRS_TYPE_HARDWARE_LEGACY = ACPI_IVRS_TYPE_HARDWARE1, 369 /* Legacy without EFRi support. */ 370 IVRS_TYPE_HARDWARE_EFR = ACPI_IVRS_TYPE_HARDWARE2, 371 /* With EFR support. */ 372 IVRS_TYPE_HARDWARE_MIXED = 0x40, /* Mixed with EFR support. */ 373 }; 374 375 /* 376 * AMD IOMMU softc. 377 */ 378 struct amdvi_softc { 379 struct amdvi_ctrl *ctrl; /* Control area. */ 380 device_t dev; /* IOMMU device. */ 381 device_t pci_dev; /* IOMMU PCI function device. */ 382 enum IvrsType ivhd_type; /* IOMMU IVHD type. */ 383 bool iotlb; /* IOTLB supported by IOMMU */ 384 struct amdvi_cmd *cmd; /* Command descriptor area. */ 385 int cmd_max; /* Max number of commands. */ 386 uint64_t cmp_data; /* Command completion write back. */ 387 struct amdvi_event *event; /* Event descriptor area. */ 388 int event_max; /* Max number of events. */ 389 /* ACPI various flags. */ 390 uint32_t ivhd_flag; /* ACPI IVHD flag. */ 391 uint32_t ivhd_feature; /* ACPI v1 Reserved or v2 attribute. */ 392 uint64_t ext_feature; /* IVHD EFR */ 393 /* PCI related. */ 394 uint16_t cap_off; /* PCI Capability offset. */ 395 uint8_t pci_cap; /* PCI capability. */ 396 uint16_t pci_seg; /* IOMMU PCI domain/segment. */ 397 uint16_t pci_rid; /* PCI BDF of IOMMU */ 398 399 /* ACPI device configuration for end points. */ 400 struct ivhd_dev_cfg *dev_cfg; 401 int dev_cfg_cnt; 402 int dev_cfg_cap; 403 404 /* Software statistics. */ 405 uint64_t event_intr_cnt; /* Total event INTR count. */ 406 uint64_t total_cmd; /* Total number of commands. */ 407 }; 408 409 int amdvi_setup_hw(struct amdvi_softc *softc); 410 int amdvi_teardown_hw(struct amdvi_softc *softc); 411 #endif /* _AMDVI_PRIV_H_ */ 412