When Dom0 informs up about MMCFG usability, this may change whether extended capabilities are available (accessible) for devices. Zap what might be on record, and re-initialize the list.
No synchronization is added for the case where devices may already be in use. That'll need sorting when (a) DomU support was added and (b) DomU-s may run already while Dom0 / hwdom still boots (dom0less, Hyperlaunch). Signed-off-by: Jan Beulich <[email protected]> --- vpci_reinit_ext_capability_list()'s return value isn't checked, as it doesn't feel quite right to fail the hypercall because of this. At the same time it also doesn't feel quite right to have the function return "void". Thoughts? --- v3: New. --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -8,6 +8,8 @@ #include <xen/guest_access.h> #include <xen/iocap.h> #include <xen/serial.h> +#include <xen/vpci.h> + #include <asm/current.h> #include <asm/io_apic.h> #include <asm/msi.h> @@ -169,7 +171,10 @@ int cf_check physdev_check_pci_extcfg(st ASSERT(pdev->seg == info->segment); if ( pdev->bus >= info->start_bus && pdev->bus <= info->end_bus ) + { pci_check_extcfg(pdev); + vpci_reinit_ext_capability_list(pdev); + } return 0; } --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -869,6 +869,18 @@ static int vpci_init_ext_capability_list return 0; } +int vpci_reinit_ext_capability_list(const struct pci_dev *pdev) +{ + if ( !pdev->vpci ) + return 0; + + if ( vpci_remove_registers(pdev->vpci, PCI_CFG_SPACE_SIZE, + PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) ) + ASSERT_UNREACHABLE(); + + return vpci_init_ext_capability_list(pdev); +} + int vpci_init_header(struct pci_dev *pdev) { uint16_t cmd; --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -45,6 +45,7 @@ typedef struct { REGISTER_VPCI_CAPABILITY(PCI_EXT_CAP_ID_##name, name, finit, fclean, true) int __must_check vpci_init_header(struct pci_dev *pdev); +int vpci_reinit_ext_capability_list(const struct pci_dev *pdev); /* Assign vPCI to device by adding handlers. */ int __must_check vpci_assign_device(struct pci_dev *pdev); @@ -300,6 +301,11 @@ bool vpci_ecam_read(pci_sbdf_t sbdf, uns #else /* !CONFIG_HAS_VPCI */ struct vpci_vcpu {}; +static inline int vpci_reinit_ext_capability_list(const struct pci_dev *pdev) +{ + return 0; +} + static inline int vpci_assign_device(struct pci_dev *pdev) { return 0;
