ANDROID: mm/vmalloc: Add arch-specific callbacks to track io{remap,unmap} physical pages

Add a pair of hooks (ioremap_phys_range_hook/iounmap_phys_range_hook)
that can be implemented by an architecture. Contrary to the existing
arch_sync_kernel_mappings(), this one tracks things at the physical
address level.

This is specially useful in these virtualised environments where
the guest has to tell the host whether (and how) it intends to use
a MMIO device.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Bug: 233587962
Change-Id: I970c2e632cb2b01060d5e66e4194fa9248188f43
Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
Marc Zyngier
2021-06-30 13:24:32 +01:00
committed by Will Deacon
parent 9f78e5888d
commit d7ddd989d6
3 changed files with 18 additions and 1 deletions

View File

@@ -21,6 +21,8 @@ void __ioread32_copy(void *to, const void __iomem *from, size_t count);
void __iowrite64_copy(void __iomem *to, const void *from, size_t count); void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
void ioremap_phys_range_hook(phys_addr_t phys_addr, size_t size, pgprot_t prot);
void iounmap_phys_range_hook(phys_addr_t phys_addr, size_t size);
int ioremap_page_range(unsigned long addr, unsigned long end, int ioremap_page_range(unsigned long addr, unsigned long end,
phys_addr_t phys_addr, pgprot_t prot); phys_addr_t phys_addr, pgprot_t prot);
#else #else

View File

@@ -894,6 +894,11 @@ config KMAP_LOCAL_NON_LINEAR_PTE_ARRAY
config IO_MAPPING config IO_MAPPING
bool bool
# Some architectures want callbacks for all IO mappings in order to
# track the physical addresses that get used as devices.
config ARCH_HAS_IOREMAP_PHYS_HOOKS
bool
config SECRETMEM config SECRETMEM
def_bool ARCH_HAS_SET_DIRECT_MAP && !EMBEDDED def_bool ARCH_HAS_SET_DIRECT_MAP && !EMBEDDED

View File

@@ -38,6 +38,7 @@
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/io.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/shmparam.h> #include <asm/shmparam.h>
@@ -316,9 +317,14 @@ int ioremap_page_range(unsigned long addr, unsigned long end,
{ {
int err; int err;
err = vmap_range_noflush(addr, end, phys_addr, pgprot_nx(prot), prot = pgprot_nx(prot);
err = vmap_range_noflush(addr, end, phys_addr, prot,
ioremap_max_page_shift); ioremap_max_page_shift);
flush_cache_vmap(addr, end); flush_cache_vmap(addr, end);
if (IS_ENABLED(CONFIG_ARCH_HAS_IOREMAP_PHYS_HOOKS) && !err)
ioremap_phys_range_hook(phys_addr, end - addr, prot);
return err; return err;
} }
@@ -2628,6 +2634,10 @@ static void __vunmap(const void *addr, int deallocate_pages)
kasan_poison_vmalloc(area->addr, get_vm_area_size(area)); kasan_poison_vmalloc(area->addr, get_vm_area_size(area));
if (IS_ENABLED(CONFIG_ARCH_HAS_IOREMAP_PHYS_HOOKS) &&
area->flags & VM_IOREMAP)
iounmap_phys_range_hook(area->phys_addr, get_vm_area_size(area));
vm_remove_mappings(area, deallocate_pages); vm_remove_mappings(area, deallocate_pages);
if (deallocate_pages) { if (deallocate_pages) {