Skip to content

Commit d7bca91

Browse files
Alexei Starovoitovborkmann
authored andcommitted
mm: Introduce vmap_page_range() to map pages in PCI address space
ioremap_page_range() should be used for ranges within vmalloc range only. The vmalloc ranges are allocated by get_vm_area(). PCI has "resource" allocator that manages PCI_IOBASE, IO_SPACE_LIMIT address range, hence introduce vmap_page_range() to be used exclusively to map pages in PCI address space. Fixes: 3e49a86 ("mm: Enforce VM_IOREMAP flag and range in ioremap_page_range.") Reported-by: Miguel Ojeda <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Tested-by: Miguel Ojeda <[email protected]> Link: https://lore.kernel.org/bpf/CANiq72ka4rir+RTN2FQoT=Vvprp_Ao-CvoYEkSNqtSY+RZj+AA@mail.gmail.com
1 parent 96b0f5a commit d7bca91

File tree

7 files changed

+32
-18
lines changed

7 files changed

+32
-18
lines changed

arch/arm/mm/ioremap.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ void __init add_static_vm_early(struct static_vm *svm)
110110
int ioremap_page(unsigned long virt, unsigned long phys,
111111
const struct mem_type *mtype)
112112
{
113-
return ioremap_page_range(virt, virt + PAGE_SIZE, phys,
114-
__pgprot(mtype->prot_pte));
113+
return vmap_page_range(virt, virt + PAGE_SIZE, phys,
114+
__pgprot(mtype->prot_pte));
115115
}
116116
EXPORT_SYMBOL(ioremap_page);
117117

@@ -466,8 +466,8 @@ int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
466466
if (res->end > IO_SPACE_LIMIT)
467467
return -EINVAL;
468468

469-
return ioremap_page_range(vaddr, vaddr + resource_size(res), phys_addr,
470-
__pgprot(get_mem_type(pci_ioremap_mem_type)->prot_pte));
469+
return vmap_page_range(vaddr, vaddr + resource_size(res), phys_addr,
470+
__pgprot(get_mem_type(pci_ioremap_mem_type)->prot_pte));
471471
}
472472
EXPORT_SYMBOL(pci_remap_iospace);
473473

arch/loongarch/kernel/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ static int __init add_legacy_isa_io(struct fwnode_handle *fwnode,
490490
}
491491

492492
vaddr = (unsigned long)(PCI_IOBASE + range->io_start);
493-
ioremap_page_range(vaddr, vaddr + size, hw_start, pgprot_device(PAGE_KERNEL));
493+
vmap_page_range(vaddr, vaddr + size, hw_start, pgprot_device(PAGE_KERNEL));
494494

495495
return 0;
496496
}

arch/mips/loongson64/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, resource_size_
180180

181181
vaddr = PCI_IOBASE + range->io_start;
182182

183-
ioremap_page_range(vaddr, vaddr + size, hw_start, pgprot_device(PAGE_KERNEL));
183+
vmap_page_range(vaddr, vaddr + size, hw_start, pgprot_device(PAGE_KERNEL));
184184

185185
return 0;
186186
}

arch/powerpc/kernel/isa-bridge.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ static void remap_isa_base(phys_addr_t pa, unsigned long size)
4646
WARN_ON_ONCE(size & ~PAGE_MASK);
4747

4848
if (slab_is_available()) {
49-
if (ioremap_page_range(ISA_IO_BASE, ISA_IO_BASE + size, pa,
50-
pgprot_noncached(PAGE_KERNEL)))
49+
if (vmap_page_range(ISA_IO_BASE, ISA_IO_BASE + size, pa,
50+
pgprot_noncached(PAGE_KERNEL)))
5151
vunmap_range(ISA_IO_BASE, ISA_IO_BASE + size);
5252
} else {
5353
early_ioremap_range(ISA_IO_BASE, pa, size,

drivers/pci/pci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4353,8 +4353,8 @@ int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
43534353
if (res->end > IO_SPACE_LIMIT)
43544354
return -EINVAL;
43554355

4356-
return ioremap_page_range(vaddr, vaddr + resource_size(res), phys_addr,
4357-
pgprot_device(PAGE_KERNEL));
4356+
return vmap_page_range(vaddr, vaddr + resource_size(res), phys_addr,
4357+
pgprot_device(PAGE_KERNEL));
43584358
#else
43594359
/*
43604360
* This architecture does not have memory mapped I/O space,

include/linux/io.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
2323
#ifdef CONFIG_MMU
2424
int ioremap_page_range(unsigned long addr, unsigned long end,
2525
phys_addr_t phys_addr, pgprot_t prot);
26+
int vmap_page_range(unsigned long addr, unsigned long end,
27+
phys_addr_t phys_addr, pgprot_t prot);
2628
#else
2729
static inline int ioremap_page_range(unsigned long addr, unsigned long end,
2830
phys_addr_t phys_addr, pgprot_t prot)
2931
{
3032
return 0;
3133
}
34+
static inline int vmap_page_range(unsigned long addr, unsigned long end,
35+
phys_addr_t phys_addr, pgprot_t prot)
36+
{
37+
return 0;
38+
}
3239
#endif
3340

3441
/*

mm/vmalloc.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,24 @@ static int vmap_range_noflush(unsigned long addr, unsigned long end,
304304
return err;
305305
}
306306

307+
int vmap_page_range(unsigned long addr, unsigned long end,
308+
phys_addr_t phys_addr, pgprot_t prot)
309+
{
310+
int err;
311+
312+
err = vmap_range_noflush(addr, end, phys_addr, pgprot_nx(prot),
313+
ioremap_max_page_shift);
314+
flush_cache_vmap(addr, end);
315+
if (!err)
316+
err = kmsan_ioremap_page_range(addr, end, phys_addr, prot,
317+
ioremap_max_page_shift);
318+
return err;
319+
}
320+
307321
int ioremap_page_range(unsigned long addr, unsigned long end,
308322
phys_addr_t phys_addr, pgprot_t prot)
309323
{
310324
struct vm_struct *area;
311-
int err;
312325

313326
area = find_vm_area((void *)addr);
314327
if (!area || !(area->flags & VM_IOREMAP)) {
@@ -322,13 +335,7 @@ int ioremap_page_range(unsigned long addr, unsigned long end,
322335
(long)area->addr + get_vm_area_size(area));
323336
return -ERANGE;
324337
}
325-
err = vmap_range_noflush(addr, end, phys_addr, pgprot_nx(prot),
326-
ioremap_max_page_shift);
327-
flush_cache_vmap(addr, end);
328-
if (!err)
329-
err = kmsan_ioremap_page_range(addr, end, phys_addr, prot,
330-
ioremap_max_page_shift);
331-
return err;
338+
return vmap_page_range(addr, end, phys_addr, prot);
332339
}
333340

334341
static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,

0 commit comments

Comments
 (0)