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

Re: [Xen-devel] [PATCH v3 2/2] VT-d: Fix vt-d flush timeout issue.



>>> On 12.12.15 at 14:21, <quan.xu@xxxxxxxxx> wrote:
> --- a/xen/drivers/passthrough/vtd/iommu.c
> +++ b/xen/drivers/passthrough/vtd/iommu.c
> @@ -1890,6 +1890,9 @@ static int intel_iommu_add_device(u8 devfn, struct 
> pci_dev *pdev)
>      if ( !pdev->domain )
>          return -EINVAL;
>  
> +    if ( is_pdev_unassignable(pdev) )
> +        return -EACCES;

Is this case possible at all (i.e. a newly added device being
unassignable)?

> --- a/xen/drivers/passthrough/vtd/qinval.c
> +++ b/xen/drivers/passthrough/vtd/qinval.c
> @@ -27,12 +27,58 @@
>  #include "dmar.h"
>  #include "vtd.h"
>  #include "extern.h"
> +#include "../ats.h"
>  
>  static int __read_mostly iommu_qi_timeout_ms = 1;
>  integer_param("iommu_qi_timeout_ms", iommu_qi_timeout_ms);
>  
>  #define IOMMU_QI_TIMEOUT (iommu_qi_timeout_ms * MILLISECS(1))
>  
> +void invalidate_timeout(struct iommu *iommu)
> +{
> +    struct domain *d;
> +    unsigned long nr_dom, i;
> +    struct pci_dev *pdev;
> +
> +    nr_dom = cap_ndoms(iommu->cap);
> +    i = find_first_bit(iommu->domid_bitmap, nr_dom);
> +    while ( i < nr_dom ) {
> +        d = rcu_lock_domain_by_id(iommu->domid_map[i]);
> +        ASSERT(d);
> +
> +        /* Mark the devices as unassignable. */
> +        for_each_pdev(d, pdev)
> +            mark_pdev_unassignable(pdev);
> +        if ( !is_hardware_domain(d) )
> +            domain_kill(d);

DYM domain_crash() here?

> +void device_tlb_invalidate_timeout(struct iommu *iommu, u16 did,
> +                                   u16 seg, u8 bus, u8 devfn)
> +{
> +    struct domain *d;
> +    struct pci_dev *pdev;
> +
> +        d = rcu_lock_domain_by_id(iommu->domid_map[did]);
> +        ASSERT(d);
> +        for_each_pdev(d, pdev)
> +            if ( (pdev->seg == seg) &&
> +                 (pdev->bus == bus) &&
> +                 (pdev->devfn == devfn) )
> +            {
> +                mark_pdev_unassignable(pdev);
> +                break;
> +            }
> +
> +        if ( !is_hardware_domain(d) )
> +            domain_kill(d);
> +        rcu_unlock_domain(d);
> +}

Except for the variable declarations, indentation is broken for the
entire function.

> @@ -262,6 +308,14 @@ static int __iommu_flush_iec(struct iommu *iommu, u8 
> granu, u8 im, u16 iidx)
>  
>      queue_invalidate_iec(iommu, granu, im, iidx);
>      ret = invalidate_sync(iommu);
> +
> +    if ( ret == -ETIMEDOUT )
> +    {
> +        invalidate_timeout(iommu);
> +        dprintk(XENLOG_WARNING VTDPREFIX,
> +                "IEC flush timeout.\n");
> +        return ret;
> +    }
>      /*

Considering the recurring pattern, wouldn't it be better for
invalidate_sync() to invoke invalidate_timeout() (at once making
sure no current or future caller misses the need to do so)?

Also please insert the blank line at the end of your additions, and
no trailing full stops in log messages please.

> @@ -88,6 +89,16 @@ struct pci_dev {
>  #define for_each_pdev(domain, pdev) \
>      list_for_each_entry(pdev, &(domain->arch.pdev_list), domain_list)
>  
> +static inline void mark_pdev_unassignable(struct pci_dev *pdev)
> +{
> +    pdev->info.is_unassignable = 1;
> +}
> +
> +static inline bool_t is_pdev_unassignable(const struct pci_dev *pdev)
> +{
> +    return pdev->info.is_unassignable;
> +}

Are you aware that we already have a mechanism to prevent
assignment (via pci_{ro,hide}_device())? I think at the very least
this check should consider both variants. Whether fully using the
existing mechanism for your purpose is feasible I can't immediately
tell (since the ownership change may be problematic at the points
where you want the flagging to happen).

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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