|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 4/4] vpci/header: empty the BAR range sets when modify_bars() fails
On error modify_bars() returned with the ranges already collected still
in the per-BAR sets. The next request on the device then maps or unmaps
them along with its own. Purge every set when collecting the ranges
fails.
Fixes: 622bdd962822 ("vpci/header: handle p2m range sets per BAR")
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxx>
Cc: "Roger Pau Monné" <roger@xxxxxxxxxxxxxx>
Cc: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
---
xen/drivers/vpci/header.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
index 7e5f4b8a00..0bdc4d6a46 100644
--- a/xen/drivers/vpci/header.c
+++ b/xen/drivers/vpci/header.c
@@ -366,7 +366,8 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t
cmd, bool rom_only)
gprintk(XENLOG_G_WARNING,
"%pp: can't map BAR%u - offset mismatch: %#lx vs %#lx\n",
&pdev->sbdf, i, bar->guest_addr, bar->addr);
- return -EINVAL;
+ rc = -EINVAL;
+ goto fail;
}
rc = rangeset_add_range(bar->mem, start_guest, end_guest);
@@ -374,7 +375,7 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t
cmd, bool rom_only)
{
printk(XENLOG_G_WARNING "Failed to add [%lx, %lx]: %d\n",
start_guest, end_guest, rc);
- return rc;
+ goto fail;
}
/* Check for overlap with the already setup BAR ranges. */
@@ -391,7 +392,7 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t
cmd, bool rom_only)
gprintk(XENLOG_WARNING,
"%pp: failed to remove overlapping range [%lx, %lx]:
%d\n",
&pdev->sbdf, start_guest, end_guest, rc);
- return rc;
+ goto fail;
}
}
@@ -401,7 +402,7 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t
cmd, bool rom_only)
gprintk(XENLOG_WARNING,
"%pp: failed to sanitize BAR#%u memory: %d\n",
&pdev->sbdf, i, rc);
- return rc;
+ goto fail;
}
}
@@ -425,7 +426,7 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t
cmd, bool rom_only)
gprintk(XENLOG_WARNING,
"%pp: failed to remove MSIX table [%lx, %lx]: %d\n",
&pdev->sbdf, start, end, rc);
- return rc;
+ goto fail;
}
}
}
@@ -487,7 +488,7 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t
cmd, bool rom_only)
gprintk(XENLOG_WARNING,
"%pp: failed to remove [%lx, %lx]: %d\n",
&pdev->sbdf, start, end, rc);
- return rc;
+ goto fail;
}
}
}
@@ -516,6 +517,18 @@ static int modify_bars(const struct pci_dev *pdev,
uint16_t cmd, bool rom_only)
defer_map(pdev, cmd, rom_only);
return 0;
+
+ fail:
+ /*
+ * Leave no range collected for the request that failed: the next request
+ * expects every BAR's set to start empty, and a range left behind would
+ * be mapped or unmapped with it.
+ */
+ for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
+ if ( header->bars[i].mem )
+ rangeset_purge(header->bars[i].mem);
+
+ return rc;
}
static void cf_check cmd_write(
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |