dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Atharva Tiwari" <atharvatiwarilinuxdev@gmail.com>
Cc: "open list:PCI SUBSYSTEM" <linux-pci@vger.kernel.org>,
	"open list:DRM DRIVERS" <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 02/13] PCI: Disable pcie port and access on D3 on specific amd devices
Date: Sun, 25 Oct 2026 04:34:49 +0000	[thread overview]
Message-ID: <sashiko-outbox-184069@kernel.org> (raw)
In-Reply-To: <20261025040046.1602-3-atharvatiwarilinuxdev@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] PCI: uninitialized *val in pci_read_config_*() when ignoring D3cold access
- [Critical] PCI: pci_user_read_config_*() and cap walks bypass pci_dev_ignore_access()
- [High] PCI: missing 0x7360 fixup in quirk_disable_pcie_port() for MacBookPro16,4
--

commit f3d5ededdfe7b0bad0fd200b82a9eb2e3e834ed0
Author: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>

PCI: Disable pcie port and access on D3 on specific amd devices

This commit adds an early PCI fixup for Apple MacBookPro16,1 and
MacBookPro16,4 systems to disable the PCIe port driver and ignore config
space accesses on upstream bridges of the discrete GPU when those bridges
are in D3cold.

> diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
> index 795d81c7a4de4..66829941e8fe2 100644
> --- a/arch/x86/pci/fixup.c
> +++ b/arch/x86/pci/fixup.c
> @@ -1094,6 +1094,35 @@ static void asus_disable_nvme_d3cold(struct pci_dev *pdev)
>  }
>  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x9a09, asus_disable_nvme_d3cold);
>  
> +static const struct dmi_system_id quirk_disable_pcie_port_dmi_table[] = {
> +	{
> +		.matches = {
> +			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
> +			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,1"),
> +		},
> +	},
> +	{
> +		.matches = {
> +			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
> +			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4"),
> +		},
> +	},
> +	{}
> +};
> +
> +static void quirk_disable_pcie_port(struct pci_dev *pdev)
> +{
> +	struct pci_dev *upstream = pdev;
> +
> +	if (dmi_check_system(quirk_disable_pcie_port_dmi_table)) {
> +		while ((upstream = pci_upstream_bridge(upstream))) {
> +			upstream->no_pcie_port = 1;
> +			upstream->ignore_access_d3 = 1;
> +		}
> +	}
> +}
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7340, quirk_disable_pcie_port);

[Severity: High]
While quirk_disable_pcie_port_dmi_table in arch/x86/pci/fixup.c matches both
MacBookPro16,1 and MacBookPro16,4, DECLARE_PCI_FIXUP_EARLY is only registered
for PCI device ID 0x7340 (Navi 14, used in MacBookPro16,1).

MacBookPro16,4 uses the AMD Radeon Pro 5600M (Navi 12, PCI device ID 0x7360).
Without a matching fixup registration for 0x7360, will
quirk_disable_pcie_port() ever run on MacBookPro16,4, or will its upstream
bridges remain unprotected when apple-gmux powers them off?

[ ... ]

> diff --git a/drivers/pci/access.c b/drivers/pci/access.c
> index b123da16b63ba..5e95130671767 100644
> --- a/drivers/pci/access.c
> +++ b/drivers/pci/access.c
> @@ -559,6 +559,9 @@ EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
>  
>  int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
>  {
> +	if (pci_dev_ignore_access(dev))
> +		return PCIBIOS_SUCCESSFUL;
> +
>  	if (pci_dev_is_disconnected(dev)) {
>  		PCI_SET_ERROR_RESPONSE(val);
>  		return PCIBIOS_DEVICE_NOT_FOUND;
> @@ -569,6 +572,9 @@ EXPORT_SYMBOL(pci_read_config_byte);
>  
>  int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
>  {
> +	if (pci_dev_ignore_access(dev))
> +		return PCIBIOS_SUCCESSFUL;
> +
>  	if (pci_dev_is_disconnected(dev)) {
>  		PCI_SET_ERROR_RESPONSE(val);
>  		return PCIBIOS_DEVICE_NOT_FOUND;
> @@ -580,6 +586,9 @@ EXPORT_SYMBOL(pci_read_config_word);
>  int pci_read_config_dword(const struct pci_dev *dev, int where,
>  					u32 *val)
>  {
> +	if (pci_dev_ignore_access(dev))
> +		return PCIBIOS_SUCCESSFUL;
> +
>  	if (pci_dev_is_disconnected(dev)) {
>  		PCI_SET_ERROR_RESPONSE(val);
>  		return PCIBIOS_DEVICE_NOT_FOUND;

[Severity: Critical]
When pci_dev_ignore_access(dev) is true for a bridge in PCI_D3cold,
pci_read_config_byte(), pci_read_config_word(), and pci_read_config_dword()
in drivers/pci/access.c return PCIBIOS_SUCCESSFUL (0) without initializing
*val.

Many callers pass an uninitialized stack variable and rely on either a
non-zero return value or PCI_SET_ERROR_RESPONSE(val) (0xff / 0xffff /
0xffffffff) when the device cannot be read.

For example, in drivers/pci/pci-sysfs.c, secondary_bus_number_show() and
subordinate_bus_number_show() read world-readable sysfs attributes into
uninitialized stack variables:

drivers/pci/pci-sysfs.c:secondary_bus_number_show() {
	struct pci_dev *pci_dev = to_pci_dev(dev);
	u8 sec_bus;
	int err;

	pci_config_pm_runtime_get(pci_dev);
	err = pci_read_config_byte(pci_dev, PCI_SECONDARY_BUS, &sec_bus);
	pci_config_pm_runtime_put(pci_dev);

	if (err)
		return -EINVAL;

	return sysfs_emit(buf, "%u\n", sec_bus);
}

In addition, pci_update_current_state() and pci_power_up() in
drivers/pci/pci.c read PCI_PM_CTRL into an uninitialized stack variable
pmcsr and check PCI_POSSIBLE_ERROR(pmcsr):

drivers/pci/pci.c:pci_update_current_state() {
	...
	} else if (dev->pm_cap) {
		u16 pmcsr;

		pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
		if (PCI_POSSIBLE_ERROR(pmcsr)) {
			dev->current_state = PCI_D3cold;
			return;
		}
		dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK;
	}
}

If pmcsr happens not to be 0xffff on the stack, dev->current_state is
overwritten with D0..D3hot (or set to PCI_D0 in pci_power_up()), which
disarms pci_dev_ignore_access(dev) while the bridge is still powered off.
Similarly, during suspend on the driverless bridge,
pci_pm_suspend_noirq() -> pci_save_state() -> pci_save_pcie_state() ->
pcie_capability_read_word() will see PCIBIOS_SUCCESSFUL with *val == 0 and
overwrite the bridge's saved PCIe capability state with zeros.

Should pci_read_config_byte(), pci_read_config_word(), and
pci_read_config_dword() call PCI_SET_ERROR_RESPONSE(val) and return an error
such as PCIBIOS_DEVICE_NOT_FOUND (matching pci_dev_is_disconnected(dev)), or
otherwise ensure *val is never left uninitialized?

> @@ -590,6 +599,9 @@ EXPORT_SYMBOL(pci_read_config_dword);
>  
>  int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
>  {
> +	if (pci_dev_ignore_access(dev))
> +		return PCIBIOS_SUCCESSFUL;
> +
>  	if (pci_dev_is_disconnected(dev))
>  		return PCIBIOS_DEVICE_NOT_FOUND;
>  	return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
> @@ -598,6 +610,9 @@ EXPORT_SYMBOL(pci_write_config_byte);
>  
>  int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
>  {
> +	if (pci_dev_ignore_access(dev))
> +		return PCIBIOS_SUCCESSFUL;
> +
>  	if (pci_dev_is_disconnected(dev))
>  		return PCIBIOS_DEVICE_NOT_FOUND;
>  	return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
> @@ -607,6 +622,9 @@ EXPORT_SYMBOL(pci_write_config_word);
>  int pci_write_config_dword(const struct pci_dev *dev, int where,
>  					 u32 val)
>  {
> +	if (pci_dev_ignore_access(dev))
> +		return PCIBIOS_SUCCESSFUL;
> +
>  	if (pci_dev_is_disconnected(dev))
>  		return PCIBIOS_DEVICE_NOT_FOUND;
>  	return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);

[Severity: Critical]
Does restricting only pci_read_config_*() and pci_write_config_*() in
drivers/pci/access.c leave other config space access paths unprotected when
the bridge is in PCI_D3cold?

Userspace config reads and writes via sysfs (pci_read_config() and
pci_write_config() in drivers/pci/pci-sysfs.c) and procfs (drivers/pci/proc.c)
call pci_user_read_config_*() and pci_user_write_config_*(), which are
generated by PCI_USER_READ_CONFIG and PCI_USER_WRITE_CONFIG in
drivers/pci/access.c:

drivers/pci/access.c:PCI_USER_READ_CONFIG() {
	...
	raw_spin_lock_irq(&pci_lock);
	if (unlikely(dev->block_cfg_access))
		pci_wait_cfg(dev);
	ret = dev->bus->ops->read(dev->bus, dev->devfn,
				  pos, sizeof(type), &data);
	raw_spin_unlock_irq(&pci_lock);
	...
}

Because dev->no_pcie_port = 1 prevents pcie_portdrv_probe() from binding to
the upstream bridges, runtime PM is not enabled on them and
pci_config_pm_runtime_get() in pci_read_config() is a no-op. Any unprivileged
process (such as lspci or udev) reading /sys/bus/pci/devices/.../config while
the bridge is powered off in PCI_D3cold will invoke dev->bus->ops->read()
directly on the dead bridge.

In addition, capability walks in drivers/pci/pci.c (pci_find_capability() ->
__pci_bus_find_cap_start(), pci_find_next_capability(), and
pci_find_next_ext_capability()) call pci_bus_read_config_*() directly rather
than pci_read_config_*(). Because the bridge has no bound driver (pm == NULL),
during system suspend pci_pm_suspend_noirq() in drivers/pci/pci-driver.c
runs:

  pci_pm_suspend_noirq()
    -> pci_save_state()
      -> pci_save_pcix_state()
        -> pci_find_capability(dev, PCI_CAP_ID_PCIX)
          -> __pci_bus_find_cap_start()
            -> pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status)

Could these paths still access the powered-off bridge and trigger a hardware
crash unless PCI_USER_READ_CONFIG, PCI_USER_WRITE_CONFIG, and the capability
lookup paths (or a lower layer) also check pci_dev_ignore_access(dev)?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261025040046.1602-1-atharvatiwarilinuxdev@gmail.com?part=2

  reply	other threads:[~2026-10-25  4:35 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-25  3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
2026-10-25  3:59 ` [PATCH 01/13] platform/apple-gmux: Fix power for MMIO systems Atharva Tiwari
2026-10-25  4:49   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 02/13] PCI: Disable pcie port and access on D3 on specific amd devices Atharva Tiwari
2026-10-25  4:34   ` sashiko-bot [this message]
2026-10-25  3:59 ` [PATCH 03/13] platform/apple-gmux: Fix MMIO interface Atharva Tiwari
2026-10-25  4:27   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 04/13] platform/apple-gmux: Fix Interrupts for MMIO systems Atharva Tiwari
2026-10-25  4:39   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 05/13] platform/apple-gmux: Write switch state to EFI on MMIO devices Atharva Tiwari
2026-10-25  4:36   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 06/13] platform/apple-gmux: Add parameter to configure boot gpu Atharva Tiwari
2026-10-25  4:33   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 07/13] platform/apple-gmux: Add check to detect FSS Atharva Tiwari
2026-10-25  3:59 ` [PATCH 08/13] platform/apple-gmux: Add documentation about iMacs Atharva Tiwari
2026-10-25  4:37   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 09/13] drm/amdgpu: Add Apple GMUX runtime PM support Atharva Tiwari
2026-10-25  5:56   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 10/13] drm/amdgpu: Catch register access while GMUX keeps the GPU off Atharva Tiwari
2026-10-25  4:40   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 11/13] drm/amd/display: Refuse DP AUX " Atharva Tiwari
2026-10-25  4:41   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 12/13] drm/amdgpu: Skip AC/DC notification while the GPU is runtime suspended Atharva Tiwari
2026-10-25  4:43   ` sashiko-bot
2026-10-25  3:59 ` [PATCH 13/13] drm/amd/display: Skip panel power savings on eDP links without a panel Atharva Tiwari
2026-10-25  4:30   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-184069@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=atharvatiwarilinuxdev@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox