|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 2/9] vpci: make BAR mapping more resilient for the hardware domain
From: Roger Pau Monne <roger.pau@xxxxxxxxxx>
The logic in map_range() will bubble up failures to the upper layer, which
will result in any remaining regions being skip, and for the non-hardware
domain case the owner domain of the device would be destroyed. However for
the hardware domain the intent is to continue execution, hoping the
failure to modify the p2m could be worked around by the hardware domain.
To accomplish that in a better way, ignore failures and skip the range in
that case, possibly continuing to map further ranges.
Since the error path in vpci_process_pending() should only be used by domUs
now, and it will unconditionally end up calling domain_crash(), simplify
it: there's no need to cleanup if the domain will be destroyed.
Memory decoding may be left enabled in case of mapping error for devices
assigned to domUs.
No functional change for domUs intended.
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Signed-off-by: Stewart Hildebrand <stewart.hildebrand@xxxxxxx>
---
Although not strictly a pre-requisite for queued p2m mapping, I've
included this patch from Roger's vPCI fixes series since it simplifies
the error path in vpci_process_pending().
v1->v5:
* move "*c += size;" outside is_hardware_domain condition
* add note to commit message about not disabling memory decoding on failure
---
xen/drivers/vpci/header.c | 45 +++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
index 5ac525036672..9f2d0c8a5452 100644
--- a/xen/drivers/vpci/header.c
+++ b/xen/drivers/vpci/header.c
@@ -70,17 +70,26 @@ static int cf_check map_range(
rc = map->map ? map_mmio_regions(map->d, _gfn(s), size, _mfn(map_mfn))
: unmap_mmio_regions(map->d, _gfn(s), size,
_mfn(map_mfn));
- if ( rc == 0 )
- {
- *c += size;
- break;
- }
if ( rc < 0 )
{
printk(XENLOG_G_WARNING
"Failed to %smap [%lx %lx] -> [%lx %lx] for %pd: %d\n",
map->map ? "" : "un", s, e, map_mfn,
map_mfn + size, map->d, rc);
+ goto done;
+ }
+ if ( rc == 0 )
+ {
+ done:
+ if ( is_hardware_domain(map->d) )
+ /*
+ * Ignore failures for the hardware domain and skip the range.
+ * Do it as a best effort workaround to attempt to get the
+ * hardware domain to boot.
+ */
+ rc = 0;
+
+ *c += size;
break;
}
ASSERT(rc < size);
@@ -196,28 +205,22 @@ bool vpci_process_pending(struct vcpu *v)
return true;
}
- if ( rc )
+ if ( rc && !is_hardware_domain(v->domain) )
{
- spin_lock(&pdev->vpci->lock);
- /* Disable memory decoding unconditionally on failure. */
- modify_decoding(pdev, v->vpci.cmd & ~PCI_COMMAND_MEMORY,
- false);
- spin_unlock(&pdev->vpci->lock);
-
- /* Clean all the rangesets */
- for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
- if ( !rangeset_is_empty(header->bars[i].mem) )
- rangeset_purge(header->bars[i].mem);
-
- v->vpci.pdev = NULL;
-
read_unlock(&v->domain->pci_lock);
- if ( !is_hardware_domain(v->domain) )
- domain_crash(v->domain);
+ domain_crash(v->domain);
return false;
}
+ ASSERT(!rc);
+ /*
+ * Purge rangeset to deal with the hardware domain having triggered an
+ * error. It shouldn't be possible, as map_range() will always swallow
+ * errors for hardware domain owned devices, and
+ * rangeset_consume_ranges() itself doesn't generate any errors.
+ */
+ rangeset_purge(bar->mem);
}
v->vpci.pdev = NULL;
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |