From a845b50c12f3ec3a14255f5eb3062d0c9801a356 Mon Sep 17 00:00:00 2001 From: Jiqian Chen Date: Mon, 28 Jul 2025 13:08:14 +0200 Subject: [PATCH] vpci/header: Emulate extended capability list for dom0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new function to emulate extended capability list for dom0, and call it in init_header(). So that it will be easy to hide an extended capability whose initialization fails. As for the extended capability list of domU, just move the logic into above function and keep hiding it for domU. Signed-off-by: Jiqian Chen Reviewed-by: Jan Beulich Reviewed-by: Roger Pau Monné --- xen/drivers/vpci/header.c | 44 ++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c index bb76e70799..f537f3f25d 100644 --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -825,6 +825,39 @@ static int vpci_init_capability_list(struct pci_dev *pdev) PCI_STATUS_RSVDZ_MASK); } +static int vpci_init_ext_capability_list(const struct pci_dev *pdev) +{ + unsigned int pos = PCI_CFG_SPACE_SIZE; + + if ( !is_hardware_domain(pdev->domain) ) + /* Extended capabilities read as zero, write ignore for DomU */ + return vpci_add_register(pdev->vpci, vpci_read_val, NULL, + pos, 4, (void *)0); + + do + { + uint32_t header = pci_conf_read32(pdev->sbdf, pos); + int rc; + + rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL, + pos, 4, (void *)(uintptr_t)header); + if ( rc == -EEXIST ) + { + printk(XENLOG_WARNING + "%pd %pp: overlap in extended cap list, offset %#x\n", + pdev->domain, &pdev->sbdf, pos); + return 0; + } + + if ( rc ) + return rc; + + pos = PCI_EXT_CAP_NEXT(header); + } while ( pos >= PCI_CFG_SPACE_SIZE ); + + return 0; +} + static int cf_check init_header(struct pci_dev *pdev) { uint16_t cmd; @@ -877,14 +910,9 @@ static int cf_check init_header(struct pci_dev *pdev) if ( rc ) return rc; - if ( !is_hwdom ) - { - /* Extended capabilities read as zero, write ignore */ - rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL, 0x100, 4, - (void *)0); - if ( rc ) - return rc; - } + rc = vpci_init_ext_capability_list(pdev); + if ( rc ) + return rc; if ( pdev->ignore_bars ) return 0;