RISC-V: Move DT mapping outof fixmap
authorAnup Patel <anup.patel@wdc.com>
Thu, 17 Sep 2020 22:37:10 +0000 (15:37 -0700)
committerPalmer Dabbelt <palmerdabbelt@google.com>
Fri, 2 Oct 2020 21:30:57 +0000 (14:30 -0700)
Currently, RISC-V reserves 1MB of fixmap memory for device tree. However,
it maps only single PMD (2MB) space for fixmap which leaves only < 1MB space
left for other kernel features such as early ioremap which requires fixmap
as well. The fixmap size can be increased by another 2MB but it brings
additional complexity and changes the virtual memory layout as well.
If we require some additional feature requiring fixmap again, it has to be
moved again.

Technically, DT doesn't need a fixmap as the memory occupied by the DT is
only used during boot. That's why, We map device tree in early page table
using two consecutive PGD mappings at lower addresses (< PAGE_OFFSET).
This frees lot of space in fixmap and also makes maximum supported
device tree size supported as PGDIR_SIZE. Thus, init memory section can be used
for the same purpose as well. This simplifies fixmap implementation.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Atish Patra <atish.patra@wdc.com>
Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
arch/riscv/include/asm/fixmap.h
arch/riscv/include/asm/pgtable.h
arch/riscv/kernel/head.S
arch/riscv/kernel/head.h
arch/riscv/kernel/setup.c
arch/riscv/mm/init.c

index 1ff075a8dfc732fd88e227202aa9a4224ee42b25..11613f38228ae7804e01e83c985353db3b526141 100644 (file)
@@ -22,9 +22,6 @@
  */
 enum fixed_addresses {
        FIX_HOLE,
-#define FIX_FDT_SIZE   SZ_1M
-       FIX_FDT_END,
-       FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,
        FIX_PTE,
        FIX_PMD,
        FIX_TEXT_POKE1,
index eaea1f717010e5ae02223a09f0baa9f109dac899..815f8c959dd4f7b709875c5715440772bcfc6328 100644 (file)
@@ -464,6 +464,7 @@ static inline void __kernel_map_pages(struct page *page, int numpages, int enabl
 #define kern_addr_valid(addr)   (1) /* FIXME */
 
 extern void *dtb_early_va;
+extern uintptr_t dtb_early_pa;
 void setup_bootmem(void);
 void paging_init(void);
 
index 9ade707b8ed8d3f05b86d97cbd7a2ca22bd132ed..703e59d717f0688c86a0117931fb6f5d77968fd1 100644 (file)
@@ -258,7 +258,6 @@ clear_bss_done:
 #endif
        /* Start the kernel */
        call soc_early_init
-       call parse_dtb
        tail start_kernel
 
 .Lsecondary_start:
index 105fb0496b24d3bc0b15c6fc1ea88a6e806bc498..b48dda3d04f6adc658e1da400ecdbf7a51ec0b3a 100644 (file)
@@ -16,6 +16,4 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa);
 extern void *__cpu_up_stack_pointer[];
 extern void *__cpu_up_task_pointer[];
 
-void __init parse_dtb(void);
-
 #endif /* __ASM_HEAD_H */
index 2c6dd329312bd282a830685cc57331a90944889c..edea7ef884021fd2d2fa954d41539da4e7d70806 100644 (file)
@@ -48,8 +48,9 @@ atomic_t hart_lottery __section(.sdata);
 unsigned long boot_cpu_hartid;
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
-void __init parse_dtb(void)
+static void __init parse_dtb(void)
 {
+       /* Early scan of device tree from init memory */
        if (early_init_dt_scan(dtb_early_va))
                return;
 
@@ -62,6 +63,7 @@ void __init parse_dtb(void)
 
 void __init setup_arch(char **cmdline_p)
 {
+       parse_dtb();
        init_mm.start_code = (unsigned long) _stext;
        init_mm.end_code   = (unsigned long) _etext;
        init_mm.end_data   = (unsigned long) _edata;
@@ -76,7 +78,10 @@ void __init setup_arch(char **cmdline_p)
 #if IS_ENABLED(CONFIG_BUILTIN_DTB)
        unflatten_and_copy_device_tree();
 #else
-       unflatten_device_tree();
+       if (early_init_dt_verify(__va(dtb_early_pa)))
+               unflatten_device_tree();
+       else
+               pr_err("No DTB found in kernel mappings\n");
 #endif
 
 #ifdef CONFIG_SWIOTLB
index 787c75f751a55ec4f2dba3d9c5de5ad2d57fc28f..2b651f63f5c4b6522046fe8f8ef0452876e92998 100644 (file)
@@ -28,7 +28,9 @@ unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
 EXPORT_SYMBOL(empty_zero_page);
 
 extern char _start[];
-void *dtb_early_va;
+#define DTB_EARLY_BASE_VA      PGDIR_SIZE
+void *dtb_early_va __initdata;
+uintptr_t dtb_early_pa __initdata;
 
 static void __init zone_sizes_init(void)
 {
@@ -141,8 +143,6 @@ disable:
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
 
-static phys_addr_t dtb_early_pa __initdata;
-
 void __init setup_bootmem(void)
 {
        struct memblock_region *reg;
@@ -399,7 +399,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
 
 asmlinkage void __init setup_vm(uintptr_t dtb_pa)
 {
-       uintptr_t va, end_va;
+       uintptr_t va, pa, end_va;
        uintptr_t load_pa = (uintptr_t)(&_start);
        uintptr_t load_sz = (uintptr_t)(&_end) - load_pa;
        uintptr_t map_size = best_map_size(load_pa, MAX_EARLY_MAPPING_SIZE);
@@ -448,16 +448,13 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
                                   load_pa + (va - PAGE_OFFSET),
                                   map_size, PAGE_KERNEL_EXEC);
 
-       /* Create fixed mapping for early FDT parsing */
-       end_va = __fix_to_virt(FIX_FDT) + FIX_FDT_SIZE;
-       for (va = __fix_to_virt(FIX_FDT); va < end_va; va += PAGE_SIZE)
-               create_pte_mapping(fixmap_pte, va,
-                                  dtb_pa + (va - __fix_to_virt(FIX_FDT)),
-                                  PAGE_SIZE, PAGE_KERNEL);
-
-       /* Save pointer to DTB for early FDT parsing */
-       dtb_early_va = (void *)fix_to_virt(FIX_FDT) + (dtb_pa & ~PAGE_MASK);
-       /* Save physical address for memblock reservation */
+       /* 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));
        dtb_early_pa = dtb_pa;
 }
 
@@ -516,6 +513,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
 #else
        dtb_early_va = (void *)dtb_pa;
 #endif
+       dtb_early_pa = dtb_pa;
 }
 
 static inline void setup_vm_final(void)