diff options
author | Alexandre Ghiti <alex@ghiti.fr> | 2021-07-23 15:01:28 +0200 |
---|---|---|
committer | Palmer Dabbelt <palmerdabbelt@google.com> | 2021-08-11 22:41:38 -0700 |
commit | fe45ffa4c505783637233609b677446020738b87 (patch) | |
tree | 32ec59da03e33565b7bd0494ae73272977218623 /arch/riscv | |
parent | 977765ce319b98939205cf07aa1d76150713c69b (diff) | |
download | lwn-fe45ffa4c505783637233609b677446020738b87.tar.gz lwn-fe45ffa4c505783637233609b677446020738b87.zip |
riscv: Move early fdt mapping creation in its own function
The code that handles the early fdt mapping is hard to read and does not
create the same mapping size depending on the kernel:
- for 64-bit, 2 PMD entries are used which amounts to a 4MB mapping
- for 32-bit, 2 PGDIR entries are used which amounts to a 8MB mapping
So keep using 2 PMD entries for 64-bit and use only one PGD entry for
32-bit needed to cover 4MB. Move that into a new function called
create_fdt_early_page_table which, using the same naming as
create_kernel_page_table.
Signed-off-by: Alexandre Ghiti <alex@ghiti.fr>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
Diffstat (limited to 'arch/riscv')
-rw-r--r-- | arch/riscv/mm/init.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index a93822df9d81..fdf093d01c6f 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -222,6 +222,7 @@ pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss; static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss; pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); +static pmd_t __maybe_unused early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); #ifdef CONFIG_XIP_KERNEL #define trampoline_pg_dir ((pgd_t *)XIP_FIXUP(trampoline_pg_dir)) @@ -302,7 +303,6 @@ static void __init create_pte_mapping(pte_t *ptep, static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss; static pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss; static pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); -static pmd_t early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); #ifdef CONFIG_XIP_KERNEL #define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd)) @@ -388,6 +388,7 @@ static void __init create_pmd_mapping(pmd_t *pmdp, #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ create_pte_mapping(__nextp, __va, __pa, __sz, __prot) #define fixmap_pgd_next fixmap_pte +#define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) #endif void __init create_pgd_mapping(pgd_t *pgdp, @@ -529,9 +530,44 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early) } #endif +/* + * Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel, + * this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR + * entry. + */ +static void __init create_fdt_early_page_table(pgd_t *pgdir, uintptr_t dtb_pa) +{ +#ifndef CONFIG_BUILTIN_DTB + uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1); + + create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, + IS_ENABLED(CONFIG_64BIT) ? (uintptr_t)early_dtb_pmd : pa, + PGDIR_SIZE, + IS_ENABLED(CONFIG_64BIT) ? PAGE_TABLE : PAGE_KERNEL); + + if (IS_ENABLED(CONFIG_64BIT)) { + create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA, + pa, PMD_SIZE, PAGE_KERNEL); + create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE, + pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL); + } + + dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1)); +#else + /* + * For 64-bit kernel, __va can't be used since it would return a linear + * mapping address whereas dtb_early_va will be used before + * setup_vm_final installs the linear mapping. For 32-bit kernel, as the + * kernel is mapped in the linear mapping, that makes no difference. + */ + dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa)); +#endif + + dtb_early_pa = dtb_pa; +} + asmlinkage void __init setup_vm(uintptr_t dtb_pa) { - uintptr_t __maybe_unused pa; pmd_t __maybe_unused fix_bmap_spmd, fix_bmap_epmd; kernel_map.virt_addr = KERNEL_LINK_ADDR; @@ -594,40 +630,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) */ create_kernel_page_table(early_pg_dir, true); -#ifndef __PAGETABLE_PMD_FOLDED - /* Setup early PMD for DTB */ - create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, - (uintptr_t)early_dtb_pmd, PGDIR_SIZE, PAGE_TABLE); -#ifndef CONFIG_BUILTIN_DTB - /* Create two consecutive PMD mappings for FDT early scan */ - pa = dtb_pa & ~(PMD_SIZE - 1); - create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA, - pa, PMD_SIZE, PAGE_KERNEL); - create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE, - pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL); - dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1)); -#else /* CONFIG_BUILTIN_DTB */ - /* - * __va can't be used since it would return a linear mapping address - * whereas dtb_early_va will be used before setup_vm_final installs - * the linear mapping. - */ - dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa)); -#endif /* CONFIG_BUILTIN_DTB */ -#else /* __PAGETABLE_PMD_FOLDED */ -#ifndef CONFIG_BUILTIN_DTB - /* Create two consecutive PGD mappings for FDT early scan */ - pa = dtb_pa & ~(PGDIR_SIZE - 1); - create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, - pa, PGDIR_SIZE, PAGE_KERNEL); - create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE, - pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL); - dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1)); -#else /* CONFIG_BUILTIN_DTB */ - dtb_early_va = __va(dtb_pa); -#endif /* CONFIG_BUILTIN_DTB */ -#endif /* __PAGETABLE_PMD_FOLDED */ - dtb_early_pa = dtb_pa; + /* Setup early mapping for FDT early scan */ + create_fdt_early_page_table(early_pg_dir, dtb_pa); /* * Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap |