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

arm64: Add support for 48-bit VA space with 64KB page configuration

This patch allows support for 3 levels of page tables with 64KB page
configuration allowing 48-bit VA space. The pgd is no longer a full
PAGE_SIZE (PTRS_PER_PGD is 64) and (swapper|idmap)_pg_dir are not fully
populated (pgd_alloc falls back to kzalloc).

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Jungseok Lee <jungseoklee85@gmail.com>

+22 -9
+8
Documentation/arm64/memory.txt
··· 45 45 fffffc0000000000 ffffffffffffffff 4TB kernel 46 46 47 47 48 + AArch64 Linux memory layout with 64KB pages + 3 levels: 49 + 50 + Start End Size Use 51 + ----------------------------------------------------------------------- 52 + 0000000000000000 0000ffffffffffff 256TB user 53 + ffff000000000000 ffffffffffffffff 256TB kernel 54 + 55 + 48 56 For details of the virtual kernel memory layout please see the kernel 49 57 booting log. 50 58
+1
arch/arm64/Kconfig
··· 210 210 config ARM64_PGTABLE_LEVELS 211 211 int 212 212 default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42 213 + default 3 if ARM64_64K_PAGES && ARM64_VA_BITS_48 213 214 default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39 214 215 default 4 if ARM64_4K_PAGES && ARM64_VA_BITS_48 215 216
+9 -7
arch/arm64/include/asm/page.h
··· 34 34 /* 35 35 * The idmap and swapper page tables need some space reserved in the kernel 36 36 * image. Both require pgd, pud (4 levels only) and pmd tables to (section) 37 - * map the kernel. The swapper also maps the FDT (see __create_page_tables for 38 - * more information). 37 + * map the kernel. With the 64K page configuration, swapper and idmap need to 38 + * map to pte level. The swapper also maps the FDT (see __create_page_tables 39 + * for more information). 39 40 */ 40 - #if CONFIG_ARM64_PGTABLE_LEVELS == 4 41 - #define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) 42 - #define IDMAP_DIR_SIZE (3 * PAGE_SIZE) 41 + #ifdef CONFIG_ARM64_64K_PAGES 42 + #define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS) 43 43 #else 44 - #define SWAPPER_DIR_SIZE (2 * PAGE_SIZE) 45 - #define IDMAP_DIR_SIZE (2 * PAGE_SIZE) 44 + #define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS - 1) 46 45 #endif 46 + 47 + #define SWAPPER_DIR_SIZE (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE) 48 + #define IDMAP_DIR_SIZE (SWAPPER_DIR_SIZE) 47 49 48 50 #ifndef __ASSEMBLY__ 49 51
+4 -2
arch/arm64/kernel/head.S
··· 55 55 #ifdef CONFIG_ARM64_64K_PAGES 56 56 #define BLOCK_SHIFT PAGE_SHIFT 57 57 #define BLOCK_SIZE PAGE_SIZE 58 + #define TABLE_SHIFT PMD_SHIFT 58 59 #else 59 60 #define BLOCK_SHIFT SECTION_SHIFT 60 61 #define BLOCK_SIZE SECTION_SIZE 62 + #define TABLE_SHIFT PUD_SHIFT 61 63 #endif 62 64 63 65 #define KERNEL_START KERNEL_RAM_VADDR ··· 507 505 */ 508 506 .macro create_pgd_entry, tbl, virt, tmp1, tmp2 509 507 create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2 510 - #if CONFIG_ARM64_PGTABLE_LEVELS == 4 511 - create_table_entry \tbl, \virt, PUD_SHIFT, PTRS_PER_PUD, \tmp1, \tmp2 508 + #if SWAPPER_PGTABLE_LEVELS == 3 509 + create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2 512 510 #endif 513 511 .endm 514 512