107ff474aSAnish Gupta /*- 207ff474aSAnish Gupta * Copyright (c) 2016 Anish Gupta (anish@freebsd.org) 307ff474aSAnish Gupta * All rights reserved. 407ff474aSAnish Gupta * 507ff474aSAnish Gupta * Redistribution and use in source and binary forms, with or without 607ff474aSAnish Gupta * modification, are permitted provided that the following conditions 707ff474aSAnish Gupta * are met: 807ff474aSAnish Gupta * 1. Redistributions of source code must retain the above copyright 907ff474aSAnish Gupta * notice unmodified, this list of conditions, and the following 1007ff474aSAnish Gupta * disclaimer. 1107ff474aSAnish Gupta * 2. Redistributions in binary form must reproduce the above copyright 1207ff474aSAnish Gupta * notice, this list of conditions and the following disclaimer in the 1307ff474aSAnish Gupta * documentation and/or other materials provided with the distribution. 1407ff474aSAnish Gupta * 1507ff474aSAnish Gupta * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1607ff474aSAnish Gupta * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1707ff474aSAnish Gupta * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1807ff474aSAnish Gupta * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1907ff474aSAnish Gupta * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2007ff474aSAnish Gupta * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2107ff474aSAnish Gupta * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2207ff474aSAnish Gupta * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2307ff474aSAnish Gupta * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2407ff474aSAnish Gupta * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2507ff474aSAnish Gupta * 2607ff474aSAnish Gupta * $FreeBSD$ 2707ff474aSAnish Gupta */ 2807ff474aSAnish Gupta 2907ff474aSAnish Gupta #ifndef _AMDVI_PRIV_H_ 3007ff474aSAnish Gupta #define _AMDVI_PRIV_H_ 3107ff474aSAnish Gupta 320b37d3d9SAnish Gupta #include <contrib/dev/acpica/include/acpi.h> 330b37d3d9SAnish Gupta 3407ff474aSAnish Gupta #define BIT(n) (1ULL << (n)) 3507ff474aSAnish Gupta /* Return value of bits[n:m] where n and (n >= ) m are bit positions. */ 3607ff474aSAnish Gupta #define REG_BITS(x, n, m) (((x) >> (m)) & \ 3707ff474aSAnish Gupta ((1 << (((n) - (m)) + 1)) - 1)) 3807ff474aSAnish Gupta 3907ff474aSAnish Gupta /* 4007ff474aSAnish Gupta * IOMMU PCI capability. 4107ff474aSAnish Gupta */ 4207ff474aSAnish Gupta #define AMDVI_PCI_CAP_IOTLB BIT(0) /* IOTLB is supported. */ 4307ff474aSAnish Gupta #define AMDVI_PCI_CAP_HT BIT(1) /* HyperTransport tunnel support. */ 4407ff474aSAnish Gupta #define AMDVI_PCI_CAP_NPCACHE BIT(2) /* Not present page cached. */ 4507ff474aSAnish Gupta #define AMDVI_PCI_CAP_EFR BIT(3) /* Extended features. */ 4607ff474aSAnish Gupta #define AMDVI_PCI_CAP_EXT BIT(4) /* Miscellaneous information reg. */ 4707ff474aSAnish Gupta 4807ff474aSAnish Gupta /* 4907ff474aSAnish Gupta * IOMMU extended features. 5007ff474aSAnish Gupta */ 5107ff474aSAnish Gupta #define AMDVI_EX_FEA_PREFSUP BIT(0) /* Prefetch command support. */ 5207ff474aSAnish Gupta #define AMDVI_EX_FEA_PPRSUP BIT(1) /* PPR support */ 5307ff474aSAnish Gupta #define AMDVI_EX_FEA_XTSUP BIT(2) /* Reserved */ 5407ff474aSAnish Gupta #define AMDVI_EX_FEA_NXSUP BIT(3) /* No-execute. */ 5507ff474aSAnish Gupta #define AMDVI_EX_FEA_GTSUP BIT(4) /* Guest translation support. */ 5607ff474aSAnish Gupta #define AMDVI_EX_FEA_EFRW BIT(5) /* Reserved */ 5707ff474aSAnish Gupta #define AMDVI_EX_FEA_IASUP BIT(6) /* Invalidate all command supp. */ 5807ff474aSAnish Gupta #define AMDVI_EX_FEA_GASUP BIT(7) /* Guest APIC or AVIC support. */ 5907ff474aSAnish Gupta #define AMDVI_EX_FEA_HESUP BIT(8) /* Hardware Error. */ 6007ff474aSAnish Gupta #define AMDVI_EX_FEA_PCSUP BIT(9) /* Performance counters support. */ 6107ff474aSAnish Gupta /* XXX: add more EFER bits. */ 6207ff474aSAnish Gupta 6307ff474aSAnish Gupta /* 6407ff474aSAnish Gupta * Device table entry or DTE 6507ff474aSAnish Gupta * NOTE: Must be 256-bits/32 bytes aligned. 6607ff474aSAnish Gupta */ 6707ff474aSAnish Gupta struct amdvi_dte { 6807ff474aSAnish Gupta uint32_t dt_valid:1; /* Device Table valid. */ 6907ff474aSAnish Gupta uint32_t pt_valid:1; /* Page translation valid. */ 705228ad10SRyan Libby uint16_t :7; /* Reserved[8:2] */ 7107ff474aSAnish Gupta uint8_t pt_level:3; /* Paging level, 0 to disable. */ 7207ff474aSAnish Gupta uint64_t pt_base:40; /* Page table root pointer. */ 7307ff474aSAnish Gupta uint8_t :3; /* Reserved[54:52] */ 7407ff474aSAnish Gupta uint8_t gv_valid:1; /* Revision 2, GVA to SPA. */ 7507ff474aSAnish Gupta uint8_t gv_level:2; /* Revision 2, GLX level. */ 7607ff474aSAnish Gupta uint8_t gv_cr3_lsb:3; /* Revision 2, GCR3[14:12] */ 7707ff474aSAnish Gupta uint8_t read_allow:1; /* I/O read enabled. */ 7807ff474aSAnish Gupta uint8_t write_allow:1; /* I/O write enabled. */ 7907ff474aSAnish Gupta uint8_t :1; /* Reserved[63] */ 8007ff474aSAnish Gupta uint16_t domain_id:16; /* Domain ID */ 8107ff474aSAnish Gupta uint16_t gv_cr3_lsb2:16; /* Revision 2, GCR3[30:15] */ 8207ff474aSAnish Gupta uint8_t iotlb_enable:1; /* Device support IOTLB */ 8307ff474aSAnish Gupta uint8_t sup_second_io_fault:1; /* Suppress subsequent I/O faults. */ 8407ff474aSAnish Gupta uint8_t sup_all_io_fault:1; /* Suppress all I/O page faults. */ 8507ff474aSAnish Gupta uint8_t IOctl:2; /* Port I/O control. */ 8607ff474aSAnish Gupta uint8_t iotlb_cache_disable:1; /* IOTLB cache hints. */ 8707ff474aSAnish Gupta uint8_t snoop_disable:1; /* Snoop disable. */ 8807ff474aSAnish Gupta uint8_t allow_ex:1; /* Allow exclusion. */ 8907ff474aSAnish Gupta uint8_t sysmgmt:2; /* System management message.*/ 9007ff474aSAnish Gupta uint8_t :1; /* Reserved[106] */ 9107ff474aSAnish Gupta uint32_t gv_cr3_msb:21; /* Revision 2, GCR3[51:31] */ 9207ff474aSAnish Gupta uint8_t intmap_valid:1; /* Interrupt map valid. */ 9307ff474aSAnish Gupta uint8_t intmap_len:4; /* Interrupt map table length. */ 9407ff474aSAnish Gupta uint8_t intmap_ign:1; /* Ignore unmapped interrupts. */ 9507ff474aSAnish Gupta uint64_t intmap_base:46; /* IntMap base. */ 9607ff474aSAnish Gupta uint8_t :4; /* Reserved[183:180] */ 9707ff474aSAnish Gupta uint8_t init_pass:1; /* INIT pass through or PT */ 9807ff474aSAnish Gupta uint8_t extintr_pass:1; /* External Interrupt PT */ 9907ff474aSAnish Gupta uint8_t nmi_pass:1; /* NMI PT */ 10007ff474aSAnish Gupta uint8_t :1; /* Reserved[187] */ 10107ff474aSAnish Gupta uint8_t intr_ctrl:2; /* Interrupt control */ 10207ff474aSAnish Gupta uint8_t lint0_pass:1; /* LINT0 PT */ 10307ff474aSAnish Gupta uint8_t lint1_pass:1; /* LINT1 PT */ 10407ff474aSAnish Gupta uint64_t :64; /* Reserved[255:192] */ 10507ff474aSAnish Gupta } __attribute__((__packed__)); 10607ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_dte) == 32); 10707ff474aSAnish Gupta 10807ff474aSAnish Gupta /* 10907ff474aSAnish Gupta * IOMMU command entry. 11007ff474aSAnish Gupta */ 11107ff474aSAnish Gupta struct amdvi_cmd { 11207ff474aSAnish Gupta uint32_t word0; 11307ff474aSAnish Gupta uint32_t word1:28; 11407ff474aSAnish Gupta uint8_t opcode:4; 11507ff474aSAnish Gupta uint64_t addr; 11607ff474aSAnish Gupta } __attribute__((__packed__)); 11707ff474aSAnish Gupta 11807ff474aSAnish Gupta /* Command opcodes. */ 11907ff474aSAnish Gupta #define AMDVI_CMP_WAIT_OPCODE 0x1 /* Completion wait. */ 12007ff474aSAnish Gupta #define AMDVI_INVD_DTE_OPCODE 0x2 /* Invalidate device table entry. */ 12107ff474aSAnish Gupta #define AMDVI_INVD_PAGE_OPCODE 0x3 /* Invalidate pages. */ 12207ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_OPCODE 0x4 /* Invalidate IOTLB pages. */ 12307ff474aSAnish Gupta #define AMDVI_INVD_INTR_OPCODE 0x5 /* Invalidate Interrupt table. */ 12407ff474aSAnish Gupta #define AMDVI_PREFETCH_PAGES_OPCODE 0x6 /* Prefetch IOMMU pages. */ 12507ff474aSAnish Gupta #define AMDVI_COMP_PPR_OPCODE 0x7 /* Complete PPR request. */ 12607ff474aSAnish Gupta #define AMDVI_INV_ALL_OPCODE 0x8 /* Invalidate all. */ 12707ff474aSAnish Gupta 12807ff474aSAnish Gupta /* Completion wait attributes. */ 12907ff474aSAnish Gupta #define AMDVI_CMP_WAIT_STORE BIT(0) /* Write back data. */ 13007ff474aSAnish Gupta #define AMDVI_CMP_WAIT_INTR BIT(1) /* Completion wait interrupt. */ 13107ff474aSAnish Gupta #define AMDVI_CMP_WAIT_FLUSH BIT(2) /* Flush queue. */ 13207ff474aSAnish Gupta 13307ff474aSAnish Gupta /* Invalidate page. */ 13407ff474aSAnish Gupta #define AMDVI_INVD_PAGE_S BIT(0) /* Invalidation size. */ 13507ff474aSAnish Gupta #define AMDVI_INVD_PAGE_PDE BIT(1) /* Invalidate PDE. */ 13607ff474aSAnish Gupta #define AMDVI_INVD_PAGE_GN_GVA BIT(2) /* GPA or GVA. */ 13707ff474aSAnish Gupta 13807ff474aSAnish Gupta #define AMDVI_INVD_PAGE_ALL_ADDR (0x7FFFFFFFFFFFFULL << 12) 13907ff474aSAnish Gupta 14007ff474aSAnish Gupta /* Invalidate IOTLB. */ 14107ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_S BIT(0) /* Invalidation size 4k or addr */ 14207ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_GN_GVA BIT(2) /* GPA or GVA. */ 14307ff474aSAnish Gupta 14407ff474aSAnish Gupta #define AMDVI_INVD_IOTLB_ALL_ADDR (0x7FFFFFFFFFFFFULL << 12) 14507ff474aSAnish Gupta /* XXX: add more command entries. */ 14607ff474aSAnish Gupta 14707ff474aSAnish Gupta /* 14807ff474aSAnish Gupta * IOMMU event entry. 14907ff474aSAnish Gupta */ 15007ff474aSAnish Gupta struct amdvi_event { 15107ff474aSAnish Gupta uint16_t devid; 15207ff474aSAnish Gupta uint16_t pasid_hi; 15307ff474aSAnish Gupta uint16_t pasid_domid; /* PASID low or DomainID */ 15407ff474aSAnish Gupta uint16_t flag:12; 15507ff474aSAnish Gupta uint8_t opcode:4; 15607ff474aSAnish Gupta uint64_t addr; 15707ff474aSAnish Gupta } __attribute__((__packed__)); 15807ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_event) == 16); 15907ff474aSAnish Gupta 16007ff474aSAnish Gupta /* Various event types. */ 16107ff474aSAnish Gupta #define AMDVI_EVENT_INVALID_DTE 0x1 16207ff474aSAnish Gupta #define AMDVI_EVENT_PFAULT 0x2 16307ff474aSAnish Gupta #define AMDVI_EVENT_DTE_HW_ERROR 0x3 16407ff474aSAnish Gupta #define AMDVI_EVENT_PAGE_HW_ERROR 0x4 16507ff474aSAnish Gupta #define AMDVI_EVENT_ILLEGAL_CMD 0x5 16607ff474aSAnish Gupta #define AMDVI_EVENT_CMD_HW_ERROR 0x6 16707ff474aSAnish Gupta #define AMDVI_EVENT_IOTLB_TIMEOUT 0x7 16807ff474aSAnish Gupta #define AMDVI_EVENT_INVALID_DTE_REQ 0x8 16907ff474aSAnish Gupta #define AMDVI_EVENT_INVALID_PPR_REQ 0x9 17007ff474aSAnish Gupta #define AMDVI_EVENT_COUNTER_ZERO 0xA 17107ff474aSAnish Gupta 17207ff474aSAnish Gupta #define AMDVI_EVENT_FLAG_MASK 0x1FF /* Mask for event flags. */ 17307ff474aSAnish Gupta #define AMDVI_EVENT_FLAG_TYPE(x) (((x) >> 9) & 0x3) 17407ff474aSAnish Gupta 17507ff474aSAnish Gupta /* 17607ff474aSAnish Gupta * IOMMU control block. 17707ff474aSAnish Gupta */ 17807ff474aSAnish Gupta struct amdvi_ctrl { 17907ff474aSAnish Gupta struct { 18007ff474aSAnish Gupta uint16_t size:9; 18107ff474aSAnish Gupta uint16_t :3; 18207ff474aSAnish Gupta uint64_t base:40; /* Devtable register base. */ 18307ff474aSAnish Gupta uint16_t :12; 18407ff474aSAnish Gupta } dte; 18507ff474aSAnish Gupta struct { 18607ff474aSAnish Gupta uint16_t :12; 18707ff474aSAnish Gupta uint64_t base:40; 18807ff474aSAnish Gupta uint8_t :4; 18907ff474aSAnish Gupta uint8_t len:4; 19007ff474aSAnish Gupta uint8_t :4; 19107ff474aSAnish Gupta } cmd; 19207ff474aSAnish Gupta struct { 19307ff474aSAnish Gupta uint16_t :12; 19407ff474aSAnish Gupta uint64_t base:40; 19507ff474aSAnish Gupta uint8_t :4; 19607ff474aSAnish Gupta uint8_t len:4; 19707ff474aSAnish Gupta uint8_t :4; 19807ff474aSAnish Gupta } event; 19907ff474aSAnish Gupta uint16_t control :13; 20007ff474aSAnish Gupta uint64_t :51; 20107ff474aSAnish Gupta struct { 20207ff474aSAnish Gupta uint8_t enable:1; 20307ff474aSAnish Gupta uint8_t allow:1; 20407ff474aSAnish Gupta uint16_t :10; 20507ff474aSAnish Gupta uint64_t base:40; 20607ff474aSAnish Gupta uint16_t :12; 20707ff474aSAnish Gupta uint16_t :12; 20807ff474aSAnish Gupta uint64_t limit:40; 20907ff474aSAnish Gupta uint16_t :12; 21007ff474aSAnish Gupta } excl; 21107ff474aSAnish Gupta /* 21207ff474aSAnish Gupta * Revision 2 only. 21307ff474aSAnish Gupta */ 21407ff474aSAnish Gupta uint64_t ex_feature; 21507ff474aSAnish Gupta struct { 21607ff474aSAnish Gupta uint16_t :12; 21707ff474aSAnish Gupta uint64_t base:40; 21807ff474aSAnish Gupta uint8_t :4; 21907ff474aSAnish Gupta uint8_t len:4; 22007ff474aSAnish Gupta uint8_t :4; 22107ff474aSAnish Gupta } ppr; 22207ff474aSAnish Gupta uint64_t first_event; 22307ff474aSAnish Gupta uint64_t second_event; 22407ff474aSAnish Gupta uint64_t event_status; 22507ff474aSAnish Gupta /* Revision 2 only, end. */ 22607ff474aSAnish Gupta uint8_t pad1[0x1FA8]; /* Padding. */ 22707ff474aSAnish Gupta uint32_t cmd_head:19; 22807ff474aSAnish Gupta uint64_t :45; 22907ff474aSAnish Gupta uint32_t cmd_tail:19; 23007ff474aSAnish Gupta uint64_t :45; 23107ff474aSAnish Gupta uint32_t evt_head:19; 23207ff474aSAnish Gupta uint64_t :45; 23307ff474aSAnish Gupta uint32_t evt_tail:19; 23407ff474aSAnish Gupta uint64_t :45; 23553d580f9SAndriy Gapon uint32_t status:19; 2365a041f21SAndriy Gapon uint64_t :45; 23707ff474aSAnish Gupta uint64_t pad2; 23807ff474aSAnish Gupta uint8_t :4; 23907ff474aSAnish Gupta uint16_t ppr_head:15; 24007ff474aSAnish Gupta uint64_t :45; 24107ff474aSAnish Gupta uint8_t :4; 24207ff474aSAnish Gupta uint16_t ppr_tail:15; 24307ff474aSAnish Gupta uint64_t :45; 24407ff474aSAnish Gupta uint8_t pad3[0x1FC0]; /* Padding. */ 24507ff474aSAnish Gupta 24607ff474aSAnish Gupta /* XXX: More for rev2. */ 24707ff474aSAnish Gupta } __attribute__((__packed__)); 24807ff474aSAnish Gupta CTASSERT(offsetof(struct amdvi_ctrl, pad1)== 0x58); 24907ff474aSAnish Gupta CTASSERT(offsetof(struct amdvi_ctrl, pad2)== 0x2028); 25007ff474aSAnish Gupta CTASSERT(offsetof(struct amdvi_ctrl, pad3)== 0x2040); 25107ff474aSAnish Gupta 25207ff474aSAnish Gupta #define AMDVI_MMIO_V1_SIZE (4 * PAGE_SIZE) /* v1 size */ 25307ff474aSAnish Gupta /* 25407ff474aSAnish Gupta * AMF IOMMU v2 size including event counters 25507ff474aSAnish Gupta */ 25607ff474aSAnish Gupta #define AMDVI_MMIO_V2_SIZE (8 * PAGE_SIZE) 25707ff474aSAnish Gupta 25807ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_ctrl) == 0x4000); 25907ff474aSAnish Gupta CTASSERT(sizeof(struct amdvi_ctrl) == AMDVI_MMIO_V1_SIZE); 26007ff474aSAnish Gupta 26107ff474aSAnish Gupta /* IVHD flag */ 26207ff474aSAnish Gupta #define IVHD_FLAG_HTT BIT(0) /* Hypertransport Tunnel. */ 26307ff474aSAnish Gupta #define IVHD_FLAG_PPW BIT(1) /* Pass posted write. */ 26407ff474aSAnish Gupta #define IVHD_FLAG_RPPW BIT(2) /* Response pass posted write. */ 26507ff474aSAnish Gupta #define IVHD_FLAG_ISOC BIT(3) /* Isoc support. */ 26607ff474aSAnish Gupta #define IVHD_FLAG_IOTLB BIT(4) /* IOTLB support. */ 26707ff474aSAnish Gupta #define IVHD_FLAG_COH BIT(5) /* Coherent control, default 1 */ 26807ff474aSAnish Gupta #define IVHD_FLAG_PFS BIT(6) /* Prefetch IOMMU pages. */ 26907ff474aSAnish Gupta #define IVHD_FLAG_PPRS BIT(7) /* Peripheral page support. */ 27007ff474aSAnish Gupta 27107ff474aSAnish Gupta /* IVHD device entry data setting. */ 27207ff474aSAnish Gupta #define IVHD_DEV_LINT0_PASS BIT(6) /* LINT0 interrupts. */ 27307ff474aSAnish Gupta #define IVHD_DEV_LINT1_PASS BIT(7) /* LINT1 interrupts. */ 27407ff474aSAnish Gupta 27507ff474aSAnish Gupta /* Bit[5:4] for System Mgmt. Bit3 is reserved. */ 27607ff474aSAnish Gupta #define IVHD_DEV_INIT_PASS BIT(0) /* INIT */ 27707ff474aSAnish Gupta #define IVHD_DEV_EXTINTR_PASS BIT(1) /* ExtInt */ 27807ff474aSAnish Gupta #define IVHD_DEV_NMI_PASS BIT(2) /* NMI */ 27907ff474aSAnish Gupta 28007ff474aSAnish Gupta /* IVHD 8-byte extended data settings. */ 28107ff474aSAnish Gupta #define IVHD_DEV_EXT_ATS_DISABLE BIT(31) /* Disable ATS */ 28207ff474aSAnish Gupta 28307ff474aSAnish Gupta /* IOMMU control register. */ 28407ff474aSAnish Gupta #define AMDVI_CTRL_EN BIT(0) /* IOMMU enable. */ 28507ff474aSAnish Gupta #define AMDVI_CTRL_HTT BIT(1) /* Hypertransport tunnel enable. */ 28607ff474aSAnish Gupta #define AMDVI_CTRL_ELOG BIT(2) /* Event log enable. */ 28707ff474aSAnish Gupta #define AMDVI_CTRL_ELOGINT BIT(3) /* Event log interrupt. */ 28807ff474aSAnish Gupta #define AMDVI_CTRL_COMINT BIT(4) /* Completion wait interrupt. */ 28907ff474aSAnish Gupta #define AMDVI_CTRL_PPW BIT(8) 29007ff474aSAnish Gupta #define AMDVI_CTRL_RPPW BIT(9) 29107ff474aSAnish Gupta #define AMDVI_CTRL_COH BIT(10) 29207ff474aSAnish Gupta #define AMDVI_CTRL_ISOC BIT(11) 29307ff474aSAnish Gupta #define AMDVI_CTRL_CMD BIT(12) /* Command buffer enable. */ 29407ff474aSAnish Gupta #define AMDVI_CTRL_PPRLOG BIT(13) 29507ff474aSAnish Gupta #define AMDVI_CTRL_PPRINT BIT(14) 29607ff474aSAnish Gupta #define AMDVI_CTRL_PPREN BIT(15) 29707ff474aSAnish Gupta #define AMDVI_CTRL_GTE BIT(16) /* Guest translation enable. */ 29807ff474aSAnish Gupta #define AMDVI_CTRL_GAE BIT(17) /* Guest APIC enable. */ 29907ff474aSAnish Gupta 30007ff474aSAnish Gupta /* Invalidation timeout. */ 30107ff474aSAnish Gupta #define AMDVI_CTRL_INV_NO_TO 0 /* No timeout. */ 30207ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_1ms 1 /* 1 ms */ 30307ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_10ms 2 /* 10 ms */ 30407ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_100ms 3 /* 100 ms */ 30507ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_1S 4 /* 1 second */ 30607ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_10S 5 /* 10 second */ 30707ff474aSAnish Gupta #define AMDVI_CTRL_INV_TO_100S 6 /* 100 second */ 30807ff474aSAnish Gupta 30907ff474aSAnish Gupta /* 31007ff474aSAnish Gupta * Max number of PCI devices. 31107ff474aSAnish Gupta * 256 bus x 32 slot/devices x 8 functions. 31207ff474aSAnish Gupta */ 31307ff474aSAnish Gupta #define PCI_NUM_DEV_MAX 0x10000 31407ff474aSAnish Gupta 31507ff474aSAnish Gupta /* Maximum number of domains supported by IOMMU. */ 31607ff474aSAnish Gupta #define AMDVI_MAX_DOMAIN (BIT(16) - 1) 31707ff474aSAnish Gupta 31807ff474aSAnish Gupta /* 31907ff474aSAnish Gupta * IOMMU Page Table attributes. 32007ff474aSAnish Gupta */ 32107ff474aSAnish Gupta #define AMDVI_PT_PRESENT BIT(0) 32207ff474aSAnish Gupta #define AMDVI_PT_COHERENT BIT(60) 32307ff474aSAnish Gupta #define AMDVI_PT_READ BIT(61) 32407ff474aSAnish Gupta #define AMDVI_PT_WRITE BIT(62) 32507ff474aSAnish Gupta 32607ff474aSAnish Gupta #define AMDVI_PT_RW (AMDVI_PT_READ | AMDVI_PT_WRITE) 32707ff474aSAnish Gupta #define AMDVI_PT_MASK 0xFFFFFFFFFF000UL /* Only [51:12] for PA */ 32807ff474aSAnish Gupta 32907ff474aSAnish Gupta #define AMDVI_PD_LEVEL_SHIFT 9 33007ff474aSAnish Gupta #define AMDVI_PD_SUPER(x) (((x) >> AMDVI_PD_LEVEL_SHIFT) == 7) 33107ff474aSAnish Gupta /* 33207ff474aSAnish Gupta * IOMMU Status, offset 0x2020 33307ff474aSAnish Gupta */ 33407ff474aSAnish Gupta #define AMDVI_STATUS_EV_OF BIT(0) /* Event overflow. */ 33507ff474aSAnish Gupta #define AMDVI_STATUS_EV_INTR BIT(1) /* Event interrupt. */ 33607ff474aSAnish Gupta /* Completion wait command completed. */ 33707ff474aSAnish Gupta #define AMDVI_STATUS_CMP BIT(2) 33807ff474aSAnish Gupta 33907ff474aSAnish Gupta #define IVRS_CTRL_RID 1 /* MMIO RID */ 34007ff474aSAnish Gupta 34107ff474aSAnish Gupta /* ACPI IVHD */ 34207ff474aSAnish Gupta struct ivhd_dev_cfg { 34307ff474aSAnish Gupta uint32_t start_id; 34407ff474aSAnish Gupta uint32_t end_id; 34507ff474aSAnish Gupta uint8_t data; /* Device configuration. */ 34607ff474aSAnish Gupta bool enable_ats; /* ATS enabled for the device. */ 34707ff474aSAnish Gupta int ats_qlen; /* ATS invalidation queue depth. */ 34807ff474aSAnish Gupta }; 34907ff474aSAnish Gupta 35007ff474aSAnish Gupta struct amdvi_domain { 35107ff474aSAnish Gupta uint64_t *ptp; /* Highest level page table */ 35207ff474aSAnish Gupta int ptp_level; /* Level of page tables */ 35307ff474aSAnish Gupta u_int id; /* Domain id */ 35407ff474aSAnish Gupta SLIST_ENTRY (amdvi_domain) next; 35507ff474aSAnish Gupta }; 35607ff474aSAnish Gupta 35707ff474aSAnish Gupta /* 358*9363000dSAnish Gupta * I/O Virtualization Hardware Definition Block (IVHD) type 0x10 (legacy) 359*9363000dSAnish Gupta * uses ACPI_IVRS_HARDWARE define in contrib/dev/acpica/include/actbl2.h 360*9363000dSAnish Gupta * New IVHD types 0x11 and 0x40 as defined in AMD IOMMU spec[48882] are missing in 361*9363000dSAnish Gupta * ACPI code. These new types add extra field EFR(Extended Feature Register). 362*9363000dSAnish Gupta * XXX : Use definition from ACPI when it is available. 363*9363000dSAnish Gupta */ 364*9363000dSAnish Gupta typedef struct acpi_ivrs_hardware_efr_sup 365*9363000dSAnish Gupta { 366*9363000dSAnish Gupta ACPI_IVRS_HEADER Header; 367*9363000dSAnish Gupta UINT16 CapabilityOffset; /* Offset for IOMMU control fields */ 368*9363000dSAnish Gupta UINT64 BaseAddress; /* IOMMU control registers */ 369*9363000dSAnish Gupta UINT16 PciSegmentGroup; 370*9363000dSAnish Gupta UINT16 Info; /* MSI number and unit ID */ 371*9363000dSAnish Gupta UINT32 Attr; /* IOMMU Feature */ 372*9363000dSAnish Gupta UINT64 ExtFR; /* IOMMU Extended Feature */ 373*9363000dSAnish Gupta UINT64 Reserved; /* v1 feature or v2 attribute */ 374*9363000dSAnish Gupta } __attribute__ ((__packed__)) ACPI_IVRS_HARDWARE_EFRSUP; 375*9363000dSAnish Gupta CTASSERT(sizeof(ACPI_IVRS_HARDWARE_EFRSUP) == 40); 376*9363000dSAnish Gupta 377*9363000dSAnish Gupta /* 378*9363000dSAnish Gupta * Different type of IVHD. 379*9363000dSAnish Gupta * XXX: Use AcpiIvrsType once new IVHD types are available. 380*9363000dSAnish Gupta */ 381*9363000dSAnish Gupta enum IvrsType 382*9363000dSAnish Gupta { 383*9363000dSAnish Gupta IVRS_TYPE_HARDWARE_LEGACY = 0x10, /* Legacy without EFRi support. */ 384*9363000dSAnish Gupta IVRS_TYPE_HARDWARE_EFR = 0x11, /* With EFR support. */ 385*9363000dSAnish Gupta IVRS_TYPE_HARDWARE_MIXED = 0x40, /* Mixed with EFR support. */ 386*9363000dSAnish Gupta }; 387*9363000dSAnish Gupta 388*9363000dSAnish Gupta /* 38907ff474aSAnish Gupta * AMD IOMMU softc. 39007ff474aSAnish Gupta */ 39107ff474aSAnish Gupta struct amdvi_softc { 39207ff474aSAnish Gupta struct amdvi_ctrl *ctrl; /* Control area. */ 39307ff474aSAnish Gupta device_t dev; /* IOMMU device. */ 394*9363000dSAnish Gupta enum IvrsType ivhd_type; /* IOMMU IVHD type. */ 39507ff474aSAnish Gupta bool iotlb; /* IOTLB supported by IOMMU */ 39607ff474aSAnish Gupta struct amdvi_cmd *cmd; /* Command descriptor area. */ 39707ff474aSAnish Gupta int cmd_max; /* Max number of commands. */ 39807ff474aSAnish Gupta uint64_t cmp_data; /* Command completion write back. */ 39907ff474aSAnish Gupta struct amdvi_event *event; /* Event descriptor area. */ 40007ff474aSAnish Gupta struct resource *event_res; /* Event interrupt resource. */ 40107ff474aSAnish Gupta void *event_tag; /* Event interrupt tag. */ 40207ff474aSAnish Gupta int event_max; /* Max number of events. */ 40307ff474aSAnish Gupta int event_irq; 40407ff474aSAnish Gupta int event_rid; 40507ff474aSAnish Gupta /* ACPI various flags. */ 40607ff474aSAnish Gupta uint32_t ivhd_flag; /* ACPI IVHD flag. */ 4070b37d3d9SAnish Gupta uint32_t ivhd_feature; /* ACPI v1 Reserved or v2 attribute. */ 4080b37d3d9SAnish Gupta uint64_t ext_feature; /* IVHD EFR */ 40907ff474aSAnish Gupta /* PCI related. */ 41007ff474aSAnish Gupta uint16_t cap_off; /* PCI Capability offset. */ 41107ff474aSAnish Gupta uint8_t pci_cap; /* PCI capability. */ 41207ff474aSAnish Gupta uint16_t pci_seg; /* IOMMU PCI domain/segment. */ 41307ff474aSAnish Gupta uint16_t pci_rid; /* PCI BDF of IOMMU */ 41407ff474aSAnish Gupta /* Device range under this IOMMU. */ 41507ff474aSAnish Gupta uint16_t start_dev_rid; /* First device under this IOMMU. */ 41607ff474aSAnish Gupta uint16_t end_dev_rid; /* Last device under this IOMMU. */ 41707ff474aSAnish Gupta 41807ff474aSAnish Gupta /* BIOS provided device configuration for end points. */ 41907ff474aSAnish Gupta struct ivhd_dev_cfg dev_cfg[10]; 42007ff474aSAnish Gupta int dev_cfg_cnt; 42107ff474aSAnish Gupta 42207ff474aSAnish Gupta /* Software statistics. */ 42307ff474aSAnish Gupta uint64_t event_intr_cnt; /* Total event INTR count. */ 42407ff474aSAnish Gupta uint64_t total_cmd; /* Total number of commands. */ 42507ff474aSAnish Gupta }; 42607ff474aSAnish Gupta 42707ff474aSAnish Gupta int amdvi_setup_hw(struct amdvi_softc *softc); 42807ff474aSAnish Gupta int amdvi_teardown_hw(struct amdvi_softc *softc); 42907ff474aSAnish Gupta #endif /* _AMDVI_PRIV_H_ */ 430