|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [Xen-users] ARM: "xen_add_mach_to_phys_entry: cannot add ... already exists and panics"
On Fri, 4 Jul 2014, David Vrabel wrote:
> On 04/07/14 17:36, David Vrabel wrote:
> > On 04/07/14 15:31, Stefano Stabellini wrote:
> >> On Fri, 4 Jul 2014, David Vrabel wrote:
> >>> On 04/07/14 15:12, Stefano Stabellini wrote:
> >>>> On Fri, 4 Jul 2014, David Vrabel wrote:
> >>>>> On 03/07/14 18:47, Stefano Stabellini wrote:
> >>>>>>
> >>>>>> At the moment I would like a way to disable grant mappings and go back
> >>>>>> to grant copies on demand. Maybe we could have a feature flag to change
> >>>>>> the behaviour of the network backend?
> >>>>>
> >>>>> You must fix the ARM code to handle this properly.
> >>>>>
> >>>>> blkback also uses grant maps and depending on the frontend blkback may
> >>>>> grant map the same machine frame multiple time. We have see frontends
> >>>>> that send such requests.
> >>>>
> >>>> Indeed, it must be fixed properly. The workaround of disabling grant
> >>>> mappings would be just to buy us some time to come up with the fix.
> >>>
> >>> It's an expensive workaround though.
> >>
> >> In terms of performances or in terms of code?
> >> If it's the performances you are worried about, we could enable the
> >> workaround just for arm and arm64.
> >
> > Expensive in terms of effort required to implement and maintain.
> >
> >>>>> I can't remember how the ARM code works. Where is the problematic m2p
> >>>>> lookup?
> >>>>
> >>>> arch/arm/xen/p2m.c
> >>>>
> >>>>
> >>>>> Perhaps this could be avoided for foreign frames?
> >>>>
> >>>> Unfortunately no. The whole point of p2m.c is to be able to translate
> >>>> foreign frames for dma operations.
> >>>
> >>> This is a p2m lookup though, which is fine, yes? Where, specifically is
> >>> a mfn_to_pfn() lookup needed for a foreign MFN.
> >>
> >> drivers/xen/swiotlb-xen.c:xen_unmap_single. xen_bus_to_phys is based on
> >> the value returned by mfn_to_pfn.
> >
> > I think you can probably get away with not doing the cache operations on
> > foreign pages when DMA map/unmapping. DMA mapped foreign pages are
> > (currently) either:
> >
> > a) packets from a guest being Tx'd off host. These are read-only and
> > are immediately freed after they're tranmitted.
> >
> > b) block requests from blkback and these pages are never accessed.
Unfortunately it doesn't look like it is possible to skip the call to
__dma_page_dev_to_cpu
(xen_dma_unmap_page->arm_dma_unmap_page->__dma_page_dev_to_cpu), because
otherwise the data written by DMA to system memory won't be visible to
the CPU, at least on ARM32.
In fact the grant_unmap operation might issue flushes, but they are
inner flushes. While here we would need to issue an outer flush at the
very least. In addition to it, __dma_page_dev_to_cpu also calls
dmac_unmap_area, that on v7 becomes v7_dma_inv_range that issues a bunch
of DCCIMVAC.
So in order for this to work on grant_unmap Xen would have to:
- issue an outer flush
- DCCIMVAC the page
Also not all devices need this, only the non-coherent ones.
Given that we assume that Dom0 is mapped 1:1, one way to solve this
would be for Dom0 to map the grant on PFN=MFN too, then issue all the
required flushed on the machine address instead of the physical address.
> Something like:
>
> --- a/drivers/xen/swiotlb-xen.c
> +++ b/drivers/xen/swiotlb-xen.c
> @@ -90,17 +90,18 @@ static inline dma_addr_t xen_phys_to_bus(phys_addr_t
> paddr)
> return dma;
> }
>
> -static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr)
> +/* Return true if baddr is the address of a foreign frame. */
> +static inline int xen_bus_to_phys(dma_addr_t baddr, phys_addr_t *paddr)
> {
> unsigned long pfn = mfn_to_pfn(PFN_DOWN(baddr));
> dma_addr_t dma = (dma_addr_t)pfn << PAGE_SHIFT;
> - phys_addr_t paddr = dma;
>
> - BUG_ON(paddr != dma); /* truncation has occurred, should never happen */
> + if (pfn == INVALID_P2M_ENTRY)
> + return true;
>
> - paddr |= baddr & ~PAGE_MASK;
> + *paddr = dma | (baddr & ~PAGE_MASK);
>
> - return paddr;
> + return false;
> }
>
> static inline dma_addr_t xen_virt_to_bus(void *address)
> @@ -443,10 +444,30 @@ static void xen_unmap_single(struct device *hwdev,
> dma_addr_t dev_addr,
> size_t size, enum dma_data_direction dir,
> struct dma_attrs *attrs)
> {
> - phys_addr_t paddr = xen_bus_to_phys(dev_addr);
> + phys_addr_t paddr;
> + bool is_foreign;
>
> BUG_ON(dir == DMA_NONE);
>
> + is_foreign = xen_bus_to_phys(dev_addr, &paddr);
> +
> + /*
> + * We can't get the appropriate PFN for a foreign frame since
> + * it may be grant mapped multiple times.
> + *
> + * Assume that the grant unmap will do any appropriate cache
> + * operations, and that the frontend will do any for its own
> + * mappings.
> + *
> + * This does mean there is a window between the DMA unmap and
> + * the grant unmap where the CPU may see stale data (for a
> + * FROM_DEVICE operation), but this is not a problem in
> + * practice with the current users of foreign mappings
> + * (netback and blkback).
> + */
> + if (is_foreign)
> + return;
> +
> xen_dma_unmap_page(hwdev, paddr, size, dir, attrs);
>
> /* NOTE: We use dev_addr here, not paddr! */
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |