[PATCH 1/9] alpha: Convert mapping routine to rely on physical address

Leon Romanovsky posted 9 patches 1 week, 6 days ago
There is a newer version of this series
[PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Leon Romanovsky 1 week, 6 days ago
From: Leon Romanovsky <leonro@nvidia.com>

Alpha doesn't need struct *page and can perform mapping based on
physical addresses. So convert it to implement new .map_phys callback.

As part of this change, remove useless BUG_ON() as DMA mapping layer
ensures that right direction is provided.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 arch/alpha/kernel/pci_iommu.c | 47 +++++++++++++++--------------------
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index dc91de50f906d..b62d9937d1d3a 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -224,28 +224,25 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
    until either pci_unmap_single or pci_dma_sync_single is performed.  */
 
 static dma_addr_t
-pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
+pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size,
 		 int dac_allowed)
 {
 	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
 	dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
 	struct pci_iommu_arena *arena;
 	long npages, dma_ofs, i;
-	unsigned long paddr;
 	dma_addr_t ret;
 	unsigned int align = 0;
 	struct device *dev = pdev ? &pdev->dev : NULL;
 
-	paddr = __pa(cpu_addr);
-
 #if !DEBUG_NODIRECT
 	/* First check to see if we can use the direct map window.  */
 	if (paddr + size + __direct_map_base - 1 <= max_dma
 	    && paddr + size <= __direct_map_size) {
 		ret = paddr + __direct_map_base;
 
-		DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %ps\n",
-		      cpu_addr, size, ret, __builtin_return_address(0));
+		DBGA2("pci_map_single: [%pa,%zx] -> direct %llx from %ps\n",
+		      &paddr, size, ret, __builtin_return_address(0));
 
 		return ret;
 	}
@@ -255,8 +252,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
 	if (dac_allowed) {
 		ret = paddr + alpha_mv.pci_dac_offset;
 
-		DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %ps\n",
-		      cpu_addr, size, ret, __builtin_return_address(0));
+		DBGA2("pci_map_single: [%pa,%zx] -> DAC %llx from %ps\n",
+		      &paddr, size, ret, __builtin_return_address(0));
 
 		return ret;
 	}
@@ -290,10 +287,10 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
 		arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
 
 	ret = arena->dma_base + dma_ofs * PAGE_SIZE;
-	ret += (unsigned long)cpu_addr & ~PAGE_MASK;
+	ret += offset_in_page(paddr);
 
-	DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %ps\n",
-	      cpu_addr, size, npages, ret, __builtin_return_address(0));
+	DBGA2("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n",
+	      &paddr, size, npages, ret, __builtin_return_address(0));
 
 	return ret;
 }
@@ -322,19 +319,18 @@ static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
 	return NULL;
 }
 
-static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
-				     unsigned long offset, size_t size,
-				     enum dma_data_direction dir,
+static dma_addr_t alpha_pci_map_phys(struct device *dev, phys_addr_t phys,
+				     size_t size, enum dma_data_direction dir,
 				     unsigned long attrs)
 {
 	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	int dac_allowed;
 
-	BUG_ON(dir == DMA_NONE);
+	if (attrs & DMA_ATTR_MMIO)
+		return DMA_MAPPING_ERROR;
 
-	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
-	return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
-				size, dac_allowed);
+	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+	return pci_map_single_1(pdev, phys, size, dac_allowed);
 }
 
 /* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
@@ -343,7 +339,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
    the cpu to the buffer are guaranteed to see whatever the device
    wrote there.  */
 
-static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
+static void alpha_pci_unmap_phys(struct device *dev, dma_addr_t dma_addr,
 				 size_t size, enum dma_data_direction dir,
 				 unsigned long attrs)
 {
@@ -353,8 +349,6 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
 	struct pci_iommu_arena *arena;
 	long dma_ofs, npages;
 
-	BUG_ON(dir == DMA_NONE);
-
 	if (dma_addr >= __direct_map_base
 	    && dma_addr < __direct_map_base + __direct_map_size) {
 		/* Nothing to do.  */
@@ -429,7 +423,7 @@ static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
 	}
 	memset(cpu_addr, 0, size);
 
-	*dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
+	*dma_addrp = pci_map_single_1(pdev, virt_to_phys(cpu_addr), size, 0);
 	if (*dma_addrp == DMA_MAPPING_ERROR) {
 		free_pages((unsigned long)cpu_addr, order);
 		if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
@@ -643,9 +637,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
 	/* Fast path single entry scatterlists.  */
 	if (nents == 1) {
 		sg->dma_length = sg->length;
-		sg->dma_address
-		  = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
-				     sg->length, dac_allowed);
+		sg->dma_address = pci_map_single_1(pdev, sg_phys(sg),
+						   sg->length, dac_allowed);
 		if (sg->dma_address == DMA_MAPPING_ERROR)
 			return -EIO;
 		return 1;
@@ -917,8 +910,8 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
 const struct dma_map_ops alpha_pci_ops = {
 	.alloc			= alpha_pci_alloc_coherent,
 	.free			= alpha_pci_free_coherent,
-	.map_page		= alpha_pci_map_page,
-	.unmap_page		= alpha_pci_unmap_page,
+	.map_phys		= alpha_pci_map_phys,
+	.unmap_phys		= alpha_pci_unmap_phys,
 	.map_sg			= alpha_pci_map_sg,
 	.unmap_sg		= alpha_pci_unmap_sg,
 	.dma_supported		= alpha_pci_supported,
-- 
2.51.0
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Magnus Lindholm 1 week, 2 days ago
On Thu, Sep 18, 2025 at 8:45 PM Leon Romanovsky <leon@kernel.org> wrote:
>
> From: Leon Romanovsky <leonro@nvidia.com>
>
> Alpha doesn't need struct *page and can perform mapping based on
> physical addresses. So convert it to implement new .map_phys callback.


Hi,

SInce this patch affects the Alpha platform I got curious and decided to
try it out. The patch series requires some preparatory patches. Leon
provided me with links to his dmabuf-vfio branch, which had the
patches (and some prerequisite stuff) applied already.

Based on the dmabuf-vfio branch,  I've built a kernel and tested it on
my ES40 Alphaserver, the kernel booted fine but after a while of
moderate filesystem load I started seeing some ext3/4 related error
messages in the system logs. Rebooting with my old kernel into
single user mode, I was able to recover the filesystem using fsck.
Clearly this set of patches breaks things (at least on Alpha).

I haven't yet dug any deeper into the root causes of the file system
corruptions and I've only tested this on Alpha, maybe there has been
more testing done on other platforms targeted by this set
of patches?

Regards

Magnus Lindholm
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Leon Romanovsky 1 week, 1 day ago
On Mon, Sep 22, 2025 at 11:04:06PM +0200, Magnus Lindholm wrote:
> On Thu, Sep 18, 2025 at 8:45 PM Leon Romanovsky <leon@kernel.org> wrote:
> >
> > From: Leon Romanovsky <leonro@nvidia.com>
> >
> > Alpha doesn't need struct *page and can perform mapping based on
> > physical addresses. So convert it to implement new .map_phys callback.
> 
> 
> Hi,
> 
> SInce this patch affects the Alpha platform I got curious and decided to
> try it out. The patch series requires some preparatory patches. Leon
> provided me with links to his dmabuf-vfio branch, which had the
> patches (and some prerequisite stuff) applied already.
> 
> Based on the dmabuf-vfio branch,  I've built a kernel and tested it on
> my ES40 Alphaserver, the kernel booted fine but after a while of
> moderate filesystem load I started seeing some ext3/4 related error
> messages in the system logs. Rebooting with my old kernel into
> single user mode, I was able to recover the filesystem using fsck.
> Clearly this set of patches breaks things (at least on Alpha).

I will try to setup Alpha architecture in QEMU in following days, but
would like to ask first. Did you test alpha on clean v6.17-rc5 (without
my patches) as a reference?

Thanks
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Magnus Lindholm 1 week, 1 day ago
>
> I will try to setup Alpha architecture in QEMU in following days, but
> would like to ask first. Did you test alpha on clean v6.17-rc5 (without
> my patches) as a reference?
>
I'm running now on a fresh git pull from today so it's more like a
6.17-rc7. So no problems running the latest git at least.  I can
dig deeper into this to see if we can figure this one out. First
of all, is this alpha specific?

Regards

Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Jason Gunthorpe 1 week, 1 day ago
On Tue, Sep 23, 2025 at 09:34:31PM +0200, Magnus Lindholm wrote:
> >
> > I will try to setup Alpha architecture in QEMU in following days, but
> > would like to ask first. Did you test alpha on clean v6.17-rc5 (without
> > my patches) as a reference?
> >
> I'm running now on a fresh git pull from today so it's more like a
> 6.17-rc7. So no problems running the latest git at least.  I can
> dig deeper into this to see if we can figure this one out. First
> of all, is this alpha specific?

I spent a bit of time looking at the alpha patch and could not spot a
typo, it looked OK to me. I was worried for a bit that virt_to_phys()
vs __pa() were different, but I could not find a difference.

Suggest testing the same branch with the alpha patch reverted just to
rule out any issue in the core code. If it reproduces suggest to
bisect Leon's branch.

Thanks,
Jason
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Magnus Lindholm 1 week, 1 day ago
> Suggest testing the same branch with the alpha patch reverted just to
> rule out any issue in the core code. If it reproduces suggest to
> bisect Leon's branch.
>
I can try to revert just the patch containing the alpha-specific stuff and
see what happens and then, as  you say, maybe do a bisect from there.
First I'll just try the same kernel again a few times more just to make sure
that this is really reproducible.

/Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Magnus Lindholm 4 days, 14 hours ago
> > Suggest testing the same branch with the alpha patch reverted just to
> > rule out any issue in the core code. If it reproduces suggest to
> > bisect Leon's branch.

Hi again, I've booted up the ES40 again with the kernel build from Leons
branch, it boots up but message log is full off messages like
"EXT4-fs error (device sda4): ext4_find_extent:939: inode
#16257327: comm init: pblk 65114257 bad header/extent:
invalid magic"

The filesystem is broken after just booting with the kernel.
This time fsck did not fix it, I needed to re-install gentoo stage3.
So it's for sure reproducible as well as destructive.  It's not possible to
revert all the commits individually, since this will leave the source tree
in a state where the kernel doesn't build. I've started off by reverting
the following commits:

e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unused map_page callback)

d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)

3cd47242d513050d7a81ac6e7020fd3ef5462ad4
(block-dma: properly take MMIO path)

7950995bef32aa7e5f74699c7d0fdac41d2dad14
 (block-dma: migrate to dma_map_phys instead of map_page)


After reverting the above commits, I'm able to build a working kernel,
that is, no filesystem corruption occurs. I'll take a closer look at this
after the weekend.

Regards

Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Magnus Lindholm 3 days, 22 hours ago
> After reverting the above commits, I'm able to build a working kernel,
> that is, no filesystem corruption occurs. I'll take a closer look at this
> after the weekend.
>

Short update,  It is enough to revert the following commits, in order to
have a working kernel on alpha:

e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unused map_page callback)

d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)


/Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Leon Romanovsky 3 days, 22 hours ago
On Sun, Sep 28, 2025 at 12:23:48PM +0200, Magnus Lindholm wrote:
> > After reverting the above commits, I'm able to build a working kernel,
> > that is, no filesystem corruption occurs. I'll take a closer look at this
> > after the weekend.
> >
> 
> Short update,  It is enough to revert the following commits, in order to
> have a working kernel on alpha:
> 
> e78a9d72517a88faa6f16dab4d1c6f966ed378ae
> (dma-mapping: remove unused map_page callback)
> 
> d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
> (alpha: Convert mapping routine to rely on physical address)

Thanks for the effort.

Can you please check the following change instead of reverting the patches?

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index b62d9937d1d3a..3e4f631a1f27d 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -229,6 +229,7 @@ pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size,
 {
        struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
        dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+       unsigned long offset = offset_in_page(paddr);
        struct pci_iommu_arena *arena;
        long npages, dma_ofs, i;
        dma_addr_t ret;
@@ -287,7 +288,7 @@ pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size,
                arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);

        ret = arena->dma_base + dma_ofs * PAGE_SIZE;
-       ret += offset_in_page(paddr);
+       ret += offset;

        DBGA2("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n",
              &paddr, size, npages, ret, __builtin_return_address(0));
~


> 
> 
> /Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Magnus Lindholm 3 days, 21 hours ago
> Thanks for the effort.
>
> Can you please check the following change instead of reverting the patches?
>

No problem, happy to assist. I think this did the trick! preliminary
testing shows
that this now works on alpha! I guess the offset information in paddr was lost
by doing "paddr &= PAGE_MASK" before retrieving the offset, well spotted!

I'll keep running the system with some load to make sure there is nothing else
we haven't spotted yet, but so far so good. I'll keep you posted.

Will you be putting out a v2 of this patchset with these updates?

Regards

Magnus Lindholm
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Posted by Leon Romanovsky 3 days, 21 hours ago
On Sun, Sep 28, 2025 at 01:27:12PM +0200, Magnus Lindholm wrote:
> > Thanks for the effort.
> >
> > Can you please check the following change instead of reverting the patches?
> >
> 
> No problem, happy to assist. I think this did the trick! preliminary
> testing shows
> that this now works on alpha! I guess the offset information in paddr was lost
> by doing "paddr &= PAGE_MASK" before retrieving the offset, well spotted!
> 
> I'll keep running the system with some load to make sure there is nothing else
> we haven't spotted yet, but so far so good. I'll keep you posted.
> 
> Will you be putting out a v2 of this patchset with these updates?

Yes, will try to send today. 

Thanks again for your help.

> 
> Regards
> 
> Magnus Lindholm