[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: xen-swiotlb issue when NVMe driver is enabled in Dom0 on ARM
On Thu, 21 Apr 2022, Rahul Singh wrote: > > On 20 Apr 2022, at 11:46 pm, Stefano Stabellini <sstabellini@xxxxxxxxxx> > > wrote: > > On Wed, 20 Apr 2022, Rahul Singh wrote: > >>> On 20 Apr 2022, at 3:36 am, Stefano Stabellini <sstabellini@xxxxxxxxxx> > >>> wrote: > >>>>> Then there is xen_swiotlb_init() which allocates some memory for > >>>>> swiotlb-xen at boot. It could lower the total amount of memory > >>>>> available, but if you disabled swiotlb-xen like I suggested, > >>>>> xen_swiotlb_init() still should get called and executed anyway at boot > >>>>> (it is called from arch/arm/xen/mm.c:xen_mm_init). So xen_swiotlb_init() > >>>>> shouldn't be the one causing problems. > >>>>> > >>>>> That's it -- there is nothing else in swiotlb-xen that I can think of. > >>>>> > >>>>> I don't have any good ideas, so I would only suggest to add more printks > >>>>> and report the results, for instance: > >>>> > >>>> As suggested I added the more printks but only difference I see is the > >>>> size apart > >>>> from that everything looks same . > >>>> > >>>> Please find the attached logs for xen and native linux boot. > >>> > >>> One difference is that the order of the allocations is significantly > >>> different after the first 3 allocations. It is very unlikely but > >>> possible that this is an unrelated concurrency bug that only occurs on > >>> Xen. I doubt it. > >> > >> I am not sure but just to confirm with you, I see below logs in every > >> scenario. > >> SWIOTLB memory allocated by linux swiotlb and used by xen-swiotlb. Is that > >> okay or it can cause some issue. > >> > >> [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off > >> [ 0.000000] software IO TLB: mapped [mem > >> 0x00000000f4000000-0x00000000f8000000] (64MB) > >> > >> snip from int __ref xen_swiotlb_init(int verbose, bool early) > >> /* > >> * IO TLB memory already allocated. Just use it. > >> > >> */ > >> > >> if (io_tlb_start != 0) { > >> > >> xen_io_tlb_start = phys_to_virt(io_tlb_start); > >> > >> goto end; > >> > >> } > > > > Unfortunately there is nothing obvious in the logs. I think we need to > > look at the in-details executions of Linux on Xen with swiotlb-xen and > > Linux on Xen without swiotlb-xen. The comparison with Linux on native is > > not very interesting because the memory layout is a bit different. > > > > The comparison between the two executions should be simple because > > swiotlb-xen should be transparent: in this simple case swiotlb-xen > > should end up calling always the same functions that would end up being > > called anyway without swiotlb-xen. Basically, it should only add a > > couple of extra steps in between, nothing else. > > > > As we have already discussed: > > > > - [no swiotlb-xen] dma_alloc_attrs --> dma_direct_alloc > > - [swiotlb-xen] dma_alloc_attrs --> xen_swiotlb_alloc_coherent --> > > dma_direct_alloc > > > > The result should be identical. In xen_swiotlb_alloc_coherent the code > > path taken should be: > > > > - xen_alloc_coherent_pages > > - if (((dev_addr + size - 1 <= dma_mask)) && > > !range_straddles_page_boundary(phys, size)) { > > *dma_handle = dev_addr; > > - return ret > > > > So basically, it should make zero difference. That is expected because > > swiotlb-xen really only comes into play for domU pages. For booting > > dom0, it should only be a "useless" indirection. > > > > In the case of xen_swiotlb_map_page, it should be similar. The path > > taken should be: > > > > if (dma_capable(dev, dev_addr, size, true) && > > !range_straddles_page_boundary(phys, size) && > > !xen_arch_need_swiotlb(dev, phys, dev_addr) && > > swiotlb_force != SWIOTLB_FORCE) > > goto done; > > > > which I think should correspond to this prints in your logs at line 400: > > > > DEBUG xen_swiotlb_map_page 400 phys=80003c4f000 dev_addr=80003c4f000 > > > > So that should be OK too. If different paths are taken, then we have a > > problem. If the paths above are taken there should be zero difference > > between the swiotlb-xen and the non-swiotlb-xen cases. > > > > Which brings me to your question about xen_swiotlb_init and this > > message: > > > > software IO TLB: mapped [mem 0x00000000f4000000-0x00000000f8000000] > > (64MB) > > > > The swiotlb-xen buffer should *not* be used if the code paths taken are > > the ones above. So it doesn't matter if it is allocated or not. You > > could comment out the code in xen_swiotlb_init and everything should > > still behave the same. > > > > Finally, my suggestion. Considering all the above, I would look *very* > > closely at the execution of Linux on Xen with and without swiotlb-xen. > > The differences should be really minimal. Adds prints to all the > > swiotlb-xen functions, but really only the following should matter: > > - xen_swiotlb_alloc_coherent > > - xen_swiotlb_map_page > > - xen_swiotlb_unmap_page > > > > What are the differences between the two executions? From the logs: > > > > - the allocation of the swiotlb-xen buffer which leads to 64MB of less > > memory available, but actually if you compared to Linux on Xen > > with/without swiotlb-xen this different would go away because > > xen_swiotlb_init would be called in both cases anyway > > > > - the size upgrade in xen_swiotlb_alloc_coherent: I can see several > > instances of the allocation size being increased. Is that causing the > > problem? It seems unlikely and you have already verified it is not the > > case by removing the size increase in xen_swiotlb_alloc_coherent > > > > - What else is different? There *must* be something, but it is not > > showing in the logs so far. > > > > > > The only other observation that I have, but it doesn't help, is that the > > failure happens on the second 4MB allocation when there is another > > concurrent memory allocation of 4K. Neither the 4MB nor the 4K are > > size-upgrades by xen_swiotlb_alloc_coherent. > > > > 4MB is an larger-than-usual size, but it shouldn't make that much of a > > difference. Is that problem that the 4MB have to be contiguous? I don't > > see how swiotlb-xen could have an impact in that regard, if not for the > > size increase in xen_swiotlb_alloc_coherent. > > > > Please let me know what you find. > > I debug the issue more today and found out that the only difference when > calling dma_alloc_attrs() from the NVMe driver [1] and the other driver is the > attribute “DMA_ATTR_NO_KERNEL_MAPPING". This is progress! > I remove the attribute "DMA_ATTR_NO_KERNEL_MAPPING” before > calling the xen_alloc_coherent_pages() , NVMe DMA allocation is successful > and the issue is not observed. > > Do you have any idea why attribute DMA_ATTR_NO_KERNEL_MAPPING is > causing the the issue with xen-swiotlb. Yes, if you look at xen_swiotlb_free_coherent, it is clear that things won't work for the DMA_ATTR_NO_KERNEL_MAPPING case. Can you have a try at the patch below? --- swiotlb-xen: handle DMA_ATTR_NO_KERNEL_MAPPING If DMA_ATTR_NO_KERNEL_MAPPING is set then the returned vaddr is a struct *page instead of the virtual mapping of the buffer. In xen_swiotlb_alloc_coherent, do not call virt_to_page, instead use the returned pointer directly. Also do not memset the buffer or struct page to zero. In xen_swiotlb_free_coherent, check DMA_ATTR_NO_KERNEL_MAPPING and set the page pointer appropriately. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 2b385c1b4a99..22d8779d3ac0 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -318,15 +318,21 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, !range_straddles_page_boundary(phys, size)) *dma_handle = dev_addr; else { + struct page *page; + if (xen_create_contiguous_region(phys, order, fls64(dma_mask), dma_handle) != 0) { xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs); return NULL; } *dma_handle = phys_to_dma(hwdev, *dma_handle); - SetPageXenRemapped(virt_to_page(ret)); + + if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) + page = ret; + else + virt_to_page(ret); + SetPageXenRemapped(page); } - memset(ret, 0, size); return ret; } @@ -349,7 +355,9 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, /* Convert the size to actually allocated. */ size = 1UL << (order + XEN_PAGE_SHIFT); - if (is_vmalloc_addr(vaddr)) + if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) + page = vaddr; + else if (is_vmalloc_addr(vaddr)) page = vmalloc_to_page(vaddr); else page = virt_to_page(vaddr);
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |