svn commit: r317972 - in projects/pnfs-planb-server/sys: . amd64/pci amd64/vmm/amd arm/conf arm/ralink arm64/arm64 boot/common boot/efi/libefi boot/efi/loader boot/fdt/dts/arm boot/i386/libi386 boo...
Rick Macklem
rmacklem at FreeBSD.org
Mon May 8 19:46:35 UTC 2017
Author: rmacklem
Date: Mon May 8 19:46:33 2017
New Revision: 317972
URL: https://svnweb.freebsd.org/changeset/base/317972
Log:
Update kernel sources to head.
Added:
projects/pnfs-planb-server/sys/amd64/vmm/amd/amdvi_hw.c
- copied unchanged from r317971, head/sys/amd64/vmm/amd/amdvi_hw.c
projects/pnfs-planb-server/sys/amd64/vmm/amd/amdvi_priv.h
- copied unchanged from r317971, head/sys/amd64/vmm/amd/amdvi_priv.h
projects/pnfs-planb-server/sys/amd64/vmm/amd/ivrs_drv.c
- copied unchanged from r317971, head/sys/amd64/vmm/amd/ivrs_drv.c
projects/pnfs-planb-server/sys/arm/conf/RT1310
- copied unchanged from r317971, head/sys/arm/conf/RT1310
projects/pnfs-planb-server/sys/arm/ralink/
- copied from r317971, head/sys/arm/ralink/
projects/pnfs-planb-server/sys/boot/fdt/dts/arm/rt1310a.dtsi
- copied unchanged from r317971, head/sys/boot/fdt/dts/arm/rt1310a.dtsi
projects/pnfs-planb-server/sys/boot/fdt/dts/arm/wzr2-g300n.dts
- copied unchanged from r317971, head/sys/boot/fdt/dts/arm/wzr2-g300n.dts
projects/pnfs-planb-server/sys/compat/linuxkpi/common/include/asm/smp.h
- copied unchanged from r317971, head/sys/compat/linuxkpi/common/include/asm/smp.h
projects/pnfs-planb-server/sys/compat/linuxkpi/common/include/linux/smp.h
- copied unchanged from r317971, head/sys/compat/linuxkpi/common/include/linux/smp.h
projects/pnfs-planb-server/sys/contrib/ena-com/
- copied from r317971, head/sys/contrib/ena-com/
projects/pnfs-planb-server/sys/dev/cxgbe/t4_sched.c
- copied unchanged from r317971, head/sys/dev/cxgbe/t4_sched.c
projects/pnfs-planb-server/sys/dev/cy/
- copied from r317971, head/sys/dev/cy/
projects/pnfs-planb-server/sys/gnu/dts/mips/MZK-W04N-XX.dts
- copied unchanged from r317971, head/sys/gnu/dts/mips/MZK-W04N-XX.dts
projects/pnfs-planb-server/sys/libkern/arm64/
- copied from r317971, head/sys/libkern/arm64/
projects/pnfs-planb-server/sys/mips/conf/RT2880_FDT
- copied unchanged from r317971, head/sys/mips/conf/RT2880_FDT
projects/pnfs-planb-server/sys/mips/mediatek/std.rt2880
- copied unchanged from r317971, head/sys/mips/mediatek/std.rt2880
Modified:
projects/pnfs-planb-server/sys/Makefile
projects/pnfs-planb-server/sys/amd64/pci/pci_cfgreg.c
projects/pnfs-planb-server/sys/arm64/arm64/machdep.c
projects/pnfs-planb-server/sys/arm64/arm64/pmap.c
projects/pnfs-planb-server/sys/boot/common/dev_net.c
projects/pnfs-planb-server/sys/boot/efi/libefi/efinet.c
projects/pnfs-planb-server/sys/boot/efi/libefi/time.c
projects/pnfs-planb-server/sys/boot/efi/loader/Makefile
projects/pnfs-planb-server/sys/boot/efi/loader/main.c
projects/pnfs-planb-server/sys/boot/i386/libi386/pxe.c
projects/pnfs-planb-server/sys/boot/i386/libi386/pxe.h
projects/pnfs-planb-server/sys/boot/i386/loader/Makefile
projects/pnfs-planb-server/sys/boot/i386/zfsboot/zfsboot.c
projects/pnfs-planb-server/sys/boot/ofw/libofw/ofw_net.c
projects/pnfs-planb-server/sys/boot/uboot/lib/net.c
projects/pnfs-planb-server/sys/cam/cam_periph.c
projects/pnfs-planb-server/sys/cam/scsi/scsi_all.c
projects/pnfs-planb-server/sys/cam/scsi/scsi_all.h
projects/pnfs-planb-server/sys/cam/scsi/scsi_pass.c
projects/pnfs-planb-server/sys/cam/scsi/scsi_sa.c
projects/pnfs-planb-server/sys/cam/scsi/scsi_sa.h
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab_impl.h
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
projects/pnfs-planb-server/sys/cddl/dev/dtrace/dtrace_load.c
projects/pnfs-planb-server/sys/compat/freebsd32/freebsd32_misc.c
projects/pnfs-planb-server/sys/compat/freebsd32/freebsd32_proto.h
projects/pnfs-planb-server/sys/compat/freebsd32/freebsd32_syscall.h
projects/pnfs-planb-server/sys/compat/freebsd32/freebsd32_syscalls.c
projects/pnfs-planb-server/sys/compat/freebsd32/freebsd32_sysent.c
projects/pnfs-planb-server/sys/compat/freebsd32/freebsd32_systrace_args.c
projects/pnfs-planb-server/sys/compat/freebsd32/syscalls.master
projects/pnfs-planb-server/sys/compat/linprocfs/linprocfs.c
projects/pnfs-planb-server/sys/compat/linux/linux_file.c
projects/pnfs-planb-server/sys/compat/linux/linux_futex.c
projects/pnfs-planb-server/sys/compat/linuxkpi/common/src/linux_compat.c
projects/pnfs-planb-server/sys/compat/linuxkpi/common/src/linux_page.c
projects/pnfs-planb-server/sys/conf/files
projects/pnfs-planb-server/sys/conf/files.arm64
projects/pnfs-planb-server/sys/conf/options.mips
projects/pnfs-planb-server/sys/contrib/octeon-sdk/cvmx-app-init.h
projects/pnfs-planb-server/sys/contrib/octeon-sdk/cvmx-helper-board.c
projects/pnfs-planb-server/sys/dev/acpica/acpi_pcib_acpi.c
projects/pnfs-planb-server/sys/dev/acpica/acpivar.h
projects/pnfs-planb-server/sys/dev/atkbdc/psm.c
projects/pnfs-planb-server/sys/dev/bnxt/bnxt.h
projects/pnfs-planb-server/sys/dev/bnxt/if_bnxt.c
projects/pnfs-planb-server/sys/dev/cfi/cfi_core.c
projects/pnfs-planb-server/sys/dev/cfi/cfi_reg.h
projects/pnfs-planb-server/sys/dev/cxgbe/adapter.h
projects/pnfs-planb-server/sys/dev/cxgbe/common/common.h
projects/pnfs-planb-server/sys/dev/cxgbe/common/t4_hw.c
projects/pnfs-planb-server/sys/dev/cxgbe/t4_iov.c
projects/pnfs-planb-server/sys/dev/cxgbe/t4_main.c
projects/pnfs-planb-server/sys/dev/cxgbe/t4_sge.c
projects/pnfs-planb-server/sys/dev/cxgbe/t4_vf.c
projects/pnfs-planb-server/sys/dev/cxgbe/tom/t4_cpl_io.c
projects/pnfs-planb-server/sys/dev/cxgbe/tom/t4_tom.c
projects/pnfs-planb-server/sys/dev/cxgbe/tom/t4_tom.h
projects/pnfs-planb-server/sys/dev/drm2/radeon/radeon_drv.c
projects/pnfs-planb-server/sys/dev/etherswitch/e6000sw/e6000sw.c
projects/pnfs-planb-server/sys/dev/etherswitch/e6000sw/e6060sw.c
projects/pnfs-planb-server/sys/dev/etherswitch/infineon/adm6996fc.c
projects/pnfs-planb-server/sys/dev/etherswitch/ip17x/ip17x.c
projects/pnfs-planb-server/sys/dev/etherswitch/ip17x/ip17x_var.h
projects/pnfs-planb-server/sys/dev/fdt/fdt_common.c
projects/pnfs-planb-server/sys/dev/flash/mx25l.c
projects/pnfs-planb-server/sys/dev/hyperv/input/hv_kbd.c
projects/pnfs-planb-server/sys/dev/isp/isp.c
projects/pnfs-planb-server/sys/dev/isp/isp_freebsd.c
projects/pnfs-planb-server/sys/dev/isp/ispmbox.h
projects/pnfs-planb-server/sys/dev/isp/ispvar.h
projects/pnfs-planb-server/sys/dev/mlx4/mlx4_en/en.h
projects/pnfs-planb-server/sys/dev/mlx4/mlx4_en/mlx4_en_netdev.c
projects/pnfs-planb-server/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
projects/pnfs-planb-server/sys/dev/nand/nandsim.c
projects/pnfs-planb-server/sys/dev/pci/pci_pci.c
projects/pnfs-planb-server/sys/dev/pci/pcib_private.h
projects/pnfs-planb-server/sys/dev/rt/if_rt.c
projects/pnfs-planb-server/sys/dev/rt/if_rtreg.h
projects/pnfs-planb-server/sys/dev/sdhci/sdhci_fdt.c
projects/pnfs-planb-server/sys/dev/sound/pcm/feeder_matrix.c
projects/pnfs-planb-server/sys/dev/uart/uart_dev_lpc.c
projects/pnfs-planb-server/sys/dev/uart/uart_dev_ns8250.c
projects/pnfs-planb-server/sys/dev/vt/vt_core.c
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_alloc.c
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_extattr.c
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_extattr.h
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_extern.h
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_inode.c
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_inode_cnv.c
projects/pnfs-planb-server/sys/fs/ext2fs/ext2_vnops.c
projects/pnfs-planb-server/sys/fs/nfsclient/nfs_clrpcops.c
projects/pnfs-planb-server/sys/geom/mirror/g_mirror.c
projects/pnfs-planb-server/sys/gnu/dts/mips/rt2880.dtsi
projects/pnfs-planb-server/sys/kern/kern_cpuset.c
projects/pnfs-planb-server/sys/kern/kern_intr.c
projects/pnfs-planb-server/sys/kern/kern_sig.c
projects/pnfs-planb-server/sys/kern/kern_thread.c
projects/pnfs-planb-server/sys/kern/subr_gtaskqueue.c
projects/pnfs-planb-server/sys/kern/vfs_cache.c
projects/pnfs-planb-server/sys/libkern/crc32.c
projects/pnfs-planb-server/sys/mips/atheros/ar531x/if_are.c
projects/pnfs-planb-server/sys/mips/atheros/ar531x/if_arereg.h
projects/pnfs-planb-server/sys/mips/atheros/ar934x_chip.c
projects/pnfs-planb-server/sys/mips/conf/CARAMBOLA2
projects/pnfs-planb-server/sys/mips/conf/std.AR933X
projects/pnfs-planb-server/sys/mips/conf/std.AR934X
projects/pnfs-planb-server/sys/mips/mediatek/mtk_gpio_v1.c
projects/pnfs-planb-server/sys/mips/mediatek/mtk_machdep.c
projects/pnfs-planb-server/sys/mips/mediatek/mtk_soc.c
projects/pnfs-planb-server/sys/mips/mediatek/mtk_soc.h
projects/pnfs-planb-server/sys/modules/cxgbe/if_cxgbe/Makefile
projects/pnfs-planb-server/sys/modules/cxgbe/tom/Makefile
projects/pnfs-planb-server/sys/modules/vmm/Makefile
projects/pnfs-planb-server/sys/net/if_bridge.c
projects/pnfs-planb-server/sys/net/if_lagg.c
projects/pnfs-planb-server/sys/net/if_lagg.h
projects/pnfs-planb-server/sys/net/if_vlan.c
projects/pnfs-planb-server/sys/netgraph/bluetooth/hci/ng_hci_evnt.c
projects/pnfs-planb-server/sys/netgraph/bluetooth/hci/ng_hci_main.c
projects/pnfs-planb-server/sys/netgraph/bluetooth/hci/ng_hci_var.h
projects/pnfs-planb-server/sys/netgraph/bluetooth/include/ng_bluetooth.h
projects/pnfs-planb-server/sys/netgraph/bluetooth/include/ng_btsocket.h
projects/pnfs-planb-server/sys/netgraph/bluetooth/include/ng_hci.h
projects/pnfs-planb-server/sys/netinet/sctp_output.c
projects/pnfs-planb-server/sys/netinet/sctp_pcb.c
projects/pnfs-planb-server/sys/netinet/sctp_timer.c
projects/pnfs-planb-server/sys/netinet/sctp_usrreq.c
projects/pnfs-planb-server/sys/netinet/sctputil.c
projects/pnfs-planb-server/sys/netinet/sctputil.h
projects/pnfs-planb-server/sys/netpfil/pf/pf_ioctl.c
projects/pnfs-planb-server/sys/rpc/clnt_vc.c
projects/pnfs-planb-server/sys/sparc64/pci/psycho.c
projects/pnfs-planb-server/sys/sys/cpuset.h
projects/pnfs-planb-server/sys/sys/interrupt.h
projects/pnfs-planb-server/sys/sys/libkern.h
projects/pnfs-planb-server/sys/sys/syscallsubr.h
projects/pnfs-planb-server/sys/ufs/ffs/ffs_rawread.c
projects/pnfs-planb-server/sys/ufs/ffs/fs.h
projects/pnfs-planb-server/sys/vm/vm_meter.c
projects/pnfs-planb-server/sys/x86/x86/mca.c
Directory Properties:
projects/pnfs-planb-server/sys/ (props changed)
projects/pnfs-planb-server/sys/cddl/contrib/opensolaris/ (props changed)
projects/pnfs-planb-server/sys/contrib/octeon-sdk/ (props changed)
Modified: projects/pnfs-planb-server/sys/Makefile
==============================================================================
--- projects/pnfs-planb-server/sys/Makefile Mon May 8 19:27:44 2017 (r317971)
+++ projects/pnfs-planb-server/sys/Makefile Mon May 8 19:46:33 2017 (r317972)
@@ -3,7 +3,7 @@
# Directories to include in cscope name file and TAGS.
CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \
geom gnu isa kern libkern modules net net80211 \
- netgraph netinet netinet6 netipsec netnatm netpfil \
+ netgraph netinet netinet6 netipsec netpfil \
netsmb nfs nfsclient nfsserver nlm ofed opencrypto \
rpc security sys ufs vm xdr xen ${CSCOPE_ARCHDIR}
.if !defined(CSCOPE_ARCHDIR)
@@ -32,7 +32,8 @@ ${.CURDIR}/cscope.files: .PHONY
find ${CSCOPEDIRS} -name "*.[chSsly]" -a -type f > ${.TARGET}
cscope-clean:
- rm -f cscope.files cscope.out cscope.in.out cscope.po.out
+ cd ${.CURDIR}; \
+ rm -f cscope.files cscope.out cscope.in.out cscope.po.out
#
# Installs SCM hooks to update the cscope database every time the source tree
Modified: projects/pnfs-planb-server/sys/amd64/pci/pci_cfgreg.c
==============================================================================
--- projects/pnfs-planb-server/sys/amd64/pci/pci_cfgreg.c Mon May 8 19:27:44 2017 (r317971)
+++ projects/pnfs-planb-server/sys/amd64/pci/pci_cfgreg.c Mon May 8 19:46:33 2017 (r317972)
@@ -64,6 +64,7 @@ static vm_offset_t pcie_base;
static int pcie_minbus, pcie_maxbus;
static uint32_t pcie_badslots;
static struct mtx pcicfg_mtx;
+MTX_SYSINIT(pcicfg_mtx, &pcicfg_mtx, "pcicfg_mtx", MTX_SPIN);
static int mcfg_enable = 1;
SYSCTL_INT(_hw_pci, OID_AUTO, mcfg, CTLFLAG_RDTUN, &mcfg_enable, 0,
"Enable support for PCI-e memory mapped config access");
@@ -74,15 +75,9 @@ SYSCTL_INT(_hw_pci, OID_AUTO, mcfg, CTLF
int
pci_cfgregopen(void)
{
- static int once = 0;
uint64_t pciebar;
uint16_t did, vid;
- if (!once) {
- mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
- once = 1;
- }
-
if (cfgmech != CFGMECH_NONE)
return (1);
cfgmech = CFGMECH_1;
@@ -138,6 +133,9 @@ pci_cfgregread(int bus, int slot, int fu
{
uint32_t line;
+ if (cfgmech == CFGMECH_NONE)
+ return (0xffffffff);
+
/*
* Some BIOS writers seem to want to ignore the spec and put
* 0 in the intline rather than 255 to indicate none. Some use
@@ -162,6 +160,9 @@ void
pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
{
+ if (cfgmech == CFGMECH_NONE)
+ return;
+
if (cfgmech == CFGMECH_PCIE &&
(bus >= pcie_minbus && bus <= pcie_maxbus) &&
(bus != 0 || !(1 << slot & pcie_badslots)))
Copied: projects/pnfs-planb-server/sys/amd64/vmm/amd/amdvi_hw.c (from r317971, head/sys/amd64/vmm/amd/amdvi_hw.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/pnfs-planb-server/sys/amd64/vmm/amd/amdvi_hw.c Mon May 8 19:46:33 2017 (r317972, copy of r317971, head/sys/amd64/vmm/amd/amdvi_hw.c)
@@ -0,0 +1,1509 @@
+/*-
+ * Copyright (c) 2016, Anish Gupta (anish at freebsd.org)
+ * All rights reserved.
+ *
+ * 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 unmodified, 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 ``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 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/rman.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/resource.h>
+#include <machine/vmm.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pci_cfgreg.h>
+
+#include "pcib_if.h"
+
+#include "io/iommu.h"
+#include "amdvi_priv.h"
+
+SYSCTL_DECL(_hw_vmm);
+SYSCTL_NODE(_hw_vmm, OID_AUTO, amdvi, CTLFLAG_RW, NULL, NULL);
+
+#define MOD_INC(a, s, m) (((a) + (s)) % ((m) * (s)))
+#define MOD_DEC(a, s, m) (((a) - (s)) % ((m) * (s)))
+
+/* Print RID or device ID in PCI string format. */
+#define RID2PCI_STR(d) PCI_RID2BUS(d), PCI_RID2SLOT(d), PCI_RID2FUNC(d)
+
+static void amdvi_dump_cmds(struct amdvi_softc *softc);
+static void amdvi_print_dev_cap(struct amdvi_softc *softc);
+
+MALLOC_DEFINE(M_AMDVI, "amdvi", "amdvi");
+
+extern device_t *ivhd_devs;
+
+extern int ivhd_count;
+SYSCTL_INT(_hw_vmm_amdvi, OID_AUTO, count, CTLFLAG_RDTUN, &ivhd_count,
+ 0, NULL);
+
+static int amdvi_enable_user = 0;
+SYSCTL_INT(_hw_vmm_amdvi, OID_AUTO, enable, CTLFLAG_RDTUN,
+ &amdvi_enable_user, 0, NULL);
+TUNABLE_INT("hw.vmm.amdvi_enable", &amdvi_enable_user);
+
+#ifdef AMDVI_ATS_ENABLE
+/* XXX: ATS is not tested. */
+static int amdvi_enable_iotlb = 1;
+SYSCTL_INT(_hw_vmm_amdvi, OID_AUTO, iotlb_enabled, CTLFLAG_RDTUN,
+ &amdvi_enable_iotlb, 0, NULL);
+TUNABLE_INT("hw.vmm.enable_iotlb", &amdvi_enable_iotlb);
+#endif
+
+static int amdvi_host_ptp = 1; /* Use page tables for host. */
+SYSCTL_INT(_hw_vmm_amdvi, OID_AUTO, host_ptp, CTLFLAG_RDTUN,
+ &amdvi_host_ptp, 0, NULL);
+TUNABLE_INT("hw.vmm.amdvi.host_ptp", &amdvi_host_ptp);
+
+/* Page table level used <= supported by h/w[v1=7]. */
+static int amdvi_ptp_level = 4;
+SYSCTL_INT(_hw_vmm_amdvi, OID_AUTO, ptp_level, CTLFLAG_RDTUN,
+ &amdvi_ptp_level, 0, NULL);
+TUNABLE_INT("hw.vmm.amdvi.ptp_level", &amdvi_ptp_level);
+
+/* Disable fault event reporting. */
+static int amdvi_disable_io_fault = 0;
+SYSCTL_INT(_hw_vmm_amdvi, OID_AUTO, disable_io_fault, CTLFLAG_RDTUN,
+ &amdvi_disable_io_fault, 0, NULL);
+TUNABLE_INT("hw.vmm.amdvi.disable_io_fault", &amdvi_disable_io_fault);
+
+static uint32_t amdvi_dom_id = 0; /* 0 is reserved for host. */
+SYSCTL_UINT(_hw_vmm_amdvi, OID_AUTO, domain_id, CTLFLAG_RD,
+ &amdvi_dom_id, 0, NULL);
+/*
+ * Device table entry.
+ * Bus(256) x Dev(32) x Fun(8) x DTE(256 bits or 32 bytes).
+ * = 256 * 2 * PAGE_SIZE.
+ */
+static struct amdvi_dte amdvi_dte[PCI_NUM_DEV_MAX] __aligned(PAGE_SIZE);
+CTASSERT(PCI_NUM_DEV_MAX == 0x10000);
+CTASSERT(sizeof(amdvi_dte) == 0x200000);
+
+static SLIST_HEAD (, amdvi_domain) dom_head;
+
+static inline void
+amdvi_pci_write(struct amdvi_softc *softc, int off, uint32_t data)
+{
+
+ pci_cfgregwrite(PCI_RID2BUS(softc->pci_rid),
+ PCI_RID2SLOT(softc->pci_rid), PCI_RID2FUNC(softc->pci_rid),
+ off, data, 4);
+}
+
+static inline uint32_t
+amdvi_pci_read(struct amdvi_softc *softc, int off)
+{
+
+ return (pci_cfgregread(PCI_RID2BUS(softc->pci_rid),
+ PCI_RID2SLOT(softc->pci_rid), PCI_RID2FUNC(softc->pci_rid),
+ off, 4));
+}
+
+static int
+amdvi_find_pci_cap(struct amdvi_softc *softc, uint8_t capability, int *off)
+{
+ uint32_t read;
+ uint8_t ptr;
+
+ read = amdvi_pci_read(softc, PCIR_COMMAND);
+ if (((read >> 16) & PCIM_STATUS_CAPPRESENT) == 0)
+ return (ENXIO);
+
+ /* Read the starting of capability pointer. */
+ read = amdvi_pci_read(softc, PCIR_CAP_PTR);
+ ptr = read & 0xFF;
+
+ while (ptr != 0) {
+ read = amdvi_pci_read(softc, ptr);
+ if ((read & 0xFF) == capability) {
+ *off = ptr;
+ return (0);
+ }
+ ptr = (read >> 8) & 0xFF;
+ }
+
+ return (ENOENT);
+}
+
+#ifdef AMDVI_ATS_ENABLE
+/* XXX: Should be in pci.c */
+/*
+ * Check if device has ATS capability and its enabled.
+ * If ATS is absent or disabled, return (-1), otherwise ATS
+ * queue length.
+ */
+static int
+amdvi_find_ats_qlen(uint16_t devid)
+{
+ device_t dev;
+ uint32_t off, cap;
+ int qlen = -1;
+
+ dev = pci_find_bsf(PCI_RID2BUS(devid), PCI_RID2SLOT(devid),
+ PCI_RID2FUNC(devid));
+
+ if (!dev) {
+ return (-1);
+ }
+#define PCIM_ATS_EN BIT(31)
+
+ if (pci_find_extcap(dev, PCIZ_ATS, &off) == 0) {
+ cap = pci_read_config(dev, off + 4, 4);
+ qlen = (cap & 0x1F);
+ qlen = qlen ? qlen : 32;
+ printf("AMD-Vi: PCI device %d.%d.%d ATS %s qlen=%d\n",
+ RID2PCI_STR(devid),
+ (cap & PCIM_ATS_EN) ? "enabled" : "Disabled",
+ qlen);
+ qlen = (cap & PCIM_ATS_EN) ? qlen : -1;
+ }
+
+ return (qlen);
+}
+
+/*
+ * Check if an endpoint device support device IOTLB or ATS.
+ */
+static inline bool
+amdvi_dev_support_iotlb(struct amdvi_softc *softc, uint16_t devid)
+{
+ struct ivhd_dev_cfg *cfg;
+ int qlen, i;
+ bool pci_ats, ivhd_ats;
+
+ qlen = amdvi_find_ats_qlen(devid);
+ if (qlen < 0)
+ return (false);
+
+ KASSERT(softc, ("softc is NULL"));
+ cfg = softc->dev_cfg;
+
+ ivhd_ats = false;
+ for (i = 0; i < softc->dev_cfg_cnt; i++) {
+ if ((cfg->start_id <= devid) && (cfg->end_id >= devid)) {
+ ivhd_ats = cfg->enable_ats;
+ break;
+ }
+ cfg++;
+ }
+
+ pci_ats = (qlen < 0) ? false : true;
+ if (pci_ats != ivhd_ats)
+ device_printf(softc->dev,
+ "BIOS bug: mismatch in ATS setting for %d.%d.%d,"
+ "ATS inv qlen = %d\n", RID2PCI_STR(devid), qlen);
+
+ /* Ignore IVRS setting and respect PCI setting. */
+ return (pci_ats);
+}
+#endif
+
+/* Enable IOTLB support for IOMMU if its supported. */
+static inline void
+amdvi_hw_enable_iotlb(struct amdvi_softc *softc)
+{
+#ifndef AMDVI_ATS_ENABLE
+ softc->iotlb = false;
+#else
+ bool supported;
+
+ supported = (softc->ivhd_flag & IVHD_FLAG_IOTLB) ? true : false;
+
+ if (softc->pci_cap & AMDVI_PCI_CAP_IOTLB) {
+ if (!supported)
+ device_printf(softc->dev, "IOTLB disabled by BIOS.\n");
+
+ if (supported && !amdvi_enable_iotlb) {
+ device_printf(softc->dev, "IOTLB disabled by user.\n");
+ supported = false;
+ }
+ } else
+ supported = false;
+
+ softc->iotlb = supported;
+
+#endif
+}
+
+static int
+amdvi_init_cmd(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl = softc->ctrl;
+
+ ctrl->cmd.len = 8; /* Use 256 command buffer entries. */
+ softc->cmd_max = 1 << ctrl->cmd.len;
+
+ softc->cmd = malloc(sizeof(struct amdvi_cmd) *
+ softc->cmd_max, M_AMDVI, M_WAITOK | M_ZERO);
+
+ if ((uintptr_t)softc->cmd & PAGE_MASK)
+ panic("AMDVi: Command buffer not aligned on page boundary.");
+
+ ctrl->cmd.base = vtophys(softc->cmd) / PAGE_SIZE;
+ /*
+ * XXX: Reset the h/w pointers in case IOMMU is restarting,
+ * h/w doesn't clear these pointers based on empirical data.
+ */
+ ctrl->cmd_tail = 0;
+ ctrl->cmd_head = 0;
+
+ return (0);
+}
+
+/*
+ * Note: Update tail pointer after we have written the command since tail
+ * pointer update cause h/w to execute new commands, see section 3.3
+ * of AMD IOMMU spec ver 2.0.
+ */
+/* Get the command tail pointer w/o updating it. */
+static struct amdvi_cmd *
+amdvi_get_cmd_tail(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+ struct amdvi_cmd *tail;
+
+ KASSERT(softc, ("softc is NULL"));
+ KASSERT(softc->cmd != NULL, ("cmd is NULL"));
+
+ ctrl = softc->ctrl;
+ KASSERT(ctrl != NULL, ("ctrl is NULL"));
+
+ tail = (struct amdvi_cmd *)((uint8_t *)softc->cmd +
+ ctrl->cmd_tail);
+
+ return (tail);
+}
+
+/*
+ * Update the command tail pointer which will start command execution.
+ */
+static void
+amdvi_update_cmd_tail(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+ int size;
+
+ size = sizeof(struct amdvi_cmd);
+ KASSERT(softc->cmd != NULL, ("cmd is NULL"));
+
+ ctrl = softc->ctrl;
+ KASSERT(ctrl != NULL, ("ctrl is NULL"));
+
+ ctrl->cmd_tail = MOD_INC(ctrl->cmd_tail, size, softc->cmd_max);
+ softc->total_cmd++;
+
+#ifdef AMDVI_DEBUG_CMD
+ device_printf(softc->dev, "cmd_tail: %s Tail:0x%x, Head:0x%x.\n",
+ ctrl->cmd_tail,
+ ctrl->cmd_head);
+#endif
+
+}
+
+/*
+ * Various commands supported by IOMMU.
+ */
+
+/* Completion wait command. */
+static void
+amdvi_cmd_cmp(struct amdvi_softc *softc, const uint64_t data)
+{
+ struct amdvi_cmd *cmd;
+ uint64_t pa;
+
+ cmd = amdvi_get_cmd_tail(softc);
+ KASSERT(cmd != NULL, ("Cmd is NULL"));
+
+ pa = vtophys(&softc->cmp_data);
+ cmd->opcode = AMDVI_CMP_WAIT_OPCODE;
+ cmd->word0 = (pa & 0xFFFFFFF8) |
+ (AMDVI_CMP_WAIT_STORE);
+ //(AMDVI_CMP_WAIT_FLUSH | AMDVI_CMP_WAIT_STORE);
+ cmd->word1 = (pa >> 32) & 0xFFFFF;
+ cmd->addr = data;
+
+ amdvi_update_cmd_tail(softc);
+}
+
+/* Invalidate device table entry. */
+static void
+amdvi_cmd_inv_dte(struct amdvi_softc *softc, uint16_t devid)
+{
+ struct amdvi_cmd *cmd;
+
+ cmd = amdvi_get_cmd_tail(softc);
+ KASSERT(cmd != NULL, ("Cmd is NULL"));
+ cmd->opcode = AMDVI_INVD_DTE_OPCODE;
+ cmd->word0 = devid;
+ amdvi_update_cmd_tail(softc);
+#ifdef AMDVI_DEBUG_CMD
+ device_printf(softc->dev, "Invalidated DTE:0x%x\n", devid);
+#endif
+}
+
+/* Invalidate IOMMU page, use for invalidation of domain. */
+static void
+amdvi_cmd_inv_iommu_pages(struct amdvi_softc *softc, uint16_t domain_id,
+ uint64_t addr, bool guest_nested,
+ bool pde, bool page)
+{
+ struct amdvi_cmd *cmd;
+
+ cmd = amdvi_get_cmd_tail(softc);
+ KASSERT(cmd != NULL, ("Cmd is NULL"));
+
+
+ cmd->opcode = AMDVI_INVD_PAGE_OPCODE;
+ cmd->word1 = domain_id;
+ /*
+ * Invalidate all addresses for this domain.
+ */
+ cmd->addr = addr;
+ cmd->addr |= pde ? AMDVI_INVD_PAGE_PDE : 0;
+ cmd->addr |= page ? AMDVI_INVD_PAGE_S : 0;
+
+ amdvi_update_cmd_tail(softc);
+}
+
+#ifdef AMDVI_ATS_ENABLE
+/* Invalidate device IOTLB. */
+static void
+amdvi_cmd_inv_iotlb(struct amdvi_softc *softc, uint16_t devid)
+{
+ struct amdvi_cmd *cmd;
+ int qlen;
+
+ if (!softc->iotlb)
+ return;
+
+ qlen = amdvi_find_ats_qlen(devid);
+ if (qlen < 0) {
+ panic("AMDVI: Invalid ATS qlen(%d) for device %d.%d.%d\n",
+ qlen, RID2PCI_STR(devid));
+ }
+ cmd = amdvi_get_cmd_tail(softc);
+ KASSERT(cmd != NULL, ("Cmd is NULL"));
+
+#ifdef AMDVI_DEBUG_CMD
+ device_printf(softc->dev, "Invalidate IOTLB devID 0x%x"
+ " Qlen:%d\n", devid, qlen);
+#endif
+ cmd->opcode = AMDVI_INVD_IOTLB_OPCODE;
+ cmd->word0 = devid;
+ cmd->word1 = qlen;
+ cmd->addr = AMDVI_INVD_IOTLB_ALL_ADDR |
+ AMDVI_INVD_IOTLB_S;
+ amdvi_update_cmd_tail(softc);
+}
+#endif
+
+#ifdef notyet /* For Interrupt Remap. */
+static void
+amdvi_cmd_inv_intr_map(struct amdvi_softc *softc,
+ uint16_t devid)
+{
+ struct amdvi_cmd *cmd;
+
+ cmd = amdvi_get_cmd_tail(softc);
+ KASSERT(cmd != NULL, ("Cmd is NULL"));
+ cmd->opcode = AMDVI_INVD_INTR_OPCODE;
+ cmd->word0 = devid;
+ amdvi_update_cmd_tail(softc);
+#ifdef AMDVI_DEBUG_CMD
+ device_printf(softc->dev, "Invalidate INTR map of devID 0x%x\n", devid);
+#endif
+}
+#endif
+
+/* Invalidate domain using INVALIDATE_IOMMU_PAGES command. */
+static void
+amdvi_inv_domain(struct amdvi_softc *softc, uint16_t domain_id)
+{
+ struct amdvi_cmd *cmd;
+
+ cmd = amdvi_get_cmd_tail(softc);
+ KASSERT(cmd != NULL, ("Cmd is NULL"));
+
+ /*
+ * See section 3.3.3 of IOMMU spec rev 2.0, software note
+ * for invalidating domain.
+ */
+ amdvi_cmd_inv_iommu_pages(softc, domain_id, AMDVI_INVD_PAGE_ALL_ADDR,
+ false, true, true);
+
+#ifdef AMDVI_DEBUG_CMD
+ device_printf(softc->dev, "Invalidate domain:0x%x\n", domain_id);
+
+#endif
+}
+
+static bool
+amdvi_cmp_wait(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+ const uint64_t VERIFY = 0xA5A5;
+ volatile uint64_t *read;
+ int i;
+ bool status;
+
+ ctrl = softc->ctrl;
+ read = &softc->cmp_data;
+ *read = 0;
+ amdvi_cmd_cmp(softc, VERIFY);
+ /* Wait for h/w to update completion data. */
+ for (i = 0; i < 100 && (*read != VERIFY); i++) {
+ DELAY(1000); /* 1 ms */
+ }
+ status = (VERIFY == softc->cmp_data) ? true : false;
+
+#ifdef AMDVI_DEBUG_CMD
+ if (status)
+ device_printf(softc->dev, "CMD completion DONE Tail:0x%x,
+ "Head:0x%x, loop:%d.\n", ctrl->cmd_tail,
+ ctrl->cmd_head, loop);
+#endif
+ return (status);
+}
+
+static void
+amdvi_wait(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+ int i;
+
+ KASSERT(softc, ("softc is NULL"));
+
+ ctrl = softc->ctrl;
+ KASSERT(ctrl != NULL, ("ctrl is NULL"));
+ /* Don't wait if h/w is not enabled. */
+ if ((ctrl->control & AMDVI_CTRL_EN) == 0)
+ return;
+
+ for (i = 0; i < 10; i++) {
+ if (amdvi_cmp_wait(softc))
+ return;
+ }
+
+ device_printf(softc->dev, "Error: completion failed"
+ " tail:0x%x, head:0x%x.\n",
+ ctrl->cmd_tail, ctrl->cmd_head);
+ amdvi_dump_cmds(softc);
+}
+
+static void
+amdvi_dump_cmds(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+ struct amdvi_cmd *cmd;
+ int off, i;
+
+ ctrl = softc->ctrl;
+ device_printf(softc->dev, "Dump all the commands:\n");
+ /*
+ * If h/w is stuck in completion, it is the previous command,
+ * start dumping from previous command onward.
+ */
+ off = MOD_DEC(ctrl->cmd_head, sizeof(struct amdvi_cmd),
+ softc->cmd_max);
+ for (i = 0; off != ctrl->cmd_tail &&
+ i < softc->cmd_max; i++) {
+ cmd = (struct amdvi_cmd *)((uint8_t *)softc->cmd + off);
+ printf(" [CMD%d, off:0x%x] opcode= 0x%x 0x%x"
+ " 0x%x 0x%lx\n", i, off, cmd->opcode,
+ cmd->word0, cmd->word1, cmd->addr);
+ off = (off + sizeof(struct amdvi_cmd)) %
+ (softc->cmd_max * sizeof(struct amdvi_cmd));
+ }
+}
+
+static int
+amdvi_init_event(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+
+ ctrl = softc->ctrl;
+ ctrl->event.len = 8;
+ softc->event_max = 1 << ctrl->event.len;
+ softc->event = malloc(sizeof(struct amdvi_event) *
+ softc->event_max, M_AMDVI, M_WAITOK | M_ZERO);
+ if ((uintptr_t)softc->event & PAGE_MASK) {
+ device_printf(softc->dev, "Event buffer not aligned on page.");
+ return (false);
+ }
+ ctrl->event.base = vtophys(softc->event) / PAGE_SIZE;
+
+ /* Reset the pointers. */
+ ctrl->evt_head = 0;
+ ctrl->evt_tail = 0;
+
+ return (0);
+}
+
+static inline void
+amdvi_decode_evt_flag(uint16_t flag)
+{
+
+ flag &= AMDVI_EVENT_FLAG_MASK;
+ printf("0x%b]\n", flag,
+ "\020"
+ "\001GN"
+ "\002NX"
+ "\003US"
+ "\004I"
+ "\005PR"
+ "\006RW"
+ "\007PE"
+ "\010RZ"
+ "\011TR"
+ );
+}
+
+/* See section 2.5.4 of AMD IOMMU spec ver 2.62.*/
+static inline void
+amdvi_decode_evt_flag_type(uint8_t type)
+{
+
+ switch (AMDVI_EVENT_FLAG_TYPE(type)) {
+ case 0:
+ printf("RSVD\n");
+ break;
+ case 1:
+ printf("Master Abort\n");
+ break;
+ case 2:
+ printf("Target Abort\n");
+ break;
+ case 3:
+ printf("Data Err\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+amdvi_decode_inv_dte_evt(uint16_t devid, uint16_t domid, uint64_t addr,
+ uint16_t flag)
+{
+
+ printf("\t[IO_PAGE_FAULT EVT: devId:0x%x DomId:0x%x"
+ " Addr:0x%lx",
+ devid, domid, addr);
+ amdvi_decode_evt_flag(flag);
+}
+
+static void
+amdvi_decode_pf_evt(uint16_t devid, uint16_t domid, uint64_t addr,
+ uint16_t flag)
+{
+
+ printf("\t[IO_PAGE_FAULT EVT: devId:0x%x DomId:0x%x"
+ " Addr:0x%lx",
+ devid, domid, addr);
+ amdvi_decode_evt_flag(flag);
+}
+
+static void
+amdvi_decode_dte_hwerr_evt(uint16_t devid, uint16_t domid,
+ uint64_t addr, uint16_t flag)
+{
+
+ printf("\t[DEV_TAB_HW_ERR EVT: devId:0x%x DomId:0x%x"
+ " Addr:0x%lx", devid, domid, addr);
+ amdvi_decode_evt_flag(flag);
+ amdvi_decode_evt_flag_type(flag);
+}
+
+static void
+amdvi_decode_page_hwerr_evt(uint16_t devid, uint16_t domid, uint64_t addr,
+ uint16_t flag)
+{
+
+ printf("\t[PAGE_TAB_HW_ERR EVT: devId:0x%x DomId:0x%x"
+ " Addr:0x%lx", devid, domid, addr);
+ amdvi_decode_evt_flag(flag);
+ amdvi_decode_evt_flag_type(AMDVI_EVENT_FLAG_TYPE(flag));
+}
+
+static void
+amdvi_decode_evt(struct amdvi_event *evt)
+{
+ struct amdvi_cmd *cmd;
+
+ switch (evt->opcode) {
+ case AMDVI_EVENT_INVALID_DTE:
+ amdvi_decode_inv_dte_evt(evt->devid, evt->pasid_domid,
+ evt->addr, evt->flag);
+ break;
+
+ case AMDVI_EVENT_PFAULT:
+ amdvi_decode_pf_evt(evt->devid, evt->pasid_domid,
+ evt->addr, evt->flag);
+ break;
+
+ case AMDVI_EVENT_DTE_HW_ERROR:
+ amdvi_decode_dte_hwerr_evt(evt->devid, evt->pasid_domid,
+ evt->addr, evt->flag);
+ break;
+
+ case AMDVI_EVENT_PAGE_HW_ERROR:
+ amdvi_decode_page_hwerr_evt(evt->devid, evt->pasid_domid,
+ evt->addr, evt->flag);
+ break;
+
+ case AMDVI_EVENT_ILLEGAL_CMD:
+ /* FALL THROUGH */
+ case AMDVI_EVENT_CMD_HW_ERROR:
+ printf("\t[%s EVT]", (evt->opcode == AMDVI_EVENT_ILLEGAL_CMD) ?
+ "ILLEGAL CMD" : "CMD HW ERR");
+ cmd = (struct amdvi_cmd *)PHYS_TO_DMAP(evt->addr);
+ printf("\tCMD opcode= 0x%x 0x%x 0x%x 0x%lx\n",
+ cmd->opcode, cmd->word0, cmd->word1, cmd->addr);
+ break;
+
+ case AMDVI_EVENT_IOTLB_TIMEOUT:
+ printf("\t[IOTLB_INV_TIMEOUT devid:0x%x addr:0x%lx",
+ evt->devid, evt->addr);
+ break;
+
+ case AMDVI_EVENT_INVALID_DTE_REQ:
+ printf("\t[INV_DTE devid:0x%x addr:0x%lx",
+ evt->devid, evt->addr);
+ break;
+
+ case AMDVI_EVENT_INVALID_PPR_REQ:
+ case AMDVI_EVENT_COUNTER_ZERO:
+ printf("AMD-Vi: v2 events.\n");
+ break;
+
+ default:
+ printf("Unsupported AMD-Vi event:%d", evt->opcode);
+ }
+}
+
+static void
+amdvi_print_events(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+ struct amdvi_event *event;
+ int i, size;
+
+ ctrl = softc->ctrl;
+ size = sizeof(struct amdvi_event);
+ for (i = 0; i < softc->event_max; i++) {
+ event = &softc->event[ctrl->evt_head / size];
+ if (!event->opcode)
+ break;
+ device_printf(softc->dev, "\t[Event%d: Head:0x%x Tail:0x%x]\n",
+ i, ctrl->evt_head, ctrl->evt_tail);
+ amdvi_decode_evt(event);
+ ctrl->evt_head = MOD_INC(ctrl->evt_head, size,
+ softc->event_max);
+ }
+}
+
+static int
+amdvi_init_dte(struct amdvi_softc *softc)
+{
+ struct amdvi_ctrl *ctrl;
+
+ ctrl = softc->ctrl;
+ ctrl->dte.base = vtophys(amdvi_dte) / PAGE_SIZE;
+ ctrl->dte.size = 0x1FF; /* 2MB device table. */
+
+ return (0);
+}
+
+/*
+ * Not all capabilities of IOMMU are available in ACPI IVHD flag
+ * or EFR entry, read directly from device.
+ */
+static int
+amdvi_print_pci_cap(device_t dev)
+{
+ struct amdvi_softc *softc;
+ uint32_t off, cap;
+
+
+ softc = device_get_softc(dev);
+ off = softc->cap_off;
+
+ /*
+ * Section 3.7.1 of IOMMU sepc rev 2.0.
+ * Read capability from device.
+ */
+ cap = amdvi_pci_read(softc, off);
+
+ /* Make sure capability type[18:16] is 3. */
+ KASSERT((((cap >> 16) & 0x7) == 0x3),
+ ("Not a IOMMU capability 0x%x at 0x%x", cap, off));
+
+ softc->pci_cap = cap >> 24;
+ device_printf(softc->dev, "PCI cap 0x%x at 0x%x feature:%b\n",
+ cap, off, softc->pci_cap,
+ "\020\001IOTLB\002HT\003NPCache\004EFR");
+
+ /* IOMMU spec Rev 2.0, section 3.7.2.1 */
+ softc->pci_efr = softc->ctrl->ex_feature;
+ if (softc->pci_efr) {
+ device_printf(softc->dev, "PCI extended Feature:%b\n",
+ (int)softc->pci_efr,
+ "\020\001PreFSup\002PPRSup\003XTSup\004NXSup\006IASup"
+ "\007GASup\008HESup\009PCSup");
+ device_printf(softc->dev,
+ "PCI HATS = %d GATS = %d GLXSup = %d, max PASID: 0x%x ",
+ (int)((softc->pci_efr >> 10) & 0x3),
+ (int)((softc->pci_efr >> 12) & 0x3),
+ (int)((softc->pci_efr >> 14) & 0x3),
+ (int)((softc->pci_efr >> 32) & 0x1F) + 1);
+ }
+
+ return (0);
+}
+
+static void
+amdvi_event_intr(void *arg)
+{
+ struct amdvi_softc *softc;
+ struct amdvi_ctrl *ctrl;
+
+ softc = (struct amdvi_softc *)arg;
+ ctrl = softc->ctrl;
+ device_printf(softc->dev, "EVT INTR %ld Status:0x%x"
+ " EVT Head:0x%x Tail:0x%x]\n", softc->event_intr_cnt++,
+ ctrl->status, ctrl->evt_head, ctrl->evt_tail);
+ printf(" [CMD Total 0x%lx] Tail:0x%x, Head:0x%x.\n",
+ softc->total_cmd, ctrl->cmd_tail, ctrl->cmd_head);
+
+ amdvi_print_events(softc);
+}
+
+static void
+amdvi_free_evt_intr_res(device_t dev)
+{
+
+ struct amdvi_softc *softc;
+
+ softc = device_get_softc(dev);
+ if (softc->event_tag != NULL) {
+ bus_teardown_intr(dev, softc->event_res, softc->event_tag);
+ }
+ if (softc->event_res != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ, softc->event_rid,
+ softc->event_res);
+ }
+ bus_delete_resource(dev, SYS_RES_IRQ, softc->event_rid);
+ PCIB_RELEASE_MSI(device_get_parent(device_get_parent(dev)),
+ dev, 1, &softc->event_irq);
+}
+
+static bool
+amdvi_alloc_intr_resources(struct amdvi_softc *softc)
+{
+ device_t dev, pcib;
+ uint64_t msi_addr;
+ uint32_t msi_data, temp;
+ int err, msi_off;
+
+ dev = softc->dev;
+ pcib = device_get_parent(device_get_parent(dev));
+ softc->event_irq = -1;
+ softc->event_rid = 0;
+ /*
+ * Section 3.7.1 of IOMMU rev 2.0. With MSI, there is only one
+ * interrupt. XXX: Enable MSI/X support.
+ */
+
+ err = PCIB_ALLOC_MSI(pcib, dev, 1, 1, &softc->event_irq);
+ if (err) {
+ device_printf(dev,
+ "Couldn't find event MSI IRQ resource.\n");
+ return (ENOENT);
+ }
+ err = bus_set_resource(dev, SYS_RES_IRQ, softc->event_rid,
+ softc->event_irq, 1);
+ if (err) {
+ device_printf(dev, "Couldn't set event MSI resource.\n");
+ return (ENXIO);
+ }
+ softc->event_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &softc->event_rid, RF_ACTIVE);
+ if (!softc->event_res) {
+ device_printf(dev,
+ "Unable to allocate event INTR resource.\n");
+ return (ENOMEM);
+ }
+
+ if (bus_setup_intr(dev, softc->event_res,
+ INTR_TYPE_MISC | INTR_MPSAFE, NULL, amdvi_event_intr,
+ softc, &softc->event_tag)) {
+ device_printf(dev, "Fail to setup event intr\n");
+ bus_release_resource(softc->dev, SYS_RES_IRQ,
+ softc->event_rid, softc->event_res);
+ softc->event_res = NULL;
+ return (ENXIO);
+ }
+
+ bus_describe_intr(dev, softc->event_res, softc->event_tag,
+ "fault");
+
+ err = amdvi_find_pci_cap(softc, PCIY_MSI, &msi_off);
+ if (err) {
+ device_printf(dev, "Couldn't find MSI capability, err = %d.\n",
+ err);
+ return (err);
+ }
+
+ err = PCIB_MAP_MSI(pcib, dev, softc->event_irq, &msi_addr,
+ &msi_data);
+ if (err) {
+ device_printf(dev,
+ "Event interrupt config failed, err=%d.\n",
+ err);
+ amdvi_free_evt_intr_res(softc->dev);
+ return (err);
+ }
+
+ /* Configure MSI */
+ amdvi_pci_write(softc, msi_off + PCIR_MSI_ADDR, msi_addr);
+ amdvi_pci_write(softc, msi_off + PCIR_MSI_ADDR_HIGH,
+ msi_addr >> 32);
+ amdvi_pci_write(softc, msi_off + PCIR_MSI_DATA_64BIT, msi_data);
+
+ /* Now enable MSI interrupt. */
+ temp = amdvi_pci_read(softc, msi_off);
+ temp |= (PCIM_MSICTRL_MSI_ENABLE << 16); /* MSI enable. */
+ amdvi_pci_write(softc, msi_off, temp);
+
+ return (0);
+}
+
+
+static void
+amdvi_print_dev_cap(struct amdvi_softc *softc)
+{
+ struct ivhd_dev_cfg *cfg;
+ int i;
+
+ cfg = softc->dev_cfg;
+ for (i = 0; i < softc->dev_cfg_cnt; i++) {
+ device_printf(softc->dev, "device [0x%x - 0x%x]"
+ "config:%b%s\n", cfg->start_id, cfg->end_id,
+ cfg->data,
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list