diff options
author | Kefeng Wang <wangkefeng.wang@huawei.com> | 2022-06-07 14:50:25 +0200 |
---|---|---|
committer | Will Deacon <will@kernel.org> | 2022-06-27 13:22:31 +0200 |
commit | 18e780b4e6ab89a3a10f46d151971863562c1c91 (patch) | |
tree | af78abe8a479005ef769c60ac3d772d4a6afc014 /mm/ioremap.c | |
parent | mm: ioremap: Setup phys_addr of struct vm_struct (diff) | |
download | linux-18e780b4e6ab89a3a10f46d151971863562c1c91.tar.xz linux-18e780b4e6ab89a3a10f46d151971863562c1c91.zip |
mm: ioremap: Add ioremap/iounmap_allowed()
Add special hook for architecture to verify addr, size or prot
when ioremap() or iounmap(), which will make the generic ioremap
more useful.
ioremap_allowed() return a bool,
- true means continue to remap
- false means skip remap and return directly
iounmap_allowed() return a bool,
- true means continue to vunmap
- false code means skip vunmap and return directly
Meanwhile, only vunmap the address when it is in vmalloc area
as the generic ioremap only returns vmalloc addresses.
Acked-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Baoquan He <bhe@redhat.com>
Link: https://lore.kernel.org/r/20220607125027.44946-5-wangkefeng.wang@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'mm/ioremap.c')
-rw-r--r-- | mm/ioremap.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/mm/ioremap.c b/mm/ioremap.c index e1d008e8f87f..8652426282cc 100644 --- a/mm/ioremap.c +++ b/mm/ioremap.c @@ -28,6 +28,9 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, phys_addr -= offset; size = PAGE_ALIGN(size + offset); + if (!ioremap_allowed(phys_addr, size, prot)) + return NULL; + area = get_vm_area_caller(size, VM_IOREMAP, __builtin_return_address(0)); if (!area) @@ -47,6 +50,12 @@ 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 (!iounmap_allowed(vaddr)) + return; + + if (is_vmalloc_addr(vaddr)) + vunmap(vaddr); } EXPORT_SYMBOL(iounmap); |