196940271Sjordan /* 296940271Sjordan * Copyright (c) 2015 Jordan Hargrave <jordan_hargrave@hotmail.com> 396940271Sjordan * 496940271Sjordan * Permission to use, copy, modify, and distribute this software for any 596940271Sjordan * purpose with or without fee is hereby granted, provided that the above 696940271Sjordan * copyright notice and this permission notice appear in all copies. 796940271Sjordan * 896940271Sjordan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 996940271Sjordan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1096940271Sjordan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1196940271Sjordan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1296940271Sjordan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1396940271Sjordan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1496940271Sjordan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1596940271Sjordan */ 1696940271Sjordan 1796940271Sjordan #ifndef _DEV_ACPI_DMARREG_H_ 1896940271Sjordan #define _DEV_ACPI_DMARREG_H_ 1996940271Sjordan 2096940271Sjordan /*#define IOMMU_DEBUG*/ 2196940271Sjordan 2296940271Sjordan #define VTD_STRIDE_MASK 0x1FF 2396940271Sjordan #define VTD_STRIDE_SIZE 9 2496940271Sjordan #define VTD_PAGE_SIZE 4096 2596940271Sjordan #define VTD_PAGE_MASK 0xFFF 2696940271Sjordan #define VTD_PTE_MASK 0x0000FFFFFFFFF000LL 2796940271Sjordan 2896940271Sjordan #define VTD_LEVEL0 12 2996940271Sjordan #define VTD_LEVEL1 21 3096940271Sjordan #define VTD_LEVEL2 30 /* Minimum level supported */ 3196940271Sjordan #define VTD_LEVEL3 39 /* Also supported */ 3296940271Sjordan #define VTD_LEVEL4 48 3396940271Sjordan #define VTD_LEVEL5 57 3496940271Sjordan 3596940271Sjordan #define _xbit(x,y) (((x)>> (y)) & 1) 3696940271Sjordan #define _xfld(x,y) (uint32_t)(((x)>> y##_SHIFT) & y##_MASK) 3796940271Sjordan 3896940271Sjordan #define VTD_AWTOLEVEL(x) (((x) - 30) / VTD_STRIDE_SIZE) 3996940271Sjordan #define VTD_LEVELTOAW(x) (((x) * VTD_STRIDE_SIZE) + 30) 4096940271Sjordan 4196940271Sjordan #define DMAR_VER_REG 0x00 /* 32:Arch version supported by this IOMMU */ 4296940271Sjordan #define DMAR_RTADDR_REG 0x20 /* 64:Root entry table */ 4396940271Sjordan #define DMAR_FEDATA_REG 0x3c /* 32:Fault event interrupt data register */ 4496940271Sjordan #define DMAR_FEADDR_REG 0x40 /* 32:Fault event interrupt addr register */ 4596940271Sjordan #define DMAR_FEUADDR_REG 0x44 /* 32:Upper address register */ 4696940271Sjordan #define DMAR_AFLOG_REG 0x58 /* 64:Advanced Fault control */ 4796940271Sjordan #define DMAR_PMEN_REG 0x64 /* 32:Enable Protected Memory Region */ 4896940271Sjordan #define DMAR_PLMBASE_REG 0x68 /* 32:PMRR Low addr */ 4996940271Sjordan #define DMAR_PLMLIMIT_REG 0x6c /* 32:PMRR low limit */ 5096940271Sjordan #define DMAR_PHMBASE_REG 0x70 /* 64:pmrr high base addr */ 5196940271Sjordan #define DMAR_PHMLIMIT_REG 0x78 /* 64:pmrr high limit */ 5296940271Sjordan #define DMAR_ICS_REG 0x9C /* 32:Invalidation complete status register */ 5396940271Sjordan #define DMAR_IECTL_REG 0xa0 /* 32:Invalidation event control register */ 5496940271Sjordan #define DMAR_IEDATA_REG 0xa4 /* 32:Invalidation event data register */ 5596940271Sjordan #define DMAR_IEADDR_REG 0xa8 /* 32:Invalidation event address register */ 5696940271Sjordan #define DMAR_IEUADDR_REG 0xac /* 32:Invalidation event upper address register */ 5796940271Sjordan #define DMAR_IRTA_REG 0xb8 /* 64:Interrupt remapping table addr register */ 5896940271Sjordan #define DMAR_CAP_REG 0x08 /* 64:Hardware supported capabilities */ 5996940271Sjordan #define CAP_PI (1LL << 59) 6096940271Sjordan #define CAP_FL1GP (1LL << 56) 6196940271Sjordan #define CAP_DRD (1LL << 55) 6296940271Sjordan #define CAP_DWD (1LL << 54) 6396940271Sjordan #define CAP_MAMV_MASK 0x3F 6496940271Sjordan #define CAP_MAMV_SHIFT 48LL 6596940271Sjordan #define cap_mamv(x) _xfld(x,CAP_MAMV) 6696940271Sjordan #define CAP_NFR_MASK 0xFF 6796940271Sjordan #define CAP_NFR_SHIFT 40LL 6896940271Sjordan #define cap_nfr(x) (_xfld(x,CAP_NFR) + 1) 6996940271Sjordan #define CAP_PSI (1LL << 39) 7096940271Sjordan #define CAP_SLLPS_MASK 0xF 7196940271Sjordan #define CAP_SLLPS_SHIFT 34LL 7296940271Sjordan #define cap_sllps(x) _xfld(x,CAP_SLLPS) 7396940271Sjordan #define CAP_FRO_MASK 0x3FF 7496940271Sjordan #define CAP_FRO_SHIFT 24LL 7596940271Sjordan #define cap_fro(x) (_xfld(x,CAP_FRO) * 16) 7696940271Sjordan #define CAP_ZLR (1LL << 22) 7796940271Sjordan #define CAP_MGAW_MASK 0x3F 7896940271Sjordan #define CAP_MGAW_SHIFT 16LL 7996940271Sjordan #define cap_mgaw(x) (_xfld(x,CAP_MGAW) + 1) 8096940271Sjordan #define CAP_SAGAW_MASK 0x1F 8196940271Sjordan #define CAP_SAGAW_SHIFT 8LL 8296940271Sjordan #define cap_sagaw(x) _xfld(x,CAP_SAGAW) 8396940271Sjordan #define CAP_CM (1LL << 7) 8496940271Sjordan #define CAP_PHMR (1LL << 6) 8596940271Sjordan #define CAP_PLMR (1LL << 5) 8696940271Sjordan #define CAP_RWBF (1LL << 4) 8796940271Sjordan #define CAP_AFL (1LL << 3) 8896940271Sjordan #define CAP_ND_MASK 0x7 8996940271Sjordan #define CAP_ND_SHIFT 0x00 9096940271Sjordan #define cap_nd(x) (16 << (((x) & CAP_ND_MASK) << 1)) 9196940271Sjordan 9296940271Sjordan #define DMAR_ECAP_REG 0x10 /* 64:Extended capabilities supported */ 9396940271Sjordan #define ECAP_PSS_MASK 0x1F 9496940271Sjordan #define ECAP_PSS_SHIFT 35 9596940271Sjordan #define ECAP_EAFS (1LL << 34) 9696940271Sjordan #define ECAP_NWFS (1LL << 33) 9796940271Sjordan #define ECAP_SRS (1LL << 31) 9896940271Sjordan #define ECAP_ERS (1LL << 30) 9996940271Sjordan #define ECAP_PRS (1LL << 29) 10096940271Sjordan #define ECAP_PASID (1LL << 28) 10196940271Sjordan #define ECAP_DIS (1LL << 27) 10296940271Sjordan #define ECAP_NEST (1LL << 26) 10396940271Sjordan #define ECAP_MTS (1LL << 25) 10496940271Sjordan #define ECAP_ECS (1LL << 24) 10596940271Sjordan #define ECAP_MHMV_MASK 0xF 10696940271Sjordan #define ECAP_MHMV_SHIFT 0x20 10796940271Sjordan #define ecap_mhmv(x) _xfld(x,ECAP_MHMV) 10896940271Sjordan #define ECAP_IRO_MASK 0x3FF /* IOTLB Register */ 10996940271Sjordan #define ECAP_IRO_SHIFT 0x8 11096940271Sjordan #define ecap_iro(x) (_xfld(x,ECAP_IRO) * 16) 11196940271Sjordan #define ECAP_SC (1LL << 7) /* Snoop Control */ 11296940271Sjordan #define ECAP_PT (1LL << 6) /* HW Passthru */ 11396940271Sjordan #define ECAP_EIM (1LL << 4) 11496940271Sjordan #define ECAP_IR (1LL << 3) /* Interrupt remap */ 11596940271Sjordan #define ECAP_DT (1LL << 2) /* Device IOTLB */ 11696940271Sjordan #define ECAP_QI (1LL << 1) /* Queued Invalidation */ 11796940271Sjordan #define ECAP_C (1LL << 0) /* Coherent cache */ 11896940271Sjordan 11996940271Sjordan #define DMAR_GCMD_REG 0x18 /* 32:Global command register */ 12096940271Sjordan #define GCMD_TE (1LL << 31) 12196940271Sjordan #define GCMD_SRTP (1LL << 30) 12296940271Sjordan #define GCMD_SFL (1LL << 29) 12396940271Sjordan #define GCMD_EAFL (1LL << 28) 12496940271Sjordan #define GCMD_WBF (1LL << 27) 12596940271Sjordan #define GCMD_QIE (1LL << 26) 12696940271Sjordan #define GCMD_IRE (1LL << 25) 12796940271Sjordan #define GCMD_SIRTP (1LL << 24) 12896940271Sjordan #define GCMD_CFI (1LL << 23) 12996940271Sjordan 13096940271Sjordan #define DMAR_GSTS_REG 0x1c /* 32:Global status register */ 13196940271Sjordan #define GSTS_TES (1LL << 31) 13296940271Sjordan #define GSTS_RTPS (1LL << 30) 13396940271Sjordan #define GSTS_FLS (1LL << 29) 13496940271Sjordan #define GSTS_AFLS (1LL << 28) 13596940271Sjordan #define GSTS_WBFS (1LL << 27) 13696940271Sjordan #define GSTS_QIES (1LL << 26) 13796940271Sjordan #define GSTS_IRES (1LL << 25) 13896940271Sjordan #define GSTS_IRTPS (1LL << 24) 13996940271Sjordan #define GSTS_CFIS (1LL << 23) 14096940271Sjordan 14196940271Sjordan #define DMAR_CCMD_REG 0x28 /* 64:Context command reg */ 14296940271Sjordan #define CCMD_ICC (1LL << 63) 14396940271Sjordan #define CCMD_CIRG_MASK 0x3 14496940271Sjordan #define CCMD_CIRG_SHIFT 61 14596940271Sjordan #define CCMD_CIRG(x) ((uint64_t)(x) << CCMD_CIRG_SHIFT) 14696940271Sjordan #define CCMD_CAIG_MASK 0x3 14796940271Sjordan #define CCMD_CAIG_SHIFT 59 14896940271Sjordan #define CCMD_FM_MASK 0x3 14996940271Sjordan #define CCMD_FM_SHIFT 32 15096940271Sjordan #define CCMD_FM(x) (((uint64_t)(x) << CCMD_FM_SHIFT)) 15196940271Sjordan #define CCMD_SID_MASK 0xFFFF 15296940271Sjordan #define CCMD_SID_SHIFT 8 15396940271Sjordan #define CCMD_SID(x) (((x) << CCMD_SID_SHIFT)) 15496940271Sjordan #define CCMD_DID_MASK 0xFFFF 15596940271Sjordan #define CCMD_DID_SHIFT 0 15696940271Sjordan #define CCMD_DID(x) (((x) << CCMD_DID_SHIFT)) 15796940271Sjordan 15896940271Sjordan #define CIG_GLOBAL CCMD_CIRG(CTX_GLOBAL) 15996940271Sjordan #define CIG_DOMAIN CCMD_CIRG(CTX_DOMAIN) 16096940271Sjordan #define CIG_DEVICE CCMD_CIRG(CTX_DEVICE) 16196940271Sjordan 16296940271Sjordan 16396940271Sjordan #define DMAR_FSTS_REG 0x34 /* 32:Fault Status register */ 16496940271Sjordan #define FSTS_FRI_MASK 0xFF 16596940271Sjordan #define FSTS_FRI_SHIFT 8 16696940271Sjordan #define FSTS_PRO (1LL << 7) 16796940271Sjordan #define FSTS_ITE (1LL << 6) 16896940271Sjordan #define FSTS_ICE (1LL << 5) 16996940271Sjordan #define FSTS_IQE (1LL << 4) 17096940271Sjordan #define FSTS_APF (1LL << 3) 17196940271Sjordan #define FSTS_APO (1LL << 2) 17296940271Sjordan #define FSTS_PPF (1LL << 1) 17396940271Sjordan #define FSTS_PFO (1LL << 0) 17496940271Sjordan 17596940271Sjordan #define DMAR_FECTL_REG 0x38 /* 32:Fault control register */ 17696940271Sjordan #define FECTL_IM (1LL << 31) 17796940271Sjordan #define FECTL_IP (1LL << 30) 17896940271Sjordan 17996940271Sjordan #define FRCD_HI_F (1LL << (127-64)) 18096940271Sjordan #define FRCD_HI_T (1LL << (126-64)) 18196940271Sjordan #define FRCD_HI_AT_MASK 0x3 18296940271Sjordan #define FRCD_HI_AT_SHIFT (124-64) 18396940271Sjordan #define FRCD_HI_PV_MASK 0xFFFFF 18496940271Sjordan #define FRCD_HI_PV_SHIFT (104-64) 18596940271Sjordan #define FRCD_HI_FR_MASK 0xFF 18696940271Sjordan #define FRCD_HI_FR_SHIFT (96-64) 18796940271Sjordan #define FRCD_HI_PP (1LL << (95-64)) 18896940271Sjordan 18996940271Sjordan #define FRCD_HI_SID_MASK 0xFF 19096940271Sjordan #define FRCD_HI_SID_SHIFT 0 19196940271Sjordan #define FRCD_HI_BUS_SHIFT 8 19296940271Sjordan #define FRCD_HI_BUS_MASK 0xFF 19396940271Sjordan #define FRCD_HI_DEV_SHIFT 3 19496940271Sjordan #define FRCD_HI_DEV_MASK 0x1F 19596940271Sjordan #define FRCD_HI_FUN_SHIFT 0 19696940271Sjordan #define FRCD_HI_FUN_MASK 0x7 19796940271Sjordan 19896940271Sjordan #define DMAR_IOTLB_REG(x) (ecap_iro((x)->ecap) + 8) 19996940271Sjordan #define DMAR_IVA_REG(x) (ecap_iro((x)->ecap) + 0) 20096940271Sjordan 20196940271Sjordan #define DMAR_FRIH_REG(x,i) (cap_fro((x)->cap) + 16*(i) + 8) 20296940271Sjordan #define DMAR_FRIL_REG(x,i) (cap_fro((x)->cap) + 16*(i) + 0) 20396940271Sjordan 20496940271Sjordan #define IOTLB_IVT (1LL << 63) 20596940271Sjordan #define IOTLB_IIRG_MASK 0x3 20696940271Sjordan #define IOTLB_IIRG_SHIFT 60 20796940271Sjordan #define IOTLB_IIRG(x) ((uint64_t)(x) << IOTLB_IIRG_SHIFT) 20896940271Sjordan #define IOTLB_IAIG_MASK 0x3 20996940271Sjordan #define IOTLB_IAIG_SHIFT 57 21096940271Sjordan #define IOTLB_DR (1LL << 49) 21196940271Sjordan #define IOTLB_DW (1LL << 48) 21296940271Sjordan #define IOTLB_DID_MASK 0xFFFF 21396940271Sjordan #define IOTLB_DID_SHIFT 32 21496940271Sjordan #define IOTLB_DID(x) ((uint64_t)(x) << IOTLB_DID_SHIFT) 21596940271Sjordan 21696940271Sjordan #define IIG_GLOBAL IOTLB_IIRG(IOTLB_GLOBAL) 21796940271Sjordan #define IIG_DOMAIN IOTLB_IIRG(IOTLB_DOMAIN) 21896940271Sjordan #define IIG_PAGE IOTLB_IIRG(IOTLB_PAGE) 21996940271Sjordan 22096940271Sjordan #define DMAR_IQH_REG 0x80 /* 64:Invalidation queue head register */ 22196940271Sjordan #define DMAR_IQT_REG 0x88 /* 64:Invalidation queue tail register */ 22296940271Sjordan #define DMAR_IQA_REG 0x90 /* 64:Invalidation queue addr register */ 22396940271Sjordan #define IQA_QS_256 0 /* 256 entries */ 22496940271Sjordan #define IQA_QS_512 1 /* 512 */ 22596940271Sjordan #define IQA_QS_1K 2 /* 1024 */ 22696940271Sjordan #define IQA_QS_2K 3 /* 2048 */ 22796940271Sjordan #define IQA_QS_4K 4 /* 4096 */ 22896940271Sjordan #define IQA_QS_8K 5 /* 8192 */ 22996940271Sjordan #define IQA_QS_16K 6 /* 16384 */ 23096940271Sjordan #define IQA_QS_32K 7 /* 32768 */ 23196940271Sjordan 23296940271Sjordan /* Read-Modify-Write helpers */ 233da5607f6Sjsg static inline void 234da5607f6Sjsg iommu_rmw32(void *ov, uint32_t mask, uint32_t shift, uint32_t nv) 23596940271Sjordan { 23696940271Sjordan *(uint32_t *)ov &= ~(mask << shift); 23796940271Sjordan *(uint32_t *)ov |= (nv & mask) << shift; 23896940271Sjordan } 239da5607f6Sjsg 240da5607f6Sjsg static inline void 241da5607f6Sjsg iommu_rmw64(void *ov, uint32_t mask, uint32_t shift, uint64_t nv) 24296940271Sjordan { 24396940271Sjordan *(uint64_t *)ov &= ~(mask << shift); 24496940271Sjordan *(uint64_t *)ov |= (nv & mask) << shift; 24596940271Sjordan } 24696940271Sjordan 24796940271Sjordan /* 24896940271Sjordan * Root Entry: one per bus (256 x 128 bit = 4k) 24996940271Sjordan * 0 = Present 25096940271Sjordan * 1:11 = Reserved 25196940271Sjordan * 12:HAW-1 = Context Table Pointer 25296940271Sjordan * HAW:63 = Reserved 25396940271Sjordan * 64:127 = Reserved 25496940271Sjordan */ 25596940271Sjordan #define ROOT_P (1L << 0) 25696940271Sjordan struct root_entry { 25796940271Sjordan uint64_t lo; 25896940271Sjordan uint64_t hi; 25996940271Sjordan }; 26096940271Sjordan 26196940271Sjordan /* Check if root entry is valid */ 26296940271Sjordan static inline bool 26396940271Sjordan root_entry_is_valid(struct root_entry *re) 26496940271Sjordan { 26596940271Sjordan return (re->lo & ROOT_P); 26696940271Sjordan } 26796940271Sjordan 26896940271Sjordan /* 26996940271Sjordan * Context Entry: one per devfn (256 x 128 bit = 4k) 27096940271Sjordan * 0 = Present 27196940271Sjordan * 1 = Fault Processing Disable 27296940271Sjordan * 2:3 = Translation Type 27396940271Sjordan * 4:11 = Reserved 27496940271Sjordan * 12:63 = Second Level Page Translation 27596940271Sjordan * 64:66 = Address Width (# PTE levels) 27696940271Sjordan * 67:70 = Ignore 27796940271Sjordan * 71 = Reserved 27896940271Sjordan * 72:87 = Domain ID 27996940271Sjordan * 88:127 = Reserved 28096940271Sjordan */ 28196940271Sjordan #define CTX_P (1L << 0) 28296940271Sjordan #define CTX_FPD (1L << 1) 28396940271Sjordan #define CTX_T_MASK 0x3 28496940271Sjordan #define CTX_T_SHIFT 2 28596940271Sjordan enum { 28696940271Sjordan CTX_T_MULTI, 28796940271Sjordan CTX_T_IOTLB, 28896940271Sjordan CTX_T_PASSTHRU 28996940271Sjordan }; 29096940271Sjordan 29196940271Sjordan #define CTX_H_AW_MASK 0x7 29296940271Sjordan #define CTX_H_AW_SHIFT 0 29396940271Sjordan #define CTX_H_USER_MASK 0xF 29496940271Sjordan #define CTX_H_USER_SHIFT 3 29596940271Sjordan #define CTX_H_DID_MASK 0xFFFF 29696940271Sjordan #define CTX_H_DID_SHIFT 8 29796940271Sjordan 29896940271Sjordan struct context_entry { 29996940271Sjordan uint64_t lo; 30096940271Sjordan uint64_t hi; 30196940271Sjordan }; 30296940271Sjordan 30396940271Sjordan /* Set fault processing enable/disable */ 30496940271Sjordan static inline void 30596940271Sjordan context_set_fpd(struct context_entry *ce, int enable) 30696940271Sjordan { 30796940271Sjordan ce->lo &= ~CTX_FPD; 30896940271Sjordan if (enable) 30996940271Sjordan ce->lo |= CTX_FPD; 31096940271Sjordan } 31196940271Sjordan 31296940271Sjordan /* Set context entry present */ 31396940271Sjordan static inline void 31496940271Sjordan context_set_present(struct context_entry *ce) 31596940271Sjordan { 31696940271Sjordan ce->lo |= CTX_P; 31796940271Sjordan } 31896940271Sjordan 31996940271Sjordan /* Set Second Level Page Table Entry PA */ 32096940271Sjordan static inline void 32196940271Sjordan context_set_slpte(struct context_entry *ce, paddr_t slpte) 32296940271Sjordan { 32396940271Sjordan ce->lo &= VTD_PAGE_MASK; 32496940271Sjordan ce->lo |= (slpte & ~VTD_PAGE_MASK); 32596940271Sjordan } 32696940271Sjordan 32796940271Sjordan /* Set translation type */ 32896940271Sjordan static inline void 32996940271Sjordan context_set_translation_type(struct context_entry *ce, int tt) 33096940271Sjordan { 33196940271Sjordan ce->lo &= ~(CTX_T_MASK << CTX_T_SHIFT); 33296940271Sjordan ce->lo |= ((tt & CTX_T_MASK) << CTX_T_SHIFT); 33396940271Sjordan } 33496940271Sjordan 33596940271Sjordan /* Set Address Width (# of Page Table levels) */ 33696940271Sjordan static inline void 33796940271Sjordan context_set_address_width(struct context_entry *ce, int lvl) 33896940271Sjordan { 33996940271Sjordan ce->hi &= ~(CTX_H_AW_MASK << CTX_H_AW_SHIFT); 34096940271Sjordan ce->hi |= ((lvl & CTX_H_AW_MASK) << CTX_H_AW_SHIFT); 34196940271Sjordan } 34296940271Sjordan 34396940271Sjordan /* Set domain ID */ 34496940271Sjordan static inline void 34596940271Sjordan context_set_domain_id(struct context_entry *ce, int did) 34696940271Sjordan { 34796940271Sjordan ce->hi &= ~(CTX_H_DID_MASK << CTX_H_DID_SHIFT); 34896940271Sjordan ce->hi |= ((did & CTX_H_DID_MASK) << CTX_H_DID_SHIFT); 34996940271Sjordan } 35096940271Sjordan 35196940271Sjordan /* Get Second Level Page Table PA */ 35296940271Sjordan static inline uint64_t 35396940271Sjordan context_pte(struct context_entry *ce) 35496940271Sjordan { 35596940271Sjordan return (ce->lo & ~VTD_PAGE_MASK); 35696940271Sjordan } 35796940271Sjordan 35896940271Sjordan /* Get translation type */ 35996940271Sjordan static inline int 36096940271Sjordan context_translation_type(struct context_entry *ce) 36196940271Sjordan { 36296940271Sjordan return (ce->lo >> CTX_T_SHIFT) & CTX_T_MASK; 36396940271Sjordan } 36496940271Sjordan 36596940271Sjordan /* Get domain ID */ 36696940271Sjordan static inline int 36796940271Sjordan context_domain_id(struct context_entry *ce) 36896940271Sjordan { 36996940271Sjordan return (ce->hi >> CTX_H_DID_SHIFT) & CTX_H_DID_MASK; 37096940271Sjordan } 37196940271Sjordan 37296940271Sjordan /* Get Address Width */ 37396940271Sjordan static inline int 37496940271Sjordan context_address_width(struct context_entry *ce) 37596940271Sjordan { 37696940271Sjordan return VTD_LEVELTOAW((ce->hi >> CTX_H_AW_SHIFT) & CTX_H_AW_MASK); 37796940271Sjordan } 37896940271Sjordan 37996940271Sjordan /* Check if context entry is valid */ 38096940271Sjordan static inline bool 38196940271Sjordan context_entry_is_valid(struct context_entry *ce) 38296940271Sjordan { 38396940271Sjordan return (ce->lo & CTX_P); 38496940271Sjordan } 38596940271Sjordan 38696940271Sjordan /* User-available bits in context entry */ 38796940271Sjordan static inline int 38896940271Sjordan context_user(struct context_entry *ce) 38996940271Sjordan { 39096940271Sjordan return (ce->hi >> CTX_H_USER_SHIFT) & CTX_H_USER_MASK; 39196940271Sjordan } 39296940271Sjordan 39396940271Sjordan static inline void 39496940271Sjordan context_set_user(struct context_entry *ce, int v) 39596940271Sjordan { 39696940271Sjordan ce->hi &= ~(CTX_H_USER_MASK << CTX_H_USER_SHIFT); 39796940271Sjordan ce->hi |= ((v & CTX_H_USER_MASK) << CTX_H_USER_SHIFT); 39896940271Sjordan } 39996940271Sjordan 40096940271Sjordan /* 40196940271Sjordan * Fault entry 40296940271Sjordan * 0..HAW-1 = Fault address 40396940271Sjordan * HAW:63 = Reserved 40496940271Sjordan * 64:71 = Source ID 40596940271Sjordan * 96:103 = Fault Reason 40696940271Sjordan * 104:123 = PV 40796940271Sjordan * 124:125 = Address Translation type 40896940271Sjordan * 126 = Type (0 = Read, 1 = Write) 40996940271Sjordan * 127 = Fault bit 41096940271Sjordan */ 411*fabcfecbSjsg struct fault_entry { 41296940271Sjordan uint64_t lo; 41396940271Sjordan uint64_t hi; 41496940271Sjordan }; 41596940271Sjordan 41696940271Sjordan /* PTE Entry: 512 x 64-bit = 4k */ 41796940271Sjordan #define PTE_P (1L << 0) 41896940271Sjordan #define PTE_R 0x00 41996940271Sjordan #define PTE_W (1L << 1) 42096940271Sjordan #define PTE_US (1L << 2) 42196940271Sjordan #define PTE_PWT (1L << 3) 42296940271Sjordan #define PTE_PCD (1L << 4) 42396940271Sjordan #define PTE_A (1L << 5) 42496940271Sjordan #define PTE_D (1L << 6) 42596940271Sjordan #define PTE_PAT (1L << 7) 42696940271Sjordan #define PTE_G (1L << 8) 42796940271Sjordan #define PTE_EA (1L << 10) 42896940271Sjordan #define PTE_XD (1LL << 63) 42996940271Sjordan 43096940271Sjordan /* PDE Level entry */ 43196940271Sjordan #define PTE_PS (1L << 7) 43296940271Sjordan 43396940271Sjordan /* PDPE Level entry */ 43496940271Sjordan 43596940271Sjordan /* ---------------------------------------------------------------- 43696940271Sjordan * 5555555444444444333333333222222222111111111000000000------------ 43796940271Sjordan * [PML4 ->] PDPE.1GB 43896940271Sjordan * [PML4 ->] PDPE.PDE -> PDE.2MB 43996940271Sjordan * [PML4 ->] PDPE.PDE -> PDE -> PTE 44096940271Sjordan * GAW0 = (12.20) (PTE) 44196940271Sjordan * GAW1 = (21.29) (PDE) 44296940271Sjordan * GAW2 = (30.38) (PDPE) 44396940271Sjordan * GAW3 = (39.47) (PML4) 44496940271Sjordan * GAW4 = (48.57) (n/a) 44596940271Sjordan * GAW5 = (58.63) (n/a) 44696940271Sjordan */ 44796940271Sjordan struct pte_entry { 44896940271Sjordan uint64_t val; 44996940271Sjordan }; 45096940271Sjordan 45196940271Sjordan /* 45296940271Sjordan * Queued Invalidation entry 45396940271Sjordan * 0:3 = 01h 45496940271Sjordan * 4:5 = Granularity 45596940271Sjordan * 6:15 = Reserved 45696940271Sjordan * 16:31 = Domain ID 45796940271Sjordan * 32:47 = Source ID 45896940271Sjordan * 48:49 = FM 45996940271Sjordan */ 46096940271Sjordan 46196940271Sjordan /* Invalidate Context Entry */ 46296940271Sjordan #define QI_CTX_DID_MASK 0xFFFF 46396940271Sjordan #define QI_CTX_DID_SHIFT 16 46496940271Sjordan #define QI_CTX_SID_MASK 0xFFFF 46596940271Sjordan #define QI_CTX_SID_SHIFT 32 46696940271Sjordan #define QI_CTX_FM_MASK 0x3 46796940271Sjordan #define QI_CTX_FM_SHIFT 48 46896940271Sjordan #define QI_CTX_IG_MASK 0x3 46996940271Sjordan #define QI_CTX_IG_SHIFT 4 47096940271Sjordan #define QI_CTX_DID(x) (((uint64_t)(x) << QI_CTX_DID_SHIFT)) 47196940271Sjordan #define QI_CTX_SID(x) (((uint64_t)(x) << QI_CTX_SID_SHIFT)) 47296940271Sjordan #define QI_CTX_FM(x) (((uint64_t)(x) << QI_CTX_FM_SHIFT)) 47396940271Sjordan 47496940271Sjordan #define QI_CTX_IG_GLOBAL (CTX_GLOBAL << QI_CTX_IG_SHIFT) 47596940271Sjordan #define QI_CTX_IG_DOMAIN (CTX_DOMAIN << QI_CTX_IG_SHIFT) 47696940271Sjordan #define QI_CTX_IG_DEVICE (CTX_DEVICE << QI_CTX_IG_SHIFT) 47796940271Sjordan 47896940271Sjordan /* Invalidate IOTLB Entry */ 47996940271Sjordan #define QI_IOTLB_DID_MASK 0xFFFF 48096940271Sjordan #define QI_IOTLB_DID_SHIFT 16 48196940271Sjordan #define QI_IOTLB_IG_MASK 0x3 48296940271Sjordan #define QI_IOTLB_IG_SHIFT 4 48396940271Sjordan #define QI_IOTLB_DR (1LL << 6) 48496940271Sjordan #define QI_IOTLB_DW (1LL << 5) 48596940271Sjordan #define QI_IOTLB_DID(x) (((uint64_t)(x) << QI_IOTLB_DID_SHIFT)) 48696940271Sjordan 48796940271Sjordan #define QI_IOTLB_IG_GLOBAL (1 << QI_IOTLB_IG_SHIFT) 48896940271Sjordan #define QI_IOTLB_IG_DOMAIN (2 << QI_IOTLB_IG_SHIFT) 48996940271Sjordan #define QI_IOTLB_IG_PAGE (3 << QI_IOTLB_IG_SHIFT) 49096940271Sjordan 49196940271Sjordan /* QI Commands */ 49296940271Sjordan #define QI_CTX 0x1 49396940271Sjordan #define QI_IOTLB 0x2 49496940271Sjordan #define QI_DEVTLB 0x3 49596940271Sjordan #define QI_INTR 0x4 49696940271Sjordan #define QI_WAIT 0x5 49796940271Sjordan #define QI_EXTTLB 0x6 49896940271Sjordan #define QI_PAS 0x7 49996940271Sjordan #define QI_EXTDEV 0x8 50096940271Sjordan 50196940271Sjordan struct qi_entry { 50296940271Sjordan uint64_t lo; 50396940271Sjordan uint64_t hi; 50496940271Sjordan }; 50596940271Sjordan 50696940271Sjordan enum { 50796940271Sjordan CTX_GLOBAL = 1, 50896940271Sjordan CTX_DOMAIN, 50996940271Sjordan CTX_DEVICE, 51096940271Sjordan 51196940271Sjordan IOTLB_GLOBAL = 1, 51296940271Sjordan IOTLB_DOMAIN, 51396940271Sjordan IOTLB_PAGE, 51496940271Sjordan }; 51596940271Sjordan 51696940271Sjordan enum { 51796940271Sjordan VTD_FAULT_ROOT_P = 0x1, /* P field in root entry is 0 */ 51896940271Sjordan VTD_FAULT_CTX_P = 0x2, /* P field in context entry is 0 */ 51996940271Sjordan VTD_FAULT_CTX_INVAL = 0x3, /* context AW/TT/SLPPTR invalid */ 52096940271Sjordan VTD_FAULT_LIMIT = 0x4, /* Address is outside of MGAW */ 52196940271Sjordan VTD_FAULT_WRITE = 0x5, /* Address-translation fault, non-writable */ 52296940271Sjordan VTD_FAULT_READ = 0x6, /* Address-translation fault, non-readable */ 52396940271Sjordan VTD_FAULT_PTE_INVAL = 0x7, /* page table hw access error */ 52496940271Sjordan VTD_FAULT_ROOT_INVAL = 0x8, /* root table hw access error */ 52596940271Sjordan VTD_FAULT_CTX_TBL_INVAL = 0x9, /* context entry hw access error */ 52696940271Sjordan VTD_FAULT_ROOT_RESERVED = 0xa, /* non-zero reserved field in root entry */ 52796940271Sjordan VTD_FAULT_CTX_RESERVED = 0xb, /* non-zero reserved field in context entry */ 52896940271Sjordan VTD_FAULT_PTE_RESERVED = 0xc, /* non-zero reserved field in paging entry */ 52996940271Sjordan VTD_FAULT_CTX_TT = 0xd, /* invalid translation type */ 53096940271Sjordan }; 53196940271Sjordan 53296940271Sjordan #endif 53396940271Sjordan 53496940271Sjordan void acpidmar_pci_hook(pci_chipset_tag_t, struct pci_attach_args *); 53596940271Sjordan void dmar_ptmap(bus_dma_tag_t, bus_addr_t); 53696940271Sjordan 53796940271Sjordan #define __EXTRACT(v,m) (((v) >> m##_SHIFT) & m##_MASK) 538