mm/ioremap: pass pgprot_t to ioremap_prot() instead of unsigned long

ioremap_prot() currently accepts pgprot_val parameter as an unsigned long,
thus implicitly assuming that pgprot_val and pgprot_t could never be
bigger than unsigned long.  But this assumption soon will not be true on
arm64 when using D128 pgtables.  In 128 bit page table configuration,
unsigned long is 64 bit, but pgprot_t is 128 bit.

Passing platform abstracted pgprot_t argument is better as compared to
size based data types.  Let's change the parameter to directly pass
pgprot_t like another similar helper generic_ioremap_prot().

Without this change in place, D128 configuration does not work on arm64 as
the top 64 bits gets silently stripped when passing the protection value
to this function.

Link: https://lkml.kernel.org/r/20250218101954.415331-1-anshuman.khandual@arm.com
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
Co-developed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com> [arm64]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Ryan Roberts 2025-02-18 15:49:54 +05:30 committed by Andrew Morton
parent af3b45aac5
commit 86758b5048
30 changed files with 55 additions and 59 deletions

View File

@ -32,7 +32,7 @@ void __iomem *ioremap(phys_addr_t paddr, unsigned long size)
return (void __iomem *)(u32)paddr;
return ioremap_prot(paddr, size,
pgprot_val(pgprot_noncached(PAGE_KERNEL)));
pgprot_noncached(PAGE_KERNEL));
}
EXPORT_SYMBOL(ioremap);
@ -44,10 +44,8 @@ EXPORT_SYMBOL(ioremap);
* might need finer access control (R/W/X)
*/
void __iomem *ioremap_prot(phys_addr_t paddr, size_t size,
unsigned long flags)
pgprot_t prot)
{
pgprot_t prot = __pgprot(flags);
/* force uncached */
return generic_ioremap_prot(paddr, size, pgprot_noncached(prot));
}

View File

@ -270,9 +270,9 @@ int arm64_ioremap_prot_hook_register(const ioremap_prot_hook_t hook);
#define _PAGE_IOREMAP PROT_DEVICE_nGnRE
#define ioremap_wc(addr, size) \
ioremap_prot((addr), (size), PROT_NORMAL_NC)
ioremap_prot((addr), (size), __pgprot(PROT_NORMAL_NC))
#define ioremap_np(addr, size) \
ioremap_prot((addr), (size), PROT_DEVICE_nGnRnE)
ioremap_prot((addr), (size), __pgprot(PROT_DEVICE_nGnRnE))
/*
* io{read,write}{16,32,64}be() macros
@ -293,7 +293,7 @@ static inline void __iomem *ioremap_cache(phys_addr_t addr, size_t size)
if (pfn_is_map_memory(__phys_to_pfn(addr)))
return (void __iomem *)__phys_to_virt(addr);
return ioremap_prot(addr, size, PROT_NORMAL);
return ioremap_prot(addr, size, __pgprot(PROT_NORMAL));
}
/*

View File

@ -379,7 +379,7 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
prot = __acpi_get_writethrough_mem_attribute();
}
}
return ioremap_prot(phys, size, pgprot_val(prot));
return ioremap_prot(phys, size, prot);
}
/*

View File

@ -15,10 +15,9 @@ int arm64_ioremap_prot_hook_register(ioremap_prot_hook_t hook)
}
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot)
pgprot_t pgprot)
{
unsigned long last_addr = phys_addr + size - 1;
pgprot_t pgprot = __pgprot(prot);
/* Don't allow outside PHYS_MASK */
if (last_addr & ~PHYS_MASK)

View File

@ -36,7 +36,7 @@
*/
#define ioremap_wc(addr, size) \
ioremap_prot((addr), (size), \
(_PAGE_IOREMAP & ~_CACHE_MASK) | _CACHE_UNCACHED)
__pgprot((_PAGE_IOREMAP & ~_CACHE_MASK) | _CACHE_UNCACHED))
#include <asm-generic/io.h>

View File

@ -23,9 +23,9 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size);
#ifdef CONFIG_ARCH_IOREMAP
static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val)
pgprot_t prot)
{
switch (prot_val & _CACHE_MASK) {
switch (pgprot_val(prot) & _CACHE_MASK) {
case _CACHE_CC:
return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
case _CACHE_SUC:
@ -38,7 +38,7 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
}
#define ioremap(offset, size) \
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_SUC))
ioremap_prot((offset), (size), PAGE_KERNEL_SUC)
#define iounmap(addr) ((void)(addr))
@ -55,10 +55,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
*/
#define ioremap_wc(offset, size) \
ioremap_prot((offset), (size), \
pgprot_val(wc_enabled ? PAGE_KERNEL_WUC : PAGE_KERNEL_SUC))
wc_enabled ? PAGE_KERNEL_WUC : PAGE_KERNEL_SUC)
#define ioremap_cache(offset, size) \
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
ioremap_prot((offset), (size), PAGE_KERNEL)
#define mmiowb() wmb()

View File

@ -126,7 +126,7 @@ static inline unsigned long isa_virt_to_bus(volatile void *address)
}
void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val);
pgprot_t prot);
void iounmap(const volatile void __iomem *addr);
/*
@ -141,7 +141,7 @@ void iounmap(const volatile void __iomem *addr);
* address.
*/
#define ioremap(offset, size) \
ioremap_prot((offset), (size), _CACHE_UNCACHED)
ioremap_prot((offset), (size), __pgprot(_CACHE_UNCACHED))
/*
* ioremap_cache - map bus memory into CPU space
@ -159,7 +159,7 @@ void iounmap(const volatile void __iomem *addr);
* memory-like regions on I/O busses.
*/
#define ioremap_cache(offset, size) \
ioremap_prot((offset), (size), _page_cachable_default)
ioremap_prot((offset), (size), __pgprot(_page_cachable_default))
/*
* ioremap_wc - map bus memory into CPU space
@ -180,7 +180,7 @@ void iounmap(const volatile void __iomem *addr);
* _CACHE_UNCACHED option (see cpu_probe() method).
*/
#define ioremap_wc(offset, size) \
ioremap_prot((offset), (size), boot_cpu_data.writecombine)
ioremap_prot((offset), (size), __pgprot(boot_cpu_data.writecombine))
#if defined(CONFIG_CPU_CAVIUM_OCTEON)
#define war_io_reorder_wmb() wmb()

View File

@ -44,9 +44,9 @@ static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages,
* ioremap_prot gives the caller control over cache coherency attributes (CCA)
*/
void __iomem *ioremap_prot(phys_addr_t phys_addr, unsigned long size,
unsigned long prot_val)
pgprot_t prot)
{
unsigned long flags = prot_val & _CACHE_MASK;
unsigned long flags = pgprot_val(prot) & _CACHE_MASK;
unsigned long offset, pfn, last_pfn;
struct vm_struct *area;
phys_addr_t last_addr;

View File

@ -3,9 +3,9 @@
#include <ioremap.h>
void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val)
pgprot_t prot)
{
unsigned long flags = prot_val & _CACHE_MASK;
unsigned long flags = pgprot_val(prot) & _CACHE_MASK;
u64 base = (flags == _CACHE_UNCACHED ? IO_BASE : UNCAC_BASE);
void __iomem *addr;

View File

@ -131,7 +131,7 @@ static inline void gsc_writeq(unsigned long long val, unsigned long addr)
_PAGE_ACCESSED | _PAGE_NO_CACHE)
#define ioremap_wc(addr, size) \
ioremap_prot((addr), (size), _PAGE_IOREMAP)
ioremap_prot((addr), (size), __pgprot(_PAGE_IOREMAP))
#define pci_iounmap pci_iounmap

View File

@ -14,7 +14,7 @@
#include <linux/mm.h>
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot)
pgprot_t prot)
{
#ifdef CONFIG_EISA
unsigned long end = phys_addr + size - 1;
@ -41,6 +41,6 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
}
}
return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
return generic_ioremap_prot(phys_addr, size, prot);
}
EXPORT_SYMBOL(ioremap_prot);

View File

@ -895,7 +895,7 @@ void __iomem *ioremap_wt(phys_addr_t address, unsigned long size);
void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size);
#define ioremap_cache(addr, size) \
ioremap_prot((addr), (size), pgprot_val(PAGE_KERNEL))
ioremap_prot((addr), (size), PAGE_KERNEL)
#define iounmap iounmap

View File

@ -41,9 +41,9 @@ void __iomem *ioremap_coherent(phys_addr_t addr, unsigned long size)
return __ioremap_caller(addr, size, prot, caller);
}
void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long flags)
void __iomem *ioremap_prot(phys_addr_t addr, size_t size, pgprot_t prot)
{
pte_t pte = __pte(flags);
pte_t pte = __pte(pgprot_val(prot));
void *caller = __builtin_return_address(0);
/* writeable implies dirty for kernel addresses */

View File

@ -190,10 +190,10 @@ static void spu_unmap(struct spu *spu)
static int __init setup_areas(struct spu *spu)
{
struct table {char* name; unsigned long addr; unsigned long size;};
unsigned long shadow_flags = pgprot_val(pgprot_noncached_wc(PAGE_KERNEL_RO));
spu_pdata(spu)->shadow = ioremap_prot(spu_pdata(spu)->shadow_addr,
sizeof(struct spe_shadow), shadow_flags);
sizeof(struct spe_shadow),
pgprot_noncached_wc(PAGE_KERNEL_RO));
if (!spu_pdata(spu)->shadow) {
pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
goto fail_ioremap;

View File

@ -137,7 +137,7 @@ __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw())
#ifdef CONFIG_MMU
#define arch_memremap_wb(addr, size) \
((__force void *)ioremap_prot((addr), (size), _PAGE_KERNEL))
((__force void *)ioremap_prot((addr), (size), __pgprot(_PAGE_KERNEL)))
#endif
#endif /* _ASM_RISCV_IO_H */

View File

@ -305,7 +305,7 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
}
}
return ioremap_prot(phys, size, pgprot_val(prot));
return ioremap_prot(phys, size, prot);
}
#ifdef CONFIG_PCI

View File

@ -33,9 +33,9 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
#define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL)
#define ioremap_wc(addr, size) \
ioremap_prot((addr), (size), pgprot_val(pgprot_writecombine(PAGE_KERNEL)))
ioremap_prot((addr), (size), pgprot_writecombine(PAGE_KERNEL))
#define ioremap_wt(addr, size) \
ioremap_prot((addr), (size), pgprot_val(pgprot_writethrough(PAGE_KERNEL)))
ioremap_prot((addr), (size), pgprot_writethrough(PAGE_KERNEL))
static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
{

View File

@ -255,7 +255,7 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
}
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot)
pgprot_t prot)
{
/*
* When PCI MIO instructions are unavailable the "physical" address
@ -265,7 +265,7 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
if (!static_branch_unlikely(&have_mio))
return (void __iomem *)phys_addr;
return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
return generic_ioremap_prot(phys_addr, size, prot);
}
EXPORT_SYMBOL(ioremap_prot);

View File

@ -58,7 +58,7 @@ static int __init landisk_devices_setup(void)
/* open I/O area window */
paddrbase = virt_to_phys((void *)PA_AREA5_IO);
prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, pgprot_val(prot));
cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, prot);
if (!cf_ide_base) {
printk("allocate_cf_area : can't open CF I/O window!\n");
return -ENOMEM;

View File

@ -53,7 +53,7 @@ static int __init lboxre2_devices_setup(void)
paddrbase = virt_to_phys((void*)PA_AREA5_IO);
psize = PAGE_SIZE;
prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
cf0_io_base = (u32)ioremap_prot(paddrbase, psize, pgprot_val(prot));
cf0_io_base = (u32)ioremap_prot(paddrbase, psize, prot);
if (!cf0_io_base) {
printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ );
return -ENOMEM;

View File

@ -75,7 +75,7 @@ static int __init sh03_devices_setup(void)
/* open I/O area window */
paddrbase = virt_to_phys((void *)PA_AREA5_IO);
prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, pgprot_val(prot));
cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, prot);
if (!cf_ide_base) {
printk("allocate_cf_area : can't open CF I/O window!\n");
return -ENOMEM;

View File

@ -299,7 +299,7 @@ unsigned long long poke_real_address_q(unsigned long long addr,
#define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL_NOCACHE)
#define ioremap_cache(addr, size) \
ioremap_prot((addr), (size), pgprot_val(PAGE_KERNEL))
ioremap_prot((addr), (size), PAGE_KERNEL)
#endif /* CONFIG_MMU */
#include <asm-generic/io.h>

View File

@ -73,10 +73,9 @@ __ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot)
#endif /* CONFIG_29BIT */
void __iomem __ref *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot)
pgprot_t pgprot)
{
void __iomem *mapped;
pgprot_t pgprot = __pgprot(prot);
mapped = __ioremap_trapped(phys_addr, size);
if (mapped)

View File

@ -170,7 +170,7 @@ extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
#define ioremap_uc ioremap_uc
extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
#define ioremap_cache ioremap_cache
extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, unsigned long prot_val);
extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, pgprot_t prot);
#define ioremap_prot ioremap_prot
extern void __iomem *ioremap_encrypted(resource_size_t phys_addr, unsigned long size);
#define ioremap_encrypted ioremap_encrypted

View File

@ -440,10 +440,10 @@ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
EXPORT_SYMBOL(ioremap_cache);
void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
unsigned long prot_val)
pgprot_t prot)
{
return __ioremap_caller(phys_addr, size,
pgprot2cachemode(__pgprot(prot_val)),
pgprot2cachemode(prot),
__builtin_return_address(0), false);
}
EXPORT_SYMBOL(ioremap_prot);

View File

@ -29,7 +29,7 @@
* I/O memory mapping functions.
*/
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot);
pgprot_t prot);
#define ioremap_prot ioremap_prot
#define iounmap iounmap
@ -40,7 +40,7 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR);
else
return ioremap_prot(offset, size,
pgprot_val(pgprot_noncached(PAGE_KERNEL)));
pgprot_noncached(PAGE_KERNEL));
}
#define ioremap ioremap
@ -51,7 +51,7 @@ static inline void __iomem *ioremap_cache(unsigned long offset,
&& offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE)
return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR);
else
return ioremap_prot(offset, size, pgprot_val(PAGE_KERNEL));
return ioremap_prot(offset, size, PAGE_KERNEL);
}
#define ioremap_cache ioremap_cache

View File

@ -11,12 +11,12 @@
#include <asm/io.h>
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot)
pgprot_t prot)
{
unsigned long pfn = __phys_to_pfn((phys_addr));
WARN_ON(pfn_valid(pfn));
return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
return generic_ioremap_prot(phys_addr, size, prot);
}
EXPORT_SYMBOL(ioremap_prot);

View File

@ -1111,7 +1111,7 @@ void __iomem *generic_ioremap_prot(phys_addr_t phys_addr, size_t size,
pgprot_t prot);
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot);
pgprot_t prot);
void iounmap(volatile void __iomem *addr);
void generic_iounmap(volatile void __iomem *addr);
@ -1120,7 +1120,7 @@ void generic_iounmap(volatile void __iomem *addr);
static inline void __iomem *ioremap(phys_addr_t addr, size_t size)
{
/* _PAGE_IOREMAP needs to be supplied by the architecture */
return ioremap_prot(addr, size, _PAGE_IOREMAP);
return ioremap_prot(addr, size, __pgprot(_PAGE_IOREMAP));
}
#endif
#endif /* !CONFIG_MMU || CONFIG_GENERIC_IOREMAP */

View File

@ -50,9 +50,9 @@ void __iomem *generic_ioremap_prot(phys_addr_t phys_addr, size_t size,
#ifndef ioremap_prot
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
unsigned long prot)
pgprot_t prot)
{
return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
return generic_ioremap_prot(phys_addr, size, prot);
}
EXPORT_SYMBOL(ioremap_prot);
#endif

View File

@ -6727,7 +6727,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
void *buf, int len, int write)
{
resource_size_t phys_addr;
unsigned long prot = 0;
pgprot_t prot = __pgprot(0);
void __iomem *maddr;
int offset = offset_in_page(addr);
int ret = -EINVAL;
@ -6737,7 +6737,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
retry:
if (follow_pfnmap_start(&args))
return -EINVAL;
prot = pgprot_val(args.pgprot);
prot = args.pgprot;
phys_addr = (resource_size_t)args.pfn << PAGE_SHIFT;
writable = args.writable;
follow_pfnmap_end(&args);
@ -6752,7 +6752,7 @@ retry:
if (follow_pfnmap_start(&args))
goto out_unmap;
if ((prot != pgprot_val(args.pgprot)) ||
if ((pgprot_val(prot) != pgprot_val(args.pgprot)) ||
(phys_addr != (args.pfn << PAGE_SHIFT)) ||
(writable != args.writable)) {
follow_pfnmap_end(&args);