xref: /freebsd/sys/x86/iommu/amd_reg.h (revision 57aebec4f767db3b3b8c7af813e5f1080d0e08ec)
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_EPH_EN		0x0000200000000000ull	/* Enh PPR Handling En */
190 #define	AMDIOMMU_CTRL_HADUP_MASK	0x0000c00000000000ull	/* Access and Dirty in host PT */
191 #define	AMDIOMMU_CTRL_GDUP_DIS		0x0001000000000000ull	/* Dis Dirty in guest PT */
192 #define	AMDIOMMU_CTRL_XT_EN		0x0004000000000000ull	/* x2APIC mode */
193 #define	AMDIOMMU_CTRL_INTCAPXT_EN	0x0008000000000000ull	/* x2APIC mode for IOMMU intrs */
194 #define	AMDIOMMU_CTRL_vCMD_EN		0x0010000000000000ull	/* vCMD buffer proc En */
195 #define	AMDIOMMU_CTRL_vIOMMU_EN		0x0020000000000000ull	/* vIOMMU En */
196 #define	AMDIOMMU_CTRL_GAUP_DIS		0x0040000000000000ull	/* Dis Access in guest PT */
197 #define	AMDIOMMU_CTRL_GAPPI_EN		0x0080000000000000ull	/* Guest APIC phys proc intr En */
198 #define	AMDIOMMU_CTRL_TMPM_EN		0x0100000000000000ull	/* Tiered Mem Page Migration En */
199 #define	AMDIOMMU_CTRL_GGCR3TRP_PHYS	0x0400000000000000ull	/* GCR3 is GPA (otherwise SPA) */
200 #define	AMDIOMMU_CTRL_IRTCACHE_DIS	0x0800000000000000ull	/* IRT Caching Dis */
201 #define	AMDIOMMU_CTRL_GSTBUFTRP_MODE	0x1000000000000000ull	/* See spec */
202 #define	AMDIOMMU_CTRL_SNPAVIC_MASK	0xe000000000000000ull	/* MBZ */
203 
204 /*
205  * IOMMU Extended Feature Register AMDIOMMU_EFR fields
206  */
207 #define	AMDIOMMU_EFR_XT_SUP		0x0000000000000004ull	/* x2APIC */
208 #define	AMDIOMMU_EFR_HWEV_SUP		0x0000000000000100ull	/* HW Event regs */
209 #define	AMDIOMMU_EFR_PC_SUP		0x0000000000000200ull	/* Perf counters */
210 #define	AMDIOMMU_EFR_HATS_MASK		0x0000000000000c00ull	/* Host Addr Trans Size */
211 #define	AMDIOMMU_EFR_HATS_4LVL		0x0000000000000000ull
212 #define	AMDIOMMU_EFR_HATS_5LVL		0x0000000000000400ull
213 #define	AMDIOMMU_EFR_HATS_6LVL		0x0000000000000800ull
214 #define	AMDIOMMU_EFR_DEVTBLSEG_MASK	0x000000c000000000ull	/* DevTbl segmentation */
215 #define	AMDIOMMU_EFR_DEVTBLSEG_SHIFT	38
216 
217 /* IOMMU Command Pointers (Head/Tail) registers fields */
218 #define	AMDIOMMU_CMDPTR_MASK		0x000000000007fff0ull
219 
220 /* IOMMU Command Buffer Base fields */
221 #define	AMDIOMMU_CMDBUF_BASE_SZSHIFT	56			/* Shift for size */
222 #define	AMDIOMMU_CMDBUF_MAX		(512 * 1024)
223 
224 /* IOMMU Event Log Base register fields */
225 #define	AMDIOMMU_EVNTLOG_BASE_SZSHIFT	56			/* Shift for size */
226 #define	AMDIOMMU_EVNTLOG_MIN		256
227 #define	AMDIOMMU_EVNTLOG_MAX		32768
228 
229 /* IOMMU Hardware Event Status register fields */
230 #define	AMDIOMMU_HWEVS_HEV		0x00000001		/* HW Ev Valid */
231 #define	AMDIOMMU_HWEVS_HEO		0x00000002		/* HW Ev Overfl */
232 
233 /*
234  * IOMMU Command and Event Status register fields.
235  * From the spec, all defined bits are either RO or RW1C.  As a consequence,
236  * single bit can be safely written to the register to clean a specific
237  * condition.
238  */
239 #define	AMDIOMMU_CMDEVS_EVOVRFLW	0x00000001
240 #define	AMDIOMMU_CMDEVS_EVLOGINT	0x00000002
241 #define	AMDIOMMU_CMDEVS_COMWAITINT	0x00000004
242 #define	AMDIOMMU_CMDEVS_EVLOGRUN	0x00000008
243 #define	AMDIOMMU_CMDEVS_CMDBUFRUN	0x00000010
244 #define	AMDIOMMU_CMDEVS_PPROVRFLW	0x00000020
245 #define	AMDIOMMU_CMDEVS_PPRINT		0x00000040
246 #define	AMDIOMMU_CMDEVS_PPRLOGRUN	0x00000080
247 #define	AMDIOMMU_CMDEVS_GALOGRUN	0x00000100
248 #define	AMDIOMMU_CMDEVS_GALOVRFLW	0x00000200
249 #define	AMDIOMMU_CMDEVS_GAINT		0x00000400
250 #define	AMDIOMMU_CMDEVS_PPROVRFLWB	0x00000800
251 #define	AMDIOMMU_CMDEVS_PPRLOGACTIVE	0x00001000
252 #define	AMDIOMMU_CMDEVS_RESV1		0x00002000
253 #define	AMDIOMMU_CMDEVS_RESV2		0x00004000
254 #define	AMDIOMMU_CMDEVS_EVOVRFLWB	0x00008000
255 #define	AMDIOMMU_CMDEVS_EVLOGACTIVE	0x00010000
256 #define	AMDIOMMU_CMDEVS_PPROVRFLWEB	0x00020000
257 #define	AMDIOMMU_CMDEVS_PPROVRFLWE	0x00040000
258 
259 /*
260  * Device Table Entry (DTE)
261  */
262 struct amdiommu_dte {
263 	u_int		v:1;		/* Valid */
264 	u_int		tv:1;		/* Translation Valid */
265 	u_int		rsrv0:5;
266 	u_int		had:2;		/* Host Access Dirty */
267 	u_int		pgmode:3;	/* Paging Mode */
268 	uint64_t	ptroot:40;	/* Page Table Root */
269 	u_int		ppr:1;		/* PPR En */
270 	u_int		gprp:1;		/* Guest PPR Resp with PASID */
271 	u_int		giov:1;		/* Guest IO Prot Valid */
272 	u_int		gv:1;		/* Guest Translation Valid */
273 	u_int		glx:2;		/* Guest Levels Translated */
274 	u_int		gcr3root0:3;	/* GCR3 root pointer part */
275 	u_int		ir:1;		/* Read Perm */
276 	u_int		iw:1;		/* Write Perm */
277 	u_int		rsrv1:1;
278 	u_int		domainid:16;	/* domain tag */
279 	u_int		gcr3root1:16;	/* GCR3 root pointer part */
280 	u_int		i:1;		/* IOTLB En */
281 	u_int		se:1;		/* Suppress IO Fault Events */
282 	u_int		sa:1;		/* Suppress All IO Fault Events */
283 	u_int		pioctl:2;	/* Port IO Control */
284 	u_int		cache:1;	/* IOTLB Cache Hint */
285 	u_int		sd:1;		/* Snoop Disable */
286 	u_int		ex:1;		/* Allow Exclusion */
287 	u_int		sysmgt:2;	/* System Management Msg Handling */
288 	u_int		sats:1;		/* Secure/Non-secure ATS */
289 	u_int		gcr3root2:21;	/* GCR3 root pointer part */
290 	u_int		iv:1;		/* Intr Map Valid */
291 	u_int		inttablen:4;	/* log2 Intr Table Len */
292 	u_int		ig:1;		/* Ignore Unmapped Interrupts */
293 	uint64_t	intrroot:46;	/* Interrupt Table Root (-low 6bits) */
294 	u_int		rsrv2:2;
295 	u_int		gpm:2;		/* Guest Paging Mode */
296 	u_int		initpass:1;	/* INIT pass-through */
297 	u_int		eintpass:1;	/* ExtInt pass-through */
298 	u_int		nmipass:1;	/* NMI pass-through */
299 	u_int		hptmode:1;	/* Host Page Table Mode Hint */
300 	u_int		intctl:2;	/* Interrupt Control */
301 	u_int		lint0pass:1;	/* LINT0 pass-through */
302 	u_int		lint1pass:1;	/* LINT1 pass-through */
303 	u_int		rsrv3:15;
304 	u_int		vimu:1;		/* Virtualize IOMMU En */
305 	u_int		gdevid:16;	/* Guest Dev Id */
306 	u_int		gid:16;		/* Guest Id */
307 	u_int		rsrv4:5;
308 	u_int		rsrv5:1;	/* Not Checked, sw avail */
309 	u_int		attrv:1;	/* Attr Override Valid */
310 	u_int		mode0fc:1;	/* Replace for PTE.FC */
311 	u_int		snoopattr:8;	/* GuestPTE.PAT -> ATS.N xlat */
312 } __packed;
313 _Static_assert(sizeof(struct amdiommu_dte) == 8 * sizeof(uint32_t), "DTE");
314 
315 #define	AMDIOMMU_DTE_HAD_NAND		0x0	/* No Access, No Dirty */
316 #define	AMDIOMMU_DTE_HAD_AND		0x1	/* Access, No Dirty */
317 #define	AMDIOMMU_DTE_HAD_RSRV		0x2
318 #define	AMDIOMMU_DTE_HAD_AD		0x3	/* Access, Dirty */
319 
320 #define	AMDIOMMU_DTE_PGMODE_1T1		0x0	/* SPA = GPA */
321 #define	AMDIOMMU_DTE_PGMODE_1LV		0x1	/* 1 Level PT */
322 #define	AMDIOMMU_DTE_PGMODE_2LV		0x2	/* 2 Level PT */
323 #define	AMDIOMMU_DTE_PGMODE_3LV		0x3	/* 3 Level PT */
324 #define	AMDIOMMU_DTE_PGMODE_4LV		0x4	/* 4 Level PT */
325 #define	AMDIOMMU_DTE_PGMODE_5LV		0x5	/* 5 Level PT */
326 #define	AMDIOMMU_DTE_PGMODE_6LV		0x6	/* 6 Level PT */
327 #define	AMDIOMMU_DTE_PGMODE_RSRV	0x7
328 
329 #define	AMDIOMMU_DTE_GLX_1LV		0x0	/* 1 Level GCR3 */
330 #define	AMDIOMMU_DTE_GLX_2LV		0x1	/* 2 Level GCR3 */
331 #define	AMDIOMMU_DTE_GLX_3LV		0x2	/* 3 Level GCR3 */
332 #define	AMDIOMMU_DTE_GLX_RSRV		0x3
333 
334 #define	AMDIOMMU_DTE_PIOCTL_DIS		0x0
335 #define	AMDIOMMU_DTE_PIOCTL_EN		0x1
336 #define	AMDIOMMU_DTE_PIOCTL_MAP		0x2
337 #define	AMDIOMMU_DTE_PIOCTL_RSRV	0x3
338 
339 #define	AMDIOMMU_DTE_SYSMGT_DIS		0x0	/* Target Abort */
340 #define	AMDIOMMU_DTE_SYSMGT_FW		0x0	/* Forwarded All */
341 #define	AMDIOMMU_DTE_SYSMGT_FWI		0x0	/* Forwarded INT */
342 #define	AMDIOMMU_DTE_SYSMGT_T		0x0	/* Translated */
343 
344 #define	AMDIOMMU_DTE_GPM_4LV		0x0	/* 4 Level */
345 #define	AMDIOMMU_DTE_GPM_5LV		0x1	/* 5 Level */
346 #define	AMDIOMMU_DTE_GPM_RSRV1		0x2
347 #define	AMDIOMMU_DTE_GPM_RSRV2		0x3
348 
349 #define	AMDIOMMU_DTE_INTCTL_DIS		0x0	/* Target Abort */
350 #define	AMDIOMMU_DTE_INTCTL_FW		0x1	/* Forward Unmapped */
351 #define	AMDIOMMU_DTE_INTCTL_MAP		0x2	/* Forward Remapped */
352 #define	AMDIOMMU_DTE_INTCTL_RSRV	0x3
353 
354 #define	AMDIOMMU_PGTBL_MAXLVL		6
355 
356 /*
357  * Page Table Entry (PTE/PDE)
358  */
359 #define	AMDIOMMU_PTE_PR			0x0001	/* Present, AKA V */
360 #define	AMDIOMMU_IGN1			0x0002
361 #define	AMDIOMMU_IGN2			0x0004
362 #define	AMDIOMMU_IGN3			0x0008
363 #define	AMDIOMMU_IGN4			0x0010
364 #define	AMDIOMMU_PTE_A			0x0020	/* Accessed */
365 #define	AMDIOMMU_PTE_D			0x0040	/* Dirty */
366 #define	AMDIOMMU_IGN5			0x0080
367 #define	AMDIOMMU_IGN6			0x0100
368 #define	AMDIOMMU_PTE_NLVL_MASK		0x0e00	/* Next Level */
369 #define	AMDIOMMU_PTE_NLVL_SHIFT		9
370 #define	AMDIOMMU_PTE_NLVL_7h		0x0e00	/* Magic Next Level */
371 #define	AMDIOMMU_PTE_PA_MASK		0x000ffffffffff000ull
372 #define	AMDIOMMU_PTE_PA_SHIFT		12
373 #define	AMDIOMMU_PTE_PMC_MASK		0x0600000000000000ull	/* Page Migr */
374 #define	AMDIOMMU_PTE_U			0x0800000000000000ull	/* ATS.U */
375 #define	AMDIOMMU_PTE_FC			0x1000000000000000ull	/* Force Coh */
376 #define	AMDIOMMU_PTE_IR			0x2000000000000000ull	/* Read Perm */
377 #define	AMDIOMMU_PTE_IW			0x4000000000000000ull	/* Write Perm */
378 #define	AMDIOMMU_PTE_IGN7		0x8000000000000000ull
379 
380 /*
381  * IRTEs
382  */
383 
384 /* vAPIC is not enabled, guestmode = 0 */
385 struct amdiommu_irte_basic_novapic {
386 	u_int	remapen:1;	/* 0 - Target Abort */
387 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
388 	u_int	inttype:3;
389 	u_int	rqeoi:1;	/* Request EOI */
390 	u_int	dm:1;		/* Dest Mode */
391 	u_int	guestmode:1;	/* MBZ */
392 	u_int	dest:8;		/* Destination APIC */
393 	u_int	vector:8;
394 	u_int	rsrv:8;
395 } __packed;
396 _Static_assert(sizeof(struct amdiommu_irte_basic_novapic) ==
397     1 * sizeof(uint32_t), "IRTE 1");
398 
399 /* vAPIC is enabled, guestmode = 0 */
400 struct amdiommu_irte_basic_vapic {
401 	u_int	remapen:1;	/* 0 - Target Abort */
402 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
403 	u_int	inttype:3;
404 	u_int	rqeoi:1;	/* Request EOI */
405 	u_int	dm:1;		/* Dest Mode */
406 	u_int	guestmode:1;	/* MBZ */
407 	u_int	dest:8;		/* Destination APIC */
408 	u_int	rsrv0:16;
409 	u_int	rsrv1:32;
410 	u_int	vector:8;
411 	u_int	rsrv2:24;
412 	u_int	rsrv3:32;
413 } __packed;
414 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic) ==
415     4 * sizeof(uint32_t), "IRTE 2");
416 
417 /* vAPIC is enabled, guestmode = 1 */
418 struct amdiommu_irte_guest_vapic {
419 	u_int	remapen:1;	/* 0 - Target Abort */
420 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
421 	u_int	galogintr:1;
422 	u_int	rsrv0:2;
423 	u_int	gappidis:1;	/* supress GAPPI */
424 	u_int	isrun:1;	/* Guest Running hint */
425 	u_int	guestmode:1;	/* MB1 */
426 	u_int	dest:8;		/* Destination APIC for dorbell */
427 	u_int	rsrv1:16;
428 	u_int	gatag:32;
429 	u_int	vector:8;
430 	u_int	rsrv2:4;
431 	uint64_t vapicrp:40;	/* 51:12 bits of SPA for APIC backing page */
432 	u_int	rsrv3:12;
433 } __packed;
434 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic) ==
435     4 * sizeof(uint32_t), "IRTE 3");
436 
437 /* vAPIC is enabled, guestmode = 0, x2APIC */
438 struct amdiommu_irte_basic_vapic_x2 {
439 	u_int	remapen:1;	/* 0 - Target Abort */
440 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
441 	u_int	inttype:3;
442 	u_int	rqeoi:1;	/* Request EOI */
443 	u_int	dm:1;		/* Dest Mode */
444 	u_int	guestmode:1;	/* MBZ */
445 	u_int	dest0:24;	/* Destination APIC 23:0 */
446 	u_int	rsrv0:32;
447 	u_int	vector:8;
448 	u_int	rsrv1:24;
449 	u_int	rsrv2:24;
450 	u_int	dest1:8;	/* Destination APIC 31:24 */
451 } __packed;
452 _Static_assert(sizeof(struct amdiommu_irte_basic_vapic_x2) ==
453     4 * sizeof(uint32_t), "IRTE 4");
454 
455 /* vAPIC is enabled, guestmode = 1, x2APIC */
456 struct amdiommu_irte_guest_vapic_x2 {
457 	u_int	remapen:1;	/* 0 - Target Abort */
458 	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
459 	u_int	galogintr:1;
460 	u_int	rsrv0:2;
461 	u_int	gappidis:1;	/* supress GAPPI */
462 	u_int	isrun:1;	/* Guest Running hint */
463 	u_int	guestmode:1;	/* MB1 */
464 	u_int	dest0:24;	/* Destination APIC for dorbell 23:0 */
465 	u_int	gatag:32;
466 	u_int	vector:8;
467 	u_int	rsrv2:4;
468 	uint64_t vapicrp:40;	/* 51:12 bits of SPA for APIC backing page */
469 	u_int	rsrv3:4;
470 	u_int	dest1:8;	/* Destination APIC 31:24 */
471 } __packed;
472 _Static_assert(sizeof(struct amdiommu_irte_guest_vapic_x2) ==
473     4 * sizeof(uint32_t), "IRTE 5");
474 
475 #define	AMDIOMMU_IRTE_INTTYPE_FIXED	0
476 #define	AMDIOMMU_IRTE_INTTYPE_ARBITR	1
477 
478 #define	AMDIOMMU_IRTE_DM_LOGICAL	1
479 #define	AMDIOMMU_IRTE_DM_PHYSICAL	1
480 
481 /*
482  * Commands
483  */
484 
485 struct amdiommu_cmd_generic {
486 	u_int	w0:32;
487 	union {
488 		u_int ww1:32;
489 		struct {
490 			u_int	w1:28;
491 			u_int	op:4;
492 		};
493 	};
494 	u_int	w2:32;
495 	u_int	w3:32;
496 } __packed;
497 _Static_assert(sizeof(struct amdiommu_cmd_generic) ==
498     4 * sizeof(uint32_t), "CMD_GENERIC");
499 
500 #define	AMDIOMMU_CMD_SZ_SHIFT	4	/* Shift for cmd count
501 					   to ring offset */
502 #define	AMDIOMMU_CMD_SZ		sizeof(struct amdiommu_cmd_generic)
503 					/* Command size */
504 _Static_assert((1 << AMDIOMMU_CMD_SZ_SHIFT) == AMDIOMMU_CMD_SZ,
505     "CMD size shift");
506 
507 struct amdiommu_cmd_completion_wait {
508 	u_int	s:1;
509 	u_int	i:1;
510 	u_int	f:1;
511 	u_int	address0:29;	/* Store Address 31:3 */
512 	u_int	address1:20;	/* Store Address 51:32 */
513 	u_int	rsrv:8;
514 	u_int	op:4;
515 	u_int	data0:32;
516 	u_int	data1:32;
517 } __packed;
518 _Static_assert(sizeof(struct amdiommu_cmd_completion_wait) ==
519     4 * sizeof(uint32_t), "CMD_COMPLETION_WAIT");
520 
521 struct amdiommu_cmd_invalidate_devtab_entry {
522 	u_int	devid:16;
523 	u_int	rsrv0:16;
524 	u_int	rsrv1:28;
525 	u_int	op:4;
526 	u_int	rsrv2:32;
527 	u_int	rsrv3:32;
528 } __packed;
529 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_devtab_entry) ==
530     4 * sizeof(uint32_t), "CMD_INVALIDATE_DEVTAB_ENTRY");
531 
532 struct amdiommu_cmd_invalidate_iommu_pages {
533 	u_int	pasid:20;
534 	u_int	rsrv0:12;
535 	u_int	domainid:16;
536 	u_int	rsrv1:12;
537 	u_int	op:4;
538 	u_int	s:1;
539 	u_int	pde:1;
540 	u_int	gn:1;
541 	u_int	rsrv2:9;
542 	uint64_t address:52;	/* Address 63:12 */
543 } __packed;
544 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_pages) ==
545     4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_PAGES");
546 
547 struct amdiommu_cmd_invalidate_iotlb_pages {
548 	u_int	devid:16;
549 	u_int	pasid1:8;
550 	u_int	maxpend0:8;
551 	u_int	queueid:16;
552 	u_int	pasid0:8;
553 	u_int	pasid2:4;
554 	u_int	op:4;
555 	u_int	s:1;
556 	u_int	rsrv0:1;
557 	u_int	gn:1;
558 	u_int	rsrv1:1;
559 	u_int	type:2;
560 	u_int	rsrv2:6;
561 	uint64_t address:52;	/* Address 63:12 */
562 } __packed;
563 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iotlb_pages) ==
564     4 * sizeof(uint32_t), "CMD_INVALIDATE_IOTLB_PAGES");
565 
566 struct amdiommu_cmd_invalidate_interrupt_table {
567 	u_int	devid:16;
568 	u_int	rsrv0:16;
569 	u_int	rsrv1:28;
570 	u_int	op:4;
571 	u_int	rsrv2:32;
572 	u_int	rsrv3:32;
573 } __packed;
574 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_interrupt_table) ==
575     4 * sizeof(uint32_t), "CMD_INVALIDATE_INTERRUPT_TABLE");
576 
577 struct amdiommu_cmd_prefetch_iommu_pages {
578 	u_int	devid:16;
579 	u_int	rsrv0:8;
580 	u_int	pfcount:8;
581 	u_int	pasid:20;
582 	u_int	rsrv1:8;
583 	u_int	op:4;
584 	u_int	s:1;
585 	u_int	rsrv2:1;
586 	u_int	gn:1;
587 	u_int	rsrv3:1;
588 	u_int	inval:1;	/* Invalidate First */
589 	u_int	rsrv4:7;
590 	uint64_t address:52;	/* Address 63:12 */
591 } __packed;
592 _Static_assert(sizeof(struct amdiommu_cmd_prefetch_iommu_pages) ==
593     4 * sizeof(uint32_t), "CMD_PREFETCH_IOMMU_PAGES");
594 
595 struct amdiommu_cmd_complete_ppr_request {
596 	u_int	devid:16;
597 	u_int	rsrv0:16;
598 	u_int	pasid:20;
599 	u_int	rsrv1:8;
600 	u_int	op:4;
601 	u_int	rsrv2:2;
602 	u_int	gn:1;
603 	u_int	rsrv3:29;
604 	u_int	compltag:16;
605 	u_int	rsrv4:16;
606 } __packed;
607 _Static_assert(sizeof(struct amdiommu_cmd_complete_ppr_request) ==
608     4 * sizeof(uint32_t), "CMD_COMPLETE_PPR_REQUEST");
609 
610 struct amdiommu_cmd_invalidate_iommu_all {
611 	u_int	rsrv0:32;
612 	u_int	op:4;
613 	u_int	rsrv1:28;
614 	u_int	rsrv2:32;
615 	u_int	rsrv3:32;
616 } __packed;
617 _Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_all) ==
618     4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_ALL");
619 
620 struct amdiommu_cmd_insert_guest_event {
621 	u_int	rsrv0:32;
622 	u_int	guestid:16;
623 	u_int	rsrv1:12;
624 	u_int	op:4;
625 	u_int	rsrv2:32;
626 	u_int	rsrv3:32;
627 } __packed;
628 _Static_assert(sizeof(struct amdiommu_cmd_insert_guest_event) ==
629     4 * sizeof(uint32_t), "CMD_INSERT_GUEST_EVENT");
630 
631 struct amdiommu_cmd_reset_vmmio {
632 	u_int	guestid:16;
633 	u_int	rsrv0:11;
634 	u_int	all:1;
635 	u_int	rsrv1:3;
636 	u_int	vcmd:1;
637 	u_int	rsrv2:27;
638 	u_int	op:4;
639 	u_int	rsrv3:32;
640 	u_int	rsrv4:32;
641 } __packed;
642 _Static_assert(sizeof(struct amdiommu_cmd_reset_vmmio) ==
643     4 * sizeof(uint32_t), "CMD_RESET_VMMIO");
644 
645 #define AMDIOMMU_CMD_COMPLETION_WAIT		0x1
646 #define AMDIOMMU_CMD_INVALIDATE_DEVTAB_ENTRY	0x2
647 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_PAGES	0x3
648 #define AMDIOMMU_CMD_INVALIDATE_IOTLB_PAGES	0x4
649 #define AMDIOMMU_CMD_INVALIDATE_INTERRUPT_TABLE	0x5
650 #define AMDIOMMU_CMD_PREFETCH_IOMMU_PAGES	0x6
651 #define AMDIOMMU_CMD_COMPLETE_PPR_REQUEST	0x7
652 #define AMDIOMMU_CMD_INVALIDATE_IOMMU_ALL	0x8
653 #define AMDIOMMU_CMD_INSERT_GUEST_EVENT		0x9
654 #define AMDIOMMU_CMD_RESET_VMMIO		0xa
655 
656 /*
657  * Logging
658  */
659 struct amdiommu_event_generic {
660 	u_int	w0:32;
661 	union {
662 		u_int ww1:32;
663 		struct {
664 			u_int	w1:28;
665 			u_int	code:4;
666 		};
667 	};
668 	u_int	w2:32;
669 	u_int	w3:32;
670 } __packed;
671 _Static_assert(sizeof(struct amdiommu_event_generic) ==
672     4 * sizeof(uint32_t), "EVENT_GENERIC");
673 
674 #define	AMDIOMMU_EV_SZ_SHIFT	4	/* Shift for event count
675 					   to ring offset */
676 #define	AMDIOMMU_EV_SZ		sizeof(struct amdiommu_event_generic)
677 					/* Event size */
678 _Static_assert((1 << AMDIOMMU_EV_SZ_SHIFT) == AMDIOMMU_EV_SZ,
679     "Event size shift");
680 
681 struct amdiommu_event_ill_dev_table_entry {
682 	u_int	devid:16;
683 	u_int	pasid1:4;
684 	u_int	rsrv0:7;
685 	u_int	vnr:1;
686 	u_int	rsrv1:1;
687 	u_int	vevent:1;
688 	u_int	vptr:1;
689 	u_int	vcmd:1;
690 	u_int	pasid:16;
691 	u_int	gn:1;
692 	u_int	rsrv2:2;
693 	u_int	i:1;
694 	u_int	rsrv3:1;
695 	u_int	rw:1;
696 	u_int	rsrv4:1;
697 	u_int	rz:1;
698 	u_int	tr:1;
699 	u_int	rsrv5:3;
700 	u_int	code:4;
701 	u_int	rsrv6:2;
702 	u_int	addr1:30;
703 	u_int	addr2:32;
704 } __packed;
705 _Static_assert(sizeof(struct amdiommu_event_ill_dev_table_entry) ==
706     4 * sizeof(uint32_t), "EVENT_ILLEGAL_DEV_TABLE_ENTRY");
707 
708 struct amdiommu_event_io_page_fault_entry {
709 	u_int	devid:16;
710 	u_int	pasid1:4;
711 	u_int	rsrv0:7;
712 	u_int	vnr:1;
713 	u_int	rsrv1:1;
714 	u_int	vevent:1;
715 	u_int	vptr:1;
716 	u_int	vcmd:1;
717 	u_int	pasid:16;	/* also domain id */
718 	u_int	gn:1;
719 	u_int	nx:1;
720 	u_int	us:1;
721 	u_int	i:1;
722 	u_int	pr:1;
723 	u_int	rw:1;
724 	u_int	pe:1;
725 	u_int	rz:1;
726 	u_int	tr:1;
727 	u_int	rsrv2:3;
728 	u_int	code:4;
729 	u_int	addr1:32;
730 	u_int	addr2:32;
731 } __packed;
732 _Static_assert(sizeof(struct amdiommu_event_io_page_fault_entry) ==
733     4 * sizeof(uint32_t), "EVENT_IO_PAGE_FAULT_ENTRY");
734 
735 #define	AMDIOMMU_EV_ILL_DEV_TABLE_ENTRY		0x1
736 #define	AMDIOMMU_EV_IO_PAGE_FAULT		0x2
737 #define	AMDIOMMU_EV_DEV_TAB_HW_ERROR		0x3
738 #define	AMDIOMMU_EV_PAGE_TAB_HW_ERROR		0x4
739 #define	AMDIOMMU_EV_ILL_CMD_ERROR		0x5
740 #define	AMDIOMMU_EV_CMD_HW_ERROR		0x6
741 #define	AMDIOMMU_EV_IOTLB_INV_TIMEOUT		0x7
742 #define	AMDIOMMU_EV_INVALID_DEV_REQ		0x8
743 #define	AMDIOMMU_EV_INVALID_PPR_REQ		0x9
744 #define	AMDIOMMU_EV_COUNTER_ZERO		0xa	/* Typo in table 42? */
745 
746 #endif	/* __X86_IOMMU_AMD_REG_H */
747