Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: add support for ioremap() block mappings

This wires up the existing generic huge-vmap feature, which allows
ioremap() to use PMD or PUD sized block mappings. It also adds support
to the unmap path for dealing with block mappings, which will allow us
to unmap the __init region using unmap_kernel_range() in a subsequent
patch.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Ard Biesheuvel and committed by
Catalin Marinas
324420bf 03336b1d

+49 -1
+1 -1
Documentation/features/vm/huge-vmap/arch-support.txt
··· 9 9 | alpha: | TODO | 10 10 | arc: | TODO | 11 11 | arm: | TODO | 12 - | arm64: | TODO | 12 + | arm64: | ok | 13 13 | avr32: | TODO | 14 14 | blackfin: | TODO | 15 15 | c6x: | TODO |
+1
arch/arm64/Kconfig
··· 50 50 select HAVE_ALIGNED_STRUCT_PAGE if SLUB 51 51 select HAVE_ARCH_AUDITSYSCALL 52 52 select HAVE_ARCH_BITREVERSE 53 + select HAVE_ARCH_HUGE_VMAP 53 54 select HAVE_ARCH_JUMP_LABEL 54 55 select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48) 55 56 select HAVE_ARCH_KGDB
+6
arch/arm64/include/asm/memory.h
··· 100 100 #define MT_S2_NORMAL 0xf 101 101 #define MT_S2_DEVICE_nGnRE 0x1 102 102 103 + #ifdef CONFIG_ARM64_4K_PAGES 104 + #define IOREMAP_MAX_ORDER (PUD_SHIFT) 105 + #else 106 + #define IOREMAP_MAX_ORDER (PMD_SHIFT) 107 + #endif 108 + 103 109 #ifndef __ASSEMBLY__ 104 110 105 111 extern phys_addr_t memstart_addr;
+41
arch/arm64/mm/mmu.c
··· 747 747 748 748 return dt_virt; 749 749 } 750 + 751 + int __init arch_ioremap_pud_supported(void) 752 + { 753 + /* only 4k granule supports level 1 block mappings */ 754 + return IS_ENABLED(CONFIG_ARM64_4K_PAGES); 755 + } 756 + 757 + int __init arch_ioremap_pmd_supported(void) 758 + { 759 + return 1; 760 + } 761 + 762 + int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) 763 + { 764 + BUG_ON(phys & ~PUD_MASK); 765 + set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); 766 + return 1; 767 + } 768 + 769 + int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) 770 + { 771 + BUG_ON(phys & ~PMD_MASK); 772 + set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); 773 + return 1; 774 + } 775 + 776 + int pud_clear_huge(pud_t *pud) 777 + { 778 + if (!pud_sect(*pud)) 779 + return 0; 780 + pud_clear(pud); 781 + return 1; 782 + } 783 + 784 + int pmd_clear_huge(pmd_t *pmd) 785 + { 786 + if (!pmd_sect(*pmd)) 787 + return 0; 788 + pmd_clear(pmd); 789 + return 1; 790 + }