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

Re: [Xen-devel] [PATCH v4 01/10] vt-d: fix the IOMMU flush issue



On May 10, 2016 12:10 AM, Jan Beulich <JBeulich@xxxxxxxx> wrote:
> >>> On 06.05.16 at 10:54, <quan.xu@xxxxxxxxx> wrote:
> > -static void intel_iommu_iotlb_flush(struct domain *d, unsigned long
> > gfn, unsigned int page_count)
> > +static void iommu_flush_iotlb_page(struct domain *d, unsigned long gfn,
> > +                                   unsigned int page_count)
> 
> The new name suggests just one page. Please use e.g.
> iommu_flush_iotlb_pages() instead.
> 

Make sense. 

> >  {
> > -    __intel_iommu_iotlb_flush(d, gfn, 1, page_count);
> > +    iommu_flush_iotlb(d, gfn, 1, page_count);
> >  }
> 
> But of course the question is whether having this wrapper is useful in the 
> first
> place,


This wrapper assumes the 'dma_old_pte_present' is '1', but in another caller 
intel_iommu_map_page(), i.e. 


     intel_iommu_map_page()
    {
       ...
             if ( !this_cpu(iommu_dont_flush_iotlb) )
                  iommu_flush_iotlb(d, gfn, dma_pte_present(old), 1);
       ...
    }


the 'dma_old_pte_present' is not sure. 

in intel_iommu_map_page(),  if we can check the 'dma_pte_present(old)':
          -- 1, flush the pages.
          -- 0, don't flush the pages.

Then we can remove this wrapper.

If my description is not clear, I can send out the related change.

> the more that ...
> 
> > @@ -639,7 +646,7 @@ static void dma_pte_clear_one(struct domain
> *domain, u64 addr)
> >      iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
> >
> >      if ( !this_cpu(iommu_dont_flush_iotlb) )
> > -        __intel_iommu_iotlb_flush(domain, addr >> PAGE_SHIFT_4K, 1, 1);
> > +        iommu_flush_iotlb(domain, addr >> PAGE_SHIFT_4K, 1, 1);
> 
> ... it's being open coded here. IOW if you want to retain the wrapper, please
> use it here.
>

Waiting for the above discussion, if we still need the wrapper, I will use it 
here.


 
> > @@ -1391,13 +1399,19 @@ int domain_context_mapping_one(
> >      spin_unlock(&iommu->lock);
> >
> >      /* Context entry was previously non-present (with domid 0). */
> > -    if ( iommu_flush_context_device(iommu, 0, (((u16)bus) << 8) | devfn,
> > -                                    DMA_CCMD_MASK_NOBIT, 1) )
> > -        iommu_flush_write_buffer(iommu);
> > -    else
> > +    rc = iommu_flush_context_device(iommu, 0, (((u16)bus) << 8) | devfn,
> > +                                    DMA_CCMD_MASK_NOBIT, 1);
> > +
> > +    if ( !rc )
> >      {
> >          int flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0;
> > -        iommu_flush_iotlb_dsi(iommu, 0, 1, flush_dev_iotlb);
> > +        rc = iommu_flush_iotlb_dsi(iommu, 0, 1, flush_dev_iotlb);
> 
> Please take the opportunity and add the missing blank line (between
> declaration(s) and statement(s) in cases like this.
> 
> > +    }
> > +
> > +    if ( rc > 0 )
> 
> Can iommu_flush_context_device() return a positive value? If so, the logic is
> now likely wrong. If not (which is what I assume) I'd like to suggest adding a
> respective ASSERT() (even if only to document the fact). Or alternatively this
> if() could move into the immediately preceding one.
> 


Check it again. iommu_flush_context_device() can return a positive value.

If VT-d QI is enabled, the call tree up to iommu_flush_context_device():
                         -- flush_context_qi()  -- iommu_flush_context_device() 


i.e. 

In flush_context_qi()
{
...
    if ( flush_non_present_entry )
    {
        if ( !cap_caching_mode(iommu->cap) )
            return 1;
        else
            did = 0;
    }
...
}


and the ' flush_non_present_entry '  is really '1' for above code.



Could you tell me why the logic is now likely wrong? I will fix it first.

Quan
_______________________________________________
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®.