[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 3/3] vpci: allow 32-bit BAR writes with memory decoding enabled
Currently, Xen vPCI refuses BAR writes if the BAR is mapped in p2m. If firmware initializes a 32-bit BAR to a bad address, Linux may try to write a new address to the 32-bit BAR without disabling memory decoding. Since Xen refuses such writes, the BAR (and thus PCI device) will be non-functional. Allow the hardware domain to issue 32-bit BAR writes with memory decoding enabled. This increases the compatibility of PVH dom0 with more hardware. Note that Linux aims at disabling memory decoding before writing 64-bit BARs. Continue to refuse 64-bit BAR writes in Xen while those BARs are mapped for now to avoid mapping half-updated BARs in p2m. Take the opportunity to remove a stray newline in bar_write(). Resolves: https://gitlab.com/xen-project/xen/-/issues/197 Signed-off-by: Stewart Hildebrand <stewart.hildebrand@xxxxxxx> --- v1->v2: * rework on top of queued BAR map/unmap operation machinery RFC->v1: * keep memory decoding enabled in hardware * allow write while memory decoding is enabled for 32-bit BARs only * rework BAR mapping machinery to support unmap-then-map operation --- xen/drivers/vpci/header.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c index 1c66796b625b..06c1dbfd5de0 100644 --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -404,9 +404,7 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, if ( !MAPPABLE_BAR(bar) || (rom_only ? bar->type != VPCI_BAR_ROM - : (bar->type == VPCI_BAR_ROM && !header->rom_enabled)) || - /* Skip BARs already in the requested state. */ - bar->enabled == !!(cmd & PCI_COMMAND_MEMORY) ) + : (bar->type == VPCI_BAR_ROM && !header->rom_enabled)) ) continue; if ( !pci_check_bar(pdev, _mfn(start), _mfn(end)) ) @@ -650,19 +648,29 @@ static void cf_check bar_write( val &= PCI_BASE_ADDRESS_MEM_MASK; /* - * Xen only cares whether the BAR is mapped into the p2m, so allow BAR - * writes as long as the BAR is not mapped into the p2m. + * Allow 64-bit BAR writes only when the BAR is not mapped in p2m. Always + * allow 32-bit BAR writes. */ if ( bar->enabled ) { - /* If the value written is the current one avoid printing a warning. */ - if ( val != (uint32_t)(bar->addr >> (hi ? 32 : 0)) ) - gprintk(XENLOG_WARNING, - "%pp: ignored BAR %zu write while mapped\n", - &pdev->sbdf, bar - pdev->vpci->header.bars + hi); - return; - } + if ( bar->type == VPCI_BAR_MEM32 ) + { + if ( val == bar->addr ) + return; + modify_bars(pdev, pci_conf_read16(pdev->sbdf, PCI_COMMAND), + VPCI_UNMAP, false); + } + else + { + /* If the value written is the same avoid printing a warning. */ + if ( val != (uint32_t)(bar->addr >> (hi ? 32 : 0)) ) + gprintk(XENLOG_WARNING, + "%pp: ignored BAR %zu write while mapped\n", + &pdev->sbdf, bar - pdev->vpci->header.bars + hi); + return; + } + } /* * Update the cached address, so that when memory decoding is enabled @@ -682,6 +690,10 @@ static void cf_check bar_write( } pci_conf_write32(pdev->sbdf, reg, val); + + if ( bar->enabled ) + modify_bars(pdev, pci_conf_read16(pdev->sbdf, PCI_COMMAND), VPCI_MAP, + false); } static void cf_check guest_mem_bar_write(const struct pci_dev *pdev, -- 2.50.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |