git: 1587a9db92c0 - main - pci_cfgreg: Add a PCI domain argument to the low-level register API

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Wed, 29 Nov 2023 18:34:42 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=1587a9db92c03c738bb3f0fc5874b43c961e7c99

commit 1587a9db92c03c738bb3f0fc5874b43c961e7c99
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2023-11-29 18:31:47 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2023-11-29 18:31:47 +0000

    pci_cfgreg: Add a PCI domain argument to the low-level register API
    
    This commit changes the API of pci_cfgreg(read|write) to add a domain
    argument (referred to as a segment in ACPI parlance) (note that this
    is not the same as a NUMA domain, but something PCI-specific).  This
    does not yet enable access to domains other than 0, but updates the
    API to support domains.
    
    Places that use hard-coded bus/slot/function addresses have been
    updated to hardcode a domain of 0.  A few places that have the PCI
    domain (segment) available such as the acpi_pcib_acpi.c Host-PCI
    bridge driver pass the PCI domain.
    
    The hpt27xx(4) and hptnr(4) drivers fail to attach to a device not on
    domain 0 since they provide APIs to their binary blobs that only
    permit bus/slot/function addressing.
    
    The x86 non-ACPI PCI bus drivers all hardcode a domain of 0 as they do
    not support multiple domains.
    
    Reviewed by:    imp
    Differential Revision:  https://reviews.freebsd.org/D42827
---
 sys/amd64/pci/pci_cfgreg.c        | 62 +++++++++++++++++++---------------
 sys/amd64/vmm/amd/amdvi_hw.c      |  2 +-
 sys/amd64/vmm/amd/ivrs_drv.c      |  3 +-
 sys/arm64/acpica/pci_cfgreg.c     |  5 +--
 sys/arm64/include/pci_cfgreg.h    |  4 +--
 sys/dev/acpica/Osd/OsdHardware.c  |  6 ++--
 sys/dev/acpica/acpi_pci_link.c    | 33 +++++++++++-------
 sys/dev/acpica/acpi_pcib_acpi.c   |  8 +++--
 sys/dev/agp/agp_amd64.c           | 71 +++++++++++++++++++++------------------
 sys/dev/amdtemp/amdtemp.c         |  5 +--
 sys/dev/hpt27xx/hpt27xx_os_bsd.c  |  8 ++---
 sys/dev/hpt27xx/hpt27xx_osm_bsd.c |  5 +++
 sys/dev/hptnr/hptnr_os_bsd.c      |  2 +-
 sys/dev/hptnr/hptnr_osm_bsd.c     |  5 +++
 sys/dev/ichwd/ichwd.c             |  8 ++---
 sys/dev/ipmi/ipmi_isa.c           |  2 +-
 sys/dev/pci/pci_subr.c            | 18 +++++-----
 sys/dev/pci/pcib_private.h        |  3 +-
 sys/i386/pci/pci_cfgreg.c         | 62 +++++++++++++++++++---------------
 sys/i386/pci/pci_pir.c            | 10 +++---
 sys/x86/include/pci_cfgreg.h      |  4 +--
 sys/x86/iommu/intel_drv.c         |  2 +-
 sys/x86/pci/pci_bus.c             |  4 +--
 sys/x86/pci/pci_early_quirks.c    | 47 +++++++++++++-------------
 sys/x86/pci/qpi.c                 |  2 +-
 sys/x86/x86/legacy.c              |  8 ++---
 26 files changed, 218 insertions(+), 171 deletions(-)

diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index ee97f88951f0..452c5898e959 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/pci/pci_cfgreg.c
@@ -41,12 +41,12 @@
 #include <vm/pmap.h>
 #include <machine/pci_cfgreg.h>
 
-static uint32_t	pci_docfgregread(int bus, int slot, int func, int reg,
-		    int bytes);
-static int	pciereg_cfgread(int bus, unsigned slot, unsigned func,
-		    unsigned reg, unsigned bytes);
-static void	pciereg_cfgwrite(int bus, unsigned slot, unsigned func,
-		    unsigned reg, int data, unsigned bytes);
+static uint32_t	pci_docfgregread(int domain, int bus, int slot, int func,
+		    int reg, int bytes);
+static int	pciereg_cfgread(int domain, int bus, unsigned slot,
+		    unsigned func, unsigned reg, unsigned bytes);
+static void	pciereg_cfgwrite(int domain, int bus, unsigned slot,
+		    unsigned func, unsigned reg, int data, unsigned bytes);
 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
 
@@ -76,22 +76,25 @@ pci_cfgregopen(void)
 }
 
 static uint32_t
-pci_docfgregread(int bus, int slot, int func, int reg, int bytes)
+pci_docfgregread(int domain, int bus, int slot, int func, int reg, int bytes)
 {
+	if (domain == 0 && bus == 0 && (1 << slot & pcie_badslots) != 0)
+		return (pcireg_cfgread(bus, slot, func, reg, bytes));
 
 	if (cfgmech == CFGMECH_PCIE &&
-	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
-	    (bus != 0 || !(1 << slot & pcie_badslots)))
-		return (pciereg_cfgread(bus, slot, func, reg, bytes));
-	else
+	    (bus >= pcie_minbus && bus <= pcie_maxbus))
+		return (pciereg_cfgread(domain, bus, slot, func, reg, bytes));
+	else if (domain == 0)
 		return (pcireg_cfgread(bus, slot, func, reg, bytes));
+	else
+		return (-1);
 }
 
 /* 
  * Read configuration space register
  */
 u_int32_t
-pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
+pci_cfgregread(int domain, int bus, int slot, int func, int reg, int bytes)
 {
 	uint32_t line;
 
@@ -104,26 +107,31 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
 	 * as an invalid IRQ.
 	 */
 	if (reg == PCIR_INTLINE && bytes == 1) {
-		line = pci_docfgregread(bus, slot, func, PCIR_INTLINE, 1);
+		line = pci_docfgregread(domain, bus, slot, func, PCIR_INTLINE,
+		    1);
 		if (line == 0 || line >= 128)
 			line = PCI_INVALID_IRQ;
 		return (line);
 	}
-	return (pci_docfgregread(bus, slot, func, reg, bytes));
+	return (pci_docfgregread(domain, bus, slot, func, reg, bytes));
 }
 
 /* 
  * Write configuration space register 
  */
 void
-pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
+pci_cfgregwrite(int domain, int bus, int slot, int func, int reg, uint32_t data,
+    int bytes)
 {
+	if (domain == 0 && bus == 0 && (1 << slot & pcie_badslots) != 0) {
+		pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
+		return;
+	}
 
 	if (cfgmech == CFGMECH_PCIE &&
-	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
-	    (bus != 0 || !(1 << slot & pcie_badslots)))
-		pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
-	else
+	    (bus >= pcie_minbus && bus <= pcie_maxbus))
+		pciereg_cfgwrite(domain, bus, slot, func, reg, data, bytes);
+	else if (domain == 0)
 		pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
 }
 
@@ -242,7 +250,7 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
 			if (val1 == 0xffffffff)
 				continue;
 
-			val2 = pciereg_cfgread(0, slot, 0, 0, 4);
+			val2 = pciereg_cfgread(0, 0, slot, 0, 0, 4);
 			if (val2 != val1)
 				pcie_badslots |= (1 << slot);
 		}
@@ -267,14 +275,14 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
  */
 
 static int
-pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
+pciereg_cfgread(int domain, int bus, unsigned slot, unsigned func, unsigned reg,
     unsigned bytes)
 {
 	vm_offset_t va;
 	int data = -1;
 
-	if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX ||
-	    func > PCI_FUNCMAX || reg > PCIE_REGMAX)
+	if (domain != 0 || bus < pcie_minbus || bus > pcie_maxbus ||
+	    slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX)
 		return (-1);
 
 	va = PCIE_VADDR(pcie_base, reg, bus, slot, func);
@@ -298,13 +306,13 @@ pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
 }
 
 static void
-pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data,
-    unsigned bytes)
+pciereg_cfgwrite(int domain, int bus, unsigned slot, unsigned func,
+    unsigned reg, int data, unsigned bytes)
 {
 	vm_offset_t va;
 
-	if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX ||
-	    func > PCI_FUNCMAX || reg > PCIE_REGMAX)
+	if (domain != 0 || bus < pcie_minbus || bus > pcie_maxbus ||
+	    slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX)
 		return;
 
 	va = PCIE_VADDR(pcie_base, reg, bus, slot, func);
diff --git a/sys/amd64/vmm/amd/amdvi_hw.c b/sys/amd64/vmm/amd/amdvi_hw.c
index 3471c3b1932f..e87d173023f8 100644
--- a/sys/amd64/vmm/amd/amdvi_hw.c
+++ b/sys/amd64/vmm/amd/amdvi_hw.c
@@ -124,7 +124,7 @@ static inline uint32_t
 amdvi_pci_read(struct amdvi_softc *softc, int off)
 {
 
-	return (pci_cfgregread(PCI_RID2BUS(softc->pci_rid),
+	return (pci_cfgregread(softc->pci_seg, PCI_RID2BUS(softc->pci_rid),
 	    PCI_RID2SLOT(softc->pci_rid), PCI_RID2FUNC(softc->pci_rid),
 	    off, 4));
 }
diff --git a/sys/amd64/vmm/amd/ivrs_drv.c b/sys/amd64/vmm/amd/ivrs_drv.c
index d8ea2442de23..7dd68d8aea95 100644
--- a/sys/amd64/vmm/amd/ivrs_drv.c
+++ b/sys/amd64/vmm/amd/ivrs_drv.c
@@ -649,7 +649,8 @@ ivhd_attach(device_t dev)
 	softc->dev = dev;
 	ivhd = ivhd_hdrs[unit];
 	KASSERT(ivhd, ("ivhd is NULL"));
-	softc->pci_dev = pci_find_bsf(PCI_RID2BUS(ivhd->Header.DeviceId),
+	softc->pci_dev = pci_find_dbsf(ivhd->PciSegmentGroup,
+	    PCI_RID2BUS(ivhd->Header.DeviceId),
 	    PCI_RID2SLOT(ivhd->Header.DeviceId),
 	    PCI_RID2FUNC(ivhd->Header.DeviceId));
 
diff --git a/sys/arm64/acpica/pci_cfgreg.c b/sys/arm64/acpica/pci_cfgreg.c
index d2972bd1579f..f35ae9d380d8 100644
--- a/sys/arm64/acpica/pci_cfgreg.c
+++ b/sys/arm64/acpica/pci_cfgreg.c
@@ -40,7 +40,7 @@
  * Read configuration space register
  */
 uint32_t
-pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
+pci_cfgregread(int domain, int bus, int slot, int func, int reg, int bytes)
 {
 
 	/* ARM64TODO */
@@ -52,7 +52,8 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
  * Write configuration space register
  */
 void
-pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
+pci_cfgregwrite(int domain, int bus, int slot, int func, int reg, uint32_t data,
+    int bytes)
 {
 
 	/* ARM64TODO */
diff --git a/sys/arm64/include/pci_cfgreg.h b/sys/arm64/include/pci_cfgreg.h
index 2c34f62c00c8..579dcd954c9b 100644
--- a/sys/arm64/include/pci_cfgreg.h
+++ b/sys/arm64/include/pci_cfgreg.h
@@ -27,7 +27,7 @@
 #define	_MACHINE_PCI_CFGREG_H
 
 int pci_cfgregopen(void);
-uint32_t pci_cfgregread(int, int, int, int, int);
-void pci_cfgregwrite(int, int, int, int, u_int32_t, int);
+uint32_t pci_cfgregread(int, int, int, int, int, int);
+void pci_cfgregwrite(int, int, int, int, int, uint32_t, int);
 
 #endif /* !_MACHINE_PCI_CFGREG_H */
diff --git a/sys/dev/acpica/Osd/OsdHardware.c b/sys/dev/acpica/Osd/OsdHardware.c
index b9c11454913b..fbaf76d2a91a 100644
--- a/sys/dev/acpica/Osd/OsdHardware.c
+++ b/sys/dev/acpica/Osd/OsdHardware.c
@@ -110,7 +110,7 @@ AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value,
     if (!pci_cfgregopen())
 	return (AE_NOT_EXIST);
 
-    *(UINT64 *)Value = pci_cfgregread(PciId->Bus, PciId->Device,
+    *(UINT64 *)Value = pci_cfgregread(PciId->Segment, PciId->Bus, PciId->Device,
 	PciId->Function, Register, Width / 8);
 
     return (AE_OK);
@@ -132,8 +132,8 @@ AcpiOsWritePciConfiguration (ACPI_PCI_ID *PciId, UINT32 Register,
     if (!pci_cfgregopen())
     	return (AE_NOT_EXIST);
 
-    pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register,
-	Value, Width / 8);
+    pci_cfgregwrite(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function,
+	Register, Value, Width / 8);
 
     return (AE_OK);
 #endif
diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c
index f354441bfd86..dac07a07ae7d 100644
--- a/sys/dev/acpica/acpi_pci_link.c
+++ b/sys/dev/acpica/acpi_pci_link.c
@@ -572,16 +572,16 @@ fail:
 
 /* XXX: Note that this is identical to pci_pir_search_irq(). */
 static uint8_t
-acpi_pci_link_search_irq(int bus, int device, int pin)
+acpi_pci_link_search_irq(int domain, int bus, int device, int pin)
 {
 	uint32_t value;
 	uint8_t func, maxfunc;
 
 	/* See if we have a valid device at function 0. */
-	value = pci_cfgregread(bus, device, 0, PCIR_VENDOR, 2);
+	value = pci_cfgregread(domain, bus, device, 0, PCIR_VENDOR, 2);
 	if (value == PCIV_INVALID)
 		return (PCI_INVALID_IRQ);
-	value = pci_cfgregread(bus, device, 0, PCIR_HDRTYPE, 1);
+	value = pci_cfgregread(domain, bus, device, 0, PCIR_HDRTYPE, 1);
 	if ((value & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
 		return (PCI_INVALID_IRQ);
 	if (value & PCIM_MFDEV)
@@ -591,10 +591,12 @@ acpi_pci_link_search_irq(int bus, int device, int pin)
 
 	/* Scan all possible functions at this device. */
 	for (func = 0; func <= maxfunc; func++) {
-		value = pci_cfgregread(bus, device, func, PCIR_VENDOR, 2);
+		value = pci_cfgregread(domain, bus, device, func, PCIR_VENDOR,
+		    2);
 		if (value == PCIV_INVALID)
 			continue;
-		value = pci_cfgregread(bus, device, func, PCIR_INTPIN, 1);
+		value = pci_cfgregread(domain, bus, device, func, PCIR_INTPIN,
+		    1);
 
 		/*
 		 * See if it uses the pin in question.  Note that the passed
@@ -603,7 +605,8 @@ acpi_pci_link_search_irq(int bus, int device, int pin)
 		 */
 		if (value != pin + 1)
 			continue;
-		value = pci_cfgregread(bus, device, func, PCIR_INTLINE, 1);
+		value = pci_cfgregread(domain, bus, device, func, PCIR_INTLINE,
+		    1);
 		if (bootverbose)
 			printf(
 		"ACPI: Found matching pin for %d.%d.INT%c at func %d: %d\n",
@@ -638,18 +641,22 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot,
 {
 	struct link *link;
 	uint8_t bios_irq;
-	uintptr_t bus;
+	uintptr_t bus, domain;
 
 	/*
-	 * Look up the PCI bus for the specified PCI bridge device.  Note
-	 * that the PCI bridge device might not have any children yet.
-	 * However, looking up its bus number doesn't require a valid child
-	 * device, so we just pass NULL.
+	 * Look up the PCI domain and bus for the specified PCI bridge
+	 * device.  Note that the PCI bridge device might not have any
+	 * children yet.  However, looking up these IVARs doesn't
+	 * require a valid child device, so we just pass NULL.
 	 */
 	if (BUS_READ_IVAR(pcib, NULL, PCIB_IVAR_BUS, &bus) != 0) {
 		device_printf(pcib, "Unable to read PCI bus number");
 		panic("PCI bridge without a bus number");
 	}
+	if (BUS_READ_IVAR(pcib, NULL, PCIB_IVAR_DOMAIN, &domain) != 0) {
+		device_printf(pcib, "Unable to read PCI domain number");
+		panic("PCI bridge without a domain number");
+	}
 		
 	/* Bump the reference count. */
 	ACPI_SERIAL_BEGIN(pci_link);
@@ -667,7 +674,7 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot,
 	 * The BIOS only routes interrupts via ISA IRQs using the ATPICs
 	 * (8259As).  Thus, if this link is routed via an ISA IRQ, go
 	 * look to see if the BIOS routed an IRQ for this link at the
-	 * indicated (bus, slot, pin).  If so, we prefer that IRQ for
+	 * indicated (domain, bus, slot, pin).  If so, we prefer that IRQ for
 	 * this link and add that IRQ to our list of known-good IRQs.
 	 * This provides a good work-around for link devices whose _CRS
 	 * method is either broken or bogus.  We only use the value
@@ -684,7 +691,7 @@ acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot,
 	}
 
 	/* Try to find a BIOS IRQ setting from any matching devices. */
-	bios_irq = acpi_pci_link_search_irq(bus, slot, pin);
+	bios_irq = acpi_pci_link_search_irq(domain, bus, slot, pin);
 	if (!PCI_INTERRUPT_VALID(bios_irq)) {
 		ACPI_SERIAL_END(pci_link);
 		return;
diff --git a/sys/dev/acpica/acpi_pcib_acpi.c b/sys/dev/acpica/acpi_pcib_acpi.c
index a66ca1199af7..06e6bc233720 100644
--- a/sys/dev/acpica/acpi_pcib_acpi.c
+++ b/sys/dev/acpica/acpi_pcib_acpi.c
@@ -629,14 +629,18 @@ static uint32_t
 acpi_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
     u_int reg, int bytes)
 {
-    return (pci_cfgregread(bus, slot, func, reg, bytes));
+    struct acpi_hpcib_softc *sc = device_get_softc(dev);
+
+    return (pci_cfgregread(sc->ap_segment, bus, slot, func, reg, bytes));
 }
 
 static void
 acpi_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
     u_int reg, uint32_t data, int bytes)
 {
-    pci_cfgregwrite(bus, slot, func, reg, data, bytes);
+    struct acpi_hpcib_softc *sc = device_get_softc(dev);
+
+    pci_cfgregwrite(sc->ap_segment, bus, slot, func, reg, data, bytes);
 }
 
 static int
diff --git a/sys/dev/agp/agp_amd64.c b/sys/dev/agp/agp_amd64.c
index 117a22247998..ff36200bd299 100644
--- a/sys/dev/agp/agp_amd64.c
+++ b/sys/dev/agp/agp_amd64.c
@@ -118,10 +118,10 @@ static int
 agp_amd64_nvidia_match(uint16_t devid)
 {
 	/* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
-	if (pci_cfgregread(0, 11, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
-	    pci_cfgregread(0, 11, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
-	    pci_cfgregread(0, 11, 0, PCIR_VENDOR, 2) != 0x10de ||
-	    pci_cfgregread(0, 11, 0, PCIR_DEVICE, 2) != devid)
+	if (pci_cfgregread(0, 0, 11, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
+	    pci_cfgregread(0, 0, 11, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
+	    pci_cfgregread(0, 0, 11, 0, PCIR_VENDOR, 2) != 0x10de ||
+	    pci_cfgregread(0, 0, 11, 0, PCIR_DEVICE, 2) != devid)
 		return (ENXIO);
 
 	return (0);
@@ -131,11 +131,11 @@ static int
 agp_amd64_via_match(void)
 {
 	/* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
-	if (pci_cfgregread(0, 1, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
-	    pci_cfgregread(0, 1, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
-	    pci_cfgregread(0, 1, 0, PCIR_VENDOR, 2) != 0x1106 ||
-	    pci_cfgregread(0, 1, 0, PCIR_DEVICE, 2) != 0xb188 ||
-	    (pci_cfgregread(0, 1, 0, AGP_VIA_AGPSEL, 1) & 2))
+	if (pci_cfgregread(0, 0, 1, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
+	    pci_cfgregread(0, 0, 1, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
+	    pci_cfgregread(0, 0, 1, 0, PCIR_VENDOR, 2) != 0x1106 ||
+	    pci_cfgregread(0, 0, 1, 0, PCIR_DEVICE, 2) != 0xb188 ||
+	    (pci_cfgregread(0, 0, 1, 0, AGP_VIA_AGPSEL, 1) & 2))
 		return (0);
 
 	return (1);
@@ -165,7 +165,7 @@ agp_amd64_attach(device_t dev)
 	int i, n, error;
 
 	for (i = 0, n = 0; i < PCI_SLOTMAX && n < AMD64_MAX_MCTRL; i++) {
-		devid = pci_cfgregread(0, i, 3, 0, 4);
+		devid = pci_cfgregread(0, 0, i, 3, 0, 4);
 		if (devid == 0x11031022 || devid == 0x12031022) {
 			sc->mctrl[n] = i;
 			n++;
@@ -227,11 +227,11 @@ agp_amd64_attach(device_t dev)
 
 	/* Install the gatt and enable aperture. */
 	for (i = 0; i < sc->n_mctrl; i++) {
-		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_ATTBASE,
+		pci_cfgregwrite(0, 0, sc->mctrl[i], 3, AGP_AMD64_ATTBASE,
 		    (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK,
 		    4);
-		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
-		    (pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) |
+		pci_cfgregwrite(0, 0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
+		    (pci_cfgregread(0, 0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) |
 		    AGP_AMD64_APCTRL_GARTEN) &
 		    ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO),
 		    4);
@@ -249,8 +249,8 @@ agp_amd64_detach(device_t dev)
 	agp_free_cdev(dev);
 
 	for (i = 0; i < sc->n_mctrl; i++)
-		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
-		    pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) &
+		pci_cfgregwrite(0, 0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
+		    pci_cfgregread(0, 0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) &
 		    ~AGP_AMD64_APCTRL_GARTEN, 4);
 
 	AGP_SET_APERTURE(dev, sc->initial_aperture);
@@ -278,7 +278,7 @@ agp_amd64_get_aperture(device_t dev)
 	struct agp_amd64_softc *sc = device_get_softc(dev);
 	uint32_t i;
 
-	i = (pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) &
+	i = (pci_cfgregread(0, 0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) &
 		AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
 
 	if (i >= AGP_AMD64_TABLE_SIZE)
@@ -301,8 +301,8 @@ agp_amd64_set_aperture(device_t dev, uint32_t aperture)
 		return (EINVAL);
 
 	for (j = 0; j < sc->n_mctrl; j++)
-		pci_cfgregwrite(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL,
-		    (pci_cfgregread(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL, 4) &
+		pci_cfgregwrite(0, 0, sc->mctrl[j], 3, AGP_AMD64_APCTRL,
+		    (pci_cfgregread(0, 0, sc->mctrl[j], 3, AGP_AMD64_APCTRL, 4) &
 		    ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1), 4);
 
 	switch (pci_get_vendor(dev)) {
@@ -356,10 +356,15 @@ agp_amd64_flush_tlb(device_t dev)
 	struct agp_amd64_softc *sc = device_get_softc(dev);
 	int i;
 
-	for (i = 0; i < sc->n_mctrl; i++)
-		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL,
-		    pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL, 4) |
-		    AGP_AMD64_CACHECTRL_INVGART, 4);
+	for (i = 0; i < sc->n_mctrl; i++) {
+		uint32_t val;
+
+		val = pci_cfgregread(0, 0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL,
+		    4);
+		val |= AGP_AMD64_CACHECTRL_INVGART;
+		pci_cfgregwrite(0, 0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL, val,
+		    4);
+	}
 }
 
 static void
@@ -372,7 +377,7 @@ agp_amd64_apbase_fixup(device_t dev)
 	sc->apbase = rman_get_start(sc->agp.as_aperture);
 	apbase = (sc->apbase >> 25) & AGP_AMD64_APBASE_MASK;
 	for (i = 0; i < sc->n_mctrl; i++)
-		pci_cfgregwrite(0, sc->mctrl[i], 3,
+		pci_cfgregwrite(0, 0, sc->mctrl[i], 3,
 		    AGP_AMD64_APBASE, apbase, 4);
 }
 
@@ -418,8 +423,8 @@ agp_amd64_nvidia_init(device_t dev)
 	pci_write_config(dev, AGP_AMD64_NVIDIA_0_APBASE,
 	    (pci_read_config(dev, AGP_AMD64_NVIDIA_0_APBASE, 4) & 0x0000000f) |
 	    sc->apbase, 4);
-	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE1, sc->apbase, 4);
-	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE2, sc->apbase, 4);
+	pci_cfgregwrite(0, 0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE1, sc->apbase, 4);
+	pci_cfgregwrite(0, 0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE2, sc->apbase, 4);
 }
 
 static int
@@ -438,12 +443,12 @@ agp_amd64_nvidia_set_aperture(device_t dev, uint32_t aperture)
 		return (EINVAL);
 	}
 
-	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE,
-	    (pci_cfgregread(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE, 4) &
+	pci_cfgregwrite(0, 0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE,
+	    (pci_cfgregread(0, 0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE, 4) &
 	    0xfffffff0) | apsize, 4);
-	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT1,
+	pci_cfgregwrite(0, 0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT1,
 	    sc->apbase + aperture - 1, 4);
-	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT2,
+	pci_cfgregwrite(0, 0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT2,
 	    sc->apbase + aperture - 1, 4);
 
 	return (0);
@@ -455,9 +460,9 @@ agp_amd64_via_init(device_t dev)
 	struct agp_amd64_softc *sc = device_get_softc(dev);
 
 	agp_amd64_apbase_fixup(dev);
-	pci_cfgregwrite(0, 1, 0, AGP3_VIA_ATTBASE, sc->gatt->ag_physical, 4);
-	pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL,
-	    pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180, 4);
+	pci_cfgregwrite(0, 0, 1, 0, AGP3_VIA_ATTBASE, sc->gatt->ag_physical, 4);
+	pci_cfgregwrite(0, 0, 1, 0, AGP3_VIA_GARTCTRL,
+	    pci_cfgregread(0, 0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180, 4);
 }
 
 static int
@@ -468,7 +473,7 @@ agp_amd64_via_set_aperture(device_t dev, uint32_t aperture)
 	apsize = ((aperture - 1) >> 20) ^ 0xff;
 	if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
 		return (EINVAL);
-	pci_cfgregwrite(0, 1, 0, AGP3_VIA_APSIZE, apsize, 1);
+	pci_cfgregwrite(0, 0, 1, 0, AGP3_VIA_APSIZE, apsize, 1);
 
 	return (0);
 }
diff --git a/sys/dev/amdtemp/amdtemp.c b/sys/dev/amdtemp/amdtemp.c
index 1b66bde0bdad..865804bdc96e 100644
--- a/sys/dev/amdtemp/amdtemp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -434,8 +434,9 @@ amdtemp_attach(device_t dev)
 			erratum319 = 1;
 			break;
 		case 1:	/* Socket AM2+ or AM3 */
-			if ((pci_cfgregread(pci_get_bus(dev),
-			    pci_get_slot(dev), 2, AMDTEMP_DRAM_CONF_HIGH, 2) &
+			if ((pci_cfgregread(pci_get_domain(dev),
+			    pci_get_bus(dev), pci_get_slot(dev), 2,
+			    AMDTEMP_DRAM_CONF_HIGH, 2) &
 			    AMDTEMP_DRAM_MODE_DDR3) != 0 || model > 0x04 ||
 			    (model == 0x04 && (cpuid & CPUID_STEPPING) >= 3))
 				break;
diff --git a/sys/dev/hpt27xx/hpt27xx_os_bsd.c b/sys/dev/hpt27xx/hpt27xx_os_bsd.c
index ebd58e771462..f4bbcfd11e82 100644
--- a/sys/dev/hpt27xx/hpt27xx_os_bsd.c
+++ b/sys/dev/hpt27xx/hpt27xx_os_bsd.c
@@ -90,19 +90,19 @@ BUS_ADDRESS get_dmapool_phy_addr(void *osext, void * dmapool_virt_addr)
 /* PCI space access */
 HPT_U8 pcicfg_read_byte (HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg)
 {
-	return (HPT_U8)pci_cfgregread(bus, dev, func, reg, 1);
+	return (HPT_U8)pci_cfgregread(0, bus, dev, func, reg, 1);
 }
 HPT_U32 pcicfg_read_dword(HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg)
 {
-	return (HPT_U32)pci_cfgregread(bus, dev, func, reg, 4);
+	return (HPT_U32)pci_cfgregread(0, bus, dev, func, reg, 4);
 }
 void pcicfg_write_byte (HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg, HPT_U8 v)
 {
-	pci_cfgregwrite(bus, dev, func, reg, v, 1);
+	pci_cfgregwrite(0, bus, dev, func, reg, v, 1);
 }
 void pcicfg_write_dword(HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg, HPT_U32 v)
 {
-	pci_cfgregwrite(bus, dev, func, reg, v, 4);
+	pci_cfgregwrite(0, bus, dev, func, reg, v, 4);
 }/* PCI space access */
 
 void *os_map_pci_bar(
diff --git a/sys/dev/hpt27xx/hpt27xx_osm_bsd.c b/sys/dev/hpt27xx/hpt27xx_osm_bsd.c
index 7eb7dbc8fc72..32d3e465c569 100644
--- a/sys/dev/hpt27xx/hpt27xx_osm_bsd.c
+++ b/sys/dev/hpt27xx/hpt27xx_osm_bsd.c
@@ -75,6 +75,11 @@ static int hpt_attach(device_t dev)
 	PVBUS vbus;
 	PVBUS_EXT vbus_ext;
 	
+	if (pci_get_domain(dev) != 0) {
+		device_printf(dev, "does not support PCI domains\n");
+		return (ENXIO);
+	}
+
 	KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)));
 
 	him = hpt_match(dev, 1);
diff --git a/sys/dev/hptnr/hptnr_os_bsd.c b/sys/dev/hptnr/hptnr_os_bsd.c
index 62b852ddb6af..59f6fb651db9 100644
--- a/sys/dev/hptnr/hptnr_os_bsd.c
+++ b/sys/dev/hptnr/hptnr_os_bsd.c
@@ -88,7 +88,7 @@ BUS_ADDRESS get_dmapool_phy_addr(void *osext, void * dmapool_virt_addr)
 
 HPT_U32 pcicfg_read_dword(HPT_U8 bus, HPT_U8 dev, HPT_U8 func, HPT_U8 reg)
 {
-	return (HPT_U32)pci_cfgregread(bus, dev, func, reg, 4);
+	return (HPT_U32)pci_cfgregread(0, bus, dev, func, reg, 4);
 }/* PCI space access */
 
 void *os_map_pci_bar(
diff --git a/sys/dev/hptnr/hptnr_osm_bsd.c b/sys/dev/hptnr/hptnr_osm_bsd.c
index c1c908b62c9d..00774bf9be4a 100644
--- a/sys/dev/hptnr/hptnr_osm_bsd.c
+++ b/sys/dev/hptnr/hptnr_osm_bsd.c
@@ -77,6 +77,11 @@ static int hpt_attach(device_t dev)
 	PVBUS vbus;
 	PVBUS_EXT vbus_ext;
 	
+	if (pci_get_domain(dev) != 0) {
+		device_printf(dev, "does not support PCI domains\n");
+		return (ENXIO);
+	}
+
 	KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)));
 
 	him = hpt_match(dev, 1);
diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c
index cdba8319daea..cade2cc4fb45 100644
--- a/sys/dev/ichwd/ichwd.c
+++ b/sys/dev/ichwd/ichwd.c
@@ -698,12 +698,12 @@ ichwd_identify(driver_t *driver, device_t parent)
 		 * Space via the bridge's BAR.
 		 * Then hide back the bridge.
 		 */
-		pci_cfgregwrite(0, 31, 1, 0xe1, 0, 1);
-		base_address64 = pci_cfgregread(0, 31, 1, SBREG_BAR + 4, 4);
+		pci_cfgregwrite(0, 0, 31, 1, 0xe1, 0, 1);
+		base_address64 = pci_cfgregread(0, 0, 31, 1, SBREG_BAR + 4, 4);
 		base_address64 <<= 32;
-		base_address64 |= pci_cfgregread(0, 31, 1, SBREG_BAR, 4);
+		base_address64 |= pci_cfgregread(0, 0, 31, 1, SBREG_BAR, 4);
 		base_address64 &= ~0xfull;
-		pci_cfgregwrite(0, 31, 1, 0xe1, 1, 1);
+		pci_cfgregwrite(0, 0, 31, 1, 0xe1, 1, 1);
 
 		/*
 		 * No Reboot bit is in General Control register, offset 0xc,
diff --git a/sys/dev/ipmi/ipmi_isa.c b/sys/dev/ipmi/ipmi_isa.c
index 6c8be8616ddf..432c63b327ee 100644
--- a/sys/dev/ipmi/ipmi_isa.c
+++ b/sys/dev/ipmi/ipmi_isa.c
@@ -66,7 +66,7 @@ ipmi_isa_identify(driver_t *driver, device_t parent)
 		 * create an isa ipmi device.  For now we hardcode the list
 		 * of bus, device, function tuples.
 		 */
-		devid = pci_cfgregread(0, 4, 2, PCIR_DEVVENDOR, 4);
+		devid = pci_cfgregread(0, 0, 4, 2, PCIR_DEVVENDOR, 4);
 		if (devid != 0xffffffff &&
 		    ipmi_pci_match(devid & 0xffff, devid >> 16) != NULL)
 			return;
diff --git a/sys/dev/pci/pci_subr.c b/sys/dev/pci/pci_subr.c
index c869959da73d..71485875ebe3 100644
--- a/sys/dev/pci/pci_subr.c
+++ b/sys/dev/pci/pci_subr.c
@@ -53,7 +53,7 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
 {
 	uint32_t id;
 
-	id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4);
+	id = read_config(0, bus, slot, func, PCIR_DEVVENDOR, 4);
 	if (id == 0xffffffff)
 		return (0);
 
@@ -61,12 +61,12 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
 	case 0x12258086:
 		/* Intel 824?? */
 		/* XXX This is a guess */
-		/* *busnum = read_config(bus, slot, func, 0x41, 1); */
+		/* *busnum = read_config(0, bus, slot, func, 0x41, 1); */
 		*busnum = bus;
 		break;
 	case 0x84c48086:
 		/* Intel 82454KX/GX (Orion) */
-		*busnum = read_config(bus, slot, func, 0x4a, 1);
+		*busnum = read_config(0, bus, slot, func, 0x4a, 1);
 		break;
 	case 0x84ca8086:
 		/*
@@ -85,19 +85,19 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
 		switch (slot) {
 		case 0x12:
 			/* Intel 82454NX PXB#0, Bus#A */
-			*busnum = read_config(bus, 0x10, func, 0xd0, 1);
+			*busnum = read_config(0, bus, 0x10, func, 0xd0, 1);
 			break;
 		case 0x13:
 			/* Intel 82454NX PXB#0, Bus#B */
-			*busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1;
+			*busnum = read_config(0, bus, 0x10, func, 0xd1, 1) + 1;
 			break;
 		case 0x14:
 			/* Intel 82454NX PXB#1, Bus#A */
-			*busnum = read_config(bus, 0x10, func, 0xd3, 1);
+			*busnum = read_config(0, bus, 0x10, func, 0xd3, 1);
 			break;
 		case 0x15:
 			/* Intel 82454NX PXB#1, Bus#B */
-			*busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1;
+			*busnum = read_config(0, bus, 0x10, func, 0xd4, 1) + 1;
 			break;
 		}
 		break;
@@ -116,12 +116,12 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
 	case 0x02011166:
 	case 0x02251166:
 	case 0x03021014:
-		*busnum = read_config(bus, slot, func, 0x44, 1);
+		*busnum = read_config(0, bus, slot, func, 0x44, 1);
 		break;
 
 		/* Compaq/HP -- vendor 0x0e11 */
 	case 0x60100e11:
-		*busnum = read_config(bus, slot, func, 0xc8, 1);
+		*busnum = read_config(0, bus, slot, func, 0xc8, 1);
 		break;
 	default:
 		/* Don't know how to read bus number. */
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index e1e15caa17e4..cf689026a033 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -148,7 +148,8 @@ struct pcib_softc
 
 #define	PCIB_SUPPORTED_ARI_VER	1
 
-typedef uint32_t pci_read_config_fn(int b, int s, int f, int reg, int width);
+typedef uint32_t pci_read_config_fn(int d, int b, int s, int f, int reg,
+    int width);
 
 int		host_pcib_get_busno(pci_read_config_fn read_config, int bus,
     int slot, int func, uint8_t *busnum);
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c
index 35710510fbbb..fa7f31c22eb3 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -74,15 +74,15 @@ 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");
 
-static uint32_t	pci_docfgregread(int bus, int slot, int func, int reg,
-		    int bytes);
+static uint32_t	pci_docfgregread(int domain, int bus, int slot, int func,
+		    int reg, int bytes);
 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
 static int	pcireg_cfgopen(void);
-static int	pciereg_cfgread(int bus, unsigned slot, unsigned func,
-		    unsigned reg, unsigned bytes);
-static void	pciereg_cfgwrite(int bus, unsigned slot, unsigned func,
-		    unsigned reg, int data, unsigned bytes);
+static int	pciereg_cfgread(int domain, int bus, unsigned slot,
+		    unsigned func, unsigned reg, unsigned bytes);
+static void	pciereg_cfgwrite(int domain, int bus, unsigned slot,
+		    unsigned func, unsigned reg, int data, unsigned bytes);
 
 /*
  * Some BIOS writers seem to want to ignore the spec and put
@@ -150,22 +150,25 @@ pci_cfgregopen(void)
 }
 
 static uint32_t
-pci_docfgregread(int bus, int slot, int func, int reg, int bytes)
+pci_docfgregread(int domain, int bus, int slot, int func, int reg, int bytes)
 {
+	if (domain == 0 && bus == 0 && (1 << slot & pcie_badslots) != 0)
+		return (pcireg_cfgread(bus, slot, func, reg, bytes));
 
 	if (cfgmech == CFGMECH_PCIE &&
-	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
-	    (bus != 0 || !(1 << slot & pcie_badslots)))
-		return (pciereg_cfgread(bus, slot, func, reg, bytes));
-	else
+	    (bus >= pcie_minbus && bus <= pcie_maxbus))
+		return (pciereg_cfgread(domain, bus, slot, func, reg, bytes));
+	else if (domain == 0)
 		return (pcireg_cfgread(bus, slot, func, reg, bytes));
+	else
+		return (-1);
 }
 
 /* 
  * Read configuration space register
  */
 u_int32_t
-pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
+pci_cfgregread(int domain, int bus, int slot, int func, int reg, int bytes)
 {
 	uint32_t line;
 
@@ -175,24 +178,29 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
 	 * the code uses 255 as an invalid IRQ.
 	 */
 	if (reg == PCIR_INTLINE && bytes == 1) {
-		line = pci_docfgregread(bus, slot, func, PCIR_INTLINE, 1);
+		line = pci_docfgregread(domain, bus, slot, func, PCIR_INTLINE,
+		    1);
 		return (pci_i386_map_intline(line));
 	}
-	return (pci_docfgregread(bus, slot, func, reg, bytes));
+	return (pci_docfgregread(domain, bus, slot, func, reg, bytes));
 }
 
 /* 
  * Write configuration space register 
  */
 void
-pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
+pci_cfgregwrite(int domain, int bus, int slot, int func, int reg, uint32_t data,
+    int bytes)
 {
+	if (domain == 0 && bus == 0 && (1 << slot & pcie_badslots) != 0) {
+		pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
+		return;
+	}
 
 	if (cfgmech == CFGMECH_PCIE &&
-	    (bus >= pcie_minbus && bus <= pcie_maxbus) &&
-	    (bus != 0 || !(1 << slot & pcie_badslots)))
-		pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
-	else
+	    (bus >= pcie_minbus && bus <= pcie_maxbus))
+		pciereg_cfgwrite(domain, bus, slot, func, reg, data, bytes);
+	else if (domain == 0)
 		pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
 }
 
@@ -505,7 +513,7 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
 			if (val1 == 0xffffffff)
 				continue;
 
-			val2 = pciereg_cfgread(0, slot, 0, 0, 4);
+			val2 = pciereg_cfgread(0, 0, slot, 0, 0, 4);
 			if (val2 != val1)
 				pcie_badslots |= (1 << slot);
 		}
@@ -569,14 +577,14 @@ pciereg_findaddr(int bus, unsigned slot, unsigned func, unsigned reg)
  */
 
 static int
-pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
+pciereg_cfgread(int domain, int bus, unsigned slot, unsigned func, unsigned reg,
     unsigned bytes)
 {
 	vm_offset_t va;
 	int data = -1;
 
-	if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX ||
-	    func > PCI_FUNCMAX || reg > PCIE_REGMAX)
+	if (domain != 0 || bus < pcie_minbus || bus > pcie_maxbus ||
+	    slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX)
 		return (-1);
 
 	critical_enter();
@@ -602,13 +610,13 @@ pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
 }
 
 static void
-pciereg_cfgwrite(int bus, unsigned slot, unsigned func, unsigned reg, int data,
-    unsigned bytes)
+pciereg_cfgwrite(int domain, int bus, unsigned slot, unsigned func,
+    unsigned reg, int data, unsigned bytes)
 {
 	vm_offset_t va;
 
-	if (bus < pcie_minbus || bus > pcie_maxbus || slot > PCI_SLOTMAX ||
-	    func > PCI_FUNCMAX || reg > PCIE_REGMAX)
+	if (domain != 0 || bus < pcie_minbus || bus > pcie_maxbus ||
+	    slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX)
 		return;
 
 	critical_enter();
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c
index b9325de01fa6..6750e85deb40 100644
--- a/sys/i386/pci/pci_pir.c
+++ b/sys/i386/pci/pci_pir.c
@@ -264,10 +264,10 @@ pci_pir_search_irq(int bus, int device, int pin)
 	uint8_t func, maxfunc;
 
 	/* See if we have a valid device at function 0. */
-	value = pci_cfgregread(bus, device, 0, PCIR_VENDOR, 2);
+	value = pci_cfgregread(0, bus, device, 0, PCIR_VENDOR, 2);
 	if (value == PCIV_INVALID)
 		return (PCI_INVALID_IRQ);
-	value = pci_cfgregread(bus, device, 0, PCIR_HDRTYPE, 1);
+	value = pci_cfgregread(0, bus, device, 0, PCIR_HDRTYPE, 1);
 	if ((value & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
 		return (PCI_INVALID_IRQ);
 	if (value & PCIM_MFDEV)
@@ -277,10 +277,10 @@ pci_pir_search_irq(int bus, int device, int pin)
 
 	/* Scan all possible functions at this device. */
 	for (func = 0; func <= maxfunc; func++) {
-		value = pci_cfgregread(bus, device, func, PCIR_VENDOR, 2);
+		value = pci_cfgregread(0, bus, device, func, PCIR_VENDOR, 2);
 		if (value == PCIV_INVALID)
 			continue;
-		value = pci_cfgregread(bus, device, func, PCIR_INTPIN, 1);
+		value = pci_cfgregread(0, bus, device, func, PCIR_INTPIN, 1);
 
 		/*
 		 * See if it uses the pin in question.  Note that the passed
@@ -289,7 +289,7 @@ pci_pir_search_irq(int bus, int device, int pin)
 		 */
 		if (value != pin + 1)
 			continue;
-		value = pci_cfgregread(bus, device, func, PCIR_INTLINE, 1);
+		value = pci_cfgregread(0, bus, device, func, PCIR_INTLINE, 1);
 		if (bootverbose)
 			printf(
 		"$PIR: Found matching pin for %d.%d.INT%c at func %d: %d\n",
diff --git a/sys/x86/include/pci_cfgreg.h b/sys/x86/include/pci_cfgreg.h
index 890d7233f658..370113b9d7bd 100644
--- a/sys/x86/include/pci_cfgreg.h
+++ b/sys/x86/include/pci_cfgreg.h
@@ -58,8 +58,8 @@ extern int cfgmech;
 rman_res_t	hostb_alloc_start(int type, rman_res_t start, rman_res_t end, rman_res_t count);
 int		pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus);
 int		pci_cfgregopen(void);
-u_int32_t	pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
-void		pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
+u_int32_t	pci_cfgregread(int domain, int bus, int slot, int func, int reg, int bytes);
+void		pci_cfgregwrite(int domain, int bus, int slot, int func, int reg, u_int32_t data, int bytes);
 #ifdef __HAVE_PIR
 void		pci_pir_open(void);
 int		pci_pir_probe(int bus, int require_parse);
diff --git a/sys/x86/iommu/intel_drv.c b/sys/x86/iommu/intel_drv.c
index ebdf24976504..aa3297fef253 100644
--- a/sys/x86/iommu/intel_drv.c
+++ b/sys/x86/iommu/intel_drv.c
@@ -969,7 +969,7 @@ dmar_path_dev(int segment, int path_len, int busno,
 		dev = pci_find_dbsf(segment, busno, path->Device,
 		    path->Function);
 		if (i != path_len - 1) {
-			busno = pci_cfgregread(busno, path->Device,
+			busno = pci_cfgregread(segment, busno, path->Device,
*** 224 LINES SKIPPED ***