Add special check hook for architecture to verify addr, size or prot when ioremap() or iounmap(), which will make the generic ioremap more useful. Signed-off-by: Kefeng Wang <wangkefeng.wang@xxxxxxxxxx> --- include/asm-generic/io.h | 3 +++ mm/ioremap.c | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 7ce93aaf69f8..26924fded7c3 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -964,6 +964,9 @@ static inline void iounmap(volatile void __iomem *addr) #elif defined(CONFIG_GENERIC_IOREMAP) #include <linux/pgtable.h> +bool arch_ioremap_check(phys_addr_t addr, size_t size, unsigned long prot); +bool arch_iounmap_check(void __iomem *addr); + void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot); void iounmap(volatile void __iomem *addr); diff --git a/mm/ioremap.c b/mm/ioremap.c index 522ef899c35f..d1117005dcc7 100644 --- a/mm/ioremap.c +++ b/mm/ioremap.c @@ -11,6 +11,16 @@ #include <linux/io.h> #include <linux/export.h> +bool __weak arch_ioremap_check(phys_addr_t addr, size_t size, unsigned long prot) +{ + return true; +} + +bool __weak arch_iounmap_check(void __iomem *addr) +{ + return true; +} + void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot) { unsigned long offset, vaddr; @@ -27,6 +37,9 @@ void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot) addr -= offset; size = PAGE_ALIGN(size + offset); + if (!arch_ioremap_check(addr, size, prot)) + return NULL; + area = get_vm_area_caller(size, VM_IOREMAP, __builtin_return_address(0)); if (!area) @@ -45,6 +58,11 @@ EXPORT_SYMBOL(ioremap_prot); void iounmap(volatile void __iomem *addr) { - vunmap((void *)((unsigned long)addr & PAGE_MASK)); + void *vaddr = (void *)((unsigned long)addr & PAGE_MASK); + + if (!arch_iounmap_check(vaddr)) + return; + + vunmap(vaddr); } EXPORT_SYMBOL(iounmap); -- 2.26.2