mm: move vmap_range from mm/ioremap.c to mm/vmalloc.c
authorNicholas Piggin <npiggin@gmail.com>
Fri, 30 Apr 2021 05:58:43 +0000 (22:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Apr 2021 18:20:40 +0000 (11:20 -0700)
This is a generic kernel virtual memory mapper, not specific to ioremap.

Code is unchanged other than making vmap_range non-static.

Link: https://lkml.kernel.org/r/20210317062402.533919-12-npiggin@gmail.com
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Ding Tianhong <dingtianhong@huawei.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Uladzislau Rezki (Sony) <urezki@gmail.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/vmalloc.h
mm/ioremap.c
mm/vmalloc.c

index eb5630b..ae9eb07 100644 (file)
@@ -189,6 +189,9 @@ extern struct vm_struct *remove_vm_area(const void *addr);
 extern struct vm_struct *find_vm_area(const void *addr);
 
 #ifdef CONFIG_MMU
+int vmap_range(unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift);
 extern int map_kernel_range_noflush(unsigned long start, unsigned long size,
                                    pgprot_t prot, struct page **pages);
 int map_kernel_range(unsigned long start, unsigned long size, pgprot_t prot,
index 3264d02..d1dcc7e 100644 (file)
@@ -28,209 +28,6 @@ early_param("nohugeiomap", set_nohugeiomap);
 static const bool iomap_max_page_shift = PAGE_SHIFT;
 #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
 
-static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       pgtbl_mod_mask *mask)
-{
-       pte_t *pte;
-       u64 pfn;
-
-       pfn = phys_addr >> PAGE_SHIFT;
-       pte = pte_alloc_kernel_track(pmd, addr, mask);
-       if (!pte)
-               return -ENOMEM;
-       do {
-               BUG_ON(!pte_none(*pte));
-               set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
-               pfn++;
-       } while (pte++, addr += PAGE_SIZE, addr != end);
-       *mask |= PGTBL_PTE_MODIFIED;
-       return 0;
-}
-
-static int vmap_try_huge_pmd(pmd_t *pmd, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift)
-{
-       if (max_page_shift < PMD_SHIFT)
-               return 0;
-
-       if (!arch_vmap_pmd_supported(prot))
-               return 0;
-
-       if ((end - addr) != PMD_SIZE)
-               return 0;
-
-       if (!IS_ALIGNED(addr, PMD_SIZE))
-               return 0;
-
-       if (!IS_ALIGNED(phys_addr, PMD_SIZE))
-               return 0;
-
-       if (pmd_present(*pmd) && !pmd_free_pte_page(pmd, addr))
-               return 0;
-
-       return pmd_set_huge(pmd, phys_addr, prot);
-}
-
-static int vmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift, pgtbl_mod_mask *mask)
-{
-       pmd_t *pmd;
-       unsigned long next;
-
-       pmd = pmd_alloc_track(&init_mm, pud, addr, mask);
-       if (!pmd)
-               return -ENOMEM;
-       do {
-               next = pmd_addr_end(addr, end);
-
-               if (vmap_try_huge_pmd(pmd, addr, next, phys_addr, prot,
-                                       max_page_shift)) {
-                       *mask |= PGTBL_PMD_MODIFIED;
-                       continue;
-               }
-
-               if (vmap_pte_range(pmd, addr, next, phys_addr, prot, mask))
-                       return -ENOMEM;
-       } while (pmd++, phys_addr += (next - addr), addr = next, addr != end);
-       return 0;
-}
-
-static int vmap_try_huge_pud(pud_t *pud, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift)
-{
-       if (max_page_shift < PUD_SHIFT)
-               return 0;
-
-       if (!arch_vmap_pud_supported(prot))
-               return 0;
-
-       if ((end - addr) != PUD_SIZE)
-               return 0;
-
-       if (!IS_ALIGNED(addr, PUD_SIZE))
-               return 0;
-
-       if (!IS_ALIGNED(phys_addr, PUD_SIZE))
-               return 0;
-
-       if (pud_present(*pud) && !pud_free_pmd_page(pud, addr))
-               return 0;
-
-       return pud_set_huge(pud, phys_addr, prot);
-}
-
-static int vmap_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift, pgtbl_mod_mask *mask)
-{
-       pud_t *pud;
-       unsigned long next;
-
-       pud = pud_alloc_track(&init_mm, p4d, addr, mask);
-       if (!pud)
-               return -ENOMEM;
-       do {
-               next = pud_addr_end(addr, end);
-
-               if (vmap_try_huge_pud(pud, addr, next, phys_addr, prot,
-                                       max_page_shift)) {
-                       *mask |= PGTBL_PUD_MODIFIED;
-                       continue;
-               }
-
-               if (vmap_pmd_range(pud, addr, next, phys_addr, prot,
-                                       max_page_shift, mask))
-                       return -ENOMEM;
-       } while (pud++, phys_addr += (next - addr), addr = next, addr != end);
-       return 0;
-}
-
-static int vmap_try_huge_p4d(p4d_t *p4d, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift)
-{
-       if (max_page_shift < P4D_SHIFT)
-               return 0;
-
-       if (!arch_vmap_p4d_supported(prot))
-               return 0;
-
-       if ((end - addr) != P4D_SIZE)
-               return 0;
-
-       if (!IS_ALIGNED(addr, P4D_SIZE))
-               return 0;
-
-       if (!IS_ALIGNED(phys_addr, P4D_SIZE))
-               return 0;
-
-       if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
-               return 0;
-
-       return p4d_set_huge(p4d, phys_addr, prot);
-}
-
-static int vmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift, pgtbl_mod_mask *mask)
-{
-       p4d_t *p4d;
-       unsigned long next;
-
-       p4d = p4d_alloc_track(&init_mm, pgd, addr, mask);
-       if (!p4d)
-               return -ENOMEM;
-       do {
-               next = p4d_addr_end(addr, end);
-
-               if (vmap_try_huge_p4d(p4d, addr, next, phys_addr, prot,
-                                       max_page_shift)) {
-                       *mask |= PGTBL_P4D_MODIFIED;
-                       continue;
-               }
-
-               if (vmap_pud_range(p4d, addr, next, phys_addr, prot,
-                                       max_page_shift, mask))
-                       return -ENOMEM;
-       } while (p4d++, phys_addr += (next - addr), addr = next, addr != end);
-       return 0;
-}
-
-static int vmap_range(unsigned long addr, unsigned long end,
-                       phys_addr_t phys_addr, pgprot_t prot,
-                       unsigned int max_page_shift)
-{
-       pgd_t *pgd;
-       unsigned long start;
-       unsigned long next;
-       int err;
-       pgtbl_mod_mask mask = 0;
-
-       might_sleep();
-       BUG_ON(addr >= end);
-
-       start = addr;
-       pgd = pgd_offset_k(addr);
-       do {
-               next = pgd_addr_end(addr, end);
-               err = vmap_p4d_range(pgd, addr, next, phys_addr, prot,
-                                       max_page_shift, &mask);
-               if (err)
-                       break;
-       } while (pgd++, phys_addr += (next - addr), addr = next, addr != end);
-
-       flush_cache_vmap(start, end);
-
-       if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
-               arch_sync_kernel_mappings(start, end);
-
-       return err;
-}
-
 int ioremap_page_range(unsigned long addr,
                       unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
 {
index ce4066b..5c81717 100644 (file)
@@ -68,6 +68,208 @@ static void free_work(struct work_struct *w)
 }
 
 /*** Page table manipulation functions ***/
+static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       pgtbl_mod_mask *mask)
+{
+       pte_t *pte;
+       u64 pfn;
+
+       pfn = phys_addr >> PAGE_SHIFT;
+       pte = pte_alloc_kernel_track(pmd, addr, mask);
+       if (!pte)
+               return -ENOMEM;
+       do {
+               BUG_ON(!pte_none(*pte));
+               set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
+               pfn++;
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+       *mask |= PGTBL_PTE_MODIFIED;
+       return 0;
+}
+
+static int vmap_try_huge_pmd(pmd_t *pmd, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift)
+{
+       if (max_page_shift < PMD_SHIFT)
+               return 0;
+
+       if (!arch_vmap_pmd_supported(prot))
+               return 0;
+
+       if ((end - addr) != PMD_SIZE)
+               return 0;
+
+       if (!IS_ALIGNED(addr, PMD_SIZE))
+               return 0;
+
+       if (!IS_ALIGNED(phys_addr, PMD_SIZE))
+               return 0;
+
+       if (pmd_present(*pmd) && !pmd_free_pte_page(pmd, addr))
+               return 0;
+
+       return pmd_set_huge(pmd, phys_addr, prot);
+}
+
+static int vmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift, pgtbl_mod_mask *mask)
+{
+       pmd_t *pmd;
+       unsigned long next;
+
+       pmd = pmd_alloc_track(&init_mm, pud, addr, mask);
+       if (!pmd)
+               return -ENOMEM;
+       do {
+               next = pmd_addr_end(addr, end);
+
+               if (vmap_try_huge_pmd(pmd, addr, next, phys_addr, prot,
+                                       max_page_shift)) {
+                       *mask |= PGTBL_PMD_MODIFIED;
+                       continue;
+               }
+
+               if (vmap_pte_range(pmd, addr, next, phys_addr, prot, mask))
+                       return -ENOMEM;
+       } while (pmd++, phys_addr += (next - addr), addr = next, addr != end);
+       return 0;
+}
+
+static int vmap_try_huge_pud(pud_t *pud, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift)
+{
+       if (max_page_shift < PUD_SHIFT)
+               return 0;
+
+       if (!arch_vmap_pud_supported(prot))
+               return 0;
+
+       if ((end - addr) != PUD_SIZE)
+               return 0;
+
+       if (!IS_ALIGNED(addr, PUD_SIZE))
+               return 0;
+
+       if (!IS_ALIGNED(phys_addr, PUD_SIZE))
+               return 0;
+
+       if (pud_present(*pud) && !pud_free_pmd_page(pud, addr))
+               return 0;
+
+       return pud_set_huge(pud, phys_addr, prot);
+}
+
+static int vmap_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift, pgtbl_mod_mask *mask)
+{
+       pud_t *pud;
+       unsigned long next;
+
+       pud = pud_alloc_track(&init_mm, p4d, addr, mask);
+       if (!pud)
+               return -ENOMEM;
+       do {
+               next = pud_addr_end(addr, end);
+
+               if (vmap_try_huge_pud(pud, addr, next, phys_addr, prot,
+                                       max_page_shift)) {
+                       *mask |= PGTBL_PUD_MODIFIED;
+                       continue;
+               }
+
+               if (vmap_pmd_range(pud, addr, next, phys_addr, prot,
+                                       max_page_shift, mask))
+                       return -ENOMEM;
+       } while (pud++, phys_addr += (next - addr), addr = next, addr != end);
+       return 0;
+}
+
+static int vmap_try_huge_p4d(p4d_t *p4d, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift)
+{
+       if (max_page_shift < P4D_SHIFT)
+               return 0;
+
+       if (!arch_vmap_p4d_supported(prot))
+               return 0;
+
+       if ((end - addr) != P4D_SIZE)
+               return 0;
+
+       if (!IS_ALIGNED(addr, P4D_SIZE))
+               return 0;
+
+       if (!IS_ALIGNED(phys_addr, P4D_SIZE))
+               return 0;
+
+       if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
+               return 0;
+
+       return p4d_set_huge(p4d, phys_addr, prot);
+}
+
+static int vmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift, pgtbl_mod_mask *mask)
+{
+       p4d_t *p4d;
+       unsigned long next;
+
+       p4d = p4d_alloc_track(&init_mm, pgd, addr, mask);
+       if (!p4d)
+               return -ENOMEM;
+       do {
+               next = p4d_addr_end(addr, end);
+
+               if (vmap_try_huge_p4d(p4d, addr, next, phys_addr, prot,
+                                       max_page_shift)) {
+                       *mask |= PGTBL_P4D_MODIFIED;
+                       continue;
+               }
+
+               if (vmap_pud_range(p4d, addr, next, phys_addr, prot,
+                                       max_page_shift, mask))
+                       return -ENOMEM;
+       } while (p4d++, phys_addr += (next - addr), addr = next, addr != end);
+       return 0;
+}
+
+int vmap_range(unsigned long addr, unsigned long end,
+                       phys_addr_t phys_addr, pgprot_t prot,
+                       unsigned int max_page_shift)
+{
+       pgd_t *pgd;
+       unsigned long start;
+       unsigned long next;
+       int err;
+       pgtbl_mod_mask mask = 0;
+
+       might_sleep();
+       BUG_ON(addr >= end);
+
+       start = addr;
+       pgd = pgd_offset_k(addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               err = vmap_p4d_range(pgd, addr, next, phys_addr, prot,
+                                       max_page_shift, &mask);
+               if (err)
+                       break;
+       } while (pgd++, phys_addr += (next - addr), addr = next, addr != end);
+
+       flush_cache_vmap(start, end);
+
+       if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
+               arch_sync_kernel_mappings(start, end);
+
+       return err;
+}
 
 static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                             pgtbl_mod_mask *mask)