| 
    
 [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] xen/mcfg: Call PHYSDEVOP_pci_mmcfg_reserved before PCI enumeration
 RFC. Tested with 3.14.51 and Xen 4.5.1. I'll make a proper patch against a more current kernel if we decide this is heading in the right direction. 
  xen/mcfg: Notify Xen of PCI MMCONFIG area before adding device  Â   On systems where the ACPI DSDT advertises a PCI MMCONFIG area but the E820   table does not reserve it, it's up to Dom0 to inform Xen of MMCONFIG areas   via PHYSDEVOP_pci_mmcfg_reserved. This needs to happen before Xen tries to   access extended capabilities like SRIOV in pci_add_device(), which is   triggered by PHYSDEVOP_pci_device_add et al.  Â   Since both MMCONFIG discovery and PCI bus enumeration occur in acpi_init(),   calling PHYSDEVOP_pci_mmcfg_reserved cannot be delegated to a separate   initcall. Instead, it can be done in xen_pci_notifier() immediately before   calling PHYSDEVOP_pci_device_add.  Â   Without this change, Xen 4.4 and 4.5 emit WARN messsages from   msix_capability_init() when setting up Intel 82599 VFs, since vf_rlen has   not been initialized by pci_add_device(). And on Xen 4.5, Xen nukes the   DomU due to "Potentially insecure use of MSI-X" when the VF driver loads in   the DomU. Both problems are fixed by this change.  Â   Signed-off-by: Ed Swierk <eswierk@xxxxxxxxxxxxxxxxxx> diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c index dd9c249..47f6b45 100644 --- a/drivers/xen/pci.c +++ b/drivers/xen/pci.c @@ -26,8 +26,57 @@ Â#include <asm/xen/hypervisor.h> Â#include <asm/xen/hypercall.h> Â#include "../pci/pci.h" + Â#ifdef CONFIG_PCI_MMCONFIG Â#include <asm/pci_x86.h> +#include <linux/list.h> + +/* pci_mmcfg_list entries that have already been reported to xen */ +LIST_HEAD(xen_pci_mmcfg_list); + +static void xen_report_pci_mmcfg_region(u16 segment, u8 bus) +{ +	struct pci_mmcfg_region *cfg, *new; +	struct physdev_pci_mmcfg_reserved r; +	int rc; + +	if ((pci_probe & PCI_PROBE_MMCONF) == 0) +		return; + +	cfg = pci_mmconfig_lookup(segment, bus); +	if (!cfg) +		return; + +	list_for_each_entry_rcu(new, &xen_pci_mmcfg_list, list) { +		if (new->segment == cfg->segment && +		  Ânew->start_bus == cfg->start_bus && +		  Ânew->end_bus == cfg->end_bus) +			return; +	} + +	r.address = cfg->address; +	r.segment = cfg->segment; +	r.start_bus = cfg->start_bus; +	r.end_bus = cfg->end_bus; +	r.flags = XEN_PCI_MMCFG_RESERVED; +	rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r); +	if (rc != 0 && rc != -ENOSYS) { +		pr_warn("Failed to report MMCONFIG reservation state for %s" +			" to hypervisor (%d)\n", cfg->name, rc); +	} + +	new = kmemdup(cfg, sizeof(*new), GFP_KERNEL); +	if (new) { +		list_add_tail_rcu(&new->list, &xen_pci_mmcfg_list); +	} else { +		pr_warn("Failed to allocate xen_pci_mmcfg_list entry\n"); +	} +} + +#else + +static void xen_report_pci_mmcfg_region(u16 segment, u8 bus) { } + Â#endif  Âstatic bool __read_mostly pci_seg_supported = true; @@ -86,6 +135,7 @@ static int xen_add_device(struct device *dev) Â		} Â#endif /* CONFIG_ACPI */  +		xen_report_pci_mmcfg_region(add.seg, add.bus); Â		r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, &add); Â		if (r != -ENOSYS) Â			return r; @@ -104,6 +154,7 @@ static int xen_add_device(struct device *dev) Â			.physfn.devfn	= physfn->devfn, Â		};  +		xen_report_pci_mmcfg_region(0, manage_pci_ext.bus); Â		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext, Â			&manage_pci_ext); Â	} @@ -115,6 +166,7 @@ static int xen_add_device(struct device *dev) Â			.is_extfn	= 1, Â		};  +		xen_report_pci_mmcfg_region(0, manage_pci_ext.bus); Â		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext, Â			&manage_pci_ext); Â	} else { @@ -123,6 +175,7 @@ static int xen_add_device(struct device *dev) Â			.devfn	= pci_dev->devfn, Â		};  +		xen_report_pci_mmcfg_region(0, manage_pci.bus); Â		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, Â			&manage_pci); Â	} @@ -142,6 +195,7 @@ static int xen_remove_device(struct device *dev) Â			.devfn = pci_dev->devfn Â		};  +		xen_report_pci_mmcfg_region(device.seg, device.bus); Â		r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove, Â					 Â&device); Â	} else if (pci_domain_nr(pci_dev->bus)) @@ -152,6 +206,7 @@ static int xen_remove_device(struct device *dev) Â			.devfn = pci_dev->devfn Â		};  +		xen_report_pci_mmcfg_region(0, manage_pci.bus); Â		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove, Â					 Â&manage_pci); Â	} @@ -195,49 +250,3 @@ static int __init register_xen_pci_notifier(void) Â}  Âarch_initcall(register_xen_pci_notifier); - -#ifdef CONFIG_PCI_MMCONFIG -static int __init xen_mcfg_late(void) -{ -	struct pci_mmcfg_region *cfg; -	int rc; - -	if (!xen_initial_domain()) -		return 0; - -	if ((pci_probe & PCI_PROBE_MMCONF) == 0) -		return 0; - -	if (list_empty(&pci_mmcfg_list)) -		return 0; - -	/* Check whether they are in the right area. */ -	list_for_each_entry(cfg, &pci_mmcfg_list, list) { -		struct physdev_pci_mmcfg_reserved r; - -		r.address = cfg->address; -		r.segment = cfg->segment; -		r.start_bus = cfg->start_bus; -		r.end_bus = cfg->end_bus; -		r.flags = XEN_PCI_MMCFG_RESERVED; - -		rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r); -		switch (rc) { -		case 0: -		case -ENOSYS: -			continue; - -		default: -			pr_warn("Failed to report MMCONFIG reservation" -				" state for %s to hypervisor" -				" (%d)\n", -				cfg->name, rc); -		} -	} -	return 0; -} -/* - * Needs to be done after acpi_init which are subsys_initcall. - */ -subsys_initcall_sync(xen_mcfg_late); -#endif On Tue, Sep 22, 2015 at 8:09 AM, Jan Beulich <JBeulich@xxxxxxxx> wrote: >>> On 22.09.15 at 16:37, <konrad.wilk@xxxxxxxxxx> wrote: _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel 
 
 
  | 
  
![]()  | 
            
         Lists.xenproject.org is hosted with RackSpace, monitoring our  |