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

arm64: Introduce VA_BITS and translation level options

This patch adds virtual address space size and a level of translation
tables to kernel configuration. It facilicates introduction of
different MMU options, such as 4KB + 4 levels, 16KB + 4 levels and
64KB + 3 levels, easily.

The idea is based on the discussion with Catalin Marinas:
http://www.spinics.net/linux/lists/arm-kernel/msg319552.html

Signed-off-by: Jungseok Lee <jays.lee@samsung.com>
Reviewed-by: Sungjinn Chung <sungjinn.chung@samsung.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Jungseok Lee <jungseoklee85@gmail.com>

authored by

Jungseok Lee and committed by
Catalin Marinas
e41ceed0 7edd88ad

+54 -15
+44 -1
arch/arm64/Kconfig
··· 157 157 158 158 menu "Kernel Features" 159 159 160 + choice 161 + prompt "Page size" 162 + default ARM64_4K_PAGES 163 + help 164 + Page size (translation granule) configuration. 165 + 166 + config ARM64_4K_PAGES 167 + bool "4KB" 168 + help 169 + This feature enables 4KB pages support. 170 + 160 171 config ARM64_64K_PAGES 161 - bool "Enable 64KB pages support" 172 + bool "64KB" 162 173 help 163 174 This feature enables 64KB pages support (4KB by default) 164 175 allowing only two levels of page tables and faster TLB 165 176 look-up. AArch32 emulation is not available when this feature 166 177 is enabled. 178 + 179 + endchoice 180 + 181 + choice 182 + prompt "Virtual address space size" 183 + default ARM64_VA_BITS_39 if ARM64_4K_PAGES 184 + default ARM64_VA_BITS_42 if ARM64_64K_PAGES 185 + help 186 + Allows choosing one of multiple possible virtual address 187 + space sizes. The level of translation table is determined by 188 + a combination of page size and virtual address space size. 189 + 190 + config ARM64_VA_BITS_39 191 + bool "39-bit" 192 + depends on ARM64_4K_PAGES 193 + 194 + config ARM64_VA_BITS_42 195 + bool "42-bit" 196 + depends on ARM64_64K_PAGES 197 + 198 + endchoice 199 + 200 + config ARM64_VA_BITS 201 + int 202 + default 39 if ARM64_VA_BITS_39 203 + default 42 if ARM64_VA_BITS_42 204 + 205 + config ARM64_2_LEVELS 206 + def_bool y if ARM64_64K_PAGES && ARM64_VA_BITS_42 207 + 208 + config ARM64_3_LEVELS 209 + def_bool y if ARM64_4K_PAGES && ARM64_VA_BITS_39 167 210 168 211 config CPU_BIG_ENDIAN 169 212 bool "Build big-endian kernel"
+1 -5
arch/arm64/include/asm/memory.h
··· 41 41 * The module space lives between the addresses given by TASK_SIZE 42 42 * and PAGE_OFFSET - it must be within 128MB of the kernel text. 43 43 */ 44 - #ifdef CONFIG_ARM64_64K_PAGES 45 - #define VA_BITS (42) 46 - #else 47 - #define VA_BITS (39) 48 - #endif 44 + #define VA_BITS (CONFIG_ARM64_VA_BITS) 49 45 #define PAGE_OFFSET (UL(0xffffffffffffffff) << (VA_BITS - 1)) 50 46 #define MODULES_END (PAGE_OFFSET) 51 47 #define MODULES_VADDR (MODULES_END - SZ_64M)
+1 -1
arch/arm64/include/asm/page.h
··· 42 42 43 43 #ifndef __ASSEMBLY__ 44 44 45 - #ifdef CONFIG_ARM64_64K_PAGES 45 + #ifdef CONFIG_ARM64_2_LEVELS 46 46 #include <asm/pgtable-2level-types.h> 47 47 #else 48 48 #include <asm/pgtable-3level-types.h>
+2 -2
arch/arm64/include/asm/pgalloc.h
··· 26 26 27 27 #define check_pgt_cache() do { } while (0) 28 28 29 - #ifndef CONFIG_ARM64_64K_PAGES 29 + #ifndef CONFIG_ARM64_2_LEVELS 30 30 31 31 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 32 32 { ··· 44 44 set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); 45 45 } 46 46 47 - #endif /* CONFIG_ARM64_64K_PAGES */ 47 + #endif /* CONFIG_ARM64_2_LEVELS */ 48 48 49 49 extern pgd_t *pgd_alloc(struct mm_struct *mm); 50 50 extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+1 -1
arch/arm64/include/asm/pgtable-hwdef.h
··· 16 16 #ifndef __ASM_PGTABLE_HWDEF_H 17 17 #define __ASM_PGTABLE_HWDEF_H 18 18 19 - #ifdef CONFIG_ARM64_64K_PAGES 19 + #ifdef CONFIG_ARM64_2_LEVELS 20 20 #include <asm/pgtable-2level-hwdef.h> 21 21 #else 22 22 #include <asm/pgtable-3level-hwdef.h>
+4 -4
arch/arm64/include/asm/pgtable.h
··· 47 47 extern void __pgd_error(const char *file, int line, unsigned long val); 48 48 49 49 #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte)) 50 - #ifndef CONFIG_ARM64_64K_PAGES 50 + #ifndef CONFIG_ARM64_2_LEVELS 51 51 #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd)) 52 52 #endif 53 53 #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) ··· 323 323 */ 324 324 #define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) 325 325 326 - #ifndef CONFIG_ARM64_64K_PAGES 326 + #ifndef CONFIG_ARM64_2_LEVELS 327 327 328 328 #define pud_none(pud) (!pud_val(pud)) 329 329 #define pud_bad(pud) (!(pud_val(pud) & 2)) ··· 345 345 return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); 346 346 } 347 347 348 - #endif /* CONFIG_ARM64_64K_PAGES */ 348 + #endif /* CONFIG_ARM64_2_LEVELS */ 349 349 350 350 /* to find an entry in a page-table-directory */ 351 351 #define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) ··· 356 356 #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) 357 357 358 358 /* Find an entry in the second-level page table.. */ 359 - #ifndef CONFIG_ARM64_64K_PAGES 359 + #ifndef CONFIG_ARM64_2_LEVELS 360 360 #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) 361 361 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) 362 362 {
+1 -1
arch/arm64/include/asm/tlb.h
··· 91 91 tlb_remove_page(tlb, pte); 92 92 } 93 93 94 - #ifndef CONFIG_ARM64_64K_PAGES 94 + #ifndef CONFIG_ARM64_2_LEVELS 95 95 static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, 96 96 unsigned long addr) 97 97 {