xref: /openbsd-src/sys/dev/acpi/acpidmar.h (revision fabcfecb28af5579f8c0c1cb806278199e88da42)
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