From mboxrd@z Thu Jan 1 00:00:00 1970 From: Konrad Rzeszutek Wilk Subject: Re: [PATCH] xen: swiotlb: handle sizeof(dma_addr_t) != sizeof(phys_addr_t) Date: Wed, 22 Jan 2014 16:01:54 -0500 Message-ID: <20140122210154.GC9585@phenom.dumpdata.com> References: <1389979493-22670-1-git-send-email-ian.campbell@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Content-Disposition: inline In-Reply-To: <1389979493-22670-1-git-send-email-ian.campbell@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Ian Campbell Cc: stefano.stabellini@eu.citrix.com, xen-devel@lists.xen.org List-Id: xen-devel@lists.xenproject.org On Fri, Jan 17, 2014 at 05:24:53PM +0000, Ian Campbell wrote: > The use of phys_to_machine and machine_to_phys in the phys<=>bus conversions > causes us to lose the top bits of the DMA address if the size of a DMA address is not the same as the size of the phyiscal address. .. physical > > This can happen in practice on ARM where foreign pages can be above 4GB even > though the local kernel does not have LPAE page tables enabled (which is > totally reasonable if the guest does not itself have >4GB of RAM). In this > case the kernel still maps the foreign pages at a phys addr below 4G (as it > must) but the resulting DMA address (returned by the grant map operation) is > much higher. > > This is analogous to a hardware device which has its view of RAM mapped up > high for some reason. > > This patch makes I/O to foreign pages (specifically blkif) work on 32-bit ARM > systems with more than 4GB of RAM. > > Signed-off-by: Ian Campbell > --- > arch/arm/Kconfig | 1 + > drivers/xen/swiotlb-xen.c | 14 ++++++++++++-- > 2 files changed, 13 insertions(+), 2 deletions(-) > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index c1f1a7e..24307dc 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -1885,6 +1885,7 @@ config XEN > depends on !GENERIC_ATOMIC64 > select ARM_PSCI > select SWIOTLB_XEN > + select ARCH_DMA_ADDR_T_64BIT > help > Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. > > diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c > index 1eac073..b626c79 100644 > --- a/drivers/xen/swiotlb-xen.c > +++ b/drivers/xen/swiotlb-xen.c > @@ -77,12 +77,22 @@ static u64 start_dma_addr; > > static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr) > { > - return phys_to_machine(XPADDR(paddr)).maddr; Why not change 'phys_addr_t' to be unsigned long? Wouldn't that solve the problem as well? Or make 'xmaddr_t' and 'xpaddr_t' use 'unsigned long' instead of phys_addr_t? > + unsigned long mfn = pfn_to_mfn(PFN_DOWN(paddr)); > + dma_addr_t dma = (dma_addr_t)mfn << PAGE_SHIFT; > + dma |= paddr & ~PAGE_MASK; > + return dma; > } > > static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr) > { > - return machine_to_phys(XMADDR(baddr)).paddr; > + dma_addr_t dma = PFN_PHYS(mfn_to_pfn(PFN_DOWN(baddr))); > + phys_addr_t paddr = dma; > + > + BUG_ON(paddr != dma); /* truncation has occurred, should never happen */ > + > + paddr |= baddr & ~PAGE_MASK; > + > + return paddr; > } > > static inline dma_addr_t xen_virt_to_bus(void *address) > -- > 1.7.10.4 >