[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 2/5] xen/vpci: make BAR mapping more resilient for the hardware domain
On 8/15/25 14:53, Stewart Hildebrand wrote: > On 8/14/25 12:03, Roger Pau Monne wrote: >> 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, hopping 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. >> >> No functional change for domUs intended. >> >> Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> >> --- >> xen/drivers/vpci/header.c | 51 +++++++++++++++++++++------------------ >> 1 file changed, 28 insertions(+), 23 deletions(-) >> >> diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c >> index b9756b364300..1035dcca242d 100644 >> --- a/xen/drivers/vpci/header.c >> +++ b/xen/drivers/vpci/header.c >> @@ -64,7 +64,8 @@ static int cf_check map_range( >> printk(XENLOG_G_WARNING >> "%pd denied access to MMIO range [%#lx, %#lx]\n", >> map->d, map_mfn, m_end); >> - return -EPERM; >> + rc = -EPERM; >> + goto done; >> } >> >> rc = xsm_iomem_mapping(XSM_HOOK, map->d, map_mfn, m_end, map->map); >> @@ -73,7 +74,7 @@ static int cf_check map_range( >> printk(XENLOG_G_WARNING >> "%pd XSM denied access to MMIO range [%#lx, %#lx]: %d\n", >> map->d, map_mfn, m_end, rc); >> - return rc; >> + goto done; >> } >> >> /* >> @@ -87,17 +88,27 @@ 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; > > If we return success and size is zero, we will potentially attempt to > map/unmap > the same region again in an infinite loop. rangeset_consume_ranges would > invoke > map_range again directly without returning to vpci_process_pending. Sorry, I sent the previous email too soon, I see now that it shouldn't be possible for size to be zero. > >> + *c += size; > > This line is now only executed for hwdom, but ... > >> + } > > ... it should go outside of the hwdom check because domUs still need it. > >> break; >> } >> ASSERT(rc < size); >> @@ -213,28 +224,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); > > This path could be taken for either map or unmap. Do we still want to disable > memory decoding in case of unmap? > >> - 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 >> shallow >> + * errors for hardware domain owned devices, and >> + * rangeset_consume_ranges() itself doesn't generate any errors. >> + */ >> + rangeset_purge(bar->mem); > > Reiterating what was mentioned above: if map_range returned 0 without > incrementing *c, we won't make it back here. > >> } >> v->vpci.pdev = NULL; >>
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |