Re: [PATCH 2/4] x86: always initialize xen-swiotlb when xen-pcifront is enabling

From: Petr Tesařík
Date: Mon May 22 2023 - 03:55:40 EST


Hi Christoph,

On Sat, 20 May 2023 08:21:03 +0200
Christoph Hellwig <hch@xxxxxx> wrote:

> On Fri, May 19, 2023 at 02:58:57PM +0200, Christoph Hellwig wrote:
> > On Fri, May 19, 2023 at 01:49:46PM +0100, Andrew Cooper wrote:
> > > > The alternative would be to finally merge swiotlb-xen into swiotlb, in
> > > > which case we might be able to do this later. Let me see what I can
> > > > do there.
> > >
> > > If that is an option, it would be great to reduce the special-cashing.
> >
> > I think it's doable, and I've been wanting it for a while. I just
> > need motivated testers, but it seems like I just found at least two :)
>
> So looking at swiotlb-xen it does these off things where it takes a value
> generated originally be xen_phys_to_dma, then only does a dma_to_phys
> to go back and call pfn_valid on the result. Does this make sense, or
> is it wrong and just works by accident? I.e. is the patch below correct?
>
>
> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
> index 67aa74d201627d..3396c5766f0dd8 100644
> --- a/drivers/xen/swiotlb-xen.c
> +++ b/drivers/xen/swiotlb-xen.c
> @@ -90,9 +90,7 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
>
> static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
> {
> - unsigned long bfn = XEN_PFN_DOWN(dma_to_phys(dev, dma_addr));
> - unsigned long xen_pfn = bfn_to_local_pfn(bfn);
> - phys_addr_t paddr = (phys_addr_t)xen_pfn << XEN_PAGE_SHIFT;
> + phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);


I'm no big Xen expert, but I think this is wrong. Let's go through it
line by line:

- bfn = XEN_PFN_DOWN(dma_to_phys(dev, dma_addr));

Take the DMA address (as seen by devices on the bus), convert it to a
physical address (as seen by the CPU on the bus) and shift it right
by XEN_PAGE_SHIFT. The result is a Xen machine PFN.

- xen_pfn = bfn_to_local_pfn(bfn);

Take the machine PFN and converts it to a physical PFN.

- paddr = (phys_addr_t)xen_pfn << XEN_PAGE_SHIFT;

Convert the physical PFN to a physical address.

The important thing here is that Xen PV does not have auto-translated
physical addresses, so physical address != machine address. Physical
addresses in Xen PV domains are "artificial", used by the kernel to
index the mem_map array, so a PFN can be easily converted to a struct
page pointer and back. However, these addresses are never used by
hardware, not even by CPU. The addresses used by the CPU are called
machine addresses. There is no address translation between VCPUs and
CPUs, because a PV domain runs directly on the CPU. After all, that's
why it is called _para_virtualized.

HTH
Petr T