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

Re: [Xen-devel] [2/3] [LINUX] gnttab: Add basic DMA tracking



On Wed, Jun 06, 2007 at 03:18:29PM +0900, Isaku Yamahata wrote:
> 
> This patch treats maddr_t as same as dma_addr_t.

Thanks I'll look into this.
 
> > diff -r 3ef0510e44d0 linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c
> > --- a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c   Tue May 08 
> > 10:21:23 2007 +0100
> > +++ b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c   Wed May 16 
> > 22:31:20 2007 +1000
>    [snip]
> > @@ -326,7 +335,8 @@ dma_map_single(struct device *dev, void 
> >     if (swiotlb) {
> >             dma = swiotlb_map_single(dev, ptr, size, direction);
> >     } else {
> > -           dma = virt_to_bus(ptr);
> > +           dma = gnttab_dma_map_page(virt_to_page(ptr)) +
> > +                 offset_in_page(ptr);
> >             IOMMU_BUG_ON(range_straddles_page_boundary(ptr, size));
> >             IOMMU_BUG_ON(address_needs_mapping(dev, dma));
> >     }
> > @@ -344,6 +354,8 @@ dma_unmap_single(struct device *dev, dma
> >             BUG();
> >     if (swiotlb)
> >             swiotlb_unmap_single(dev, dma_addr, size, direction);
> > +   else
> > +           gnttab_dma_unmap_page(dma_addr);
> >  }
> >  EXPORT_SYMBOL(dma_unmap_single);
> 
> Is it assumed that size <= PAGE_SIZE?
> Or should we iterate on the pointer with PAGE_SIZE?
> Am I missing anything else?

In this case it's a BUG if the entry crosses a page boundary.

> > diff -r 3ef0510e44d0 linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
> > --- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c       Tue May 08 
> > 10:21:23 2007 +0100
> > +++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c       Wed May 16 
> > 22:31:20 2007 +1000
>    ...
> > @@ -468,7 +467,8 @@ dma_addr_t
> >  dma_addr_t
> >  swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
> >  {
> > -   dma_addr_t dev_addr = virt_to_bus(ptr);
> > +   dma_addr_t dev_addr = gnttab_dma_map_page(virt_to_page(ptr)) +
> > +                         offset_in_page(ptr);
> >     void *map;
> >     struct phys_addr buffer;
> >  
> > @@ -486,6 +486,7 @@ swiotlb_map_single(struct device *hwdev,
> >     /*
> >      * Oh well, have to allocate and map a bounce buffer.
> >      */
> > +   gnttab_dma_unmap_page(dev_addr);
> >     buffer.page   = virt_to_page(ptr);
> >     buffer.offset = (unsigned long)ptr & ~PAGE_MASK;
> >     map = map_single(hwdev, buffer, size, dir);
> > @@ -513,6 +514,8 @@ swiotlb_unmap_single(struct device *hwde
> >     BUG_ON(dir == DMA_NONE);
> >     if (in_swiotlb_aperture(dev_addr))
> >             unmap_single(hwdev, bus_to_virt(dev_addr), size, dir);
> > +   else
> > +           gnttab_dma_unmap_page(dev_addr);
> >  }
> 
> Ditto.

It either crosses a page boundary, in which case we use the bounce
buffer, or it doesn't and this works fine.

> > +/*
> > + * Must not be called with IRQs off.  This should only be used on the
> > + * slow path.
> > + *
> > + * Copy a foreign granted page to local memory.
> > + */
> > +int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep)
> > +{
> > +   struct gnttab_unmap_and_replace unmap;
> > +   mmu_update_t mmu;
> > +   struct page *page;
> > +   struct page *new_page;
> > +   void *new_addr;
> > +   void *addr;
> > +   paddr_t pfn;
> > +   maddr_t mfn;
> > +   maddr_t new_mfn;
> > +   int err;
> > +
> > +   page = *pagep;
> > +   if (!get_page_unless_zero(page))
> > +           return -ENOENT;
> > +
> > +   err = -ENOMEM;
> > +   new_page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
> > +   if (!new_page)
> > +           goto out;
> > +
> > +   new_addr = page_address(new_page);
> > +   addr = page_address(page);
> > +   memcpy(new_addr, addr, PAGE_SIZE);
> > +
> > +   pfn = page_to_pfn(page);
> > +   mfn = pfn_to_mfn(pfn);
> > +   new_mfn = virt_to_mfn(new_addr);
> > +
> > +   if (!xen_feature(XENFEAT_auto_translated_physmap)) {
> > +           set_phys_to_machine(pfn, new_mfn);
> > +           set_phys_to_machine(page_to_pfn(new_page), INVALID_P2M_ENTRY);
> > +
> > +           mmu.ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
> > +           mmu.val = pfn;
> > +           err = HYPERVISOR_mmu_update(&mmu, 1, NULL, DOMID_SELF);
> > +           BUG_ON(err);
> > +   }
> > +
> > +   gnttab_set_replace_op(&unmap, (unsigned long)addr,
> > +                         (unsigned long)new_addr, ref);
> > +
> > +   err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
> > +                                   &unmap, 1);
> > +   BUG_ON(err);
> > +   BUG_ON(unmap.status);
> > +
> > +   new_page->mapping = page->mapping;
> > +   new_page->index = page->index;
> > +   set_bit(PG_foreign, &new_page->flags);
> > +   *pagep = new_page;
> > +
> > +   SetPageForeign(page, gnttab_page_free);
> > +   page->mapping = NULL;
> > +
> > +   /*
> > +    * Ensure that there is a barrier between setting the p2m entry
> > +    * and checking the map count.  See gnttab_dma_map_page.
> > +    */
> > +   smp_mb();
> > +
> > +   /* Has the page been DMA-mapped? */
> > +   if (unlikely(page_mapped(page))) {
> > +           err = -EBUSY;
> > +           page->mapping = (void *)new_page;
> 
> While DMA might be going on. the grant table mapped page is unmapped here.
> Since the page isn't referenced by this backend domain from the xen VMM
> point of view, the front end domain can be destroyed. (e.g. by xm destroy)
> So the page can be freed and reused for other purpose even though
> DMA is still being processed.
> The new user of the page (probably another domain) can be upset.
> Is this true?

Good catch.  If the frontend freed the page we'd be in trouble.  I suppose
we need a better solution.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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