1*3a634bfcSVikram Hegde /* 2*3a634bfcSVikram Hegde * CDDL HEADER START 3*3a634bfcSVikram Hegde * 4*3a634bfcSVikram Hegde * The contents of this file are subject to the terms of the 5*3a634bfcSVikram Hegde * Common Development and Distribution License (the "License"). 6*3a634bfcSVikram Hegde * You may not use this file except in compliance with the License. 7*3a634bfcSVikram Hegde * 8*3a634bfcSVikram Hegde * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3a634bfcSVikram Hegde * or http://www.opensolaris.org/os/licensing. 10*3a634bfcSVikram Hegde * See the License for the specific language governing permissions 11*3a634bfcSVikram Hegde * and limitations under the License. 12*3a634bfcSVikram Hegde * 13*3a634bfcSVikram Hegde * When distributing Covered Code, include this CDDL HEADER in each 14*3a634bfcSVikram Hegde * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3a634bfcSVikram Hegde * If applicable, add the following below this CDDL HEADER, with the 16*3a634bfcSVikram Hegde * fields enclosed by brackets "[]" replaced with your own identifying 17*3a634bfcSVikram Hegde * information: Portions Copyright [yyyy] [name of copyright owner] 18*3a634bfcSVikram Hegde * 19*3a634bfcSVikram Hegde * CDDL HEADER END 20*3a634bfcSVikram Hegde */ 21*3a634bfcSVikram Hegde /* 22*3a634bfcSVikram Hegde * Portions Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23*3a634bfcSVikram Hegde * Use is subject to license terms. 24*3a634bfcSVikram Hegde */ 25*3a634bfcSVikram Hegde 26*3a634bfcSVikram Hegde /* 27*3a634bfcSVikram Hegde * Copyright (c) 2008, Intel Corporation. 28*3a634bfcSVikram Hegde * All rights reserved. 29*3a634bfcSVikram Hegde */ 30*3a634bfcSVikram Hegde 31*3a634bfcSVikram Hegde #ifndef _SYS_INTEL_IOMMU_H 32*3a634bfcSVikram Hegde #define _SYS_INTEL_IOMMU_H 33*3a634bfcSVikram Hegde 34*3a634bfcSVikram Hegde /* 35*3a634bfcSVikram Hegde * Intel IOMMU implementation specific state 36*3a634bfcSVikram Hegde */ 37*3a634bfcSVikram Hegde 38*3a634bfcSVikram Hegde #ifdef __cplusplus 39*3a634bfcSVikram Hegde extern "C" { 40*3a634bfcSVikram Hegde #endif 41*3a634bfcSVikram Hegde 42*3a634bfcSVikram Hegde #include <sys/types.h> 43*3a634bfcSVikram Hegde #include <sys/bitset.h> 44*3a634bfcSVikram Hegde #include <sys/kstat.h> 45*3a634bfcSVikram Hegde #include <sys/vmem.h> 46*3a634bfcSVikram Hegde #include <sys/rootnex.h> 47*3a634bfcSVikram Hegde 48*3a634bfcSVikram Hegde /* 49*3a634bfcSVikram Hegde * Some ON drivers have bugs. Keep this define until all such drivers 50*3a634bfcSVikram Hegde * have been fixed 51*3a634bfcSVikram Hegde */ 52*3a634bfcSVikram Hegde #define BUGGY_DRIVERS 1 53*3a634bfcSVikram Hegde 54*3a634bfcSVikram Hegde /* PD(T)E entries */ 55*3a634bfcSVikram Hegde typedef uint64_t hw_pdte_t; 56*3a634bfcSVikram Hegde 57*3a634bfcSVikram Hegde #define IMMU_MAXNAMELEN (64) 58*3a634bfcSVikram Hegde #define IMMU_MAXSEG (1) 59*3a634bfcSVikram Hegde #define IMMU_REGSZ (1UL << 12) 60*3a634bfcSVikram Hegde #define IMMU_PAGESIZE (4096) 61*3a634bfcSVikram Hegde #define IMMU_PAGESHIFT (12) 62*3a634bfcSVikram Hegde #define IMMU_PAGEOFFSET (IMMU_PAGESIZE - 1) 63*3a634bfcSVikram Hegde #define IMMU_PAGEMASK (~IMMU_PAGEOFFSET) 64*3a634bfcSVikram Hegde #define IMMU_BTOP(b) (((uint64_t)b) >> IMMU_PAGESHIFT) 65*3a634bfcSVikram Hegde #define IMMU_PTOB(p) (((uint64_t)p) << IMMU_PAGESHIFT) 66*3a634bfcSVikram Hegde #define IMMU_PGTABLE_MAX_LEVELS (6) 67*3a634bfcSVikram Hegde #define IMMU_ROUNDUP(size) (((size) + IMMU_PAGEOFFSET) & ~IMMU_PAGEOFFSET) 68*3a634bfcSVikram Hegde #define IMMU_ROUNDOWN(addr) ((addr) & ~IMMU_PAGEOFFSET) 69*3a634bfcSVikram Hegde #define IMMU_PGTABLE_LEVEL_STRIDE (9) 70*3a634bfcSVikram Hegde #define IMMU_PGTABLE_LEVEL_MASK ((1<<IMMU_PGTABLE_LEVEL_STRIDE) - 1) 71*3a634bfcSVikram Hegde #define IMMU_PGTABLE_OFFSHIFT (IMMU_PAGESHIFT - IMMU_PGTABLE_LEVEL_STRIDE) 72*3a634bfcSVikram Hegde #define IMMU_PGTABLE_MAXIDX ((IMMU_PAGESIZE / sizeof (hw_pdte_t)) - 1) 73*3a634bfcSVikram Hegde 74*3a634bfcSVikram Hegde #define IMMU_ROUNDUP(size) (((size) + IMMU_PAGEOFFSET) & ~IMMU_PAGEOFFSET) 75*3a634bfcSVikram Hegde #define IMMU_ROUNDOWN(addr) ((addr) & ~IMMU_PAGEOFFSET) 76*3a634bfcSVikram Hegde 77*3a634bfcSVikram Hegde /* 78*3a634bfcSVikram Hegde * DMAR global defines 79*3a634bfcSVikram Hegde */ 80*3a634bfcSVikram Hegde #define DMAR_TABLE "dmar-table" 81*3a634bfcSVikram Hegde #define DMAR_INTRMAP_SUPPORT (0x01) 82*3a634bfcSVikram Hegde 83*3a634bfcSVikram Hegde /* DMAR unit types */ 84*3a634bfcSVikram Hegde #define DMAR_DRHD 0 85*3a634bfcSVikram Hegde #define DMAR_RMRR 1 86*3a634bfcSVikram Hegde #define DMAR_ATSR 2 87*3a634bfcSVikram Hegde #define DMAR_RHSA 3 88*3a634bfcSVikram Hegde 89*3a634bfcSVikram Hegde /* DRHD flag values */ 90*3a634bfcSVikram Hegde #define DMAR_INCLUDE_ALL (0x01) 91*3a634bfcSVikram Hegde 92*3a634bfcSVikram Hegde /* Device scope types */ 93*3a634bfcSVikram Hegde #define DMAR_ENDPOINT 1 94*3a634bfcSVikram Hegde #define DMAR_SUBTREE 2 95*3a634bfcSVikram Hegde #define DMAR_IOAPIC 3 96*3a634bfcSVikram Hegde #define DMAR_HPET 4 97*3a634bfcSVikram Hegde 98*3a634bfcSVikram Hegde 99*3a634bfcSVikram Hegde /* Forward declarations for IOMMU state structure and DVMA domain struct */ 100*3a634bfcSVikram Hegde struct immu; 101*3a634bfcSVikram Hegde struct domain; 102*3a634bfcSVikram Hegde 103*3a634bfcSVikram Hegde /* 104*3a634bfcSVikram Hegde * The following structure describes the formate of DMAR ACPI table format. 105*3a634bfcSVikram Hegde * They are used to parse DMAR ACPI table. Read the spec for the meaning 106*3a634bfcSVikram Hegde * of each member. 107*3a634bfcSVikram Hegde */ 108*3a634bfcSVikram Hegde 109*3a634bfcSVikram Hegde /* lengths of various strings */ 110*3a634bfcSVikram Hegde #define DMAR_SIG_LEN (4) /* table signature */ 111*3a634bfcSVikram Hegde #define DMAR_OEMID_LEN (6) /* OEM ID */ 112*3a634bfcSVikram Hegde #define DMAR_TBLID_LEN (8) /* OEM table ID */ 113*3a634bfcSVikram Hegde #define DMAR_ASL_LEN (4) /* ASL len */ 114*3a634bfcSVikram Hegde 115*3a634bfcSVikram Hegde typedef struct dmar_table { 116*3a634bfcSVikram Hegde kmutex_t tbl_lock; 117*3a634bfcSVikram Hegde uint8_t tbl_haw; 118*3a634bfcSVikram Hegde boolean_t tbl_intrmap; 119*3a634bfcSVikram Hegde list_t tbl_drhd_list[IMMU_MAXSEG]; 120*3a634bfcSVikram Hegde list_t tbl_rmrr_list[IMMU_MAXSEG]; 121*3a634bfcSVikram Hegde char *tbl_oem_id; 122*3a634bfcSVikram Hegde char *tbl_oem_tblid; 123*3a634bfcSVikram Hegde uint32_t tbl_oem_rev; 124*3a634bfcSVikram Hegde caddr_t tbl_raw; 125*3a634bfcSVikram Hegde int tbl_rawlen; 126*3a634bfcSVikram Hegde } dmar_table_t; 127*3a634bfcSVikram Hegde 128*3a634bfcSVikram Hegde typedef struct drhd { 129*3a634bfcSVikram Hegde kmutex_t dr_lock; /* protects the dmar field */ 130*3a634bfcSVikram Hegde struct immu *dr_immu; 131*3a634bfcSVikram Hegde dev_info_t *dr_dip; 132*3a634bfcSVikram Hegde uint16_t dr_seg; 133*3a634bfcSVikram Hegde uint64_t dr_regs; 134*3a634bfcSVikram Hegde boolean_t dr_include_all; 135*3a634bfcSVikram Hegde list_t dr_scope_list; 136*3a634bfcSVikram Hegde list_node_t dr_node; 137*3a634bfcSVikram Hegde } drhd_t; 138*3a634bfcSVikram Hegde 139*3a634bfcSVikram Hegde typedef struct rmrr { 140*3a634bfcSVikram Hegde kmutex_t rm_lock; 141*3a634bfcSVikram Hegde uint16_t rm_seg; 142*3a634bfcSVikram Hegde uint64_t rm_base; 143*3a634bfcSVikram Hegde uint64_t rm_limit; 144*3a634bfcSVikram Hegde list_t rm_scope_list; 145*3a634bfcSVikram Hegde list_node_t rm_node; 146*3a634bfcSVikram Hegde } rmrr_t; 147*3a634bfcSVikram Hegde 148*3a634bfcSVikram Hegde /* 149*3a634bfcSVikram Hegde * Macros based on PCI spec 150*3a634bfcSVikram Hegde */ 151*3a634bfcSVikram Hegde #define IMMU_PCI_DEV(devfunc) ((uint64_t)devfunc >> 3) /* from devfunc */ 152*3a634bfcSVikram Hegde #define IMMU_PCI_FUNC(devfunc) (devfunc & 7) /* get func from devfunc */ 153*3a634bfcSVikram Hegde #define IMMU_PCI_DEVFUNC(d, f) (((d) << 3) | (f)) /* create devfunc */ 154*3a634bfcSVikram Hegde 155*3a634bfcSVikram Hegde typedef struct scope { 156*3a634bfcSVikram Hegde uint8_t scp_type; 157*3a634bfcSVikram Hegde uint8_t scp_enumid; 158*3a634bfcSVikram Hegde uint8_t scp_bus; 159*3a634bfcSVikram Hegde uint8_t scp_dev; 160*3a634bfcSVikram Hegde uint8_t scp_func; 161*3a634bfcSVikram Hegde list_node_t scp_node; 162*3a634bfcSVikram Hegde } scope_t; 163*3a634bfcSVikram Hegde 164*3a634bfcSVikram Hegde /* 165*3a634bfcSVikram Hegde * interrupt source id and drhd info for ioapic 166*3a634bfcSVikram Hegde */ 167*3a634bfcSVikram Hegde typedef struct ioapic_drhd { 168*3a634bfcSVikram Hegde uchar_t ioapic_ioapicid; 169*3a634bfcSVikram Hegde uint16_t ioapic_sid; /* ioapic source id */ 170*3a634bfcSVikram Hegde drhd_t *ioapic_drhd; 171*3a634bfcSVikram Hegde list_node_t ioapic_node; 172*3a634bfcSVikram Hegde } ioapic_drhd_t; 173*3a634bfcSVikram Hegde 174*3a634bfcSVikram Hegde typedef struct memrng { 175*3a634bfcSVikram Hegde uint64_t mrng_start; 176*3a634bfcSVikram Hegde uint64_t mrng_npages; 177*3a634bfcSVikram Hegde } memrng_t; 178*3a634bfcSVikram Hegde 179*3a634bfcSVikram Hegde typedef enum immu_flags { 180*3a634bfcSVikram Hegde IMMU_FLAGS_NONE = 0x1, 181*3a634bfcSVikram Hegde IMMU_FLAGS_SLEEP = 0x1, 182*3a634bfcSVikram Hegde IMMU_FLAGS_NOSLEEP = 0x2, 183*3a634bfcSVikram Hegde IMMU_FLAGS_READ = 0x4, 184*3a634bfcSVikram Hegde IMMU_FLAGS_WRITE = 0x8, 185*3a634bfcSVikram Hegde IMMU_FLAGS_DONTPASS = 0x10, 186*3a634bfcSVikram Hegde IMMU_FLAGS_ALLOC = 0x20, 187*3a634bfcSVikram Hegde IMMU_FLAGS_MUST_MATCH = 0x40, 188*3a634bfcSVikram Hegde IMMU_FLAGS_PAGE1 = 0x80, 189*3a634bfcSVikram Hegde IMMU_FLAGS_UNITY = 0x100, 190*3a634bfcSVikram Hegde IMMU_FLAGS_DMAHDL = 0x200, 191*3a634bfcSVikram Hegde IMMU_FLAGS_MEMRNG = 0x400 192*3a634bfcSVikram Hegde } immu_flags_t; 193*3a634bfcSVikram Hegde 194*3a634bfcSVikram Hegde typedef enum cont_avail { 195*3a634bfcSVikram Hegde IMMU_CONT_BAD = 0x0, 196*3a634bfcSVikram Hegde IMMU_CONT_UNINITED = 0x1, 197*3a634bfcSVikram Hegde IMMU_CONT_INITED = 0x2 198*3a634bfcSVikram Hegde } cont_avail_t; 199*3a634bfcSVikram Hegde 200*3a634bfcSVikram Hegde /* Size of root and context tables and their entries */ 201*3a634bfcSVikram Hegde #define IMMU_ROOT_TBLSZ (4096) 202*3a634bfcSVikram Hegde #define IMMU_CONT_TBLSZ (4096) 203*3a634bfcSVikram Hegde #define IMMU_ROOT_NUM (256) 204*3a634bfcSVikram Hegde #define IMMU_CONT_NUM (256) 205*3a634bfcSVikram Hegde 206*3a634bfcSVikram Hegde /* register offset */ 207*3a634bfcSVikram Hegde #define IMMU_REG_VERSION (0x00) /* Version Rigister, 32 bit */ 208*3a634bfcSVikram Hegde #define IMMU_REG_CAP (0x08) /* Capability Register, 64 bit */ 209*3a634bfcSVikram Hegde #define IMMU_REG_EXCAP (0x10) /* Extended Capability Reg, 64 bit */ 210*3a634bfcSVikram Hegde #define IMMU_REG_GLOBAL_CMD (0x18) /* Global Command Register, 32 bit */ 211*3a634bfcSVikram Hegde #define IMMU_REG_GLOBAL_STS (0x1C) /* Global Status Register, 32 bit */ 212*3a634bfcSVikram Hegde #define IMMU_REG_ROOTENTRY (0x20) /* Root-Entry Table Addr Reg, 64 bit */ 213*3a634bfcSVikram Hegde #define IMMU_REG_CONTEXT_CMD (0x28) /* Context Comand Register, 64 bit */ 214*3a634bfcSVikram Hegde #define IMMU_REG_FAULT_STS (0x34) /* Fault Status Register, 32 bit */ 215*3a634bfcSVikram Hegde #define IMMU_REG_FEVNT_CON (0x38) /* Fault Event Control Reg, 32 bit */ 216*3a634bfcSVikram Hegde #define IMMU_REG_FEVNT_DATA (0x3C) /* Fault Event Data Register, 32 bit */ 217*3a634bfcSVikram Hegde #define IMMU_REG_FEVNT_ADDR (0x40) /* Fault Event Address Reg, 32 bit */ 218*3a634bfcSVikram Hegde #define IMMU_REG_FEVNT_UADDR (0x44) /* Fault Event Upper Addr Reg, 32 bit */ 219*3a634bfcSVikram Hegde #define IMMU_REG_AFAULT_LOG (0x58) /* Advanced Fault Log Reg, 64 bit */ 220*3a634bfcSVikram Hegde #define IMMU_REG_PMER (0x64) /* Protected Memory Enble Reg, 32 bit */ 221*3a634bfcSVikram Hegde #define IMMU_REG_PLMBR (0x68) /* Protected Low Mem Base Reg, 32 bit */ 222*3a634bfcSVikram Hegde #define IMMU_REG_PLMLR (0x6C) /* Protected Low Mem Lim Reg, 32 bit */ 223*3a634bfcSVikram Hegde #define IMMU_REG_PHMBR (0X70) /* Protectd High Mem Base Reg, 64 bit */ 224*3a634bfcSVikram Hegde #define IMMU_REG_PHMLR (0x78) /* Protected High Mem Lim Reg, 64 bit */ 225*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_QH (0x80) /* Invalidation Queue Head, 64 bit */ 226*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_QT (0x88) /* Invalidation Queue Tail, 64 bit */ 227*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_QAR (0x90) /* Invalidtion Queue Addr Reg, 64 bit */ 228*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_CSR (0x9C) /* Inval Compl Status Reg, 32 bit */ 229*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_CECR (0xA0) /* Inval Compl Evnt Ctrl Reg, 32 bit */ 230*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_CEDR (0xA4) /* Inval Compl Evnt Data Reg, 32 bit */ 231*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_CEAR (0xA8) /* Inval Compl Event Addr Reg, 32 bit */ 232*3a634bfcSVikram Hegde #define IMMU_REG_INVAL_CEUAR (0xAC) /* Inval Comp Evnt Up Addr reg, 32bit */ 233*3a634bfcSVikram Hegde #define IMMU_REG_IRTAR (0xB8) /* INTR Remap Tbl Addr Reg, 64 bit */ 234*3a634bfcSVikram Hegde 235*3a634bfcSVikram Hegde /* ioapic memory region */ 236*3a634bfcSVikram Hegde #define IOAPIC_REGION_START (0xfee00000) 237*3a634bfcSVikram Hegde #define IOAPIC_REGION_END (0xfeefffff) 238*3a634bfcSVikram Hegde 239*3a634bfcSVikram Hegde /* fault register */ 240*3a634bfcSVikram Hegde #define IMMU_FAULT_STS_PPF (2) 241*3a634bfcSVikram Hegde #define IMMU_FAULT_STS_PFO (1) 242*3a634bfcSVikram Hegde #define IMMU_FAULT_STS_ITE (1 << 6) 243*3a634bfcSVikram Hegde #define IMMU_FAULT_STS_ICE (1 << 5) 244*3a634bfcSVikram Hegde #define IMMU_FAULT_STS_IQE (1 << 4) 245*3a634bfcSVikram Hegde #define IMMU_FAULT_GET_INDEX(x) ((((uint64_t)x) >> 8) & 0xff) 246*3a634bfcSVikram Hegde #define IMMU_FRR_GET_F(x) (((uint64_t)x) >> 63) 247*3a634bfcSVikram Hegde #define IMMU_FRR_GET_FR(x) ((((uint64_t)x) >> 32) & 0xff) 248*3a634bfcSVikram Hegde #define IMMU_FRR_GET_FT(x) ((((uint64_t)x) >> 62) & 0x1) 249*3a634bfcSVikram Hegde #define IMMU_FRR_GET_SID(x) ((x) & 0xffff) 250*3a634bfcSVikram Hegde 251*3a634bfcSVikram Hegde /* (ex)capability register */ 252*3a634bfcSVikram Hegde #define IMMU_CAP_GET_NFR(x) (((((uint64_t)x) >> 40) & 0xff) + 1) 253*3a634bfcSVikram Hegde #define IMMU_CAP_GET_DWD(x) ((((uint64_t)x) >> 54) & 1) 254*3a634bfcSVikram Hegde #define IMMU_CAP_GET_DRD(x) ((((uint64_t)x) >> 55) & 1) 255*3a634bfcSVikram Hegde #define IMMU_CAP_GET_PSI(x) ((((uint64_t)x) >> 39) & 1) 256*3a634bfcSVikram Hegde #define IMMU_CAP_GET_SPS(x) ((((uint64_t)x) >> 34) & 0xf) 257*3a634bfcSVikram Hegde #define IMMU_CAP_GET_ISOCH(x) ((((uint64_t)x) >> 23) & 1) 258*3a634bfcSVikram Hegde #define IMMU_CAP_GET_ZLR(x) ((((uint64_t)x) >> 22) & 1) 259*3a634bfcSVikram Hegde #define IMMU_CAP_GET_MAMV(x) ((((uint64_t)x) >> 48) & 0x3f) 260*3a634bfcSVikram Hegde #define IMMU_CAP_GET_CM(x) ((((uint64_t)x) >> 7) & 1) 261*3a634bfcSVikram Hegde #define IMMU_CAP_GET_PHMR(x) ((((uint64_t)x) >> 6) & 1) 262*3a634bfcSVikram Hegde #define IMMU_CAP_GET_PLMR(x) ((((uint64_t)x) >> 5) & 1) 263*3a634bfcSVikram Hegde #define IMMU_CAP_GET_RWBF(x) ((((uint64_t)x) >> 4) & 1) 264*3a634bfcSVikram Hegde #define IMMU_CAP_GET_AFL(x) ((((uint64_t)x) >> 3) & 1) 265*3a634bfcSVikram Hegde #define IMMU_CAP_GET_FRO(x) (((((uint64_t)x) >> 24) & 0x3ff) * 16) 266*3a634bfcSVikram Hegde #define IMMU_CAP_MGAW(x) (((((uint64_t)x) >> 16) & 0x3f) + 1) 267*3a634bfcSVikram Hegde #define IMMU_CAP_SAGAW(x) ((((uint64_t)x) >> 8) & 0x1f) 268*3a634bfcSVikram Hegde #define IMMU_CAP_ND(x) (1 << (((x) & 0x7) *2 + 4)) -1 269*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_IRO(x) (((((uint64_t)x) >> 8) & 0x3ff) << 4) 270*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_MHMV(x) (((uint64_t)x >> 20) & 0xf) 271*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_SC(x) ((x) & 0x80) 272*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_PT(x) ((x) & 0x40) 273*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_CH(x) ((x) & 0x20) 274*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_EIM(x) ((x) & 0x10) 275*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_IR(x) ((x) & 0x8) 276*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_DI(x) ((x) & 0x4) 277*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_QI(x) ((x) & 0x2) 278*3a634bfcSVikram Hegde #define IMMU_ECAP_GET_C(x) ((x) & 0x1) 279*3a634bfcSVikram Hegde 280*3a634bfcSVikram Hegde #define IMMU_CAP_SET_RWBF(x) ((x) |= (1 << 4)) 281*3a634bfcSVikram Hegde 282*3a634bfcSVikram Hegde 283*3a634bfcSVikram Hegde /* iotlb invalidation */ 284*3a634bfcSVikram Hegde #define TLB_INV_GLOBAL (((uint64_t)1) << 60) 285*3a634bfcSVikram Hegde #define TLB_INV_DOMAIN (((uint64_t)2) << 60) 286*3a634bfcSVikram Hegde #define TLB_INV_PAGE (((uint64_t)3) << 60) 287*3a634bfcSVikram Hegde #define TLB_INV_GET_IAIG(x) ((((uint64_t)x) >> 57) & 7) 288*3a634bfcSVikram Hegde #define TLB_INV_DRAIN_READ (((uint64_t)1) << 49) 289*3a634bfcSVikram Hegde #define TLB_INV_DRAIN_WRITE (((uint64_t)1) << 48) 290*3a634bfcSVikram Hegde #define TLB_INV_DID(x) (((uint64_t)((x) & 0xffff)) << 32) 291*3a634bfcSVikram Hegde #define TLB_INV_IVT (((uint64_t)1) << 63) 292*3a634bfcSVikram Hegde #define TLB_IVA_HINT(x) (((x) & 0x1) << 6) 293*3a634bfcSVikram Hegde #define TLB_IVA_LEAF 1 294*3a634bfcSVikram Hegde #define TLB_IVA_WHOLE 0 295*3a634bfcSVikram Hegde 296*3a634bfcSVikram Hegde /* dont use value 0 for enums - to catch unit 8 */ 297*3a634bfcSVikram Hegde typedef enum iotlb_inv { 298*3a634bfcSVikram Hegde IOTLB_PSI = 1, 299*3a634bfcSVikram Hegde IOTLB_DSI, 300*3a634bfcSVikram Hegde IOTLB_GLOBAL 301*3a634bfcSVikram Hegde } immu_iotlb_inv_t; 302*3a634bfcSVikram Hegde 303*3a634bfcSVikram Hegde typedef enum context_inv { 304*3a634bfcSVikram Hegde CONTEXT_FSI = 1, 305*3a634bfcSVikram Hegde CONTEXT_DSI, 306*3a634bfcSVikram Hegde CONTEXT_GLOBAL 307*3a634bfcSVikram Hegde } immu_context_inv_t; 308*3a634bfcSVikram Hegde 309*3a634bfcSVikram Hegde /* context invalidation */ 310*3a634bfcSVikram Hegde #define CCMD_INV_ICC (((uint64_t)1) << 63) 311*3a634bfcSVikram Hegde #define CCMD_INV_GLOBAL (((uint64_t)1) << 61) 312*3a634bfcSVikram Hegde #define CCMD_INV_DOMAIN (((uint64_t)2) << 61) 313*3a634bfcSVikram Hegde #define CCMD_INV_DEVICE (((uint64_t)3) << 61) 314*3a634bfcSVikram Hegde #define CCMD_INV_DID(x) ((uint64_t)((x) & 0xffff)) 315*3a634bfcSVikram Hegde #define CCMD_INV_SID(x) (((uint64_t)((x) & 0xffff)) << 16) 316*3a634bfcSVikram Hegde #define CCMD_INV_FM(x) (((uint64_t)((x) & 0x3)) << 32) 317*3a634bfcSVikram Hegde 318*3a634bfcSVikram Hegde /* global command register */ 319*3a634bfcSVikram Hegde #define IMMU_GCMD_TE (((uint32_t)1) << 31) 320*3a634bfcSVikram Hegde #define IMMU_GCMD_SRTP (((uint32_t)1) << 30) 321*3a634bfcSVikram Hegde #define IMMU_GCMD_SFL (((uint32_t)1) << 29) 322*3a634bfcSVikram Hegde #define IMMU_GCMD_EAFL (((uint32_t)1) << 28) 323*3a634bfcSVikram Hegde #define IMMU_GCMD_WBF (((uint32_t)1) << 27) 324*3a634bfcSVikram Hegde #define IMMU_GCMD_QIE (((uint32_t)1) << 26) 325*3a634bfcSVikram Hegde #define IMMU_GCMD_IRE (((uint32_t)1) << 25) 326*3a634bfcSVikram Hegde #define IMMU_GCMD_SIRTP (((uint32_t)1) << 24) 327*3a634bfcSVikram Hegde #define IMMU_GCMD_CFI (((uint32_t)1) << 23) 328*3a634bfcSVikram Hegde 329*3a634bfcSVikram Hegde /* global status register */ 330*3a634bfcSVikram Hegde #define IMMU_GSTS_TES (((uint32_t)1) << 31) 331*3a634bfcSVikram Hegde #define IMMU_GSTS_RTPS (((uint32_t)1) << 30) 332*3a634bfcSVikram Hegde #define IMMU_GSTS_FLS (((uint32_t)1) << 29) 333*3a634bfcSVikram Hegde #define IMMU_GSTS_AFLS (((uint32_t)1) << 28) 334*3a634bfcSVikram Hegde #define IMMU_GSTS_WBFS (((uint32_t)1) << 27) 335*3a634bfcSVikram Hegde #define IMMU_GSTS_QIES (((uint32_t)1) << 26) 336*3a634bfcSVikram Hegde #define IMMU_GSTS_IRES (((uint32_t)1) << 25) 337*3a634bfcSVikram Hegde #define IMMU_GSTS_IRTPS (((uint32_t)1) << 24) 338*3a634bfcSVikram Hegde #define IMMU_GSTS_CFIS (((uint32_t)1) << 23) 339*3a634bfcSVikram Hegde 340*3a634bfcSVikram Hegde /* psi address mask */ 341*3a634bfcSVikram Hegde #define ADDR_AM_MAX(m) (((uint_t)1) << (m)) 342*3a634bfcSVikram Hegde #define ADDR_AM_OFFSET(n, m) ((n) & (ADDR_AM_MAX(m) - 1)) 343*3a634bfcSVikram Hegde 344*3a634bfcSVikram Hegde /* dmar fault event */ 345*3a634bfcSVikram Hegde #define IMMU_INTR_IPL (8) 346*3a634bfcSVikram Hegde #define IMMU_REG_FEVNT_CON_IM_SHIFT (31) 347*3a634bfcSVikram Hegde 348*3a634bfcSVikram Hegde #define IMMU_ALLOC_RESOURCE_DELAY (drv_usectohz(5000)) 349*3a634bfcSVikram Hegde 350*3a634bfcSVikram Hegde /* max value of Size field of Interrupt Remapping Table Address Register */ 351*3a634bfcSVikram Hegde #define INTRMAP_MAX_IRTA_SIZE 0xf 352*3a634bfcSVikram Hegde 353*3a634bfcSVikram Hegde /* interrupt remapping table entry size */ 354*3a634bfcSVikram Hegde #define INTRMAP_RTE_SIZE 0x10 355*3a634bfcSVikram Hegde 356*3a634bfcSVikram Hegde /* ioapic redirection table entry related shift of remappable interrupt */ 357*3a634bfcSVikram Hegde #define INTRMAP_IOAPIC_IDX_SHIFT 17 358*3a634bfcSVikram Hegde #define INTRMAP_IOAPIC_FORMAT_SHIFT 16 359*3a634bfcSVikram Hegde #define INTRMAP_IOAPIC_TM_SHIFT 15 360*3a634bfcSVikram Hegde #define INTRMAP_IOAPIC_POL_SHIFT 13 361*3a634bfcSVikram Hegde #define INTRMAP_IOAPIC_IDX15_SHIFT 11 362*3a634bfcSVikram Hegde 363*3a634bfcSVikram Hegde /* msi intr entry related shift of remappable interrupt */ 364*3a634bfcSVikram Hegde #define INTRMAP_MSI_IDX_SHIFT 5 365*3a634bfcSVikram Hegde #define INTRMAP_MSI_FORMAT_SHIFT 4 366*3a634bfcSVikram Hegde #define INTRMAP_MSI_SHV_SHIFT 3 367*3a634bfcSVikram Hegde #define INTRMAP_MSI_IDX15_SHIFT 2 368*3a634bfcSVikram Hegde 369*3a634bfcSVikram Hegde #define INTRMAP_IDX_FULL (uint_t)-1 370*3a634bfcSVikram Hegde 371*3a634bfcSVikram Hegde #define RDT_DLM(rdt) BITX((rdt), 10, 8) 372*3a634bfcSVikram Hegde #define RDT_DM(rdt) BT_TEST(&(rdt), 11) 373*3a634bfcSVikram Hegde #define RDT_POL(rdt) BT_TEST(&(rdt), 13) 374*3a634bfcSVikram Hegde #define RDT_TM(rdt) BT_TEST(&(rdt), 15) 375*3a634bfcSVikram Hegde 376*3a634bfcSVikram Hegde #define INTRMAP_DISABLE (void *)-1 377*3a634bfcSVikram Hegde 378*3a634bfcSVikram Hegde /* 379*3a634bfcSVikram Hegde * invalidation granularity 380*3a634bfcSVikram Hegde */ 381*3a634bfcSVikram Hegde typedef enum { 382*3a634bfcSVikram Hegde TLB_INV_G_GLOBAL = 1, 383*3a634bfcSVikram Hegde TLB_INV_G_DOMAIN, 384*3a634bfcSVikram Hegde TLB_INV_G_PAGE 385*3a634bfcSVikram Hegde } tlb_inv_g_t; 386*3a634bfcSVikram Hegde 387*3a634bfcSVikram Hegde typedef enum { 388*3a634bfcSVikram Hegde CTT_INV_G_GLOBAL = 1, 389*3a634bfcSVikram Hegde CTT_INV_G_DOMAIN, 390*3a634bfcSVikram Hegde CTT_INV_G_DEVICE 391*3a634bfcSVikram Hegde } ctt_inv_g_t; 392*3a634bfcSVikram Hegde 393*3a634bfcSVikram Hegde typedef enum { 394*3a634bfcSVikram Hegde IEC_INV_GLOBAL = 0, 395*3a634bfcSVikram Hegde IEC_INV_INDEX 396*3a634bfcSVikram Hegde } iec_inv_g_t; 397*3a634bfcSVikram Hegde 398*3a634bfcSVikram Hegde 399*3a634bfcSVikram Hegde struct inv_queue_state; 400*3a634bfcSVikram Hegde struct intrmap_tbl_state; 401*3a634bfcSVikram Hegde 402*3a634bfcSVikram Hegde /* A software page table structure */ 403*3a634bfcSVikram Hegde typedef struct pgtable { 404*3a634bfcSVikram Hegde krwlock_t swpg_rwlock; 405*3a634bfcSVikram Hegde caddr_t hwpg_vaddr; /* HW pgtable VA */ 406*3a634bfcSVikram Hegde paddr_t hwpg_paddr; /* HW pgtable PA */ 407*3a634bfcSVikram Hegde ddi_dma_handle_t hwpg_dmahdl; 408*3a634bfcSVikram Hegde ddi_acc_handle_t hwpg_memhdl; 409*3a634bfcSVikram Hegde struct pgtable **swpg_next_array; 410*3a634bfcSVikram Hegde list_node_t swpg_domain_node; /* domain list of pgtables */ 411*3a634bfcSVikram Hegde } pgtable_t; 412*3a634bfcSVikram Hegde 413*3a634bfcSVikram Hegde /* interrupt remapping table state info */ 414*3a634bfcSVikram Hegde typedef struct intrmap { 415*3a634bfcSVikram Hegde kmutex_t intrmap_lock; 416*3a634bfcSVikram Hegde ddi_dma_handle_t intrmap_dma_hdl; 417*3a634bfcSVikram Hegde ddi_acc_handle_t intrmap_acc_hdl; 418*3a634bfcSVikram Hegde caddr_t intrmap_vaddr; 419*3a634bfcSVikram Hegde paddr_t intrmap_paddr; 420*3a634bfcSVikram Hegde uint_t intrmap_size; 421*3a634bfcSVikram Hegde bitset_t intrmap_map; 422*3a634bfcSVikram Hegde uint_t intrmap_free; 423*3a634bfcSVikram Hegde } intrmap_t; 424*3a634bfcSVikram Hegde 425*3a634bfcSVikram Hegde typedef struct hw_rce { 426*3a634bfcSVikram Hegde uint64_t lo; 427*3a634bfcSVikram Hegde uint64_t hi; 428*3a634bfcSVikram Hegde } hw_rce_t; 429*3a634bfcSVikram Hegde 430*3a634bfcSVikram Hegde 431*3a634bfcSVikram Hegde #define ROOT_GET_P(hrent) ((hrent)->lo & 0x1) 432*3a634bfcSVikram Hegde #define ROOT_SET_P(hrent) ((hrent)->lo |= 0x1) 433*3a634bfcSVikram Hegde 434*3a634bfcSVikram Hegde #define ROOT_GET_CONT(hrent) ((hrent)->lo & ~(0xFFF)) 435*3a634bfcSVikram Hegde #define ROOT_SET_CONT(hrent, paddr) ((hrent)->lo |= (paddr & (~0xFFF))) 436*3a634bfcSVikram Hegde 437*3a634bfcSVikram Hegde #define TTYPE_XLATE_ONLY (0x0) 438*3a634bfcSVikram Hegde #define TTYPE_XLATE_IOTLB (0x1) 439*3a634bfcSVikram Hegde #define TTYPE_PASSTHRU (0x2) 440*3a634bfcSVikram Hegde #define TTYPE_RESERVED (0x3) 441*3a634bfcSVikram Hegde 442*3a634bfcSVikram Hegde #define CONT_GET_DID(hcent) ((((uint64_t)(hcent)->hi) >> 8) & 0xFFFF) 443*3a634bfcSVikram Hegde #define CONT_SET_DID(hcent, did) ((hcent)->hi |= ((0xFFFF & (did)) << 8)) 444*3a634bfcSVikram Hegde 445*3a634bfcSVikram Hegde #define CONT_GET_AVAIL(hcent) ((((uint64_t)((hcent)->hi)) >> 0x3) & 0xF) 446*3a634bfcSVikram Hegde #define CONT_SET_AVAIL(hcent, av) ((hcent)->hi |= ((0xF & (av)) << 0x3)) 447*3a634bfcSVikram Hegde 448*3a634bfcSVikram Hegde #define CONT_GET_LO_AW(hcent) (30 + 9 *((hcent)->hi & 0x7)) 449*3a634bfcSVikram Hegde #define CONT_GET_AW(hcent) \ 450*3a634bfcSVikram Hegde ((CONT_GET_LO_AW(hcent) == 66) ? 64 : CONT_GET_LO_AW(hcent)) 451*3a634bfcSVikram Hegde #define CONT_SET_AW(hcent, aw) \ 452*3a634bfcSVikram Hegde ((hcent)->hi |= (((((aw) + 2) - 30) / 9) & 0x7)) 453*3a634bfcSVikram Hegde 454*3a634bfcSVikram Hegde #define CONT_GET_ASR(hcent) ((hcent)->lo & ~(0xFFF)) 455*3a634bfcSVikram Hegde #define CONT_SET_ASR(hcent, paddr) ((hcent)->lo |= (paddr & (~0xFFF))) 456*3a634bfcSVikram Hegde 457*3a634bfcSVikram Hegde #define CONT_GET_TTYPE(hcent) ((((uint64_t)(hcent)->lo) >> 0x2) & 0x3) 458*3a634bfcSVikram Hegde #define CONT_SET_TTYPE(hcent, ttype) ((hcent)->lo |= (((ttype) & 0x3) << 0x2)) 459*3a634bfcSVikram Hegde 460*3a634bfcSVikram Hegde #define CONT_GET_P(hcent) ((hcent)->lo & 0x1) 461*3a634bfcSVikram Hegde #define CONT_SET_P(hcent) ((hcent)->lo |= 0x1) 462*3a634bfcSVikram Hegde 463*3a634bfcSVikram Hegde 464*3a634bfcSVikram Hegde /* we use the bit 63 (available for system SW) as a present bit */ 465*3a634bfcSVikram Hegde #define PDTE_SW4(hw_pdte) ((hw_pdte) & ((uint64_t)1<<63)) 466*3a634bfcSVikram Hegde #define PDTE_CLEAR_SW4(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<63)) 467*3a634bfcSVikram Hegde 468*3a634bfcSVikram Hegde #define PDTE_P(hw_pdte) ((hw_pdte) & ((uint64_t)1<<63)) 469*3a634bfcSVikram Hegde #define PDTE_CLEAR_P(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<63)) 470*3a634bfcSVikram Hegde #define PDTE_SET_P(hw_pdte) ((hw_pdte) |= ((uint64_t)1<<63)) 471*3a634bfcSVikram Hegde 472*3a634bfcSVikram Hegde #define PDTE_TM(hw_pdte) ((hw_pdte) & ((uint64_t)1<<62)) 473*3a634bfcSVikram Hegde #define PDTE_CLEAR_TM(hw_pdte) ((hw_pdte) &= ~((uint64_t)1<<62)) 474*3a634bfcSVikram Hegde 475*3a634bfcSVikram Hegde #define PDTE_SW3(hw_pdte) \ 476*3a634bfcSVikram Hegde (((hw_pdte) & ~(((uint64_t)0x3<<62)|(((uint64_t)1<<52)-1))) >> 52) 477*3a634bfcSVikram Hegde #define PDTE_SW3_OVERFLOW(hw_pdte) \ 478*3a634bfcSVikram Hegde (PDTE_SW3(hw_pdte) == 0x3FF) 479*3a634bfcSVikram Hegde #define PDTE_CLEAR_SW3(hw_pdte) \ 480*3a634bfcSVikram Hegde ((hw_pdte) &= (((uint64_t)0x3<<62)|(((uint64_t)1<<52)-1))) 481*3a634bfcSVikram Hegde #define PDTE_SET_SW3(hw_pdte, ref) \ 482*3a634bfcSVikram Hegde ((hw_pdte) |= ((((uint64_t)(ref)) & 0x3FF) << 52)) 483*3a634bfcSVikram Hegde 484*3a634bfcSVikram Hegde #define PDTE_PADDR(hw_pdte) ((hw_pdte) & ~(((uint64_t)0xFFF<<52)|((1<<12)-1))) 485*3a634bfcSVikram Hegde #define PDTE_CLEAR_PADDR(hw_pdte) \ 486*3a634bfcSVikram Hegde ((hw_pdte) &= (((uint64_t)0xFFF<<52)|((1<<12)-1))) 487*3a634bfcSVikram Hegde #define PDTE_SET_PADDR(hw_pdte, paddr) ((hw_pdte) |= PDTE_PADDR(paddr)) 488*3a634bfcSVikram Hegde 489*3a634bfcSVikram Hegde #define PDTE_SNP(hw_pdte) ((hw_pdte) & (1<<11)) 490*3a634bfcSVikram Hegde #define PDTE_CLEAR_SNP(hw_pdte) ((hw_pdte) &= ~(1<<11)) 491*3a634bfcSVikram Hegde #define PDTE_SET_SNP(hw_pdte) ((hw_pdte) |= (1<<11)) 492*3a634bfcSVikram Hegde 493*3a634bfcSVikram Hegde #define PDTE_SW2(hw_pdte) ((hw_pdte) & (0x700)) 494*3a634bfcSVikram Hegde #define PDTE_CLEAR_SW2(hw_pdte) ((hw_pdte) &= ~(0x700)) 495*3a634bfcSVikram Hegde 496*3a634bfcSVikram Hegde #define PDTE_SP(hw_pdte) ((hw_pdte) & (0x80)) 497*3a634bfcSVikram Hegde #define PDTE_CLEAR_SP(hw_pdte) ((hw_pdte) &= ~(0x80)) 498*3a634bfcSVikram Hegde 499*3a634bfcSVikram Hegde #define PDTE_SW1(hw_pdte) ((hw_pdte) & (0x7C)) 500*3a634bfcSVikram Hegde #define PDTE_CLEAR_SW1(hw_pdte) ((hw_pdte) &= ~(0x7C)) 501*3a634bfcSVikram Hegde 502*3a634bfcSVikram Hegde #define PDTE_WRITE(hw_pdte) ((hw_pdte) & (0x2)) 503*3a634bfcSVikram Hegde #define PDTE_CLEAR_WRITE(hw_pdte) ((hw_pdte) &= ~(0x2)) 504*3a634bfcSVikram Hegde #define PDTE_SET_WRITE(hw_pdte) ((hw_pdte) |= (0x2)) 505*3a634bfcSVikram Hegde 506*3a634bfcSVikram Hegde #define PDTE_READ(hw_pdte) ((hw_pdte) & (0x1)) 507*3a634bfcSVikram Hegde #define PDTE_CLEAR_READ(hw_pdte) ((hw_pdte) &= ~(0x1)) 508*3a634bfcSVikram Hegde #define PDTE_SET_READ(hw_pdte) ((hw_pdte) |= (0x1)) 509*3a634bfcSVikram Hegde 510*3a634bfcSVikram Hegde typedef struct immu { 511*3a634bfcSVikram Hegde kmutex_t immu_lock; 512*3a634bfcSVikram Hegde char *immu_name; 513*3a634bfcSVikram Hegde 514*3a634bfcSVikram Hegde /* lock grabbed by interrupt handler */ 515*3a634bfcSVikram Hegde kmutex_t immu_intr_lock; 516*3a634bfcSVikram Hegde 517*3a634bfcSVikram Hegde /* ACPI/DMAR table related */ 518*3a634bfcSVikram Hegde void *immu_dmar_unit; 519*3a634bfcSVikram Hegde dev_info_t *immu_dip; 520*3a634bfcSVikram Hegde struct domain *immu_unity_domain; 521*3a634bfcSVikram Hegde 522*3a634bfcSVikram Hegde /* IOMMU register related */ 523*3a634bfcSVikram Hegde kmutex_t immu_regs_lock; 524*3a634bfcSVikram Hegde boolean_t immu_regs_setup; 525*3a634bfcSVikram Hegde boolean_t immu_regs_running; 526*3a634bfcSVikram Hegde boolean_t immu_regs_quiesced; 527*3a634bfcSVikram Hegde ddi_acc_handle_t immu_regs_handle; 528*3a634bfcSVikram Hegde caddr_t immu_regs_addr; 529*3a634bfcSVikram Hegde uint64_t immu_regs_cap; 530*3a634bfcSVikram Hegde uint64_t immu_regs_excap; 531*3a634bfcSVikram Hegde uint32_t immu_regs_cmdval; 532*3a634bfcSVikram Hegde uint32_t immu_regs_intr_msi_addr; 533*3a634bfcSVikram Hegde uint32_t immu_regs_intr_msi_data; 534*3a634bfcSVikram Hegde uint32_t immu_regs_intr_uaddr; 535*3a634bfcSVikram Hegde 536*3a634bfcSVikram Hegde /* DVMA related */ 537*3a634bfcSVikram Hegde kmutex_t immu_dvma_lock; 538*3a634bfcSVikram Hegde boolean_t immu_dvma_setup; 539*3a634bfcSVikram Hegde boolean_t immu_dvma_running; 540*3a634bfcSVikram Hegde int immu_dvma_gaw; 541*3a634bfcSVikram Hegde int immu_dvma_agaw; 542*3a634bfcSVikram Hegde int immu_dvma_nlevels; 543*3a634bfcSVikram Hegde boolean_t immu_dvma_coherent; 544*3a634bfcSVikram Hegde 545*3a634bfcSVikram Hegde /* DVMA context related */ 546*3a634bfcSVikram Hegde krwlock_t immu_ctx_rwlock; 547*3a634bfcSVikram Hegde pgtable_t *immu_ctx_root; 548*3a634bfcSVikram Hegde 549*3a634bfcSVikram Hegde /* DVMA domain related */ 550*3a634bfcSVikram Hegde int immu_max_domains; 551*3a634bfcSVikram Hegde vmem_t *immu_did_arena; 552*3a634bfcSVikram Hegde char immu_did_arena_name[IMMU_MAXNAMELEN]; 553*3a634bfcSVikram Hegde list_t immu_domain_list; 554*3a634bfcSVikram Hegde 555*3a634bfcSVikram Hegde /* DVMA special devices */ 556*3a634bfcSVikram Hegde boolean_t immu_dvma_gfx_only; 557*3a634bfcSVikram Hegde list_t immu_dvma_lpc_list; 558*3a634bfcSVikram Hegde list_t immu_dvma_gfx_list; 559*3a634bfcSVikram Hegde 560*3a634bfcSVikram Hegde /* interrupt remapping related */ 561*3a634bfcSVikram Hegde kmutex_t immu_intrmap_lock; 562*3a634bfcSVikram Hegde boolean_t immu_intrmap_setup; 563*3a634bfcSVikram Hegde boolean_t immu_intrmap_running; 564*3a634bfcSVikram Hegde intrmap_t *immu_intrmap; 565*3a634bfcSVikram Hegde uint64_t immu_intrmap_irta_reg; 566*3a634bfcSVikram Hegde 567*3a634bfcSVikram Hegde /* queued invalidation related */ 568*3a634bfcSVikram Hegde kmutex_t immu_qinv_lock; 569*3a634bfcSVikram Hegde boolean_t immu_qinv_setup; 570*3a634bfcSVikram Hegde boolean_t immu_qinv_running; 571*3a634bfcSVikram Hegde boolean_t immu_qinv_enabled; 572*3a634bfcSVikram Hegde void *immu_qinv; 573*3a634bfcSVikram Hegde uint64_t immu_qinv_reg_value; 574*3a634bfcSVikram Hegde 575*3a634bfcSVikram Hegde /* list_node for system-wide list of DMAR units */ 576*3a634bfcSVikram Hegde list_node_t immu_node; 577*3a634bfcSVikram Hegde } immu_t; 578*3a634bfcSVikram Hegde 579*3a634bfcSVikram Hegde /* properties that control DVMA */ 580*3a634bfcSVikram Hegde #define DDI_DVMA_MAPTYPE_PROP "ddi-dvma-mapping" 581*3a634bfcSVikram Hegde 582*3a634bfcSVikram Hegde /* property values */ 583*3a634bfcSVikram Hegde #define DDI_DVMA_MAPTYPE_UNITY "unity" 584*3a634bfcSVikram Hegde 585*3a634bfcSVikram Hegde typedef enum immu_maptype { 586*3a634bfcSVikram Hegde IMMU_MAPTYPE_BAD = 0, /* 0 is always bad */ 587*3a634bfcSVikram Hegde IMMU_MAPTYPE_UNITY = 1, 588*3a634bfcSVikram Hegde IMMU_MAPTYPE_XLATE 589*3a634bfcSVikram Hegde } immu_maptype_t; 590*3a634bfcSVikram Hegde 591*3a634bfcSVikram Hegde /* 592*3a634bfcSVikram Hegde * domain_t 593*3a634bfcSVikram Hegde * 594*3a634bfcSVikram Hegde */ 595*3a634bfcSVikram Hegde typedef struct domain { 596*3a634bfcSVikram Hegde /* the basics */ 597*3a634bfcSVikram Hegde uint_t dom_did; 598*3a634bfcSVikram Hegde immu_t *dom_immu; 599*3a634bfcSVikram Hegde 600*3a634bfcSVikram Hegde /* mapping related */ 601*3a634bfcSVikram Hegde immu_maptype_t dom_maptype; 602*3a634bfcSVikram Hegde vmem_t *dom_dvma_arena; 603*3a634bfcSVikram Hegde char dom_dvma_arena_name[IMMU_MAXNAMELEN]; 604*3a634bfcSVikram Hegde 605*3a634bfcSVikram Hegde /* pgtables */ 606*3a634bfcSVikram Hegde pgtable_t *dom_pgtable_root; 607*3a634bfcSVikram Hegde krwlock_t dom_pgtable_rwlock; 608*3a634bfcSVikram Hegde 609*3a634bfcSVikram Hegde /* list of pgtables for this domain */ 610*3a634bfcSVikram Hegde list_t dom_pglist; 611*3a634bfcSVikram Hegde 612*3a634bfcSVikram Hegde /* list node for list of domains (unity or xlate) */ 613*3a634bfcSVikram Hegde list_node_t dom_maptype_node; 614*3a634bfcSVikram Hegde /* list node for list of domains off immu */ 615*3a634bfcSVikram Hegde list_node_t dom_immu_node; 616*3a634bfcSVikram Hegde } domain_t; 617*3a634bfcSVikram Hegde 618*3a634bfcSVikram Hegde typedef enum immu_pcib { 619*3a634bfcSVikram Hegde IMMU_PCIB_BAD = 0, 620*3a634bfcSVikram Hegde IMMU_PCIB_NOBDF, 621*3a634bfcSVikram Hegde IMMU_PCIB_PCIE_PCIE, 622*3a634bfcSVikram Hegde IMMU_PCIB_PCIE_PCI, 623*3a634bfcSVikram Hegde IMMU_PCIB_PCI_PCI, 624*3a634bfcSVikram Hegde IMMU_PCIB_ENDPOINT 625*3a634bfcSVikram Hegde } immu_pcib_t; 626*3a634bfcSVikram Hegde 627*3a634bfcSVikram Hegde /* 628*3a634bfcSVikram Hegde * immu_devi_t 629*3a634bfcSVikram Hegde * Intel IOMMU in devinfo node 630*3a634bfcSVikram Hegde */ 631*3a634bfcSVikram Hegde typedef struct immu_devi { 632*3a634bfcSVikram Hegde /* pci seg, bus, dev, func */ 633*3a634bfcSVikram Hegde int imd_seg; 634*3a634bfcSVikram Hegde int imd_bus; 635*3a634bfcSVikram Hegde int imd_devfunc; 636*3a634bfcSVikram Hegde 637*3a634bfcSVikram Hegde /* ppb information */ 638*3a634bfcSVikram Hegde immu_pcib_t imd_pcib_type; 639*3a634bfcSVikram Hegde int imd_sec; 640*3a634bfcSVikram Hegde int imd_sub; 641*3a634bfcSVikram Hegde 642*3a634bfcSVikram Hegde /* identifier for special devices */ 643*3a634bfcSVikram Hegde boolean_t imd_display; 644*3a634bfcSVikram Hegde boolean_t imd_lpc; 645*3a634bfcSVikram Hegde 646*3a634bfcSVikram Hegde /* dmar unit to which this dip belongs */ 647*3a634bfcSVikram Hegde immu_t *imd_immu; 648*3a634bfcSVikram Hegde 649*3a634bfcSVikram Hegde /* domain ptr */ 650*3a634bfcSVikram Hegde domain_t *imd_domain; 651*3a634bfcSVikram Hegde dev_info_t *imd_ddip; 652*3a634bfcSVikram Hegde 653*3a634bfcSVikram Hegde /* my devinfo */ 654*3a634bfcSVikram Hegde dev_info_t *imd_dip; 655*3a634bfcSVikram Hegde 656*3a634bfcSVikram Hegde /* 657*3a634bfcSVikram Hegde * if we are a "special" devinfo 658*3a634bfcSVikram Hegde * the node for the special linked list 659*3a634bfcSVikram Hegde * off the DMAR unit structure 660*3a634bfcSVikram Hegde */ 661*3a634bfcSVikram Hegde list_node_t imd_spc_node; 662*3a634bfcSVikram Hegde } immu_devi_t; 663*3a634bfcSVikram Hegde 664*3a634bfcSVikram Hegde #define IMMU_DEVI(dip) ((immu_devi_t *)(DEVI(dip)->devi_iommu)) 665*3a634bfcSVikram Hegde #define IMMU_DEVI_SET(dip, imd) (DEVI(dip)->devi_iommu = (void *)imd) 666*3a634bfcSVikram Hegde 667*3a634bfcSVikram Hegde /* 668*3a634bfcSVikram Hegde * struct dmar_arg 669*3a634bfcSVikram Hegde */ 670*3a634bfcSVikram Hegde typedef struct immu_arg { 671*3a634bfcSVikram Hegde int ima_seg; 672*3a634bfcSVikram Hegde int ima_bus; 673*3a634bfcSVikram Hegde int ima_devfunc; 674*3a634bfcSVikram Hegde dev_info_t *ima_rdip; 675*3a634bfcSVikram Hegde dev_info_t *ima_ddip; 676*3a634bfcSVikram Hegde } immu_arg_t; 677*3a634bfcSVikram Hegde 678*3a634bfcSVikram Hegde /* 679*3a634bfcSVikram Hegde * Globals used by IOMMU code 680*3a634bfcSVikram Hegde */ 681*3a634bfcSVikram Hegde /* shared between IOMMU files */ 682*3a634bfcSVikram Hegde extern dev_info_t *root_devinfo; 683*3a634bfcSVikram Hegde extern kmutex_t immu_lock; 684*3a634bfcSVikram Hegde extern list_t immu_list; 685*3a634bfcSVikram Hegde extern boolean_t immu_setup; 686*3a634bfcSVikram Hegde extern boolean_t immu_running; 687*3a634bfcSVikram Hegde extern kmutex_t ioapic_drhd_lock; 688*3a634bfcSVikram Hegde extern list_t ioapic_drhd_list; 689*3a634bfcSVikram Hegde 690*3a634bfcSVikram Hegde /* switches */ 691*3a634bfcSVikram Hegde 692*3a634bfcSVikram Hegde /* Various features */ 693*3a634bfcSVikram Hegde extern boolean_t immu_enable; 694*3a634bfcSVikram Hegde extern boolean_t immu_dvma_enable; 695*3a634bfcSVikram Hegde extern boolean_t immu_gfxdvma_enable; 696*3a634bfcSVikram Hegde extern boolean_t immu_intrmap_enable; 697*3a634bfcSVikram Hegde extern boolean_t immu_qinv_enable; 698*3a634bfcSVikram Hegde extern boolean_t immu_mmio_safe; 699*3a634bfcSVikram Hegde 700*3a634bfcSVikram Hegde /* various quirks that need working around */ 701*3a634bfcSVikram Hegde extern boolean_t immu_quirk_usbpage0; 702*3a634bfcSVikram Hegde extern boolean_t immu_quirk_usbfullpa; 703*3a634bfcSVikram Hegde extern boolean_t immu_quirk_usbrmrr; 704*3a634bfcSVikram Hegde extern boolean_t immu_quirk_mobile4; 705*3a634bfcSVikram Hegde 706*3a634bfcSVikram Hegde /* debug messages */ 707*3a634bfcSVikram Hegde extern boolean_t immu_dmar_print; 708*3a634bfcSVikram Hegde 709*3a634bfcSVikram Hegde /* ################### Interfaces exported outside IOMMU code ############## */ 710*3a634bfcSVikram Hegde void immu_init(void); 711*3a634bfcSVikram Hegde void immu_startup(void); 712*3a634bfcSVikram Hegde void immu_shutdown(void); 713*3a634bfcSVikram Hegde void immu_destroy(void); 714*3a634bfcSVikram Hegde int immu_map_sgl(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq, 715*3a634bfcSVikram Hegde int prealloc_count, dev_info_t *rdip); 716*3a634bfcSVikram Hegde int immu_unmap_sgl(ddi_dma_impl_t *hp, dev_info_t *rdip); 717*3a634bfcSVikram Hegde void immu_device_tree_changed(void); 718*3a634bfcSVikram Hegde void immu_physmem_update(uint64_t addr, uint64_t size); 719*3a634bfcSVikram Hegde int immu_quiesce(void); 720*3a634bfcSVikram Hegde int immu_unquiesce(void); 721*3a634bfcSVikram Hegde /* ######################################################################### */ 722*3a634bfcSVikram Hegde 723*3a634bfcSVikram Hegde /* ################# Interfaces used within IOMMU code #################### */ 724*3a634bfcSVikram Hegde 725*3a634bfcSVikram Hegde /* functions in rootnex.c */ 726*3a634bfcSVikram Hegde int rootnex_dvcookies_alloc(ddi_dma_impl_t *hp, 727*3a634bfcSVikram Hegde struct ddi_dma_req *dmareq, dev_info_t *rdip, void *arg); 728*3a634bfcSVikram Hegde void rootnex_dvcookies_free(dvcookie_t *dvcookies, void *arg); 729*3a634bfcSVikram Hegde 730*3a634bfcSVikram Hegde /* immu_dmar.c interfaces */ 731*3a634bfcSVikram Hegde int immu_dmar_setup(void); 732*3a634bfcSVikram Hegde int immu_dmar_parse(void); 733*3a634bfcSVikram Hegde void immu_dmar_startup(void); 734*3a634bfcSVikram Hegde void immu_dmar_shutdown(void); 735*3a634bfcSVikram Hegde void immu_dmar_destroy(void); 736*3a634bfcSVikram Hegde boolean_t immu_dmar_blacklisted(char **strings_array, uint_t nstrings); 737*3a634bfcSVikram Hegde immu_t *immu_dmar_get_immu(dev_info_t *rdip); 738*3a634bfcSVikram Hegde char *immu_dmar_unit_name(void *dmar_unit); 739*3a634bfcSVikram Hegde dev_info_t *immu_dmar_unit_dip(void *dmar_unit); 740*3a634bfcSVikram Hegde void immu_dmar_set_immu(void *dmar_unit, immu_t *immu); 741*3a634bfcSVikram Hegde void *immu_dmar_walk_units(int seg, void *dmar_unit); 742*3a634bfcSVikram Hegde boolean_t immu_dmar_intrmap_supported(void); 743*3a634bfcSVikram Hegde uint16_t immu_dmar_ioapic_sid(int ioapicid); 744*3a634bfcSVikram Hegde immu_t *immu_dmar_ioapic_immu(int ioapicid); 745*3a634bfcSVikram Hegde void immu_dmar_rmrr_map(void); 746*3a634bfcSVikram Hegde 747*3a634bfcSVikram Hegde /* immu.c interfaces */ 748*3a634bfcSVikram Hegde int immu_walk_ancestor(dev_info_t *rdip, dev_info_t *ddip, 749*3a634bfcSVikram Hegde int (*func)(dev_info_t *, void *arg), void *arg, 750*3a634bfcSVikram Hegde int *level, immu_flags_t immu_flags); 751*3a634bfcSVikram Hegde 752*3a634bfcSVikram Hegde /* immu_regs.c interfaces */ 753*3a634bfcSVikram Hegde void immu_regs_setup(list_t *immu_list); 754*3a634bfcSVikram Hegde void immu_regs_startup(immu_t *immu); 755*3a634bfcSVikram Hegde int immu_regs_resume(immu_t *immu); 756*3a634bfcSVikram Hegde void immu_regs_suspend(immu_t *immu); 757*3a634bfcSVikram Hegde void immu_regs_shutdown(immu_t *immu); 758*3a634bfcSVikram Hegde void immu_regs_destroy(list_t *immu_list); 759*3a634bfcSVikram Hegde 760*3a634bfcSVikram Hegde void immu_regs_intr(immu_t *immu, uint32_t msi_addr, uint32_t msi_data, 761*3a634bfcSVikram Hegde uint32_t uaddr); 762*3a634bfcSVikram Hegde 763*3a634bfcSVikram Hegde boolean_t immu_regs_passthru_supported(immu_t *immu); 764*3a634bfcSVikram Hegde boolean_t immu_regs_is_TM_reserved(immu_t *immu); 765*3a634bfcSVikram Hegde boolean_t immu_regs_is_SNP_reserved(immu_t *immu); 766*3a634bfcSVikram Hegde 767*3a634bfcSVikram Hegde void immu_regs_wbf_flush(immu_t *immu); 768*3a634bfcSVikram Hegde void immu_regs_cpu_flush(immu_t *immu, caddr_t addr, uint_t size); 769*3a634bfcSVikram Hegde void immu_regs_iotlb_flush(immu_t *immu, uint_t domainid, uint64_t dvma, 770*3a634bfcSVikram Hegde uint64_t count, uint_t hint, immu_iotlb_inv_t type); 771*3a634bfcSVikram Hegde void immu_regs_context_flush(immu_t *immu, uint8_t function_mask, 772*3a634bfcSVikram Hegde uint16_t source_id, uint_t did, immu_context_inv_t type); 773*3a634bfcSVikram Hegde void immu_regs_set_root_table(immu_t *immu); 774*3a634bfcSVikram Hegde void immu_regs_qinv_enable(immu_t *immu, uint64_t qinv_reg_value); 775*3a634bfcSVikram Hegde void immu_regs_intr_enable(immu_t *immu, uint32_t msi_addr, uint32_t msi_data, 776*3a634bfcSVikram Hegde uint32_t uaddr); 777*3a634bfcSVikram Hegde void immu_regs_intrmap_enable(immu_t *immu, uint64_t irta_reg); 778*3a634bfcSVikram Hegde uint64_t immu_regs_get64(immu_t *immu, uint_t reg); 779*3a634bfcSVikram Hegde void immu_regs_put64(immu_t *immu, uint_t reg, uint64_t val); 780*3a634bfcSVikram Hegde uint32_t immu_regs_get32(immu_t *immu, uint_t reg); 781*3a634bfcSVikram Hegde void immu_regs_put32(immu_t *immu, uint_t reg, uint32_t val); 782*3a634bfcSVikram Hegde 783*3a634bfcSVikram Hegde /* immu_dvma.c interfaces */ 784*3a634bfcSVikram Hegde void immu_dvma_setup(list_t *immu_list); 785*3a634bfcSVikram Hegde void immu_dvma_startup(immu_t *immu); 786*3a634bfcSVikram Hegde void immu_dvma_shutdown(immu_t *immu); 787*3a634bfcSVikram Hegde void immu_dvma_destroy(list_t *immu_list); 788*3a634bfcSVikram Hegde 789*3a634bfcSVikram Hegde void immu_dvma_physmem_update(uint64_t addr, uint64_t size); 790*3a634bfcSVikram Hegde int immu_dvma_map(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq, memrng_t *, 791*3a634bfcSVikram Hegde uint_t prealloc_count, dev_info_t *rdip, immu_flags_t immu_flags); 792*3a634bfcSVikram Hegde int immu_dvma_unmap(ddi_dma_impl_t *hp, dev_info_t *rdip); 793*3a634bfcSVikram Hegde int immu_dvma_alloc(dvcookie_t *first_dvcookie, void *arg); 794*3a634bfcSVikram Hegde void immu_dvma_free(dvcookie_t *first_dvcookie, void *arg); 795*3a634bfcSVikram Hegde int immu_devi_set(dev_info_t *dip, immu_flags_t immu_flags); 796*3a634bfcSVikram Hegde immu_devi_t *immu_devi_get(dev_info_t *dip); 797*3a634bfcSVikram Hegde immu_t *immu_dvma_get_immu(dev_info_t *dip, immu_flags_t immu_flags); 798*3a634bfcSVikram Hegde 799*3a634bfcSVikram Hegde 800*3a634bfcSVikram Hegde /* immu_intrmap.c interfaces */ 801*3a634bfcSVikram Hegde void immu_intrmap_setup(list_t *immu_list); 802*3a634bfcSVikram Hegde void immu_intrmap_startup(immu_t *immu); 803*3a634bfcSVikram Hegde void immu_intrmap_shutdown(immu_t *immu); 804*3a634bfcSVikram Hegde void immu_intrmap_destroy(list_t *immu_list); 805*3a634bfcSVikram Hegde 806*3a634bfcSVikram Hegde /* registers interrupt handler for IOMMU unit */ 807*3a634bfcSVikram Hegde void immu_intr_register(immu_t *immu); 808*3a634bfcSVikram Hegde int immu_intr_handler(immu_t *immu); 809*3a634bfcSVikram Hegde 810*3a634bfcSVikram Hegde 811*3a634bfcSVikram Hegde /* immu_qinv.c interfaces */ 812*3a634bfcSVikram Hegde void immu_qinv_setup(list_t *immu_list); 813*3a634bfcSVikram Hegde void immu_qinv_startup(immu_t *immu); 814*3a634bfcSVikram Hegde void immu_qinv_shutdown(immu_t *immu); 815*3a634bfcSVikram Hegde void immu_qinv_destroy(list_t *immu_list); 816*3a634bfcSVikram Hegde 817*3a634bfcSVikram Hegde void immu_qinv_context_fsi(immu_t *immu, uint8_t function_mask, 818*3a634bfcSVikram Hegde uint16_t source_id, uint_t domain_id); 819*3a634bfcSVikram Hegde void immu_qinv_context_dsi(immu_t *immu, uint_t domain_id); 820*3a634bfcSVikram Hegde void immu_qinv_context_gbl(immu_t *immu); 821*3a634bfcSVikram Hegde void immu_qinv_iotlb_psi(immu_t *immu, uint_t domain_id, 822*3a634bfcSVikram Hegde uint64_t dvma, uint_t count, uint_t hint); 823*3a634bfcSVikram Hegde void immu_qinv_iotlb_dsi(immu_t *immu, uint_t domain_id); 824*3a634bfcSVikram Hegde void immu_qinv_iotlb_gbl(immu_t *immu); 825*3a634bfcSVikram Hegde void immu_qinv_intr_global(immu_t *immu); 826*3a634bfcSVikram Hegde void immu_qinv_intr_one_cache(immu_t *immu, uint_t idx); 827*3a634bfcSVikram Hegde void immu_qinv_intr_caches(immu_t *immu, uint_t idx, uint_t cnt); 828*3a634bfcSVikram Hegde void immu_qinv_report_fault(immu_t *immu); 829*3a634bfcSVikram Hegde 830*3a634bfcSVikram Hegde 831*3a634bfcSVikram Hegde #ifdef __cplusplus 832*3a634bfcSVikram Hegde } 833*3a634bfcSVikram Hegde #endif 834*3a634bfcSVikram Hegde 835*3a634bfcSVikram Hegde #endif /* _SYS_INTEL_IOMMU_H */ 836