xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Oleksandr Andrushchenko <andr2000@gmail.com>
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel <xen-devel@lists.xenproject.org>,
	Julien Grall <julien.grall@arm.com>
Subject: Re: arm64: dma_to_phys/phys_to_dma need to be properly implemented
Date: Tue, 28 Mar 2017 09:42:56 +0300	[thread overview]
Message-ID: <352020e8-53d5-d9f5-99d8-c8c491c5bc74@gmail.com> (raw)
In-Reply-To: <alpine.DEB.2.10.1703271312470.8001@sstabellini-ThinkPad-X260>

Hi, Stefano!

On 03/27/2017 11:23 PM, Stefano Stabellini wrote:
> Hello Oleksandr,
>
> Just to clarify, you are talking about dma_to_phys/phys_to_dma in Linux
> (not in Xen), right?
I am talking about Linux, sorry I was not clear
> Drivers shouldn't use those functions directly (see the comment in
> arch/arm64/include/asm/dma-mapping.h), they should call the appropriate
> dma_map_ops functions instead.
Yes, you are correct and I know about this and do not call
dma_to_phys/phys_to_dma directly
>   The dma_map_ops functions should do the
> right thing on Xen, even for pages where pfn != mfn, thanks to the
> swiotlb-xen (drivers/xen/swiotlb-xen.c). Specifically, you can see the
> special case for pfn != mfn here (see the "local" variable):
>
> arch/arm/include/asm/xen/page-coherent.h:xen_dma_map_page
Yes, the scenarios with pfn != mfn we had so
far are all working correct
>
> So, why are you calling dma_to_phys and phys_to_dma instead of the
> dma_map_ops functions?
Ok, let me give you an example of failing scenario which
was not used before this by any backend (this is from
my work on implementing zero copy for DRM drivers):

1. Create sg table from pages:
sg_alloc_table_from_pages(sgt, PFN_0, ...);
map it and get dev_bus_addr - at this stage sg table is
perfectly correct and properly mapped,
dev_bus_addr == (MFN_u << PAGE_SHIFT)

2. Duplicate it:
dma_get_sgtable(..., sgt, ... dev_bus_addr,...);
                               ^^^^^^^^^^^^
which finally lands at
__swiotlb_get_sgtable(..., dma_addr_t handle,...)
{
     ...
     sg_set_page(..., phys_to_page(dma_to_phys(dev, handle)),...);
                                   ^^^^^^^^^^^      ^^^^^^
     ...
}
At this stage sg table's page_link points to bad page, because
of linear translation of dma_to_phys, e.g. paddr == dev_bus_addr

3. Map the duplicated sg table:
dma_map_sg(..., sgt->sgl,...);
     xen_swiotlb_map_sg_attrs(..., struct scatterlist *sgl,...)
     {
         phys_addr_t paddr = sg_phys(sg);
                             ^^^^^^^
         dma_addr_t dev_addr = xen_phys_to_bus(paddr);
/*
the translation (sg_phys) above does:
         page_to_phys(...sg->page_link & ~0x3...) + ...;
so after this step we have WRONG paddr and correct dev_addr (because
wrong PFN is not found in P2M table, so it is used as is
*/
4. Now map segments of the table:
__swiotlb_map_page(..., struct page *page,...)
{
     ...
     dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
     if (!is_device_dma_coherent(dev))
         __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)),...);
                                     ^^^^^^^^^^^      ^^^^^^^^
     ...
}

5. Crash happens at
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)),...);
with
Unable to handle kernel paging request at virtual address
because dev_addr was NOT translated to correct paddr by dma_to_phys

Hope, this better explains why I am talking about dma_to_phys

So, I'm curious if we need to change dma_to_phys/phys_to_dma
or hide this translation in Xen specific code.
Another question is that for phys_to_dma we have __pfn_to_mfn,
but there is no reverse translation , e.g. __mfn_to_pfn
> Cheers,
>
> Stefano
Thank you,
Oleksandr
> On Mon, 27 Mar 2017, Oleksandr Andrushchenko wrote:
>> Hi, all!
>>
>> First of all this could be a generic ARM64 question, but
>> only(?) Xen users will suffer.
>>
>> At the moment for ARM64 dma_to_phys/phys_to_dma both assume that
>> MFN == PFN and though those do not do MFN <-> PFN conversion.
>> In case if MFN is mapped from other domain, then
>> MFN != PFN and the above assumption is not true any more and
>> proper MFN to PFN and vice versa must be implemented.
>>
>> Use-case:
>> 1. Get gref_u in DomU (PFN_u/MFN_u) and pass to Dom0
>> 2. Balloon out a page PFN_0
>> 3. Map gref_u onto PFN_0
>> 4. Now PFN_0 is mapped to MFN_u and PFN_0 != MFN_u
>>
>> If pair PFN_0/MFN_u is about to be used for example for
>> DMA sg table (which is my case), then conversion
>> dma_to_phys(MFN_u << PAGE_SHIFT) results in wrong PFN_bad,
>> not usable by CPU anymore because PFN_0 is expected instead
>>
>> Is there any reason for ARM64's dma_to_phys/phys_to_dma to be
>> not implemented?
>>
>> Thank you,
>>
>> Oleksandr
>>
>>
>> On 03/23/2017 05:40 PM, Oleksandr Andrushchenko wrote:
>>> Hi, all!
>>>
>>> I am trying to implement a zero-copy scenario for DRM front/back,
>>> e.g. buffers allocated by DomU in the DRM frontend used as is
>>> by Dom0. The requirement I have is that the buffer is contiguous.
>>>
>>> So, what I currently have is:
>>> 1. DomU is 1:1 mapped and is able to allocate physically contiguous
>>> buffer, e.g. PFNs and MFNs are sequential.
>>> 2. On Dom0 side I allocate ballooned pages (because I need reservation)
>>> and am able to map those (gnttab_map_refs with grefs from DomU):
>>> pfn 52a35 dev_bus_addr 6c100000
>>> pfn 52a34 dev_bus_addr 6c101000
>>> ...
>>> pfn 52a2c dev_bus_addr 6c109000
>>>
>>> 3. Then I have to create an SG table from these, so I can pass the buffer
>>> to real HW DRM driver: as you can see from the above PFNs they are not
>>> sequential as those were allocated from the balloon. Thus, sg_table
>>> is also has number of segments != 1 which is not ok for my use-case.
>>>
>>> Still, if I do __pfn_to_mfn(page_to_pfn(balloon_page[i])) I get the
>>>
>>> correct MFN, which is expected because p2m translation happens.
>>>
>>> 4. If I try to do a hack:
>>> dev_bus_pages[i] = pfn_to_page(MFN[i]) and then create an SG table from
>>> these pages then of course the sg table is configuous and
>>> I can share the SG with HW DRM driver.
>>> What is naturally happens next is:
>>> "Unable to handle kernel paging request at virtual address ffff80002c100000"
>>> [   86.263197] PC is at __clean_dcache_area_poc+0x20/0x40
>>> [   86.268377] LR is at __swiotlb_map_page+0x80/0x98
>>> for the very first maddr == 6c100000, because my dev_bus_addr[i] and
>>> dev_bus_pages[i] have no translation set up.
>>>
>>> So, the question: is there any way I can make those ballooned pages
>>> to convert into contiguous scatter-gather? So, sg table consists
>>> of a single entry?
>>>
>>> I was thinking of:
>>> 1. Is it possible to update translation manually so dev_bus_addr[i]
>>> has corresponding continuous pages, e.g. so I can do
>>> dev_bus_pages[i] = pfn_to_page(MFN[i]) and CPU can access those?
>>> 2. I can of course allocate contiguous buffer in Dom0 and
>>> manually (unfortunately there is no API to do that) increase/decrease
>>> reservation for the pages as balloon driver does and use those for mapping.
>>> This way MFN will follow PFN (we are in Dom0 which is 1:1).
>>> But this is going to be clumsy, as I'll have to copy-paste part
>>> of the balloon driver into mine (decrease_reservation/increase_reservation)
>>> 3. Any other neat solution?
>>>
>>> Thank you,
>>> Oleksandr


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

  reply	other threads:[~2017-03-28  6:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-23 15:40 gnttab_map_refs and contiguous buffer Oleksandr Andrushchenko
2017-03-27 10:16 ` arm64: dma_to_phys/phys_to_dma need to be properly implemented Oleksandr Andrushchenko
2017-03-27 20:23   ` Stefano Stabellini
2017-03-28  6:42     ` Oleksandr Andrushchenko [this message]
2017-03-28 12:40       ` Andrii Anisov
2017-03-28 13:04         ` Oleksandr Andrushchenko
2017-03-28 19:20       ` Stefano Stabellini
2017-03-29  6:17         ` Oleksandr Andrushchenko
2017-03-29 22:36           ` Stefano Stabellini
2017-03-29 22:48             ` Julien Grall
2017-03-31  8:15             ` Oleksandr Andrushchenko
2017-03-31 17:56               ` Stefano Stabellini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=352020e8-53d5-d9f5-99d8-c8c491c5bc74@gmail.com \
    --to=andr2000@gmail.com \
    --cc=julien.grall@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).