From: Song Shuai <songshuaishuai@xxxxxxxxxxx> This reverts commit 3335068f87217ea59d08f462187dc856652eea15. This commit maps the PMP regions from some versions of OpenSbi in the linear mapping, that will lead to an access fault when doing hibernation[1] or some speculative accesses. The best_map_size() function from this commit doesn't check the virtual alignment before choosing a map size, that will cause a page fault[2]. We can let best_map_size() take the VA into consideration via commit 49a0a3731596 ("riscv: Check the virtual alignment before choosing a map size"), but that commit slows down the boot time and consumes some system memory when UEFI booting. This commit uses PUD/P4D/PGD pages for the linear mapping to improve the performance is marginal from a recent talk [3] from Mike Rapoport. OpenSbi had marked all the PMP-protected regions as "no-map" [4] to practice this talk. For all those reasons, let's revert this commit. [1] https://lore.kernel.org/linux-riscv/CAAYs2=gQvkhTeioMmqRDVGjdtNF_vhB+vm_1dHJxPNi75YDQ_Q@xxxxxxxxxxxxxx/ [2] https://lore.kernel.org/linux-riscv/tencent_7C3B580B47C1B17C16488EC1@xxxxxx/ [3] https://lwn.net/Articles/931406/ [4] https://github.com/riscv-software-src/opensbi/commit/8153b2622b08802cc542f30a1fcba407a5667ab9 Signed-off-by: Song Shuai <songshuaishuai@xxxxxxxxxxx> --- arch/riscv/include/asm/page.h | 16 --------------- arch/riscv/mm/init.c | 38 ++++++----------------------------- arch/riscv/mm/physaddr.c | 16 --------------- drivers/of/fdt.c | 11 +++++----- 4 files changed, 11 insertions(+), 70 deletions(-) diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index b55ba20903ec..21b346ab81c2 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h @@ -89,14 +89,6 @@ typedef struct page *pgtable_t; #define PTE_FMT "%08lx" #endif -#ifdef CONFIG_64BIT -/* - * We override this value as its generic definition uses __pa too early in - * the boot process (before kernel_map.va_pa_offset is set). - */ -#define MIN_MEMBLOCK_ADDR 0 -#endif - #ifdef CONFIG_MMU #define ARCH_PFN_OFFSET (PFN_DOWN((unsigned long)phys_ram_base)) #else @@ -128,11 +120,7 @@ extern phys_addr_t phys_ram_base; #define is_linear_mapping(x) \ ((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < PAGE_OFFSET + KERN_VIRT_SIZE)) -#ifndef CONFIG_DEBUG_VIRTUAL #define linear_mapping_pa_to_va(x) ((void *)((unsigned long)(x) + kernel_map.va_pa_offset)) -#else -void *linear_mapping_pa_to_va(unsigned long x); -#endif #define kernel_mapping_pa_to_va(y) ({ \ unsigned long _y = (unsigned long)(y); \ (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \ @@ -141,11 +129,7 @@ void *linear_mapping_pa_to_va(unsigned long x); }) #define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x) -#ifndef CONFIG_DEBUG_VIRTUAL #define linear_mapping_va_to_pa(x) ((unsigned long)(x) - kernel_map.va_pa_offset) -#else -phys_addr_t linear_mapping_va_to_pa(unsigned long x); -#endif #define kernel_mapping_va_to_pa(y) ({ \ unsigned long _y = (unsigned long)(y); \ (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \ diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 38c4b4d6b64f..4561781bcf60 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -216,14 +216,6 @@ static void __init setup_bootmem(void) phys_ram_end = memblock_end_of_DRAM(); if (!IS_ENABLED(CONFIG_XIP_KERNEL)) phys_ram_base = memblock_start_of_DRAM(); - - /* - * In 64-bit, any use of __va/__pa before this point is wrong as we - * did not know the start of DRAM before. - */ - if (IS_ENABLED(CONFIG_64BIT)) - kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base; - /* * memblock allocator is not aware of the fact that last 4K bytes of * the addressable memory can not be mapped because of IS_ERR_VALUE @@ -662,16 +654,9 @@ void __init create_pgd_mapping(pgd_t *pgdp, static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) { - if (!(base & (PGDIR_SIZE - 1)) && size >= PGDIR_SIZE) - return PGDIR_SIZE; - - if (!(base & (P4D_SIZE - 1)) && size >= P4D_SIZE) - return P4D_SIZE; - - if (!(base & (PUD_SIZE - 1)) && size >= PUD_SIZE) - return PUD_SIZE; - - if (!(base & (PMD_SIZE - 1)) && size >= PMD_SIZE) + /* Upgrade to PMD_SIZE mappings whenever possible */ + base &= PMD_SIZE - 1; + if (!base && size >= PMD_SIZE) return PMD_SIZE; return PAGE_SIZE; @@ -1037,22 +1022,11 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) set_satp_mode(dtb_pa); #endif - /* - * In 64-bit, we defer the setup of va_pa_offset to setup_bootmem, - * where we have the system memory layout: this allows us to align - * the physical and virtual mappings and then make use of PUD/P4D/PGD - * for the linear mapping. This is only possible because the kernel - * mapping lies outside the linear mapping. - * In 32-bit however, as the kernel resides in the linear mapping, - * setup_vm_final can not change the mapping established here, - * otherwise the same kernel addresses would get mapped to different - * physical addresses (if the start of dram is different from the - * kernel physical address start). - */ - kernel_map.va_pa_offset = IS_ENABLED(CONFIG_64BIT) ? - 0UL : PAGE_OFFSET - kernel_map.phys_addr; + kernel_map.va_pa_offset = PAGE_OFFSET - kernel_map.phys_addr; kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr; + phys_ram_base = kernel_map.phys_addr; + /* * The default maximal physical memory size is KERN_VIRT_SIZE for 32-bit * kernel, whereas for 64-bit kernel, the end of the virtual address diff --git a/arch/riscv/mm/physaddr.c b/arch/riscv/mm/physaddr.c index 18706f457da7..9b18bda74154 100644 --- a/arch/riscv/mm/physaddr.c +++ b/arch/riscv/mm/physaddr.c @@ -33,19 +33,3 @@ phys_addr_t __phys_addr_symbol(unsigned long x) return __va_to_pa_nodebug(x); } EXPORT_SYMBOL(__phys_addr_symbol); - -phys_addr_t linear_mapping_va_to_pa(unsigned long x) -{ - BUG_ON(!kernel_map.va_pa_offset); - - return ((unsigned long)(x) - kernel_map.va_pa_offset); -} -EXPORT_SYMBOL(linear_mapping_va_to_pa); - -void *linear_mapping_pa_to_va(unsigned long x) -{ - BUG_ON(!kernel_map.va_pa_offset); - - return ((void *)((unsigned long)(x) + kernel_map.va_pa_offset)); -} -EXPORT_SYMBOL(linear_mapping_pa_to_va); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index bf502ba8da95..c28aedd7ae1f 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -888,13 +888,12 @@ const void * __init of_flat_dt_match_machine(const void *default_match, static void __early_init_dt_declare_initrd(unsigned long start, unsigned long end) { - /* - * __va() is not yet available this early on some platforms. In that - * case, the platform uses phys_initrd_start/phys_initrd_size instead - * and does the VA conversion itself. + /* ARM64 would cause a BUG to occur here when CONFIG_DEBUG_VM is + * enabled since __va() is called too early. ARM64 does make use + * of phys_initrd_start/phys_initrd_size so we can skip this + * conversion. */ - if (!IS_ENABLED(CONFIG_ARM64) && - !(IS_ENABLED(CONFIG_RISCV) && IS_ENABLED(CONFIG_64BIT))) { + if (!IS_ENABLED(CONFIG_ARM64)) { initrd_start = (unsigned long)__va(start); initrd_end = (unsigned long)__va(end); initrd_below_start_ok = 1; -- 2.20.1