* [PATCH 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR
@ 2026-05-05 17:00 Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-05-05 17:00 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe, Marcin Bernatowicz
PF drivers can resize a VF BAR using VF Resizable BAR (ReBAR) support via
pci_iov_vf_bar_set_size(). The new size persists in the SR-IOV capability
config space. A later reprobe / unplug-rescan / next pci_enable_sriov()
then sees the inflated VF BAR registers, and the PCI core reserves MMIO
based on that size multiplied by TotalVFs.
On platforms with tight apertures, this can make subsequent SR-IOV enable
fail due to lack of address space.
This series records the initial per-VF BAR sizes during SR-IOV init and
restores those sizes when SR-IOV is disabled, when SR-IOV enable fails,
or when the PF driver is unbound.
Note on user-visible behavior: drivers that rely on a resized VF BAR
persisting across an enable/disable cycle must now call
pci_iov_vf_bar_set_size() again before each pci_enable_sriov().
Marcin Bernatowicz (3):
PCI/IOV: Remember initial VF BAR sizes
PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
PCI/IOV: Restore initial VF ReBAR sizes on PF release
drivers/pci/iov.c | 64 +++++++++++++++++++++++++++++++++++++++++------
drivers/pci/pci.h | 3 ++-
2 files changed, 59 insertions(+), 8 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/3] PCI/IOV: Remember initial VF BAR sizes
2026-05-05 17:00 [PATCH 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
@ 2026-05-05 17:00 ` Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
` (2 subsequent siblings)
3 siblings, 0 replies; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-05-05 17:00 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe, Marcin Bernatowicz
SR-IOV initialization records the per-VF BAR sizes derived from the VF
BAR registers in the SR-IOV capability.
PF drivers may later change VF BAR sizes using VF Resizable BAR support
(pci_iov_vf_bar_set_size()). Save the initial per-VF BAR sizes so later
code can restore them when SR-IOV is disabled, when SR-IOV enable fails,
or when the PF driver is unbound while VF BARs are still resized.
The initial size is captured before the resource is multiplied by
TotalVFs, so it represents one VF's BAR size as advertised by hardware.
No functional change on its own.
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
drivers/pci/iov.c | 1 +
drivers/pci/pci.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 30ca4535fc36..19f4dca4eec1 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -869,6 +869,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
goto failed;
}
iov->barsz[i] = resource_size(res);
+ iov->barsz_orig[i] = iov->barsz[i];
resource_set_size(res, resource_size(res) * total);
pci_info(dev, "%s %pR: contains BAR %d for %d VFs\n",
res_name, res, i, total);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 19660d068fb7..441ef5b4ddc2 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -670,7 +670,8 @@ struct pci_sriov {
u8 hdr_type; /* VF header type */
u16 subsystem_vendor; /* VF subsystem vendor */
u16 subsystem_device; /* VF subsystem device */
- resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
+ resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* Current VF BAR size */
+ resource_size_t barsz_orig[PCI_SRIOV_NUM_BARS]; /* Initial VF BAR size at probe */
u16 vf_rebar_cap; /* VF Resizable BAR capability offset */
bool drivers_autoprobe; /* Auto probing of VFs by driver */
};
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
2026-05-05 17:00 [PATCH 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
@ 2026-05-05 17:00 ` Marcin Bernatowicz
2026-05-05 20:36 ` sashiko-bot
2026-05-05 17:00 ` [PATCH 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF release Marcin Bernatowicz
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
3 siblings, 1 reply; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-05-05 17:00 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe, Marcin Bernatowicz
PF drivers can resize a VF BAR via pci_iov_vf_bar_set_size(). The new
size persists in config space. A subsequent reprobe/unplug-rescan may
then cause the PCI core to reserve MMIO based on the inflated VF BAR
registers in the SR-IOV capability, often multiplied by TotalVFs.
On platforms with tight apertures, later SR-IOV enable can fail due to
lack of space.
Restore the initial VF BAR sizes saved at SR-IOV init time when SR-IOV
is disabled and when SR-IOV enable fails. Restore is only performed
when VF Memory Space is disabled, which is the precondition of
pci_iov_vf_bar_set_size() and is true at all the new call sites.
Note: this changes user-visible behavior for drivers that rely on the
resized VF BAR persisting across an enable/disable cycle. After this
change drivers must call pci_iov_vf_bar_set_size() before each
pci_enable_sriov() if a non-default size is desired.
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5937
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
drivers/pci/iov.c | 61 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 54 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 19f4dca4eec1..42b935265b3c 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -646,6 +646,40 @@ static int sriov_add_vfs(struct pci_dev *dev, u16 num_vfs)
return rc;
}
+static void sriov_restore_vf_rebar_initial_sizes(struct pci_dev *dev)
+{
+ struct pci_sriov *iov = dev->sriov;
+ int i;
+
+ if (!iov || !iov->vf_rebar_cap)
+ return;
+
+ for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+ int resno = pci_resource_num_from_vf_bar(i);
+ resource_size_t orig_sz = iov->barsz_orig[i];
+ resource_size_t cur_sz = iov->barsz[i];
+ int size, cur, rc;
+
+ if (!orig_sz || cur_sz == orig_sz)
+ continue;
+
+ size = pci_rebar_bytes_to_size(orig_sz);
+ rc = pci_iov_vf_bar_set_size(dev, resno, size);
+ if (!rc)
+ continue;
+
+ pci_warn(dev, "failed to restore %s size %#llx -> %#llx: %d\n",
+ pci_resource_name(dev, resno),
+ (unsigned long long)cur_sz,
+ (unsigned long long)orig_sz, rc);
+
+ /* Re-sync in-memory size with what hardware actually has. */
+ cur = pci_rebar_get_current_size(dev, resno);
+ if (cur >= 0)
+ iov->barsz[i] = pci_rebar_size_to_bytes(cur);
+ }
+}
+
static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
{
int rc;
@@ -687,36 +721,42 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
}
if (nres != iov->nres) {
pci_err(dev, "not enough MMIO resources for SR-IOV\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_restore;
}
bus = pci_iov_virtfn_bus(dev, nr_virtfn - 1);
if (bus > dev->bus->busn_res.end) {
pci_err(dev, "can't enable %d VFs (bus %02x out of range of %pR)\n",
nr_virtfn, bus, &dev->bus->busn_res);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_restore;
}
if (pci_enable_resources(dev, bars)) {
pci_err(dev, "SR-IOV: IOV BARS not allocated\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_restore;
}
if (iov->link != dev->devfn) {
pdev = pci_get_slot(dev->bus, iov->link);
- if (!pdev)
- return -ENODEV;
+ if (!pdev) {
+ rc = -ENODEV;
+ goto err_restore;
+ }
if (!pdev->is_physfn) {
pci_dev_put(pdev);
- return -ENOSYS;
+ rc = -ENOSYS;
+ goto err_restore;
}
rc = sysfs_create_link(&dev->dev.kobj,
&pdev->dev.kobj, "dep_link");
pci_dev_put(pdev);
if (rc)
- return rc;
+ goto err_restore;
}
iov->initial_VFs = initial;
@@ -758,6 +798,12 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
pci_iov_set_numvfs(dev, 0);
+ sriov_restore_vf_rebar_initial_sizes(dev);
+ return rc;
+
+err_restore:
+ /* pcibios_sriov_enable() was not called on these early-exit paths. */
+ sriov_restore_vf_rebar_initial_sizes(dev);
return rc;
}
@@ -791,6 +837,7 @@ static void sriov_disable(struct pci_dev *dev)
iov->num_VFs = 0;
pci_iov_set_numvfs(dev, 0);
+ sriov_restore_vf_rebar_initial_sizes(dev);
}
static int sriov_init(struct pci_dev *dev, int pos)
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF release
2026-05-05 17:00 [PATCH 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
@ 2026-05-05 17:00 ` Marcin Bernatowicz
2026-05-05 21:17 ` sashiko-bot
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
3 siblings, 1 reply; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-05-05 17:00 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe, Marcin Bernatowicz
sriov_disable() and sriov_enable() error paths restore the per-VF BAR
sizes saved at probe time. They do not cover the case where the PF
driver is unbound while VF BARs were resized but SR-IOV was never
enabled (or was already disabled).
On the next bind, sriov_init() re-reads the SR-IOV capability and
captures the current (inflated) BAR registers as the new initial sizes
in iov->barsz_orig[]. The restore logic becomes a no-op for that boot
and the kernel may reserve MMIO for the inflated VF aperture multiplied
by TotalVFs.
Restore the initial sizes from sriov_release() as well. At this point
num_VFs is 0 (BUG_ON enforces it) and VF Memory Space is therefore
disabled, satisfying the precondition of pci_iov_vf_bar_set_size().
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
drivers/pci/iov.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 42b935265b3c..d9e745e23add 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -969,6 +969,8 @@ static void sriov_release(struct pci_dev *dev)
{
BUG_ON(dev->sriov->num_VFs);
+ sriov_restore_vf_rebar_initial_sizes(dev);
+
if (dev != dev->sriov->dev)
pci_dev_put(dev->sriov->dev);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
2026-05-05 17:00 ` [PATCH 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
@ 2026-05-05 20:36 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-05 20:36 UTC (permalink / raw)
To: Marcin Bernatowicz; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Early error returns in sriov_enable() bypass the newly introduced sriov_restore_vf_rebar_initial_sizes() cleanup.
--
commit 4da183a318507a36de3ca157ee8755ad1eec90ca
Author: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
This commit introduces a mechanism to restore the initial VF BAR sizes when
SR-IOV is disabled or when enabling it fails. This prevents the PCI core
from persisting inflated VF BAR sizes, which can lead to MMIO space exhaustion.
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5937
> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> index 217e133a38c73..a05c1be388d2f 100644
> --- a/drivers/pci/iov.c
> +++ b/drivers/pci/iov.c
[ ... ]
> @@ -687,36 +721,42 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
> }
> if (nres != iov->nres) {
> pci_err(dev, "not enough MMIO resources for SR-IOV\n");
> - return -ENOMEM;
> + rc = -ENOMEM;
> + goto err_restore;
> }
Should the earlier error returns in sriov_enable() also jump to err_restore?
There are early validation checks before this point that return directly:
drivers/pci/iov.c:sriov_enable() {
...
pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
if (initial > iov->total_VFs ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
return -EIO;
if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
return -EINVAL;
...
}
If an early exit occurs here, the hardware BAR remains inflated and
iov->num_VFs remains 0.
Because iov->num_VFs is 0, subsequent cleanup calls like pci_disable_sriov()
during driver teardown or system shutdown will bypass the restore logic due to
the early return in sriov_disable():
drivers/pci/iov.c:sriov_disable() {
struct pci_sriov *iov = dev->sriov;
if (!iov->num_VFs)
return;
...
}
Will this leave the hardware BAR permanently inflated across kexec or warm
reboots, potentially leading to the MMIO space exhaustion this patch aims to
fix?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260505170010.3414074-1-marcin.bernatowicz@linux.intel.com?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF release
2026-05-05 17:00 ` [PATCH 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF release Marcin Bernatowicz
@ 2026-05-05 21:17 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-05-05 21:17 UTC (permalink / raw)
To: Marcin Bernatowicz; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unsafe hardware configuration writes during kobject .release callback and incorrect lifecycle hook.
--
commit b1af88a89dd13b3ede54e65628a75befe1b43cf4
Author: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
PCI/IOV: Restore initial VF ReBAR sizes on PF release
This commit attempts to restore the per-VF BAR sizes to their initial
values when sriov_release() is called. It aims to handle the case where
VF BARs were resized but SR-IOV was not enabled when the PF driver is
unbound.
> sriov_disable() and sriov_enable() error paths restore the per-VF BAR
> sizes saved at probe time. They do not cover the case where the PF
> driver is unbound while VF BARs were resized but SR-IOV was never
> enabled (or was already disabled).
>
> On the next bind, sriov_init() re-reads the SR-IOV capability and
> captures the current (inflated) BAR registers as the new initial sizes
> in iov->barsz_orig[]. The restore logic becomes a no-op for that boot
> and the kernel may reserve MMIO for the inflated VF aperture multiplied
> by TotalVFs.
Is sriov_release() the correct place for this restoration?
The commit message states it covers when the PF driver is unbound and mentions
the next bind, but sriov_release() is called by pci_release_dev() which is
the kobject .release callback.
This executes when the pci_dev reference count drops to 0 (such as during
device destruction), not during a driver unbind via sysfs. Furthermore,
sriov_init() is called during device enumeration, not driver bind.
> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> index a05c1be388d2f..794f956910886 100644
> --- a/drivers/pci/iov.c
> +++ b/drivers/pci/iov.c
> @@ -969,6 +969,8 @@ static void sriov_release(struct pci_dev *dev)
> {
> BUG_ON(dev->sriov->num_VFs);
>
> + sriov_restore_vf_rebar_initial_sizes(dev);
Is it safe to access the hardware configuration space here?
Since sriov_release() executes as a .release callback, it can run at an
arbitrary time, such as being delayed indefinitely by an open sysfs file
descriptor.
If the device has been surprise-removed or placed in D3cold (suspended), won't
PCIe config space reads return ~0 (0xFFFF)?
In that case, pci_iov_is_memory_decoding_enabled() would evaluate
0xFFFF & PCI_SRIOV_CTRL_MSE as true, causing pci_iov_vf_bar_set_size() to
return -EBUSY.
This could trigger a pci_warn() in sriov_restore_vf_rebar_initial_sizes() for
every resized VF BAR, spamming the kernel log with false-positive warnings, and
potentially causing PCIe Unsupported Requests or bus errors.
> +
> if (dev != dev->sriov->dev)
> pci_dev_put(dev->sriov->dev);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260505170010.3414074-1-marcin.bernatowicz@linux.intel.com?part=3
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR
2026-05-05 17:00 [PATCH 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
` (2 preceding siblings ...)
2026-05-05 17:00 ` [PATCH 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF release Marcin Bernatowicz
@ 2026-08-03 10:30 ` Marcin Bernatowicz
2026-08-03 10:30 ` [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
` (3 more replies)
3 siblings, 4 replies; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-08-03 10:30 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe
PF drivers can resize a VF BAR using VF Resizable BAR (ReBAR) support via
pci_iov_vf_bar_set_size(). The new size persists in the SR-IOV capability
config space. A later reprobe / unplug-rescan / next pci_enable_sriov()
then sees the inflated VF BAR registers, and the PCI core reserves MMIO
based on that size multiplied by TotalVFs.
On platforms with tight apertures, this can make subsequent SR-IOV enable
fail due to lack of address space.
This series records the initial per-VF BAR sizes during SR-IOV init and
restores those sizes when SR-IOV is disabled, when SR-IOV enable fails,
or when the PF driver is detached.
Note on user-visible behavior: drivers that rely on a resized VF BAR
persisting across an enable/disable cycle must now call
pci_iov_vf_bar_set_size() again before each pci_enable_sriov().
v1 -> v2:
- Addressed sashiko-bot feedback.
- Restore VF BAR sizes on early sriov_enable() validation failures too.
- Move the detach-time restore from sriov_release() to pci_iov_remove().
Marcin Bernatowicz (3):
PCI/IOV: Remember initial VF BAR sizes
PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove
drivers/pci/iov.c | 86 ++++++++++++++++++++++++++++++++++++++++-------
drivers/pci/pci.h | 3 +-
2 files changed, 76 insertions(+), 13 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
@ 2026-08-03 10:30 ` Marcin Bernatowicz
2026-08-03 10:41 ` sashiko-bot
2026-08-03 10:30 ` [PATCH v2 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
` (2 subsequent siblings)
3 siblings, 1 reply; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-08-03 10:30 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe
SR-IOV initialization records the per-VF BAR sizes derived from the VF
BAR registers in the SR-IOV capability.
PF drivers may later change VF BAR sizes using VF Resizable BAR support
(pci_iov_vf_bar_set_size()). Save the initial per-VF BAR sizes so later
code can restore them when SR-IOV is disabled, when SR-IOV enable fails,
or when the PF driver is unbound while VF BARs are still resized.
The initial size is captured before the resource is multiplied by
TotalVFs, so it represents one VF's BAR size as advertised by hardware.
No functional change on its own.
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
drivers/pci/iov.c | 1 +
drivers/pci/pci.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index b0d24839c084..ae9309fc6dd7 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -869,6 +869,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
goto failed;
}
iov->barsz[i] = resource_size(res);
+ iov->barsz_orig[i] = iov->barsz[i];
resource_set_size(res, resource_size(res) * total);
pci_info(dev, "%s %pR: contains BAR %d for %d VFs\n",
res_name, res, i, total);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 68b5fb675d1c..71c0d9fe5524 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -713,7 +713,8 @@ struct pci_sriov {
u8 hdr_type; /* VF header type */
u16 subsystem_vendor; /* VF subsystem vendor */
u16 subsystem_device; /* VF subsystem device */
- resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
+ resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* Current VF BAR size */
+ resource_size_t barsz_orig[PCI_SRIOV_NUM_BARS]; /* Initial VF BAR size at probe */
u16 vf_rebar_cap; /* VF Resizable BAR capability offset */
bool drivers_autoprobe; /* Auto probing of VFs by driver */
};
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
2026-08-03 10:30 ` [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
@ 2026-08-03 10:30 ` Marcin Bernatowicz
2026-08-03 10:46 ` sashiko-bot
2026-08-03 10:30 ` [PATCH v2 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove Marcin Bernatowicz
2026-08-03 11:17 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Simon Richter
3 siblings, 1 reply; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-08-03 10:30 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe
PF drivers can resize a VF BAR via pci_iov_vf_bar_set_size(). The new
size persists in config space. A subsequent reprobe/unplug-rescan may
then cause the PCI core to reserve MMIO based on the inflated VF BAR
registers in the SR-IOV capability, often multiplied by TotalVFs.
On platforms with tight apertures, later SR-IOV enable can fail due to
lack of space.
Restore the initial VF BAR sizes saved at SR-IOV init time when SR-IOV
is disabled and when SR-IOV enable fails. This covers both the resource
allocation failures later in sriov_enable() and the earlier validation
failures that can otherwise leave a resized VF BAR in hardware while
num_VFs remains zero.
Restore is only performed when VF Memory Space is disabled, which is the
precondition of pci_iov_vf_bar_set_size() and is true at all the new
call sites.
Note: this changes user-visible behavior for drivers that rely on the
resized VF BAR persisting across an enable/disable cycle. After this
change drivers must call pci_iov_vf_bar_set_size() before each
pci_enable_sriov() if a non-default size is desired.
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5937
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
drivers/pci/iov.c | 79 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 68 insertions(+), 11 deletions(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index ae9309fc6dd7..999938163ce9 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -646,6 +646,46 @@ static int sriov_add_vfs(struct pci_dev *dev, u16 num_vfs)
return rc;
}
+static void sriov_restore_vf_rebar_initial_sizes(struct pci_dev *dev)
+{
+ struct pci_sriov *iov = dev->sriov;
+ u16 ctrl;
+ int i;
+
+ if (!iov || !iov->vf_rebar_cap)
+ return;
+
+ /* Skip if device is inaccessible (surprise-removed, D3cold). */
+ pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &ctrl);
+ if (PCI_POSSIBLE_ERROR(ctrl))
+ return;
+
+ for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+ int resno = pci_resource_num_from_vf_bar(i);
+ resource_size_t orig_sz = iov->barsz_orig[i];
+ resource_size_t cur_sz = iov->barsz[i];
+ int size, cur, rc;
+
+ if (!orig_sz || cur_sz == orig_sz)
+ continue;
+
+ size = pci_rebar_bytes_to_size(orig_sz);
+ rc = pci_iov_vf_bar_set_size(dev, resno, size);
+ if (!rc)
+ continue;
+
+ pci_warn(dev, "failed to restore %s size %#llx -> %#llx: %d\n",
+ pci_resource_name(dev, resno),
+ (unsigned long long)cur_sz,
+ (unsigned long long)orig_sz, rc);
+
+ /* Re-sync in-memory size with what hardware actually has. */
+ cur = pci_rebar_get_current_size(dev, resno);
+ if (cur >= 0)
+ iov->barsz[i] = pci_rebar_size_to_bytes(cur);
+ }
+}
+
static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
{
int rc;
@@ -666,12 +706,16 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
if (initial > iov->total_VFs ||
- (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
- return -EIO;
+ (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs))) {
+ rc = -EIO;
+ goto err_restore;
+ }
if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
- (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
- return -EINVAL;
+ (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) {
+ rc = -EINVAL;
+ goto err_restore;
+ }
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
@@ -687,36 +731,42 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
}
if (nres != iov->nres) {
pci_err(dev, "not enough MMIO resources for SR-IOV\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_restore;
}
bus = pci_iov_virtfn_bus(dev, nr_virtfn - 1);
if (bus > dev->bus->busn_res.end) {
pci_err(dev, "can't enable %d VFs (bus %02x out of range of %pR)\n",
nr_virtfn, bus, &dev->bus->busn_res);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_restore;
}
if (pci_enable_resources(dev, bars)) {
pci_err(dev, "SR-IOV: IOV BARS not allocated\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_restore;
}
if (iov->link != dev->devfn) {
pdev = pci_get_slot(dev->bus, iov->link);
- if (!pdev)
- return -ENODEV;
+ if (!pdev) {
+ rc = -ENODEV;
+ goto err_restore;
+ }
if (!pdev->is_physfn) {
pci_dev_put(pdev);
- return -ENOSYS;
+ rc = -ENOSYS;
+ goto err_restore;
}
rc = sysfs_create_link(&dev->dev.kobj,
&pdev->dev.kobj, "dep_link");
pci_dev_put(pdev);
if (rc)
- return rc;
+ goto err_restore;
}
iov->initial_VFs = initial;
@@ -758,6 +808,12 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
pci_iov_set_numvfs(dev, 0);
+ sriov_restore_vf_rebar_initial_sizes(dev);
+ return rc;
+
+err_restore:
+ /* pcibios_sriov_enable() was not called on these early-exit paths. */
+ sriov_restore_vf_rebar_initial_sizes(dev);
return rc;
}
@@ -791,6 +847,7 @@ static void sriov_disable(struct pci_dev *dev)
iov->num_VFs = 0;
pci_iov_set_numvfs(dev, 0);
+ sriov_restore_vf_rebar_initial_sizes(dev);
}
static int sriov_init(struct pci_dev *dev, int pos)
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
2026-08-03 10:30 ` [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
2026-08-03 10:30 ` [PATCH v2 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
@ 2026-08-03 10:30 ` Marcin Bernatowicz
2026-08-03 10:41 ` sashiko-bot
2026-08-03 11:17 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Simon Richter
3 siblings, 1 reply; 14+ messages in thread
From: Marcin Bernatowicz @ 2026-08-03 10:30 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe
sriov_disable() and sriov_enable() error paths restore the per-VF BAR
sizes saved at probe time. They do not cover the case where the PF
driver is detached while VF BARs were resized but SR-IOV was never
enabled (or was already disabled).
Restore the initial sizes from pci_iov_remove() as well. That hook runs
on driver detach while the device is still live, unlike sriov_release()
which runs later from the pci_dev release path.
Skip the restore when the PF driver leaves SR-IOV enabled; in that case
VF memory decoding is still active and pci_iov_vf_bar_set_size() cannot
safely change the VF BAR size.
Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
---
drivers/pci/iov.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 999938163ce9..3739825c84e9 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -1085,8 +1085,12 @@ void pci_iov_remove(struct pci_dev *dev)
return;
iov->driver_max_VFs = iov->total_VFs;
- if (iov->num_VFs)
+ if (iov->num_VFs) {
pci_warn(dev, "driver left SR-IOV enabled after remove\n");
+ return;
+ }
+
+ sriov_restore_vf_rebar_initial_sizes(dev);
}
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove
2026-08-03 10:30 ` [PATCH v2 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove Marcin Bernatowicz
@ 2026-08-03 10:41 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-03 10:41 UTC (permalink / raw)
To: Marcin Bernatowicz; +Cc: linux-pci
> sriov_disable() and sriov_enable() error paths restore the per-VF BAR
> sizes saved at probe time. They do not cover the case where the PF
> driver is detached while VF BARs were resized but SR-IOV was never
> enabled (or was already disabled).
>
> Restore the initial sizes from pci_iov_remove() as well. That hook runs
> on driver detach while the device is still live, unlike sriov_release()
> which runs later from the pci_dev release path.
>
> Skip the restore when the PF driver leaves SR-IOV enabled; in that case
> VF memory decoding is still active and pci_iov_vf_bar_set_size() cannot
> safely change the VF BAR size.
>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260803103007.209625-1-marcin.bernatowicz@linux.intel.com?part=3
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes
2026-08-03 10:30 ` [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
@ 2026-08-03 10:41 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-03 10:41 UTC (permalink / raw)
To: Marcin Bernatowicz; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Out-of-bounds stack read when processing a 64-bit BAR at the final index.
- [High] Double multiplication of VF BAR size and incorrect per-VF size recording when initialized via Enhanced Allocation (EA).
--
--- Patch [1]: [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes ---
commit 267f03df0eb1d945e4b2134aa0c449cf8ddfcfca
Author: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
PCI/IOV: Remember initial VF BAR sizes
SR-IOV initialization records the per-VF BAR sizes derived from the VF
BAR registers in the SR-IOV capability.
PF drivers may later change VF BAR sizes using VF Resizable BAR support
(pci_iov_vf_bar_set_size()). Save the initial per-VF BAR sizes so later
code can restore them when SR-IOV is disabled, when SR-IOV enable fails,
or when the PF driver is unbound while VF BARs are still resized.
The initial size is captured before the resource is multiplied by
TotalVFs, so it represents one VF's BAR size as advertised by hardware.
No functional change on its own.
> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> index b0d24839c0840..ae9309fc6dd73 100644
> --- a/drivers/pci/iov.c
> +++ b/drivers/pci/iov.c
> @@ -869,6 +869,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
> goto failed;
> }
> iov->barsz[i] = resource_size(res);
[Severity: High]
This is a pre-existing issue, but does this handle Enhanced Allocation (EA)
initialized devices correctly?
If a device is initialized via EA in pci_ea_init(), the VF BAR resources are
initialized with a total size encompassing all VFs and marked with
IORESOURCE_PCI_FIXED.
Because they are fixed, __pci_read_base() is skipped earlier in the loop,
and resource_size(res) returns the total size instead of a single VF's size.
This results in iov->barsz[i] (and now iov->barsz_orig[i]) incorrectly saving
the total size, and the resource_set_size() call below multiplying the
already-total size by the number of VFs again, leading to exponential
inflation of requested resource sizes.
Can this cause resource allocation failures for EA-initialized devices?
> + iov->barsz_orig[i] = iov->barsz[i];
> resource_set_size(res, resource_size(res) * total);
> pci_info(dev, "%s %pR: contains BAR %d for %d VFs\n",
> res_name, res, i, total);
[Severity: High]
This isn't a bug introduced by this patch, but can this loop trigger an
out-of-bounds stack read if a 64-bit BAR is advertised at the final index
(BAR 5)?
Just above this diff hunk in sriov_init(), if the resource is not fixed,
__pci_read_base() is called:
bar64 = __pci_read_base(dev, pci_bar_unknown, res,
pos + PCI_SRIOV_BAR + i * 4,
&sriovbars[i]);
sriovbars is a 6-element stack array. If i = 5 (the last BAR), &sriovbars[5]
is a pointer to the final element.
If the hardware advertises a 64-bit BAR, __pci_read_base() in
drivers/pci/probe.c processes it by reading from index 1:
if (res->flags & IORESOURCE_MEM_64) {
pci_read_config_dword(dev, pos + 4, &l);
sz = sizes[1];
Since sizes points to the final element of the sriovbars array, sizes[1]
accesses memory past the end of the stack array. Could a malicious or
malfunctioning hot-plugged PCIe device trigger a KASAN panic here?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260803103007.209625-1-marcin.bernatowicz@linux.intel.com?part=1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure
2026-08-03 10:30 ` [PATCH v2 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
@ 2026-08-03 10:46 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-03 10:46 UTC (permalink / raw)
To: Marcin Bernatowicz; +Cc: linux-pci
> PF drivers can resize a VF BAR via pci_iov_vf_bar_set_size(). The new
> size persists in config space. A subsequent reprobe/unplug-rescan may
> then cause the PCI core to reserve MMIO based on the inflated VF BAR
> registers in the SR-IOV capability, often multiplied by TotalVFs.
> On platforms with tight apertures, later SR-IOV enable can fail due to
> lack of space.
>
> Restore the initial VF BAR sizes saved at SR-IOV init time when SR-IOV
> is disabled and when SR-IOV enable fails. This covers both the resource
> allocation failures later in sriov_enable() and the earlier validation
> failures that can otherwise leave a resized VF BAR in hardware while
> num_VFs remains zero.
>
> Restore is only performed when VF Memory Space is disabled, which is the
> precondition of pci_iov_vf_bar_set_size() and is true at all the new
> call sites.
>
> Note: this changes user-visible behavior for drivers that rely on the
> resized VF BAR persisting across an enable/disable cycle. After this
> change drivers must call pci_iov_vf_bar_set_size() before each
> pci_enable_sriov() if a non-default size is desired.
>
> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/5937
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260803103007.209625-1-marcin.bernatowicz@linux.intel.com?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
` (2 preceding siblings ...)
2026-08-03 10:30 ` [PATCH v2 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove Marcin Bernatowicz
@ 2026-08-03 11:17 ` Simon Richter
3 siblings, 0 replies; 14+ messages in thread
From: Simon Richter @ 2026-08-03 11:17 UTC (permalink / raw)
To: Marcin Bernatowicz, Bjorn Helgaas, linux-pci, linux-kernel
Cc: Michal Wajdeczko, Michał Winiarski, Ilpo Järvinen,
Krzysztof Wilczyński, Thomas Hellström, Rodrigo Vivi,
intel-xe
Hi,
On 8/3/26 7:30 PM, Marcin Bernatowicz wrote:
> PF drivers can resize a VF BAR using VF Resizable BAR (ReBAR) support via
> pci_iov_vf_bar_set_size(). The new size persists in the SR-IOV capability
> config space. A later reprobe / unplug-rescan / next pci_enable_sriov()
> then sees the inflated VF BAR registers, and the PCI core reserves MMIO
> based on that size multiplied by TotalVFs.
Would it make sense for pci_enable_sriov() to check for a ReBAR
capability in the VF and set it to the smallest possible setting, so we
get the same behaviour regardless of whether this was cleaned up correctly?
Also, should it be "previous" or "smallest" size (in order to not make a
missed cleanup permanent)?
I'm a bit worried about POWER, while we do have lots of MMIO space, we
also use kexec() quite a lot because on several machines, the bootloader
is some ancient minimal Linux system.
Simon
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-08-03 11:26 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-05 17:00 [PATCH 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
2026-05-05 17:00 ` [PATCH 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
2026-05-05 20:36 ` sashiko-bot
2026-05-05 17:00 ` [PATCH 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF release Marcin Bernatowicz
2026-05-05 21:17 ` sashiko-bot
2026-08-03 10:30 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Marcin Bernatowicz
2026-08-03 10:30 ` [PATCH v2 1/3] PCI/IOV: Remember initial VF BAR sizes Marcin Bernatowicz
2026-08-03 10:41 ` sashiko-bot
2026-08-03 10:30 ` [PATCH v2 2/3] PCI/IOV: Restore initial VF ReBAR sizes on SR-IOV disable/failure Marcin Bernatowicz
2026-08-03 10:46 ` sashiko-bot
2026-08-03 10:30 ` [PATCH v2 3/3] PCI/IOV: Restore initial VF ReBAR sizes on PF driver remove Marcin Bernatowicz
2026-08-03 10:41 ` sashiko-bot
2026-08-03 11:17 ` [PATCH v2 0/3] PCI/IOV: Restore initial VF BAR sizing after VF ReBAR Simon Richter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox