Linux PCI subsystem development
 help / color / mirror / Atom feed
* [PATCH] pci: Support preferring MMCONFIG for all config space accesses
@ 2026-10-27  8:14 Josh Triplett
  2026-10-27  8:20 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Josh Triplett @ 2026-10-27  8:14 UTC (permalink / raw)
  To: Bjorn Helgaas, Jonathan Corbet, Shuah Khan, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin
  Cc: linux-pci, x86, linux-doc, linux-kernel

Even when MMCONFIG is available, PCIe currently defaults to IO-based
accesses for the first 256 bytes of config space.

IO-based accesses are serialized, and can cause substantial scalability
issues when initializing a large number of devices on a system with many
CPUs. (Those often coincide, because many systems have PCIe devices per
CPU.)

Add a `pci=prefer_mmconf` option to use MMCONFIG for all config space
accesses. Also add a Kconfig option (default n) to make that the
default, allowing a boot-time opt out with `pci=no_prefer_mmconf`.

Tested on an AWS c8i.48xlarge system, with 192 CPUs, over five boots
with and five boots without.

Without:
PCI init 266ms
Boot to minimal /init 726ms

With:
PCI init 213ms (~20% faster)
Boot to minimal /init 661ms (~9% faster)

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
---

This has come up a few times, such as in 2017:
https://lore.kernel.org/linux-pci/20170302232104.10136-2-andi@firstfloor.org/

We have even more parallel systems now than we did then, and the
performance hit from the serialized IO path hurts.

This *should* be safe everywhere. It seems exceedingly unlikely that any
systems need this. Despite that, this patch makes it `default n` out of
an abundance of caution.

I expect this to have even more impact on larger systems. I'd be
thrilled to test this on a 384-way system, if I had access to one. If
anyone at AWS would like to approve quota increase case ID
179306079200327 so I can test on a c8i.96xlarge, I'd be happy to test
that. ;)


 .../admin-guide/kernel-parameters.txt         |  5 +++
 arch/x86/Kconfig                              | 24 +++++++++++
 arch/x86/pci/common.c                         | 41 +++++++++++++++++--
 3 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index d0f174288365..64a138ea8f54 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5018,6 +5018,11 @@ Kernel parameters
 				disable the use of PCIE advanced error reporting.
 		nodomains	[PCI] Disable support for multiple PCI
 				root domains (aka PCI segments, in ACPI-speak).
+		prefer_mmconf	[X86] Prefer use of MMCONFIG even for base (<256)
+				config space accesses.
+		no_prefer_mmconf	[X86] Don't prefer use of MMCONFIG for
+				base (<256) config space accesses, even if
+				CONFIG_PCI_MMCONFIG_PREFERRED=y.
 		nommconf	[X86] Disable use of MMCONFIG for PCI
 				Configuration
 		check_enable_amd_mmconf [X86] check for and enable
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bdad90f210e4..e8f2d02562ed 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2888,6 +2888,30 @@ config PCI_MMCONFIG
 
 	  Say Y otherwise.
 
+config PCI_MMCONFIG_PREFERRED
+	bool "Prefer mmconfig for all accesses"
+	depends on PCI_MMCONFIG
+	help
+	  Use memory-mapped accesses for all PCI config space accesses where
+	  supported.
+
+	  Historically, Linux used legacy direct accesses for the first 256
+	  bytes of each device's configuration space, even if memory-mapped
+	  accesses were supported. Legacy accesses are serialized across all
+	  CPUs, so they can become a bottleneck on systems with many CPUs.
+	  Enabling this option substantially improves the scalability of PCI
+	  config space accesses.
+
+	  In the unlikely case that enabling this configuration option causes
+	  problems, you can switch it off with `pci=no_prefer_mmconf`.
+
+	  Even if this option is disabled, it can be set at boot time with
+	  `pci=prefer_mmconf`; this option just sets the default.
+
+	  You should say Y unless you have a very old system that doesn't
+	  support this. If you have a system that requires saying N here,
+	  please report it.
+
 config PCI_OLPC
 	def_bool y
 	depends on PCI && OLPC && (PCI_GOOLPC || PCI_GOANY)
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 63105b29fbf5..13e547f88d75 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -26,6 +26,13 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
 
 static int pci_bf_sort;
 int pci_routeirq;
+#ifdef CONFIG_PCI_MMCONFIG
+#ifdef CONFIG_PCI_MMCONFIG_PREFERRED
+static int pci_prefer_mmconf = 1;
+#else
+static int pci_prefer_mmconf;
+#endif
+#endif /* #ifdef CONFIG_PCI_MMCONFIG */
 int noioapicquirk;
 #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 int noioapicreroute = 0;
@@ -40,9 +47,20 @@ const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
 int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
 						int reg, int len, u32 *val)
 {
+	bool tried_mmconf = false;
+
+#ifdef CONFIG_PCI_MMCONFIG
+	if (pci_prefer_mmconf && raw_pci_ext_ops == &pci_mmcfg) {
+		int ret = raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
+
+		if (ret != -EINVAL)
+			return ret;
+		tried_mmconf = true;
+	}
+#endif
 	if (domain == 0 && reg < 256 && raw_pci_ops)
 		return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
-	if (raw_pci_ext_ops)
+	if (!tried_mmconf && raw_pci_ext_ops)
 		return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
 	return -EINVAL;
 }
@@ -50,9 +68,20 @@ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
 int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
 						int reg, int len, u32 val)
 {
+	bool tried_mmconf = false;
+
+#ifdef CONFIG_PCI_MMCONFIG
+	if (pci_prefer_mmconf && raw_pci_ext_ops == &pci_mmcfg) {
+		int ret = raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
+
+		if (ret != -EINVAL)
+			return ret;
+		tried_mmconf = true;
+	}
+#endif
 	if (domain == 0 && reg < 256 && raw_pci_ops)
 		return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
-	if (raw_pci_ext_ops)
+	if (!tried_mmconf && raw_pci_ext_ops)
 		return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
 	return -EINVAL;
 }
@@ -551,7 +580,13 @@ char *__init pcibios_setup(char *str)
 	}
 #endif
 #ifdef CONFIG_PCI_MMCONFIG
-	else if (!strcmp(str, "nommconf")) {
+	else if (!strcmp(str, "prefer_mmconf")) {
+		pci_prefer_mmconf = 1;
+		return NULL;
+	} else if (!strcmp(str, "no_prefer_mmconf")) {
+		pci_prefer_mmconf = 0;
+		return NULL;
+	} else if (!strcmp(str, "nommconf")) {
 		pci_probe &= ~PCI_PROBE_MMCONF;
 		return NULL;
 	}
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] pci: Support preferring MMCONFIG for all config space accesses
  2026-10-27  8:14 [PATCH] pci: Support preferring MMCONFIG for all config space accesses Josh Triplett
@ 2026-10-27  8:20 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-27  8:20 UTC (permalink / raw)
  To: Josh Triplett; +Cc: linux-pci

> Even when MMCONFIG is available, PCIe currently defaults to IO-based
> accesses for the first 256 bytes of config space.
> 
> IO-based accesses are serialized, and can cause substantial scalability
> issues when initializing a large number of devices on a system with many
> CPUs. (Those often coincide, because many systems have PCIe devices per
> CPU.)
> 
> Add a `pci=prefer_mmconf` option to use MMCONFIG for all config space
> accesses. Also add a Kconfig option (default n) to make that the
> default, allowing a boot-time opt out with `pci=no_prefer_mmconf`.
> 
> Tested on an AWS c8i.48xlarge system, with 192 CPUs, over five boots
> with and five boots without.
> 
> Without:
> PCI init 266ms
> Boot to minimal /init 726ms
> 
> With:
> PCI init 213ms (~20% faster)
> Boot to minimal /init 661ms (~9% faster)
> 
> Signed-off-by: Josh Triplett <josh@joshtriplett.org>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/a7d2b402784a409f5564c1fdce77a41e09f29280.1793087687.git.josh@joshtriplett.org?part=1


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-27  8:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27  8:14 [PATCH] pci: Support preferring MMCONFIG for all config space accesses Josh Triplett
2026-10-27  8:20 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox