Skip to content

Commit

Permalink
RISC-V: Move DT mapping outof fixmap
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anup Patel authored and Palmer Dabbelt committed Oct 2, 2020
1 parent 8a3f30c commit 8f3a2b4
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 22 deletions.
3 changes: 0 additions & 3 deletions arch/riscv/include/asm/fixmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 0 additions & 1 deletion arch/riscv/kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ clear_bss_done:
#endif
/* Start the kernel */
call soc_early_init
call parse_dtb
tail start_kernel

.Lsecondary_start:
Expand Down
2 changes: 0 additions & 2 deletions arch/riscv/kernel/head.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
9 changes: 7 additions & 2 deletions arch/riscv/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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
Expand Down
26 changes: 12 additions & 14 deletions arch/riscv/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -141,8 +143,6 @@ static void __init setup_initrd(void)
}
#endif /* CONFIG_BLK_DEV_INITRD */

static phys_addr_t dtb_early_pa __initdata;

void __init setup_bootmem(void)
{
struct memblock_region *reg;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 8f3a2b4

Please sign in to comment.