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