git: 0a9bec17447c - main - x86/iommu/amd_reg.h: AMD IOMMU registers definitions

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 02 Nov 2024 23:46:38 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=0a9bec17447c1256b046a03dbf5cd40ced437b56

commit 0a9bec17447c1256b046a03dbf5cd40ced437b56
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-04-12 04:23:13 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-11-02 23:45:40 +0000

    x86/iommu/amd_reg.h: AMD IOMMU registers definitions
    
    Reviewed by:    emaste
    Sponsored by:   Advanced Micro Devices (AMD)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D47255
---
 sys/x86/iommu/amd_reg.h | 746 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 746 insertions(+)

diff --git a/sys/x86/iommu/amd_reg.h b/sys/x86/iommu/amd_reg.h
new file mode 100644
index 000000000000..33f744c65cc6
--- /dev/null
+++ b/sys/x86/iommu/amd_reg.h
@@ -0,0 +1,746 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __X86_IOMMU_AMD_REG_H
+#define	__X86_IOMMU_AMD_REG_H
+
+/*
+ * MMIO Registers. Offsets and bits definitions.
+ */
+
+#define	AMDIOMMU_DEVTAB_BASE	0x0000
+#define	AMDIOMMU_CMDBUF_BASE	0x0008
+#define	AMDIOMMU_EVNTLOG_BASE	0x0010
+#define	AMDIOMMU_CTRL		0x0018
+#define	AMDIOMMU_EXCL_BASE	0x0020
+#define	AMDIOMMU_EXCL_RANGE	0x0028
+#define	AMDIOMMU_EFR		0x0030
+#define	AMDIOMMU_PPRLOG_BASE	0x0038
+#define	AMDIOMMU_HWEV_UPPER	0x0040
+#define	AMDIOMMU_HWEV_LOWER	0x0048
+#define	AMDIOMMU_HWEV_STATUS	0x0050
+
+#define	AMDIOMMU_SMIF_0		0x0060
+#define	AMDIOMMU_SMIF_1		0x0068
+#define	AMDIOMMU_SMIF_2		0x0070
+#define	AMDIOMMU_SMIF_3		0x0078
+#define	AMDIOMMU_SMIF_4		0x0080
+#define	AMDIOMMU_SMIF_5		0x0088
+#define	AMDIOMMU_SMIF_6		0x0090
+#define	AMDIOMMU_SMIF_7		0x0098
+#define	AMDIOMMU_SMIF_8		0x00a0
+#define	AMDIOMMU_SMIF_9		0x00a8
+#define	AMDIOMMU_SMIF_10	0x00b0
+#define	AMDIOMMU_SMIF_11	0x00b8
+#define	AMDIOMMU_SMIF_12	0x00c0
+#define	AMDIOMMU_SMIF_13	0x00c8
+#define	AMDIOMMU_SMIF_14	0x00d0
+#define	AMDIOMMU_SMIF_15	0x00d8
+
+#define	AMDIOMMU_VAPIC_LOG_BASE	0x00e0
+#define	AMDIOMMU_VAPIC_LOG_TAIL	0x00e8
+#define	AMDIOMMU_PPRLOGB_BASE	0x00f0
+#define	AMDIOMMU_EVNTLOGB_BASE	0x00f0
+
+#define	AMDIOMMU_DEVTAB_S1_BASE	0x0100
+#define	AMDIOMMU_DEVTAB_S2_BASE	0x0108
+#define	AMDIOMMU_DEVTAB_S3_BASE	0x0110
+#define	AMDIOMMU_DEVTAB_S4_BASE	0x0118
+#define	AMDIOMMU_DEVTAB_S5_BASE	0x0120
+#define	AMDIOMMU_DEVTAB_S6_BASE	0x0128
+#define	AMDIOMMU_DEVTAB_S7_BASE	0x0130
+
+#define	AMDIOMMU_DSFX		0x0138
+#define	AMDIOMMU_DSCX		0x0140
+#define	AMDIOMMU_DSSX		0x0148
+
+#define	AMDIOMMU_MSI_VEC0	0x0150
+#define	AMDIOMMU_MSI_VEC1	0x0154
+#define	AMDIOMMU_MSI_CAP_H	0x0158
+#define	AMDIOMMU_MSI_ADDR_LOW	0x015c
+#define	AMDIOMMU_MSI_ADDR_HIGH	0x0160
+#define	AMDIOMMU_MSI_DATA	0x0164
+#define	AMDIOMMU_MSI_MAPCAP	0x0168
+
+#define	AMDIOMMU_PERFOPT	0x016c
+
+#define	AMDIOMMU_x2APIC_CTRL	0x0170
+#define	AMDIOMMU_PPRI_CTRL	0x0178
+#define	AMDIOMMU_GALOGI_CTRL	0x0180
+
+#define	AMDIOMMU_vIOMMU_STATUS	0x0190
+
+#define	AMDIOMMU_MARC0_BASE	0x0200
+#define	AMDIOMMU_MARC0_RELOC	0x0208
+#define	AMDIOMMU_MARC0_LEN	0x0210
+#define	AMDIOMMU_MARC1_BASE	0x0218
+#define	AMDIOMMU_MARC1_RELOC	0x0220
+#define	AMDIOMMU_MARC1_LEN	0x0228
+#define	AMDIOMMU_MARC2_BASE	0x0230
+#define	AMDIOMMU_MARC2_RELOC	0x0238
+#define	AMDIOMMU_MARC2_LEN	0x0240
+#define	AMDIOMMU_MARC3_BASE	0x0248
+#define	AMDIOMMU_MARC3_RELOC	0x0250
+#define	AMDIOMMU_MARC3_LEN	0x0258
+
+#define	AMDIOMMU_EFR2		0x01a0
+
+#define	AMDIOMMU_CMDBUF_HEAD	0x2000
+#define	AMDIOMMU_CMDBUF_TAIL	0x2008
+#define	AMDIOMMU_EVNTLOG_HEAD	0x2010
+#define	AMDIOMMU_EVNTLOG_TAIL	0x2018
+#define	AMDIOMMU_CMDEV_STATUS	0x2020
+#define	AMDIOMMU_PPRLOG_HEAD	0x2030
+#define	AMDIOMMU_PPRLOG_TAIL	0x2038
+#define	AMDIOMMU_vAPICLOG_HEAD	0x2040
+#define	AMDIOMMU_vAPICLOG_TAIL	0x2048
+#define	AMDIOMMU_PPRLOGB_HEAD	0x2050
+#define	AMDIOMMU_PPRLOGB_TAIL	0x2058
+#define	AMDIOMMU_EVNTLOGB_HEAD	0x2070
+#define	AMDIOMMU_EVNTLOGB_TAIL	0x2078
+#define	AMDIOMMU_PPRLOG_AUR	0x2080
+#define	AMDIOMMU_PPRLOG_EAI	0x2088
+#define	AMDIOMMU_PPRLOGB_AUR	0x2090
+
+/*
+ * IOMMU Control Register AMDIOMMU_CTRL fields
+ */
+#define	AMDIOMMU_CTRL_EN		0x0000000000000001ull	/* IOMMU En */
+#define	AMDIOMMU_CTRL_HTTUN_EN		0x0000000000000002ull	/* HT Tun Trans En */
+#define	AMDIOMMU_CTRL_EVNTLOG_EN	0x0000000000000004ull	/* Event Log En */
+#define	AMDIOMMU_CTRL_EVENTINT_EN	0x0000000000000008ull	/* Event Log Intr En */
+#define	AMDIOMMU_CTRL_COMWINT_EN	0x0000000000000010ull	/* Compl Wait Intr En */
+#define	AMDIOMMU_CTRL_INVTOUT_MASK	0x00000000000000e0ull	/* IOTLB Inv Timeout*/
+#define	AMDIOMMU_CTRL_INVTOUT_NO	0x0000000000000000ull
+#define	AMDIOMMU_CTRL_INVTOUT_1MS	0x0000000000000020ull
+#define	AMDIOMMU_CTRL_INVTOUT_10MS	0x0000000000000040ull
+#define	AMDIOMMU_CTRL_INVTOUT_100MS	0x0000000000000060ull
+#define	AMDIOMMU_CTRL_INVTOUT_1S	0x0000000000000080ull
+#define	AMDIOMMU_CTRL_INVTOUT_10S	0x00000000000000a0ull
+#define	AMDIOMMU_CTRL_INVTOUT_100S	0x00000000000000b0ull
+#define	AMDIOMMU_CTRL_INVTOUT_RSRV	0x00000000000000e0ull
+#define	AMDIOMMU_CTRL_PASSPW		0x0000000000000100ull	/* HT Pass Posted Wr */
+#define	AMDIOMMU_CTRL_REPASSPW		0x0000000000000200ull	/* HT Resp Pass Posted Wr */
+#define	AMDIOMMU_CTRL_COHERENT		0x0000000000000400ull	/* HT Coherent Reads */
+#define	AMDIOMMU_CTRL_ISOC		0x0000000000000800ull	/* HT Isoc Reads */
+#define	AMDIOMMU_CTRL_CMDBUF_EN		0x0000000000001000ull	/* Start CMD proc En */
+#define	AMDIOMMU_CTRL_PPRLOG_EN		0x0000000000002000ull	/* Periph Page Req Log En */
+#define	AMDIOMMU_CTRL_PPRINT_EN		0x0000000000004000ull	/* Periph Page Req Intr En */
+#define	AMDIOMMU_CTRL_PPR_EN		0x0000000000008000ull	/* Periph Page Req En */
+#define	AMDIOMMU_CTRL_GT_EN		0x0000000000010000ull	/* Guest En */
+#define	AMDIOMMU_CTRL_GA_EN		0x0000000000020000ull	/* Guest vAPIC En */
+#define	AMDIOMMU_CTRL_SMIF_EN		0x0000000000400000ull	/* SMI Filter En */
+#define	AMDIOMMU_CTRL_SLFWB_DIS		0x0000000000800000ull	/* Self WriteBack Dis */
+#define	AMDIOMMU_CTRL_SMIFLOG_EN	0x0000000001000000ull	/* SMI Filter Log En */
+#define	AMDIOMMU_CTRL_GAM_EN_MASK	0x000000000e000000ull	/* Guest vAPIC Mode En */
+#define	AMDIOMMU_CTRL_GAM_EN_vAPIC_GM0	0x0000000000000000ull	/* IRTE.GM = 0 */
+#define	AMDIOMMU_CTRL_GAM_EN_vAPIC_GM1	0x0000000002000000ull	/* IRTE.GM = 1 */
+#define	AMDIOMMU_CTRL_GALOG_EN		0x0000000010000000ull	/* Guest vAPIC GA Log En */
+#define	AMDIOMMU_CTRL_GAINT_EN		0x0000000020000000ull	/* Guest vAPIC GA Intr En */
+#define	AMDIOMMU_CTRL_DUALPPRLOG_MASK	0x00000000c0000000ull	/* Dual Periph Page Req Log En */
+#define	AMDIOMMU_CTRL_DUALPPRLOG_A	0x0000000000000000ull	/* Use Log A */
+#define	AMDIOMMU_CTRL_DUALPPRLOG_B	0x0000000040000000ull	/* Use Log B */
+#define	AMDIOMMU_CTRL_DUALPPRLOG_SWAP	0x0000000080000000ull	/* Auto-swap on full */
+#define	AMDIOMMU_CTRL_DUALPPRLOG_RSRV	0x00000000c0000000ull
+#define	AMDIOMMU_CTRL_DUALEVNTLOG_MASK	0x0000000300000000ull	/* Dual Event Log En */
+#define	AMDIOMMU_CTRL_DUALEVNTLOG_A	0x0000000000000000ull	/* Use Log A Buf */
+#define	AMDIOMMU_CTRL_DUALEVNTLOG_B	0x0000000100000000ull	/* Use Log B Buf */
+#define	AMDIOMMU_CTRL_DUALEVNTLOG_SWAP	0x0000000200000000ull	/* Auto-swap on full */
+#define	AMDIOMMU_CTRL_DUALEVNTLOG_RSRV	0x0000000300000000ull
+#define	AMDIOMMU_CTRL_DEVTABSEG_MASK	0x0000001c00000000ull	/* Dev Table Segm */
+#define	AMDIOMMU_CTRL_DEVTABSEG_1	0x0000000000000000ull	/* 1 Segment */
+#define	AMDIOMMU_CTRL_DEVTABSEG_2	0x0000000400000000ull	/* 2 Segments */
+#define	AMDIOMMU_CTRL_DEVTABSEG_4	0x0000000800000000ull	/* 4 Segments */
+#define	AMDIOMMU_CTRL_DEVTABSEG_8	0x0000000c00000000ull	/* 8 Segments */
+#define	AMDIOMMU_CTRL_PRIVABRT_MASK	0x0000006000000000ull	/* Privilege Abort En */
+#define	AMDIOMMU_CTRL_PRIVABRT_USR	0x0000000000000000ull	/* Privilege Abort User */
+#define	AMDIOMMU_CTRL_PRIVABRT_ALL	0x0000002000000000ull	/* Privilege Abort Always */
+#define	AMDIOMMU_CTRL_PPRAUTORSP_EN	0x0000008000000000ull	/* PPR Auto Resp En */
+#define	AMDIOMMU_CTRL_MARC_EN		0x0000010000000000ull	/* Memory Addr Routing En */
+#define	AMDIOMMU_CTRL_BLKSTOPMRK_EN	0x0000020000000000ull	/* Block StopMark En */
+#define	AMDIOMMU_CTRL_PPRAUTORESPA_EN	0x0000040000000000ull	/* PPR Auto Resp Always En */
+#define	AMDIOMMU_CTRL_EPH_EN		0x0000200000000000ull	/* Enh PPR Handling En */
+#define	AMDIOMMU_CTRL_HADUP_MASK	0x0000c00000000000ull	/* Access and Dirty in host PT */
+#define	AMDIOMMU_CTRL_GDUP_DIS		0x0001000000000000ull	/* Dis Dirty in guest PT */
+#define	AMDIOMMU_CTRL_XT_EN		0x0004000000000000ull	/* x2APIC mode */
+#define	AMDIOMMU_CTRL_INTCAPXT_EN	0x0008000000000000ull	/* x2APIC mode for IOMMU intrs */
+#define	AMDIOMMU_CTRL_vCMD_EN		0x0010000000000000ull	/* vCMD buffer proc En */
+#define	AMDIOMMU_CTRL_vIOMMU_EN		0x0020000000000000ull	/* vIOMMU En */
+#define	AMDIOMMU_CTRL_GAUP_DIS		0x0040000000000000ull	/* Dis Access in guest PT */
+#define	AMDIOMMU_CTRL_GAPPI_EN		0x0080000000000000ull	/* Guest APIC phys proc intr En */
+#define	AMDIOMMU_CTRL_TMPM_EN		0x0100000000000000ull	/* Tiered Mem Page Migration En */
+#define	AMDIOMMU_CTRL_GGCR3TRP_PHYS	0x0400000000000000ull	/* GCR3 is GPA (otherwise SPA) */
+#define	AMDIOMMU_CTRL_IRTCACHE_DIS	0x0800000000000000ull	/* IRT Caching Dis */
+#define	AMDIOMMU_CTRL_GSTBUFTRP_MODE	0x1000000000000000ull	/* See spec */
+#define	AMDIOMMU_CTRL_SNPAVIC_MASK	0xe000000000000000ull	/* MBZ */
+
+/*
+ * IOMMU Extended Feature Register AMDIOMMU_EFR fields
+ */
+#define	AMDIOMMU_EFR_XT_SUP		0x0000000000000004ull	/* x2APIC */
+#define	AMDIOMMU_EFR_HWEV_SUP		0x0000000000000100ull	/* HW Event regs */
+#define	AMDIOMMU_EFR_PC_SUP		0x0000000000000200ull	/* Perf counters */
+#define	AMDIOMMU_EFR_HATS_MASK		0x0000000000000c00ull	/* Host Addr Trans Size */
+#define	AMDIOMMU_EFR_HATS_4LVL		0x0000000000000000ull
+#define	AMDIOMMU_EFR_HATS_5LVL		0x0000000000000400ull
+#define	AMDIOMMU_EFR_HATS_6LVL		0x0000000000000800ull
+#define	AMDIOMMU_EFR_DEVTBLSEG_MASK	0x000000c000000000ull	/* DevTbl segmentation */
+#define	AMDIOMMU_EFR_DEVTBLSEG_SHIFT	38
+
+/* IOMMU Command Pointers (Head/Tail) registers fields */
+#define	AMDIOMMU_CMDPTR_MASK		0x000000000007fff0ull
+
+/* IOMMU Command Buffer Base fields */
+#define	AMDIOMMU_CMDBUF_BASE_SZSHIFT	56			/* Shift for size */
+#define	AMDIOMMU_CMDBUF_MAX		(512 * 1024)
+
+/* IOMMU Event Log Base register fields */
+#define	AMDIOMMU_EVNTLOG_BASE_SZSHIFT	56			/* Shift for size */
+#define	AMDIOMMU_EVNTLOG_MIN		256
+#define	AMDIOMMU_EVNTLOG_MAX		32768
+
+/* IOMMU Hardware Event Status register fields */
+#define	AMDIOMMU_HWEVS_HEV		0x00000001		/* HW Ev Valid */
+#define	AMDIOMMU_HWEVS_HEO		0x00000002		/* HW Ev Overfl */
+
+/*
+ * IOMMU Command and Event Status register fields.
+ * From the spec, all defined bits are either RO or RW1C.  As a consequence,
+ * single bit can be safely written to the register to clean a specific
+ * condition.
+ */
+#define	AMDIOMMU_CMDEVS_EVOVRFLW	0x00000001
+#define	AMDIOMMU_CMDEVS_EVLOGINT	0x00000002
+#define	AMDIOMMU_CMDEVS_COMWAITINT	0x00000004
+#define	AMDIOMMU_CMDEVS_EVLOGRUN	0x00000008
+#define	AMDIOMMU_CMDEVS_CMDBUFRUN	0x00000010
+#define	AMDIOMMU_CMDEVS_PPROVRFLW	0x00000020
+#define	AMDIOMMU_CMDEVS_PPRINT		0x00000040
+#define	AMDIOMMU_CMDEVS_PPRLOGRUN	0x00000080
+#define	AMDIOMMU_CMDEVS_GALOGRUN	0x00000100
+#define	AMDIOMMU_CMDEVS_GALOVRFLW	0x00000200
+#define	AMDIOMMU_CMDEVS_GAINT		0x00000400
+#define	AMDIOMMU_CMDEVS_PPROVRFLWB	0x00000800
+#define	AMDIOMMU_CMDEVS_PPRLOGACTIVE	0x00001000
+#define	AMDIOMMU_CMDEVS_RESV1		0x00002000
+#define	AMDIOMMU_CMDEVS_RESV2		0x00004000
+#define	AMDIOMMU_CMDEVS_EVOVRFLWB	0x00008000
+#define	AMDIOMMU_CMDEVS_EVLOGACTIVE	0x00010000
+#define	AMDIOMMU_CMDEVS_PPROVRFLWEB	0x00020000
+#define	AMDIOMMU_CMDEVS_PPROVRFLWE	0x00040000
+
+/*
+ * Device Table Entry (DTE)
+ */
+struct amdiommu_dte {
+	u_int		v:1;		/* Valid */
+	u_int		tv:1;		/* Translation Valid */
+	u_int		rsrv0:5;
+	u_int		had:2;		/* Host Access Dirty */
+	u_int		pgmode:3;	/* Paging Mode */
+	uint64_t	ptroot:40;	/* Page Table Root */
+	u_int		ppr:1;		/* PPR En */
+	u_int		gprp:1;		/* Guest PPR Resp with PASID */
+	u_int		giov:1;		/* Guest IO Prot Valid */
+	u_int		gv:1;		/* Guest Translation Valid */
+	u_int		glx:2;		/* Guest Levels Translated */
+	u_int		gcr3root0:3;	/* GCR3 root pointer part */
+	u_int		ir:1;		/* Read Perm */
+	u_int		iw:1;		/* Write Perm */
+	u_int		rsrv1:1;
+	u_int		domainid:16;	/* domain tag */
+	u_int		gcr3root1:16;	/* GCR3 root pointer part */
+	u_int		i:1;		/* IOTLB En */
+	u_int		se:1;		/* Suppress IO Fault Events */
+	u_int		sa:1;		/* Suppress All IO Fault Events */
+	u_int		pioctl:2;	/* Port IO Control */
+	u_int		cache:1;	/* IOTLB Cache Hint */
+	u_int		sd:1;		/* Snoop Disable */
+	u_int		ex:1;		/* Allow Exclusion */
+	u_int		sysmgt:2;	/* System Management Msg Handling */
+	u_int		sats:1;		/* Secure/Non-secure ATS */
+	u_int		gcr3root2:21;	/* GCR3 root pointer part */
+	u_int		iv:1;		/* Intr Map Valid */
+	u_int		inttablen:4;	/* log2 Intr Table Len */
+	u_int		ig:1;		/* Ignore Unmapped Interrupts */
+	uint64_t	intrroot:46;	/* Interrupt Table Root (-low 6bits) */
+	u_int		rsrv2:2;
+	u_int		gpm:2;		/* Guest Paging Mode */
+	u_int		initpass:1;	/* INIT pass-through */
+	u_int		eintpass:1;	/* ExtInt pass-through */
+	u_int		nmipass:1;	/* NMI pass-through */
+	u_int		hptmode:1;	/* Host Page Table Mode Hint */
+	u_int		intctl:2;	/* Interrupt Control */
+	u_int		lint0pass:1;	/* LINT0 pass-through */
+	u_int		lint1pass:1;	/* LINT1 pass-through */
+	u_int		rsrv3:15;
+	u_int		vimu:1;		/* Virtualize IOMMU En */
+	u_int		gdevid:16;	/* Guest Dev Id */
+	u_int		gid:16;		/* Guest Id */
+	u_int		rsrv4:5;
+	u_int		rsrv5:1;	/* Not Checked, sw avail */
+	u_int		attrv:1;	/* Attr Override Valid */
+	u_int		mode0fc:1;	/* Replace for PTE.FC */
+	u_int		snoopattr:8;	/* GuestPTE.PAT -> ATS.N xlat */
+} __packed;
+_Static_assert(sizeof(struct amdiommu_dte) == 8 * sizeof(uint32_t), "DTE");
+
+#define	AMDIOMMU_DTE_HAD_NAND		0x0	/* No Access, No Dirty */
+#define	AMDIOMMU_DTE_HAD_AND		0x1	/* Access, No Dirty */
+#define	AMDIOMMU_DTE_HAD_RSRV		0x2
+#define	AMDIOMMU_DTE_HAD_AD		0x3	/* Access, Dirty */
+
+#define	AMDIOMMU_DTE_PGMODE_1T1		0x0	/* SPA = GPA */
+#define	AMDIOMMU_DTE_PGMODE_1LV		0x1	/* 1 Level PT */
+#define	AMDIOMMU_DTE_PGMODE_2LV		0x2	/* 2 Level PT */
+#define	AMDIOMMU_DTE_PGMODE_3LV		0x3	/* 3 Level PT */
+#define	AMDIOMMU_DTE_PGMODE_4LV		0x4	/* 4 Level PT */
+#define	AMDIOMMU_DTE_PGMODE_5LV		0x5	/* 5 Level PT */
+#define	AMDIOMMU_DTE_PGMODE_6LV		0x6	/* 6 Level PT */
+#define	AMDIOMMU_DTE_PGMODE_RSRV	0x7
+
+#define	AMDIOMMU_DTE_GLX_1LV		0x0	/* 1 Level GCR3 */
+#define	AMDIOMMU_DTE_GLX_2LV		0x1	/* 2 Level GCR3 */
+#define	AMDIOMMU_DTE_GLX_3LV		0x2	/* 3 Level GCR3 */
+#define	AMDIOMMU_DTE_GLX_RSRV		0x3
+
+#define	AMDIOMMU_DTE_PIOCTL_DIS		0x0
+#define	AMDIOMMU_DTE_PIOCTL_EN		0x1
+#define	AMDIOMMU_DTE_PIOCTL_MAP		0x2
+#define	AMDIOMMU_DTE_PIOCTL_RSRV	0x3
+
+#define	AMDIOMMU_DTE_SYSMGT_DIS		0x0	/* Target Abort */
+#define	AMDIOMMU_DTE_SYSMGT_FW		0x0	/* Forwarded All */
+#define	AMDIOMMU_DTE_SYSMGT_FWI		0x0	/* Forwarded INT */
+#define	AMDIOMMU_DTE_SYSMGT_T		0x0	/* Translated */
+
+#define	AMDIOMMU_DTE_GPM_4LV		0x0	/* 4 Level */
+#define	AMDIOMMU_DTE_GPM_5LV		0x1	/* 4 Level */
+#define	AMDIOMMU_DTE_GPM_RSRV1		0x2
+#define	AMDIOMMU_DTE_GPM_RSRV2		0x3
+
+#define	AMDIOMMU_DTE_INTCTL_DIS		0x0	/* Target Abort */
+#define	AMDIOMMU_DTE_INTCTL_FW		0x1	/* Forward Unmapped */
+#define	AMDIOMMU_DTE_INTCTL_MAP		0x2	/* Forward Remapped */
+#define	AMDIOMMU_DTE_INTCTL_RSRV	0x3
+
+#define	AMDIOMMU_PGTBL_MAXLVL		6
+
+/*
+ * Page Table Entry (PTE/PDE)
+ */
+#define	AMDIOMMU_PTE_PR			0x0001	/* Present, AKA V */
+#define	AMDIOMMU_IGN1			0x0002
+#define	AMDIOMMU_IGN2			0x0004
+#define	AMDIOMMU_IGN3			0x0008
+#define	AMDIOMMU_IGN4			0x0010
+#define	AMDIOMMU_PTE_A			0x0020	/* Accessed */
+#define	AMDIOMMU_PTE_D			0x0040	/* Dirty */
+#define	AMDIOMMU_IGN5			0x0080
+#define	AMDIOMMU_IGN6			0x0100
+#define	AMDIOMMU_PTE_NLVL_MASK		0x0e00	/* Next Level */
+#define	AMDIOMMU_PTE_NLVL_SHIFT		9
+#define	AMDIOMMU_PTE_NLVL_7h		0x0e00	/* Magic Next Level */
+#define	AMDIOMMU_PTE_PA_MASK		0x000ffffffffff000ull
+#define	AMDIOMMU_PTE_PA_SHIFT		12
+#define	AMDIOMMU_PTE_PMC_MASK		0x0600000000000000ull	/* Page Migr */
+#define	AMDIOMMU_PTE_U			0x0800000000000000ull	/* ATS.U */
+#define	AMDIOMMU_PTE_FC			0x1000000000000000ull	/* Force Coh */
+#define	AMDIOMMU_PTE_IR			0x2000000000000000ull	/* Read Perm */
+#define	AMDIOMMU_PTE_IW			0x4000000000000000ull	/* Write Perm */
+#define	AMDIOMMU_PTE_IGN7		0x8000000000000000ull
+
+/*
+ * IRTEs
+ */
+
+/* vAPIC is not enabled, guestmode = 0 */
+struct amdiommu_irte_basic_novapic {
+	u_int	remapen:1;	/* 0 - Target Abort */
+	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
+	u_int	inttype:3;
+	u_int	rqeoi:1;	/* Request EOI */
+	u_int	dm:1;		/* Dest Mode */
+	u_int	guestmode:1;	/* MBZ */
+	u_int	dest:8;		/* Destination APIC */
+	u_int	vector:8;
+	u_int	rsrv:8;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_irte_basic_novapic) ==
+    1 * sizeof(uint32_t), "IRTE 1");
+
+/* vAPIC is enabled, guestmode = 0 */
+struct amdiommu_irte_basic_vapic {
+	u_int	remapen:1;	/* 0 - Target Abort */
+	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
+	u_int	inttype:3;
+	u_int	rqeoi:1;	/* Request EOI */
+	u_int	dm:1;		/* Dest Mode */
+	u_int	guestmode:1;	/* MBZ */
+	u_int	dest:8;		/* Destination APIC */
+	u_int	rsrv0:16;
+	u_int	rsrv1:32;
+	u_int	vector:8;
+	u_int	rsrv2:24;
+	u_int	rsrv3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_irte_basic_vapic) ==
+    4 * sizeof(uint32_t), "IRTE 2");
+
+/* vAPIC is enabled, guestmode = 1 */
+struct amdiommu_irte_guest_vapic {
+	u_int	remapen:1;	/* 0 - Target Abort */
+	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
+	u_int	galogintr:1;
+	u_int	rsrv0:2;
+	u_int	gappidis:1;	/* supress GAPPI */
+	u_int	isrun:1;	/* Guest Running hint */
+	u_int	guestmode:1;	/* MB1 */
+	u_int	dest:8;		/* Destination APIC for dorbell */
+	u_int	rsrv1:16;
+	u_int	gatag:32;
+	u_int	vector:8;
+	u_int	rsrv2:4;
+	uint64_t vapicrp:40;	/* 51:12 bits of SPA for APIC backing page */
+	u_int	rsrv3:12;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_irte_guest_vapic) ==
+    4 * sizeof(uint32_t), "IRTE 3");
+
+/* vAPIC is enabled, guestmode = 0, x2APIC */
+struct amdiommu_irte_basic_vapic_x2 {
+	u_int	remapen:1;	/* 0 - Target Abort */
+	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
+	u_int	inttype:3;
+	u_int	rqeoi:1;	/* Request EOI */
+	u_int	dm:1;		/* Dest Mode */
+	u_int	guestmode:1;	/* MBZ */
+	u_int	dest0:24;	/* Destination APIC 23:0 */
+	u_int	rsrv0:32;
+	u_int	vector:8;
+	u_int	rsrv1:24;
+	u_int	rsrv2:24;
+	u_int	dest1:8;	/* Destination APIC 31:24 */
+} __packed;
+_Static_assert(sizeof(struct amdiommu_irte_basic_vapic_x2) ==
+    4 * sizeof(uint32_t), "IRTE 4");
+
+/* vAPIC is enabled, guestmode = 1, x2APIC */
+struct amdiommu_irte_guest_vapic_x2 {
+	u_int	remapen:1;	/* 0 - Target Abort */
+	u_int	supiopf:1;	/* Supress IO_PAGE_FAULT events */
+	u_int	galogintr:1;
+	u_int	rsrv0:2;
+	u_int	gappidis:1;	/* supress GAPPI */
+	u_int	isrun:1;	/* Guest Running hint */
+	u_int	guestmode:1;	/* MB1 */
+	u_int	dest0:24;	/* Destination APIC for dorbell 23:0 */
+	u_int	gatag:32;
+	u_int	vector:8;
+	u_int	rsrv2:4;
+	uint64_t vapicrp:40;	/* 51:12 bits of SPA for APIC backing page */
+	u_int	rsrv3:4;
+	u_int	dest1:8;	/* Destination APIC 31:24 */
+} __packed;
+_Static_assert(sizeof(struct amdiommu_irte_guest_vapic_x2) ==
+    4 * sizeof(uint32_t), "IRTE 5");
+
+#define	AMDIOMMU_IRTE_INTTYPE_FIXED	0
+#define	AMDIOMMU_IRTE_INTTYPE_ARBITR	1
+
+#define	AMDIOMMU_IRTE_DM_LOGICAL	1
+#define	AMDIOMMU_IRTE_DM_PHYSICAL	1
+
+/*
+ * Commands
+ */
+
+struct amdiommu_cmd_generic {
+	u_int	w0:32;
+	union {
+		u_int ww1:32;
+		struct {
+			u_int	w1:28;
+			u_int	op:4;
+		};
+	};
+	u_int	w2:32;
+	u_int	w3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_generic) ==
+    4 * sizeof(uint32_t), "CMD_GENERIC");
+
+#define	AMDIOMMU_CMD_SZ_SHIFT	4	/* Shift for cmd count
+					   to ring offset */
+#define	AMDIOMMU_CMD_SZ		sizeof(struct amdiommu_cmd_generic)
+					/* Command size */
+_Static_assert((1 << AMDIOMMU_CMD_SZ_SHIFT) == AMDIOMMU_CMD_SZ,
+    "CMD size shift");
+
+struct amdiommu_cmd_completion_wait {
+	u_int	s:1;
+	u_int	i:1;
+	u_int	f:1;
+	u_int	address0:29;	/* Store Address 31:3 */
+	u_int	address1:20;	/* Store Address 51:32 */
+	u_int	rsrv:8;
+	u_int	op:4;
+	u_int	data0:32;
+	u_int	data1:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_completion_wait) ==
+    4 * sizeof(uint32_t), "CMD_COMPLETION_WAIT");
+
+struct amdiommu_cmd_invalidate_devtab_entry {
+	u_int	devid:16;
+	u_int	rsrv0:16;
+	u_int	rsrv1:28;
+	u_int	op:4;
+	u_int	rsrv2:32;
+	u_int	rsrv3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_invalidate_devtab_entry) ==
+    4 * sizeof(uint32_t), "CMD_INVALIDATE_DEVTAB_ENTRY");
+
+struct amdiommu_cmd_invalidate_iommu_pages {
+	u_int	pasid:20;
+	u_int	rsrv0:12;
+	u_int	domainid:16;
+	u_int	rsrv1:12;
+	u_int	op:4;
+	u_int	s:1;
+	u_int	pde:1;
+	u_int	gn:1;
+	u_int	rsrv2:9;
+	uint64_t address:52;	/* Address 63:12 */
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_pages) ==
+    4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_PAGES");
+
+struct amdiommu_cmd_invalidate_iotlb_pages {
+	u_int	devid:16;
+	u_int	pasid1:8;
+	u_int	maxpend0:8;
+	u_int	queueid:16;
+	u_int	pasid0:8;
+	u_int	pasid2:4;
+	u_int	op:4;
+	u_int	s:1;
+	u_int	rsrv0:1;
+	u_int	gn:1;
+	u_int	rsrv1:1;
+	u_int	type:2;
+	u_int	rsrv2:6;
+	uint64_t address:52;	/* Address 63:12 */
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_invalidate_iotlb_pages) ==
+    4 * sizeof(uint32_t), "CMD_INVALIDATE_IOTLB_PAGES");
+
+struct amdiommu_cmd_invalidate_interrupt_table {
+	u_int	devid:16;
+	u_int	rsrv0:16;
+	u_int	rsrv1:28;
+	u_int	op:4;
+	u_int	rsrv2:32;
+	u_int	rsrv3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_invalidate_interrupt_table) ==
+    4 * sizeof(uint32_t), "CMD_INVALIDATE_INTERRUPT_TABLE");
+
+struct amdiommu_cmd_prefetch_iommu_pages {
+	u_int	devid:16;
+	u_int	rsrv0:8;
+	u_int	pfcount:8;
+	u_int	pasid:20;
+	u_int	rsrv1:8;
+	u_int	op:4;
+	u_int	s:1;
+	u_int	rsrv2:1;
+	u_int	gn:1;
+	u_int	rsrv3:1;
+	u_int	inval:1;	/* Invalidate First */
+	u_int	rsrv4:7;
+	uint64_t address:52;	/* Address 63:12 */
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_prefetch_iommu_pages) ==
+    4 * sizeof(uint32_t), "CMD_PREFETCH_IOMMU_PAGES");
+
+struct amdiommu_cmd_complete_ppr_request {
+	u_int	devid:16;
+	u_int	rsrv0:16;
+	u_int	pasid:20;
+	u_int	rsrv1:8;
+	u_int	op:4;
+	u_int	rsrv2:2;
+	u_int	gn:1;
+	u_int	rsrv3:29;
+	u_int	compltag:16;
+	u_int	rsrv4:16;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_complete_ppr_request) ==
+    4 * sizeof(uint32_t), "CMD_COMPLETE_PPR_REQUEST");
+
+struct amdiommu_cmd_invalidate_iommu_all {
+	u_int	rsrv0:32;
+	u_int	op:4;
+	u_int	rsrv1:28;
+	u_int	rsrv2:32;
+	u_int	rsrv3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_invalidate_iommu_all) ==
+    4 * sizeof(uint32_t), "CMD_INVALIDATE_IOMMU_ALL");
+
+struct amdiommu_cmd_insert_guest_event {
+	u_int	rsrv0:32;
+	u_int	guestid:16;
+	u_int	rsrv1:12;
+	u_int	op:4;
+	u_int	rsrv2:32;
+	u_int	rsrv3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_insert_guest_event) ==
+    4 * sizeof(uint32_t), "CMD_INSERT_GUEST_EVENT");
+
+struct amdiommu_cmd_reset_vmmio {
+	u_int	guestid:16;
+	u_int	rsrv0:11;
+	u_int	all:1;
+	u_int	rsrv1:3;
+	u_int	vcmd:1;
+	u_int	rsrv2:27;
+	u_int	op:4;
+	u_int	rsrv3:32;
+	u_int	rsrv4:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_cmd_reset_vmmio) ==
+    4 * sizeof(uint32_t), "CMD_RESET_VMMIO");
+
+#define AMDIOMMU_CMD_COMPLETION_WAIT		0x1
+#define AMDIOMMU_CMD_INVALIDATE_DEVTAB_ENTRY	0x2
+#define AMDIOMMU_CMD_INVALIDATE_IOMMU_PAGES	0x3
+#define AMDIOMMU_CMD_INVALIDATE_IOTLB_PAGES	0x4
+#define AMDIOMMU_CMD_INVALIDATE_INTERRUPT_TABLE	0x5
+#define AMDIOMMU_CMD_PREFETCH_IOMMU_PAGES	0x6
+#define AMDIOMMU_CMD_COMPLETE_PPR_REQUEST	0x7
+#define AMDIOMMU_CMD_INVALIDATE_IOMMU_ALL	0x8
+#define AMDIOMMU_CMD_INSERT_GUEST_EVENT		0x9
+#define AMDIOMMU_CMD_RESET_VMMIO		0xa
+
+/*
+ * Logging
+ */
+struct amdiommu_event_generic {
+	u_int	w0:32;
+	union {
+		u_int ww1:32;
+		struct {
+			u_int	w1:28;
+			u_int	code:4;
+		};
+	};
+	u_int	w2:32;
+	u_int	w3:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_event_generic) ==
+    4 * sizeof(uint32_t), "EVENT_GENERIC");
+
+#define	AMDIOMMU_EV_SZ_SHIFT	4	/* Shift for event count
+					   to ring offset */
+#define	AMDIOMMU_EV_SZ		sizeof(struct amdiommu_event_generic)
+					/* Event size */
+_Static_assert((1 << AMDIOMMU_EV_SZ_SHIFT) == AMDIOMMU_EV_SZ,
+    "Event size shift");
+
+struct amdiommu_event_ill_dev_table_entry {
+	u_int	devid:16;
+	u_int	pasid1:4;
+	u_int	rsrv0:7;
+	u_int	vnr:1;
+	u_int	rsrv1:1;
+	u_int	vevent:1;
+	u_int	vptr:1;
+	u_int	vcmd:1;
+	u_int	pasid:16;
+	u_int	gn:1;
+	u_int	rsrv2:2;
+	u_int	i:1;
+	u_int	rsrv3:1;
+	u_int	rw:1;
+	u_int	rsrv4:1;
+	u_int	rz:1;
+	u_int	tr:1;
+	u_int	rsrv5:3;
+	u_int	code:4;
+	u_int	rsrv6:2;
+	u_int	addr1:30;
+	u_int	addr2:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_event_ill_dev_table_entry) ==
+    4 * sizeof(uint32_t), "EVENT_ILLEGAL_DEV_TABLE_ENTRY");
+
+struct amdiommu_event_io_page_fault_entry {
+	u_int	devid:16;
+	u_int	pasid1:4;
+	u_int	rsrv0:7;
+	u_int	vnr:1;
+	u_int	rsrv1:1;
+	u_int	vevent:1;
+	u_int	vptr:1;
+	u_int	vcmd:1;
+	u_int	pasid:16;	/* also domain id */
+	u_int	gn:1;
+	u_int	nx:1;
+	u_int	us:1;
+	u_int	i:1;
+	u_int	pr:1;
+	u_int	rw:1;
+	u_int	pe:1;
+	u_int	rz:1;
+	u_int	tr:1;
+	u_int	rsrv2:3;
+	u_int	code:4;
+	u_int	addr1:32;
+	u_int	addr2:32;
+} __packed;
+_Static_assert(sizeof(struct amdiommu_event_io_page_fault_entry) ==
+    4 * sizeof(uint32_t), "EVENT_IO_PAGE_FAULT_ENTRY");
+
+#define	AMDIOMMU_EV_ILL_DEV_TABLE_ENTRY		0x1
+#define	AMDIOMMU_EV_IO_PAGE_FAULT		0x2
+#define	AMDIOMMU_EV_DEV_TAB_HW_ERROR		0x3
+#define	AMDIOMMU_EV_PAGE_TAB_HW_ERROR		0x4
+#define	AMDIOMMU_EV_ILL_CMD_ERROR		0x5
+#define	AMDIOMMU_EV_CMD_HW_ERROR		0x6
+#define	AMDIOMMU_EV_IOTLB_INV_TIMEOUT		0x7
+#define	AMDIOMMU_EV_INVALID_DEV_REQ		0x8
+#define	AMDIOMMU_EV_INVALID_PPR_REQ		0x9
+#define	AMDIOMMU_EV_COUNTER_ZERO		0xa	/* Typo in table 42? */
+
+#endif	/* __X86_IOMMU_AMD_REG_H */