xref: /freebsd/sys/x86/iommu/amd_reg.h (revision bb9c3f5121b42eeda2972d282a54d4eff800297c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024 The FreeBSD Foundation
5  *
6  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
7  * under sponsorship from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #ifndef __X86_IOMMU_AMD_REG_H
32 #define	__X86_IOMMU_AMD_REG_H
33 
34 /*
35  * MMIO Registers. Offsets and bits definitions.
36  */
37 
38 #define	AMDIOMMU_DEVTAB_BASE	0x0000
39 #define	AMDIOMMU_CMDBUF_BASE	0x0008
40 #define	AMDIOMMU_EVNTLOG_BASE	0x0010
41 #define	AMDIOMMU_CTRL		0x0018
42 #define	AMDIOMMU_EXCL_BASE	0x0020
43 #define	AMDIOMMU_EXCL_RANGE	0x0028
44 #define	AMDIOMMU_EFR		0x0030
45 #define	AMDIOMMU_PPRLOG_BASE	0x0038
46 #define	AMDIOMMU_HWEV_UPPER	0x0040
47 #define	AMDIOMMU_HWEV_LOWER	0x0048
48 #define	AMDIOMMU_HWEV_STATUS	0x0050
49 
50 #define	AMDIOMMU_SMIF_0		0x0060
51 #define	AMDIOMMU_SMIF_1		0x0068
52 #define	AMDIOMMU_SMIF_2		0x0070
53 #define	AMDIOMMU_SMIF_3		0x0078
54 #define	AMDIOMMU_SMIF_4		0x0080
55 #define	AMDIOMMU_SMIF_5		0x0088
56 #define	AMDIOMMU_SMIF_6		0x0090
57 #define	AMDIOMMU_SMIF_7		0x0098
58 #define	AMDIOMMU_SMIF_8		0x00a0
59 #define	AMDIOMMU_SMIF_9		0x00a8
60 #define	AMDIOMMU_SMIF_10	0x00b0
61 #define	AMDIOMMU_SMIF_11	0x00b8
62 #define	AMDIOMMU_SMIF_12	0x00c0
63 #define	AMDIOMMU_SMIF_13	0x00c8
64 #define	AMDIOMMU_SMIF_14	0x00d0
65 #define	AMDIOMMU_SMIF_15	0x00d8
66 
67 #define	AMDIOMMU_VAPIC_LOG_BASE	0x00e0
68 #define	AMDIOMMU_VAPIC_LOG_TAIL	0x00e8
69 #define	AMDIOMMU_PPRLOGB_BASE	0x00f0
70 #define	AMDIOMMU_EVNTLOGB_BASE	0x00f0
71 
72 #define	AMDIOMMU_DEVTAB_S1_BASE	0x0100
73 #define	AMDIOMMU_DEVTAB_S2_BASE	0x0108
74 #define	AMDIOMMU_DEVTAB_S3_BASE	0x0110
75 #define	AMDIOMMU_DEVTAB_S4_BASE	0x0118
76 #define	AMDIOMMU_DEVTAB_S5_BASE	0x0120
77 #define	AMDIOMMU_DEVTAB_S6_BASE	0x0128
78 #define	AMDIOMMU_DEVTAB_S7_BASE	0x0130
79 
80 #define	AMDIOMMU_DSFX		0x0138
81 #define	AMDIOMMU_DSCX		0x0140
82 #define	AMDIOMMU_DSSX		0x0148
83 
84 #define	AMDIOMMU_MSI_VEC0	0x0150
85 #define	AMDIOMMU_MSI_VEC1	0x0154
86 #define	AMDIOMMU_MSI_CAP_H	0x0158
87 #define	AMDIOMMU_MSI_ADDR_LOW	0x015c
88 #define	AMDIOMMU_MSI_ADDR_HIGH	0x0160
89 #define	AMDIOMMU_MSI_DATA	0x0164
90 #define	AMDIOMMU_MSI_MAPCAP	0x0168
91 
92 #define	AMDIOMMU_PERFOPT	0x016c
93 
94 #define	AMDIOMMU_x2APIC_CTRL	0x0170
95 #define	AMDIOMMU_PPRI_CTRL	0x0178
96 #define	AMDIOMMU_GALOGI_CTRL	0x0180
97 
98 #define	AMDIOMMU_vIOMMU_STATUS	0x0190
99 
100 #define	AMDIOMMU_MARC0_BASE	0x0200
101 #define	AMDIOMMU_MARC0_RELOC	0x0208
102 #define	AMDIOMMU_MARC0_LEN	0x0210
103 #define	AMDIOMMU_MARC1_BASE	0x0218
104 #define	AMDIOMMU_MARC1_RELOC	0x0220
105 #define	AMDIOMMU_MARC1_LEN	0x0228
106 #define	AMDIOMMU_MARC2_BASE	0x0230
107 #define	AMDIOMMU_MARC2_RELOC	0x0238
108 #define	AMDIOMMU_MARC2_LEN	0x0240
109 #define	AMDIOMMU_MARC3_BASE	0x0248
110 #define	AMDIOMMU_MARC3_RELOC	0x0250
111 #define	AMDIOMMU_MARC3_LEN	0x0258
112 
113 #define	AMDIOMMU_EFR2		0x01a0
114 
115 #define	AMDIOMMU_CMDBUF_HEAD	0x2000
116 #define	AMDIOMMU_CMDBUF_TAIL	0x2008
117 #define	AMDIOMMU_EVNTLOG_HEAD	0x2010
118 #define	AMDIOMMU_EVNTLOG_TAIL	0x2018
119 #define	AMDIOMMU_CMDEV_STATUS	0x2020
120 #define	AMDIOMMU_PPRLOG_HEAD	0x2030
121 #define	AMDIOMMU_PPRLOG_TAIL	0x2038
122 #define	AMDIOMMU_vAPICLOG_HEAD	0x2040
123 #define	AMDIOMMU_vAPICLOG_TAIL	0x2048
124 #define	AMDIOMMU_PPRLOGB_HEAD	0x2050
125 #define	AMDIOMMU_PPRLOGB_TAIL	0x2058
126 #define	AMDIOMMU_EVNTLOGB_HEAD	0x2070
127 #define	AMDIOMMU_EVNTLOGB_TAIL	0x2078
128 #define	AMDIOMMU_PPRLOG_AUR	0x2080
129 #define	AMDIOMMU_PPRLOG_EAI	0x2088
130 #define	AMDIOMMU_PPRLOGB_AUR	0x2090
131 
132 /*
133  * IOMMU Control Register AMDIOMMU_CTRL fields
134  */
135 #define	AMDIOMMU_CTRL_EN		0x0000000000000001ull	/* IOMMU En */
136 #define	AMDIOMMU_CTRL_HTTUN_EN		0x0000000000000002ull	/* HT Tun Trans En */
137 #define	AMDIOMMU_CTRL_EVNTLOG_EN	0x0000000000000004ull	/* Event Log En */
138 #define	AMDIOMMU_CTRL_EVENTINT_EN	0x0000000000000008ull	/* Event Log Intr En */
139 #define	AMDIOMMU_CTRL_COMWINT_EN	0x0000000000000010ull	/* Compl Wait Intr En */
140 #define	AMDIOMMU_CTRL_INVTOUT_MASK	0x00000000000000e0ull	/* IOTLB Inv Timeout*/
141 #define	AMDIOMMU_CTRL_INVTOUT_NO	0x0000000000000000ull
142 #define	AMDIOMMU_CTRL_INVTOUT_1MS	0x0000000000000020ull
143 #define	AMDIOMMU_CTRL_INVTOUT_10MS	0x0000000000000040ull
144 #define	AMDIOMMU_CTRL_INVTOUT_100MS	0x0000000000000060ull
145 #define	AMDIOMMU_CTRL_INVTOUT_1S	0x0000000000000080ull
146 #define	AMDIOMMU_CTRL_INVTOUT_10S	0x00000000000000a0ull
147 #define	AMDIOMMU_CTRL_INVTOUT_100S	0x00000000000000b0ull
148 #define	AMDIOMMU_CTRL_INVTOUT_RSRV	0x00000000000000e0ull
149 #define	AMDIOMMU_CTRL_PASSPW		0x0000000000000100ull	/* HT Pass Posted Wr */
150 #define	AMDIOMMU_CTRL_REPASSPW		0x0000000000000200ull	/* HT Resp Pass Posted Wr */
151 #define	AMDIOMMU_CTRL_COHERENT		0x0000000000000400ull	/* HT Coherent Reads */
152 #define	AMDIOMMU_CTRL_ISOC		0x0000000000000800ull	/* HT Isoc Reads */
153 #define	AMDIOMMU_CTRL_CMDBUF_EN		0x0000000000001000ull	/* Start CMD proc En */
154 #define	AMDIOMMU_CTRL_PPRLOG_EN		0x0000000000002000ull	/* Periph Page Req Log En */
155 #define	AMDIOMMU_CTRL_PPRINT_EN		0x0000000000004000ull	/* Periph Page Req Intr En */
156 #define	AMDIOMMU_CTRL_PPR_EN		0x0000000000008000ull	/* Periph Page Req En */
157 #define	AMDIOMMU_CTRL_GT_EN		0x0000000000010000ull	/* Guest En */
158 #define	AMDIOMMU_CTRL_GA_EN		0x0000000000020000ull	/* Guest vAPIC En */
159 #define	AMDIOMMU_CTRL_SMIF_EN		0x0000000000400000ull	/* SMI Filter En */
160 #define	AMDIOMMU_CTRL_SLFWB_DIS		0x0000000000800000ull	/* Self WriteBack Dis */
161 #define	AMDIOMMU_CTRL_SMIFLOG_EN	0x0000000001000000ull	/* SMI Filter Log En */
162 #define	AMDIOMMU_CTRL_GAM_EN_MASK	0x000000000e000000ull	/* Guest vAPIC Mode En */
163 #define	AMDIOMMU_CTRL_GAM_EN_vAPIC_GM0	0x0000000000000000ull	/* IRTE.GM = 0 */
164 #define	AMDIOMMU_CTRL_GAM_EN_vAPIC_GM1	0x0000000002000000ull	/* IRTE.GM = 1 */
165 #define	AMDIOMMU_CTRL_GALOG_EN		0x0000000010000000ull	/* Guest vAPIC GA Log En */
166 #define	AMDIOMMU_CTRL_GAINT_EN		0x0000000020000000ull	/* Guest vAPIC GA Intr En */
167 #define	AMDIOMMU_CTRL_DUALPPRLOG_MASK	0x00000000c0000000ull	/* Dual Periph Page Req Log En */
168 #define	AMDIOMMU_CTRL_DUALPPRLOG_A	0x0000000000000000ull	/* Use Log A */
169 #define	AMDIOMMU_CTRL_DUALPPRLOG_B	0x0000000040000000ull	/* Use Log B */
170 #define	AMDIOMMU_CTRL_DUALPPRLOG_SWAP	0x0000000080000000ull	/* Auto-swap on full */
171 #define	AMDIOMMU_CTRL_DUALPPRLOG_RSRV	0x00000000c0000000ull
172 #define	AMDIOMMU_CTRL_DUALEVNTLOG_MASK	0x0000000300000000ull	/* Dual Event Log En */
173 #define	AMDIOMMU_CTRL_DUALEVNTLOG_A	0x0000000000000000ull	/* Use Log A Buf */
174 #define	AMDIOMMU_CTRL_DUALEVNTLOG_B	0x0000000100000000ull	/* Use Log B Buf */
175 #define	AMDIOMMU_CTRL_DUALEVNTLOG_SWAP	0x0000000200000000ull	/* Auto-swap on full */
176 #define	AMDIOMMU_CTRL_DUALEVNTLOG_RSRV	0x0000000300000000ull
177 #define	AMDIOMMU_CTRL_DEVTABSEG_MASK	0x0000001c00000000ull	/* Dev Table Segm */
178 #define	AMDIOMMU_CTRL_DEVTABSEG_1	0x0000000000000000ull	/* 1 Segment */
179 #define	AMDIOMMU_CTRL_DEVTABSEG_2	0x0000000400000000ull	/* 2 Segments */
180 #define	AMDIOMMU_CTRL_DEVTABSEG_4	0x0000000800000000ull	/* 4 Segments */
181 #define	AMDIOMMU_CTRL_DEVTABSEG_8	0x0000000c00000000ull	/* 8 Segments */
182 #define	AMDIOMMU_CTRL_PRIVABRT_MASK	0x0000006000000000ull	/* Privilege Abort En */
183 #define	AMDIOMMU_CTRL_PRIVABRT_USR	0x0000000000000000ull	/* Privilege Abort User */
184 #define	AMDIOMMU_CTRL_PRIVABRT_ALL	0x0000002000000000ull	/* Privilege Abort Always */
185 #define	AMDIOMMU_CTRL_PPRAUTORSP_EN	0x0000008000000000ull	/* PPR Auto Resp En */
186 #define	AMDIOMMU_CTRL_MARC_EN		0x0000010000000000ull	/* Memory Addr Routing En */
187 #define	AMDIOMMU_CTRL_BLKSTOPMRK_EN	0x0000020000000000ull	/* Block StopMark En */
188 #define	AMDIOMMU_CTRL_PPRAUTORESPA_EN	0x0000040000000000ull	/* PPR Auto Resp Always En */
189 #define	AMDIOMMU_CTRL_NUMINTRREMAP_MASK	0x0000180000000000ull	/* Remapping MSI mode */
190 #define	AMDIOMMU_CTRL_NUMINTRREMAP_512	0x0000000000000000ull	/* 512 max */
191 #define	AMDIOMMU_CTRL_NUMINTRREMAP_2048	0x0000080000000000ull	/* 2048 max */
192 #define	AMDIOMMU_CTRL_EPH_EN		0x0000200000000000ull	/* Enh PPR Handling En */
193 #define	AMDIOMMU_CTRL_HADUP_MASK	0x0000c00000000000ull	/* Access and Dirty in host PT */
194 #define	AMDIOMMU_CTRL_GDUP_DIS		0x0001000000000000ull	/* Dis Dirty in guest PT */
195 #define	AMDIOMMU_CTRL_XT_EN		0x0004000000000000ull	/* x2APIC mode */
196 #define	AMDIOMMU_CTRL_INTCAPXT_EN	0x0008000000000000ull	/* x2APIC mode for IOMMU intrs */
197 #define	AMDIOMMU_CTRL_vCMD_EN		0x0010000000000000ull	/* vCMD buffer proc En */
198 #define	AMDIOMMU_CTRL_vIOMMU_EN		0x0020000000000000ull	/* vIOMMU En */
199 #define	AMDIOMMU_CTRL_GAUP_DIS		0x0040000000000000ull	/* Dis Access in guest PT */
200 #define	AMDIOMMU_CTRL_GAPPI_EN		0x0080000000000000ull	/* Guest APIC phys proc intr En */
201 #define	AMDIOMMU_CTRL_TMPM_EN		0x0100000000000000ull	/* Tiered Mem Page Migration En */
202 #define	AMDIOMMU_CTRL_GGCR3TRP_PHYS	0x0400000000000000ull	/* GCR3 is GPA (otherwise SPA) */
203 #define	AMDIOMMU_CTRL_IRTCACHE_DIS	0x0800000000000000ull	/* IRT Caching Dis */
204 #define	AMDIOMMU_CTRL_GSTBUFTRP_MODE	0x1000000000000000ull	/* See spec */
205 #define	AMDIOMMU_CTRL_SNPAVIC_MASK	0xe000000000000000ull	/* MBZ */
206 
207 /*
208  * IOMMU Extended Feature Register AMDIOMMU_EFR fields
209  */
210 #define	AMDIOMMU_EFR_XT_SUP		0x0000000000000004ull	/* x2APIC */
211 #define	AMDIOMMU_EFR_HWEV_SUP		0x0000000000000100ull	/* HW Event regs */
212 #define	AMDIOMMU_EFR_PC_SUP		0x0000000000000200ull	/* Perf counters */
213 #define	AMDIOMMU_EFR_HATS_MASK		0x0000000000000c00ull	/* Host Addr Trans Size */
214 #define	AMDIOMMU_EFR_HATS_4LVL		0x0000000000000000ull
215 #define	AMDIOMMU_EFR_HATS_5LVL		0x0000000000000400ull
216 #define	AMDIOMMU_EFR_HATS_6LVL		0x0000000000000800ull
217 #define	AMDIOMMU_EFR_DEVTBLSEG_MASK	0x000000c000000000ull	/* DevTbl segmentation */
218 #define	AMDIOMMU_EFR_DEVTBLSEG_SHIFT	38
219 
220 /* IOMMU Command Pointers (Head/Tail) registers fields */
221 #define	AMDIOMMU_CMDPTR_MASK		0x000000000007fff0ull
222 
223 /* IOMMU Command Buffer Base fields */
224 #define	AMDIOMMU_CMDBUF_BASE_SZSHIFT	56			/* Shift for size */
225 #define	AMDIOMMU_CMDBUF_MAX		(512 * 1024)
226 
227 /* IOMMU Event Log Base register fields */
228 #define	AMDIOMMU_EVNTLOG_BASE_SZSHIFT	56			/* Shift for size */
229 #define	AMDIOMMU_EVNTLOG_MIN		256
230 #define	AMDIOMMU_EVNTLOG_MAX		32768
231 
232 /* IOMMU Hardware Event Status register fields */
233 #define	AMDIOMMU_HWEVS_HEV		0x00000001		/* HW Ev Valid */
234 #define	AMDIOMMU_HWEVS_HEO		0x00000002		/* HW Ev Overfl */
235 
236 /*
237  * IOMMU Command and Event Status register fields.
238  * From the spec, all defined bits are either RO or RW1C.  As a consequence,
239  * single bit can be safely written to the register to clean a specific
240  * condition.
241  */
242 #define	AMDIOMMU_CMDEVS_EVOVRFLW	0x00000001
243 #define	AMDIOMMU_CMDEVS_EVLOGINT	0x00000002
244 #define	AMDIOMMU_CMDEVS_COMWAITINT	0x00000004
245 #define	AMDIOMMU_CMDEVS_EVLOGRUN	0x00000008
246 #define	AMDIOMMU_CMDEVS_CMDBUFRUN	0x00000010
247 #define	AMDIOMMU_CMDEVS_PPROVRFLW	0x00000020
248 #define	AMDIOMMU_CMDEVS_PPRINT		0x00000040
249 #define	AMDIOMMU_CMDEVS_PPRLOGRUN	0x00000080
250 #define	AMDIOMMU_CMDEVS_GALOGRUN	0x00000100
251 #define	AMDIOMMU_CMDEVS_GALOVRFLW	0x00000200
252 #define	AMDIOMMU_CMDEVS_GAINT		0x00000400
253 #define	AMDIOMMU_CMDEVS_PPROVRFLWB	0x00000800
254 #define	AMDIOMMU_CMDEVS_PPRLOGACTIVE	0x00001000
255 #define	AMDIOMMU_CMDEVS_RESV1		0x00002000
256 #define	AMDIOMMU_CMDEVS_RESV2		0x00004000
257 #define	AMDIOMMU_CMDEVS_EVOVRFLWB	0x00008000
258 #define	AMDIOMMU_CMDEVS_EVLOGACTIVE	0x00010000
259 #define	AMDIOMMU_CMDEVS_PPROVRFLWEB	0x00020000
260 #define	AMDIOMMU_CMDEVS_PPROVRFLWE	0x00040000
261 
262 /*
263  * IOMMU Extended Feature2 register fields.
264  * All currently defined bits are RO.
265  */
266 #define	AMDIOMMU_EFR2_TMPMSUP		0x0000000000000004ull	/* Tiered Mem Migration */
267 #define	AMDIOMMU_EFR2_GCR3TRPM		0x0000000000000008ull	/* GPA based GCR3 pointer in DTE */
268 #define	AMDIOMMU_EFR2_GAPPID		0x0000000000000010ull	/* masking of GAPIC PPI */
269 #define	AMDIOMMU_EFR2_SNPAVIC_MASK	0x00000000000000e0ull	/* SNP-enabled Adv intr features */
270 #define	AMDIOMMU_EFR2_SNPAVIC_NO	0x0000000000000000ull	/* No features supported */
271 #define	AMDIOMMU_EFR2_SNPAVIC_REMAPV	0x0000000000000020ull	/* Intr remapping with GVAPIC */
272 #define	AMDIOMMU_EFR2_NUMINTRREMAP_MASK	0x0000000000000300ull	/* Number of remapped intr per dev */
273 #define	AMDIOMMU_EFR2_NUMINTRREMAP_512	0x0000000000000000ull	/* 512 */
274 #define	AMDIOMMU_EFR2_NUMINTRREMAP_2048	0x0000000000000100ull	/* 2048 */
275 #define	AMDIOMMU_EFR2_HTRANGEIGN	0x0000000000000800ull	/* HT range is regular GPA */
276 
277 /*
278  * Device Table Entry (DTE)
279  */
280 struct amdiommu_dte {
281 	u_int		v:1;		/* Valid */
282 	u_int		tv:1;		/* Translation Valid */
283 	u_int		rsrv0:5;
284 	u_int		had:2;		/* Host Access Dirty */
285 	u_int		pgmode:3;	/* Paging Mode */
286 	uint64_t	ptroot:40;	/* Page Table Root */
287 	u_int		ppr:1;		/* PPR En */
288 	u_int		gprp:1;		/* Guest PPR Resp with PASID */
289 	u_int		giov:1;		/* Guest IO Prot Valid */
290 	u_int		gv:1;		/* Guest Translation Valid */
291 	u_int		glx:2;		/* Guest Levels Translated */
292 	u_int		gcr3root0:3;	/* GCR3 root pointer part */
293 	u_int		ir:1;		/* Read Perm */
294 	u_int		iw:1;		/* Write Perm */
295 	u_int		rsrv1:1;
296 	u_int		domainid:16;	/* domain tag */
297 	u_int		gcr3root1:16;	/* GCR3 root pointer part */
298 	u_int		i:1;		/* IOTLB En */
299 	u_int		se:1;		/* Suppress IO Fault Events */
300 	u_int		sa:1;		/* Suppress All IO Fault Events */
301 	u_int		pioctl:2;	/* Port IO Control */
302 	u_int		cache:1;	/* IOTLB Cache Hint */
303 	u_int		sd:1;		/* Snoop Disable */
304 	u_int		ex:1;		/* Allow Exclusion */
305 	u_int		sysmgt:2;	/* System Management Msg Handling */
306 	u_int		sats:1;		/* Secure/Non-secure ATS */
307 	u_int		gcr3root2:21;	/* GCR3 root pointer part */
308 	u_int		iv:1;		/* Intr Map Valid */
309 	u_int		inttablen:4;	/* log2 Intr Table Len */
310 	u_int		ig:1;		/* Ignore Unmapped Interrupts */
311 	uint64_t	intrroot:46;	/* Interrupt Table Root (-low 6bits) */
312 	u_int		rsrv2:2;
313 	u_int		gpm:2;		/* Guest Paging Mode */
314 	u_int		initpass:1;	/* INIT pass-through */
315 	u_int		eintpass:1;	/* ExtInt pass-through */
316 	u_int		nmipass:1;	/* NMI pass-through */
317 	u_int		hptmode:1;	/* Host Page Table Mode Hint */
318 	u_int		intctl:2;	/* Interrupt Control */
319 	u_int		lint0pass:1;	/* LINT0 pass-through */
320 	u_int		lint1pass:1;	/* LINT1 pass-through */
321 	u_int		rsrv3:15;
322 	u_int		vimu:1;		/* Virtualize IOMMU En */
323 	u_int		gdevid:16;	/* Guest Dev Id */
324 	u_int		gid:16;		/* Guest Id */
325 	u_int		rsrv4:5;
326 	u_int		rsrv5:1;	/* Not Checked, sw avail */
327 	u_int		attrv:1;	/* Attr Override Valid */
328 	u_int		mode0fc:1;	/* Replace for PTE.FC */
329 	u_int		snoopattr:8;	/* GuestPTE.PAT -> ATS.N xlat */
330 } __packed;
331 _Static_assert(sizeof(struct amdiommu_dte) == 8 * sizeof(uint32_t), "DTE");
332 
333 #define	AMDIOMMU_DTE_HAD_NAND		0x0	/* No Access, No Dirty */
334 #define	AMDIOMMU_DTE_HAD_AND		0x1	/* Access, No Dirty */
335 #define	AMDIOMMU_DTE_HAD_RSRV		0x2
336 #define	AMDIOMMU_DTE_HAD_AD		0x3	/* Access, Dirty */
337 
338 #define	AMDIOMMU_DTE_PGMODE_1T1		0x0	/* SPA = GPA */
339 #define	AMDIOMMU_DTE_PGMODE_1LV		0x1	/* 1 Level PT */
340 #define	AMDIOMMU_DTE_PGMODE_2LV		0x2	/* 2 Level PT */
341 #define	AMDIOMMU_DTE_PGMODE_3LV		0x3	/* 3 Level PT */
342 #define	AMDIOMMU_DTE_PGMODE_4LV		0x4	/* 4 Level PT */
343 #define	AMDIOMMU_DTE_PGMODE_5LV		0x5	/* 5 Level PT */
344 #define	AMDIOMMU_DTE_PGMODE_6LV		0x6	/* 6 Level PT */
345 #define	AMDIOMMU_DTE_PGMODE_RSRV	0x7
346 
347 #define	AMDIOMMU_DTE_GLX_1LV		0x0	/* 1 Level GCR3 */
348 #define	AMDIOMMU_DTE_GLX_2LV		0x1	/* 2 Level GCR3 */
349 #define	AMDIOMMU_DTE_GLX_3LV		0x2	/* 3 Level GCR3 */
350 #define	AMDIOMMU_DTE_GLX_RSRV		0x3
351 
352 #define	AMDIOMMU_DTE_PIOCTL_DIS		0x0
353 #define	AMDIOMMU_DTE_PIOCTL_EN		0x1
354 #define	AMDIOMMU_DTE_PIOCTL_MAP		0x2
355 #define	AMDIOMMU_DTE_PIOCTL_RSRV	0x3
356 
357 #define	AMDIOMMU_DTE_SYSMGT_DIS		0x0	/* Target Abort */
358 #define	AMDIOMMU_DTE_SYSMGT_FW		0x0	/* Forwarded All */
359 #define	AMDIOMMU_DTE_SYSMGT_FWI		0x0	/* Forwarded INT */
360 #define	AMDIOMMU_DTE_SYSMGT_T		0x0	/* Translated */
361 
362 #define	AMDIOMMU_DTE_GPM_4LV		0x0	/* 4 Level */
363 #define	AMDIOMMU_DTE_GPM_5LV		0x1	/* 5 Level */
364 #define	AMDIOMMU_DTE_GPM_RSRV1		0x2
365 #define	AMDIOMMU_DTE_GPM_RSRV2		0x3
366 
367 #define	AMDIOMMU_DTE_INTCTL_DIS		0x0	/* Target Abort */
368 #define	AMDIOMMU_DTE_INTCTL_FW		0x1	/* Forward Unmapped */
369 #define	AMDIOMMU_DTE_INTCTL_MAP		0x2	/* Forward Remapped */
370 #define	AMDIOMMU_DTE_INTCTL_RSRV	0x3
371 
372 #define	AMDIOMMU_PGTBL_MAXLVL		6
373 
374 /*
375  * Page Table Entry (PTE/PDE)
376  */
377 #define	AMDIOMMU_PTE_PR			0x0001	/* Present, AKA V */
378 #define	AMDIOMMU_IGN1			0x0002
379 #define	AMDIOMMU_IGN2			0x0004
380 #define	AMDIOMMU_IGN3			0x0008
381 #define	AMDIOMMU_IGN4			0x0010
382 #define	AMDIOMMU_PTE_A			0x0020	/* Accessed */
383 #define	AMDIOMMU_PTE_D			0x0040	/* Dirty */
384 #define	AMDIOMMU_IGN5			0x0080
385 #define	AMDIOMMU_IGN6			0x0100
386 #define	AMDIOMMU_PTE_NLVL_MASK		0x0e00	/* Next Level */
387 #define	AMDIOMMU_PTE_NLVL_SHIFT		9
388 #define	AMDIOMMU_PTE_NLVL_7h		0x0e00	/* Magic Next Level */
389 #define	AMDIOMMU_PTE_PA_MASK		0x000ffffffffff000ull
390 #define	AMDIOMMU_PTE_PA_SHIFT		12
391 #define	AMDIOMMU_PTE_PMC_MASK		0x0600000000000000ull	/* Page Migr */
392 #define	AMDIOMMU_PTE_U			0x0800000000000000ull	/* ATS.U */
393 #define	AMDIOMMU_PTE_FC			0x1000000000000000ull	/* Force Coh */
394 #define	AMDIOMMU_PTE_IR			0x2000000000000000ull	/* Read Perm */
395 #define	AMDIOMMU_PTE_IW			0x4000000000000000ull	/* Write Perm */
396 #define	AMDIOMMU_PTE_IGN7		0x8000000000000000ull
397 
398 /*
399  * IRTEs
400  */
401 
402 /* vAPIC is not enabled, guestmode = 0 */
403 struct amdiommu_irte_basic_novapic {
404 	u_int	remapen:1;	/* 0 - Target Abort */
405 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
406 	u_int	inttype:3;
407 	u_int	rqeoi:1;	/* Request EOI */
408 	u_int	dm:1;		/* Dest Mode */
409 	u_int	guestmode:1;	/* MBZ */
410 	u_int	dest:8;		/* Destination APIC */
411 	u_int	vector:8;
412 	u_int	rsrv:8;
413 } __packed;
414 _Static_assert(sizeof(struct amdiommu_irte_basic_novapic) ==
415     1 * sizeof(uint32_t), "IRTE 1");
416 
417 /* vAPIC is enabled, guestmode = 0 */
418 struct amdiommu_irte_basic_vapic {
419 	u_int	remapen:1;	/* 0 - Target Abort */
420 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
421 	u_int	inttype:3;
422 	u_int	rqeoi:1;	/* Request EOI */
423 	u_int	dm:1;		/* Dest Mode */
424 	u_int	guestmode:1;	/* MBZ */
425 	u_int	dest:8;		/* Destination APIC */
426 	u_int	rsrv0:16;
427 	u_int	rsrv1:32;
428 	u_int	vector:8;
429 	u_int	rsrv2:24;
430 	u_int	rsrv3:32;
431 } __packed;
432 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic) ==
433     4 * sizeof(uint32_t), "IRTE 2");
434 
435 /* vAPIC is enabled, guestmode = 1 */
436 struct amdiommu_irte_guest_vapic {
437 	u_int	remapen:1;	/* 0 - Target Abort */
438 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
439 	u_int	galogintr:1;
440 	u_int	rsrv0:2;
441 	u_int	gappidis:1;	/* supress GAPPI */
442 	u_int	isrun:1;	/* Guest Running hint */
443 	u_int	guestmode:1;	/* MB1 */
444 	u_int	dest:8;		/* Destination APIC for dorbell */
445 	u_int	rsrv1:16;
446 	u_int	gatag:32;
447 	u_int	vector:8;
448 	u_int	rsrv2:4;
449 	uint64_t vapicrp:40;	/* 51:12 bits of SPA for APIC backing page */
450 	u_int	rsrv3:12;
451 } __packed;
452 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic) ==
453     4 * sizeof(uint32_t), "IRTE 3");
454 
455 /* vAPIC is enabled, guestmode = 0, x2APIC */
456 struct amdiommu_irte_basic_vapic_x2 {
457 	u_int	remapen:1;	/* 0 - Target Abort */
458 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
459 	u_int	inttype:3;
460 	u_int	rqeoi:1;	/* Request EOI */
461 	u_int	dm:1;		/* Dest Mode */
462 	u_int	guestmode:1;	/* MBZ */
463 	u_int	dest0:24;	/* Destination APIC 23:0 */
464 	u_int	rsrv0:32;
465 	u_int	vector:8;
466 	u_int	rsrv1:24;
467 	u_int	rsrv2:24;
468 	u_int	dest1:8;	/* Destination APIC 31:24 */
469 } __packed;
470 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic_x2) ==
471     4 * sizeof(uint32_t), "IRTE 4");
472 
473 /* vAPIC is enabled, guestmode = 1, x2APIC */
474 struct amdiommu_irte_guest_vapic_x2 {
475 	u_int	remapen:1;	/* 0 - Target Abort */
476 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
477 	u_int	galogintr:1;
478 	u_int	rsrv0:2;
479 	u_int	gappidis:1;	/* supress GAPPI */
480 	u_int	isrun:1;	/* Guest Running hint */
481 	u_int	guestmode:1;	/* MB1 */
482 	u_int	dest0:24;	/* Destination APIC for dorbell 23:0 */
483 	u_int	gatag:32;
484 	u_int	vector:8;
485 	u_int	rsrv2:4;
486 	uint64_t vapicrp:40;	/* 51:12 bits of SPA for APIC backing page */
487 	u_int	rsrv3:4;
488 	u_int	dest1:8;	/* Destination APIC 31:24 */
489 } __packed;
490 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic_x2) ==
491     4 * sizeof(uint32_t), "IRTE 5");
492 
493 #define	AMDIOMMU_IRTE_INTTYPE_FIXED	0
494 #define	AMDIOMMU_IRTE_INTTYPE_ARBITR	1
495 
496 #define	AMDIOMMU_IRTE_DM_LOGICAL	1
497 #define	AMDIOMMU_IRTE_DM_PHYSICAL	1
498 
499 /*
500  * Commands
501  */
502 
503 struct amdiommu_cmd_generic {
504 	u_int	w0:32;
505 	union {
506 		u_int ww1:32;
507 		struct {
508 			u_int	w1:28;
509 			u_int	op:4;
510 		};
511 	};
512 	u_int	w2:32;
513 	u_int	w3:32;
514 } __packed;
515 _Static_assert(sizeof(struct amdiommu_cmd_generic) ==
516     4 * sizeof(uint32_t), "CMD_GENERIC");
517 
518 #define	AMDIOMMU_CMD_SZ_SHIFT	4	/* Shift for cmd count
519 					   to ring offset */
520 #define	AMDIOMMU_CMD_SZ		sizeof(struct amdiommu_cmd_generic)
521 					/* Command size */
522 _Static_assert((1 << AMDIOMMU_CMD_SZ_SHIFT) == AMDIOMMU_CMD_SZ,
523     "CMD size shift");
524 
525 struct amdiommu_cmd_completion_wait {
526 	u_int	s:1;
527 	u_int	i:1;
528 	u_int	f:1;
529 	u_int	address0:29;	/* Store Address 31:3 */
530 	u_int	address1:20;	/* Store Address 51:32 */
531 	u_int	rsrv:8;
532 	u_int	op:4;
533 	u_int	data0:32;
534 	u_int	data1:32;
535 } __packed;
536 _Static_assert(sizeof(struct amdiommu_cmd_completion_wait) ==
537     4 * sizeof(uint32_t), "CMD_COMPLETION_WAIT");
538 
539 struct amdiommu_cmd_invalidate_devtab_entry {
540 	u_int	devid:16;
541 	u_int	rsrv0:16;
542 	u_int	rsrv1:28;
543 	u_int	op:4;
544 	u_int	rsrv2:32;
545 	u_int	rsrv3:32;
546 } __packed;
547 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_devtab_entry) ==
548     4 * sizeof(uint32_t), "CMD_INVALIDATE_DEVTAB_ENTRY");
549 
550 struct amdiommu_cmd_invalidate_iommu_pages {
551 	u_int	pasid:20;
552 	u_int	rsrv0:12;
553 	u_int	domainid:16;
554 	u_int	rsrv1:12;
555 	u_int	op:4;
556 	u_int	s:1;
557 	u_int	pde:1;
558 	u_int	gn:1;
559 	u_int	rsrv2:9;
560 	uint64_t address:52;	/* Address 63:12 */
561 } __packed;
562 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_pages) ==
563     4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_PAGES");
564 
565 struct amdiommu_cmd_invalidate_iotlb_pages {
566 	u_int	devid:16;
567 	u_int	pasid1:8;
568 	u_int	maxpend0:8;
569 	u_int	queueid:16;
570 	u_int	pasid0:8;
571 	u_int	pasid2:4;
572 	u_int	op:4;
573 	u_int	s:1;
574 	u_int	rsrv0:1;
575 	u_int	gn:1;
576 	u_int	rsrv1:1;
577 	u_int	type:2;
578 	u_int	rsrv2:6;
579 	uint64_t address:52;	/* Address 63:12 */
580 } __packed;
581 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iotlb_pages) ==
582     4 * sizeof(uint32_t), "CMD_INVALIDATE_IOTLB_PAGES");
583 
584 struct amdiommu_cmd_invalidate_interrupt_table {
585 	u_int	devid:16;
586 	u_int	rsrv0:16;
587 	u_int	rsrv1:28;
588 	u_int	op:4;
589 	u_int	rsrv2:32;
590 	u_int	rsrv3:32;
591 } __packed;
592 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_interrupt_table) ==
593     4 * sizeof(uint32_t), "CMD_INVALIDATE_INTERRUPT_TABLE");
594 
595 struct amdiommu_cmd_prefetch_iommu_pages {
596 	u_int	devid:16;
597 	u_int	rsrv0:8;
598 	u_int	pfcount:8;
599 	u_int	pasid:20;
600 	u_int	rsrv1:8;
601 	u_int	op:4;
602 	u_int	s:1;
603 	u_int	rsrv2:1;
604 	u_int	gn:1;
605 	u_int	rsrv3:1;
606 	u_int	inval:1;	/* Invalidate First */
607 	u_int	rsrv4:7;
608 	uint64_t address:52;	/* Address 63:12 */
609 } __packed;
610 _Static_assert(sizeof(struct amdiommu_cmd_prefetch_iommu_pages) ==
611     4 * sizeof(uint32_t), "CMD_PREFETCH_IOMMU_PAGES");
612 
613 struct amdiommu_cmd_complete_ppr_request {
614 	u_int	devid:16;
615 	u_int	rsrv0:16;
616 	u_int	pasid:20;
617 	u_int	rsrv1:8;
618 	u_int	op:4;
619 	u_int	rsrv2:2;
620 	u_int	gn:1;
621 	u_int	rsrv3:29;
622 	u_int	compltag:16;
623 	u_int	rsrv4:16;
624 } __packed;
625 _Static_assert(sizeof(struct amdiommu_cmd_complete_ppr_request) ==
626     4 * sizeof(uint32_t), "CMD_COMPLETE_PPR_REQUEST");
627 
628 struct amdiommu_cmd_invalidate_iommu_all {
629 	u_int	rsrv0:32;
630 	u_int	op:4;
631 	u_int	rsrv1:28;
632 	u_int	rsrv2:32;
633 	u_int	rsrv3:32;
634 } __packed;
635 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_all) ==
636     4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_ALL");
637 
638 struct amdiommu_cmd_insert_guest_event {
639 	u_int	rsrv0:32;
640 	u_int	guestid:16;
641 	u_int	rsrv1:12;
642 	u_int	op:4;
643 	u_int	rsrv2:32;
644 	u_int	rsrv3:32;
645 } __packed;
646 _Static_assert(sizeof(struct amdiommu_cmd_insert_guest_event) ==
647     4 * sizeof(uint32_t), "CMD_INSERT_GUEST_EVENT");
648 
649 struct amdiommu_cmd_reset_vmmio {
650 	u_int	guestid:16;
651 	u_int	rsrv0:11;
652 	u_int	all:1;
653 	u_int	rsrv1:3;
654 	u_int	vcmd:1;
655 	u_int	rsrv2:27;
656 	u_int	op:4;
657 	u_int	rsrv3:32;
658 	u_int	rsrv4:32;
659 } __packed;
660 _Static_assert(sizeof(struct amdiommu_cmd_reset_vmmio) ==
661     4 * sizeof(uint32_t), "CMD_RESET_VMMIO");
662 
663 #define AMDIOMMU_CMD_COMPLETION_WAIT		0x1
664 #define AMDIOMMU_CMD_INVALIDATE_DEVTAB_ENTRY	0x2
665 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_PAGES	0x3
666 #define AMDIOMMU_CMD_INVALIDATE_IOTLB_PAGES	0x4
667 #define AMDIOMMU_CMD_INVALIDATE_INTERRUPT_TABLE	0x5
668 #define AMDIOMMU_CMD_PREFETCH_IOMMU_PAGES	0x6
669 #define AMDIOMMU_CMD_COMPLETE_PPR_REQUEST	0x7
670 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_ALL	0x8
671 #define AMDIOMMU_CMD_INSERT_GUEST_EVENT		0x9
672 #define AMDIOMMU_CMD_RESET_VMMIO		0xa
673 
674 /*
675  * Logging
676  */
677 struct amdiommu_event_generic {
678 	u_int	w0:32;
679 	union {
680 		u_int ww1:32;
681 		struct {
682 			u_int	w1:28;
683 			u_int	code:4;
684 		};
685 	};
686 	u_int	w2:32;
687 	u_int	w3:32;
688 } __packed;
689 _Static_assert(sizeof(struct amdiommu_event_generic) ==
690     4 * sizeof(uint32_t), "EVENT_GENERIC");
691 
692 #define	AMDIOMMU_EV_SZ_SHIFT	4	/* Shift for event count
693 					   to ring offset */
694 #define	AMDIOMMU_EV_SZ		sizeof(struct amdiommu_event_generic)
695 					/* Event size */
696 _Static_assert((1 << AMDIOMMU_EV_SZ_SHIFT) == AMDIOMMU_EV_SZ,
697     "Event size shift");
698 
699 struct amdiommu_event_ill_dev_table_entry {
700 	u_int	devid:16;
701 	u_int	pasid1:4;
702 	u_int	rsrv0:7;
703 	u_int	vnr:1;
704 	u_int	rsrv1:1;
705 	u_int	vevent:1;
706 	u_int	vptr:1;
707 	u_int	vcmd:1;
708 	u_int	pasid:16;
709 	u_int	gn:1;
710 	u_int	rsrv2:2;
711 	u_int	i:1;
712 	u_int	rsrv3:1;
713 	u_int	rw:1;
714 	u_int	rsrv4:1;
715 	u_int	rz:1;
716 	u_int	tr:1;
717 	u_int	rsrv5:3;
718 	u_int	code:4;
719 	u_int	rsrv6:2;
720 	u_int	addr1:30;
721 	u_int	addr2:32;
722 } __packed;
723 _Static_assert(sizeof(struct amdiommu_event_ill_dev_table_entry) ==
724     4 * sizeof(uint32_t), "EVENT_ILLEGAL_DEV_TABLE_ENTRY");
725 
726 struct amdiommu_event_io_page_fault_entry {
727 	u_int	devid:16;
728 	u_int	pasid1:4;
729 	u_int	rsrv0:7;
730 	u_int	vnr:1;
731 	u_int	rsrv1:1;
732 	u_int	vevent:1;
733 	u_int	vptr:1;
734 	u_int	vcmd:1;
735 	u_int	pasid:16;	/* also domain id */
736 	u_int	gn:1;
737 	u_int	nx:1;
738 	u_int	us:1;
739 	u_int	i:1;
740 	u_int	pr:1;
741 	u_int	rw:1;
742 	u_int	pe:1;
743 	u_int	rz:1;
744 	u_int	tr:1;
745 	u_int	rsrv2:3;
746 	u_int	code:4;
747 	u_int	addr1:32;
748 	u_int	addr2:32;
749 } __packed;
750 _Static_assert(sizeof(struct amdiommu_event_io_page_fault_entry) ==
751     4 * sizeof(uint32_t), "EVENT_IO_PAGE_FAULT_ENTRY");
752 
753 #define	AMDIOMMU_EV_ILL_DEV_TABLE_ENTRY		0x1
754 #define	AMDIOMMU_EV_IO_PAGE_FAULT		0x2
755 #define	AMDIOMMU_EV_DEV_TAB_HW_ERROR		0x3
756 #define	AMDIOMMU_EV_PAGE_TAB_HW_ERROR		0x4
757 #define	AMDIOMMU_EV_ILL_CMD_ERROR		0x5
758 #define	AMDIOMMU_EV_CMD_HW_ERROR		0x6
759 #define	AMDIOMMU_EV_IOTLB_INV_TIMEOUT		0x7
760 #define	AMDIOMMU_EV_INVALID_DEV_REQ		0x8
761 #define	AMDIOMMU_EV_INVALID_PPR_REQ		0x9
762 #define	AMDIOMMU_EV_COUNTER_ZERO		0xa	/* Typo in table 42? */
763 
764 #endif	/* __X86_IOMMU_AMD_REG_H */
765