[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] xen, vtd: Fix device check for devices behind PCIe-to-PCI bridges



On Tue, Sep 6, 2011 at 10:16 PM, Kay, Allen M <allen.m.kay@xxxxxxxxx> wrote:
> I'm curious how does this context entry became valid in the first place if 
> pdev cannot be found?

Apparently the only code that needs the pdev is the part that does the
ownership checking. :-)

> In general, this patch seems harmless to other situations.  It just does the 
> same new and old domain checking for the case where pdev is not found.

Great, thanks.

 -George

>
> Allen
>
> -----Original Message-----
> From: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx 
> [mailto:xen-devel-bounces@xxxxxxxxxxxxxxxxxxx] On Behalf Of George Dunlap
> Sent: Thursday, September 01, 2011 7:20 AM
> To: xen-devel@xxxxxxxxxxxxxxxxxxx
> Cc: george.dunlap@xxxxxxxxxxxxx
> Subject: [Xen-devel] [PATCH] xen, vtd: Fix device check for devices behind 
> PCIe-to-PCI bridges
>
> On some systems, requests devices behind a PCIe-to-PCI bridge all
> appear to the IOMMU as though they come from from slot 0, function
> 0 on that device; so the mapping code much punch a hole for X:0.0
> in the IOMMU for such devices.  When punching the hole, if that device
> has already been mapped once, we simply need to check ownership to
> make sure it's legal.  To do so, domain_context_mapping_one() will look
> up the device for the mapping with pci_get_pdev() and look for the owner.
>
> However, if there is no device in X:0.0, this look up will fail.
>
> Rather than returning -ENODEV in this situation (causing a failure in
> mapping the device), try to get the domain ownership from the iommu context
> mapping itself.
>
> Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
>
> diff -r 4a4882df5649 -r ede81b0552be xen/drivers/passthrough/vtd/iommu.c
> --- a/xen/drivers/passthrough/vtd/iommu.c       Wed Aug 31 15:23:49 2011 +0100
> +++ b/xen/drivers/passthrough/vtd/iommu.c       Thu Sep 01 15:18:18 2011 +0100
> @@ -113,6 +113,27 @@ static int context_set_domain_id(struct
>     return 0;
>  }
>
> +static int context_get_domain_id(struct context_entry *context,
> +                                 struct iommu *iommu)
> +{
> +    unsigned long dom_index, nr_dom;
> +    int domid = -1;
> +
> +    if (iommu && context)
> +    {
> +        nr_dom = cap_ndoms(iommu->cap);
> +
> +        dom_index = context_domain_id(*context);
> +
> +        if ( dom_index < nr_dom && iommu->domid_map)
> +            domid = iommu->domid_map[dom_index];
> +        else
> +            dprintk(XENLOG_DEBUG VTDPREFIX, "%s: dom_index %lu exceeds 
> nr_dom %lu or iommu has no domid_map\n",
> +                    __func__, dom_index, nr_dom);
> +    }
> +    return domid;
> +}
> +
>  static struct intel_iommu *__init alloc_intel_iommu(void)
>  {
>     struct intel_iommu *intel;
> @@ -1237,7 +1258,6 @@ int domain_context_mapping_one(
>     struct hvm_iommu *hd = domain_hvm_iommu(domain);
>     struct context_entry *context, *context_entries;
>     u64 maddr, pgd_maddr;
> -    struct pci_dev *pdev = NULL;
>     int agaw;
>
>     ASSERT(spin_is_locked(&pcidevs_lock));
> @@ -1249,12 +1269,45 @@ int domain_context_mapping_one(
>     if ( context_present(*context) )
>     {
>         int res = 0;
> +        struct pci_dev *pdev = NULL;
>
> +        /* First try to get domain ownership from device structure.  If 
> that's
> +         * not available, try to read it from the context itself. */
>         pdev = pci_get_pdev(bus, devfn);
> -        if (!pdev)
> -            res = -ENODEV;
> -        else if (pdev->domain != domain)
> -            res = -EINVAL;
> +        if ( pdev )
> +        {
> +            if ( pdev->domain != domain )
> +            {
> +                dprintk(XENLOG_INFO VTDPREFIX, "d%d: bdf = %x:%x.%x owned by 
> d%d!",
> +                        domain->domain_id,
> +                        bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
> +                        (pdev->domain)
> +                        ? pdev->domain->domain_id : -1);
> +                res = -EINVAL;
> +            }
> +        }
> +        else
> +        {
> +            int cdomain;
> +            cdomain = context_get_domain_id(context, iommu);
> +
> +            if ( cdomain < 0 )
> +            {
> +                dprintk(VTDPREFIX, "d%d: bdf = %x:%x.%x mapped, but can't 
> find owner!\n",
> +                        domain->domain_id,
> +                        bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
> +                res = -EINVAL;
> +            }
> +            else if ( cdomain != domain->domain_id )
> +            {
> +                dprintk(XENLOG_INFO VTDPREFIX, "d%d: bdf = %x:%x.%x already 
> mapped to d%d!",
> +                        domain->domain_id,
> +                        bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
> +                        cdomain);
> +                res = -EINVAL;
> +            }
> +        }
> +
>         unmap_vtd_domain_page(context_entries);
>         spin_unlock(&iommu->lock);
>         return res;
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
>

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.