On Thu, Aug 13, 2020 at 5:18 AM Atish Patra <atish.patra@xxxxxxx> wrote: > > UEFI uses early IO or memory mappings for runtime services before > normal ioremap() is usable. Add the necessary fixmap bindings and > pmd mappings for generic ioremap support to work. > > Signed-off-by: Atish Patra <atish.patra@xxxxxxx> > --- > arch/riscv/Kconfig | 1 + > arch/riscv/include/asm/Kbuild | 1 + > arch/riscv/include/asm/fixmap.h | 13 +++++++++++++ > arch/riscv/include/asm/io.h | 1 + > arch/riscv/kernel/setup.c | 1 + > arch/riscv/mm/init.c | 33 +++++++++++++++++++++++++++++++++ > 6 files changed, 50 insertions(+) > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index 7b5905529146..15597f5f504f 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -37,6 +37,7 @@ config RISCV > select GENERIC_ARCH_TOPOLOGY if SMP > select GENERIC_ATOMIC64 if !64BIT > select GENERIC_CLOCKEVENTS > + select GENERIC_EARLY_IOREMAP > select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO > select GENERIC_IOREMAP > select GENERIC_IRQ_MULTI_HANDLER > diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild > index 3d9410bb4de0..59dd7be55005 100644 > --- a/arch/riscv/include/asm/Kbuild > +++ b/arch/riscv/include/asm/Kbuild > @@ -1,4 +1,5 @@ > # SPDX-License-Identifier: GPL-2.0 > +generic-y += early_ioremap.h > generic-y += extable.h > generic-y += flat.h > generic-y += kvm_para.h > diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h > index 11613f38228a..54cbf07fb4e9 100644 > --- a/arch/riscv/include/asm/fixmap.h > +++ b/arch/riscv/include/asm/fixmap.h > @@ -27,6 +27,19 @@ enum fixed_addresses { > FIX_TEXT_POKE1, > FIX_TEXT_POKE0, > FIX_EARLYCON_MEM_BASE, > + > + __end_of_permanent_fixed_addresses, > + /* > + * Temporary boot-time mappings, used by early_ioremap(), > + * before ioremap() is functional. > + */ > +#define NR_FIX_BTMAPS (SZ_256K / PAGE_SIZE) > +#define FIX_BTMAPS_SLOTS 7 > +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) > + > + FIX_BTMAP_END = __end_of_permanent_fixed_addresses, > + FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1, > + > __end_of_fixed_addresses > }; > > diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h > index 3835c3295dc5..c025a746a148 100644 > --- a/arch/riscv/include/asm/io.h > +++ b/arch/riscv/include/asm/io.h > @@ -14,6 +14,7 @@ > #include <linux/types.h> > #include <linux/pgtable.h> > #include <asm/mmiowb.h> > +#include <asm/early_ioremap.h> > > /* > * MMIO access functions are separated out to break dependency cycles > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c > index 6a0ee2405813..c71788e6aff4 100644 > --- a/arch/riscv/kernel/setup.c > +++ b/arch/riscv/kernel/setup.c > @@ -72,6 +72,7 @@ void __init setup_arch(char **cmdline_p) > > *cmdline_p = boot_command_line; > > + early_ioremap_setup(); > parse_early_param(); > > setup_bootmem(); > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index 2b651f63f5c4..b75ebe8e7a92 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -403,6 +403,9 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) > 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); > +#ifndef __PAGETABLE_PMD_FOLDED > + pmd_t fix_bmap_spmd, fix_bmap_epmd; > +#endif > > va_pa_offset = PAGE_OFFSET - load_pa; > pfn_base = PFN_DOWN(load_pa); > @@ -456,6 +459,36 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) > 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; > + > + /* > + * Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap > + * range can not span multiple pmds. > + */ > + BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT) > + != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT)); > + > +#ifndef __PAGETABLE_PMD_FOLDED > + /* > + * Early ioremap fixmap is already created as it lies within first 2MB > + * of fixmap region. We always map PMD_SIZE. Thus, both FIX_BTMAP_END > + * FIX_BTMAP_BEGIN should lie in the same pmd. Verify that and warn > + * the user if not. > + */ > + fix_bmap_spmd = fixmap_pmd[pmd_index(__fix_to_virt(FIX_BTMAP_BEGIN))]; > + fix_bmap_epmd = fixmap_pmd[pmd_index(__fix_to_virt(FIX_BTMAP_END))]; > + if (pmd_val(fix_bmap_spmd) != pmd_val(fix_bmap_epmd)) { > + WARN_ON(1); > + pr_warn("fixmap btmap start [%08lx] != end [%08lx]\n", > + pmd_val(fix_bmap_spmd), pmd_val(fix_bmap_epmd)); > + pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n", > + fix_to_virt(FIX_BTMAP_BEGIN)); > + pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n", > + fix_to_virt(FIX_BTMAP_END)); > + > + pr_warn("FIX_BTMAP_END: %d\n", FIX_BTMAP_END); > + pr_warn("FIX_BTMAP_BEGIN: %d\n", FIX_BTMAP_BEGIN); > + } > +#endif > } > > static void __init setup_vm_final(void) > -- > 2.24.0 > Looks good to me. Reviewed-by: Anup Patel <anup@xxxxxxxxxxxxxx> Regards, Anup