From ed6cbe6e5563452f305e89c15846820f2874e431 Mon Sep 17 00:00:00 2001 From: Harith G Date: Wed, 18 Sep 2024 06:57:11 +0100 Subject: ARM: 9419/1: mm: Fix kernel memory mapping for xip kernels The patchset introducing kernel_sec_start/end variables to separate the kernel/lowmem memory mappings, broke the mapping of the kernel memory for xipkernels. kernel_sec_start/end variables are in RO area before the MMU is switched on for xipkernels. So these cannot be set early in boot in head.S. Fix this by setting these after MMU is switched on. xipkernels need two different mappings for kernel text (starting at CONFIG_XIP_PHYS_ADDR) and data (starting at CONFIG_PHYS_OFFSET). Also, move the kernel code mapping from devicemaps_init() to map_kernel(). Fixes: a91da5457085 ("ARM: 9089/1: Define kernel physical section start and end") Signed-off-by: Harith George Reviewed-by: Linus Walleij Signed-off-by: Russell King (Oracle) --- arch/arm/kernel/head.S | 8 ++++++-- arch/arm/mm/mmu.c | 34 +++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 1ec35f065617..28873cda464f 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -252,11 +252,15 @@ __create_page_tables: */ add r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ENTRY_ORDER) ldr r6, =(_end - 1) + + /* For XIP, kernel_sec_start/kernel_sec_end are currently in RO memory */ +#ifndef CONFIG_XIP_KERNEL adr_l r5, kernel_sec_start @ _pa(kernel_sec_start) #if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32 str r8, [r5, #4] @ Save physical start of kernel (BE) #else str r8, [r5] @ Save physical start of kernel (LE) +#endif #endif orr r3, r8, r7 @ Add the MMU flags add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ENTRY_ORDER) @@ -264,6 +268,7 @@ __create_page_tables: add r3, r3, #1 << SECTION_SHIFT cmp r0, r6 bls 1b +#ifndef CONFIG_XIP_KERNEL eor r3, r3, r7 @ Remove the MMU flags adr_l r5, kernel_sec_end @ _pa(kernel_sec_end) #if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32 @@ -271,8 +276,7 @@ __create_page_tables: #else str r3, [r5] @ Save physical end of kernel (LE) #endif - -#ifdef CONFIG_XIP_KERNEL +#else /* * Map the kernel image separately as it is not located in RAM. */ diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index f85c177cdf8d..f5b7a16c5803 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1402,18 +1402,6 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) create_mapping(&map); } - /* - * Map the kernel if it is XIP. - * It is always first in the modulearea. - */ -#ifdef CONFIG_XIP_KERNEL - map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); - map.virtual = MODULES_VADDR; - map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK; - map.type = MT_ROM; - create_mapping(&map); -#endif - /* * Map the cache flushing regions. */ @@ -1603,12 +1591,27 @@ static void __init map_kernel(void) * This will only persist until we turn on proper memory management later on * and we remap the whole kernel with page granularity. */ +#ifdef CONFIG_XIP_KERNEL + phys_addr_t kernel_nx_start = kernel_sec_start; +#else phys_addr_t kernel_x_start = kernel_sec_start; phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); phys_addr_t kernel_nx_start = kernel_x_end; +#endif phys_addr_t kernel_nx_end = kernel_sec_end; struct map_desc map; + /* + * Map the kernel if it is XIP. + * It is always first in the modulearea. + */ +#ifdef CONFIG_XIP_KERNEL + map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); + map.virtual = MODULES_VADDR; + map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK; + map.type = MT_ROM; + create_mapping(&map); +#else map.pfn = __phys_to_pfn(kernel_x_start); map.virtual = __phys_to_virt(kernel_x_start); map.length = kernel_x_end - kernel_x_start; @@ -1618,7 +1621,7 @@ static void __init map_kernel(void) /* If the nx part is small it may end up covered by the tail of the RWX section */ if (kernel_x_end == kernel_nx_end) return; - +#endif map.pfn = __phys_to_pfn(kernel_nx_start); map.virtual = __phys_to_virt(kernel_nx_start); map.length = kernel_nx_end - kernel_nx_start; @@ -1764,6 +1767,11 @@ void __init paging_init(const struct machine_desc *mdesc) { void *zero_page; +#ifdef CONFIG_XIP_KERNEL + /* Store the kernel RW RAM region start/end in these variables */ + kernel_sec_start = CONFIG_PHYS_OFFSET & SECTION_MASK; + kernel_sec_end = round_up(__pa(_end), SECTION_SIZE); +#endif pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n", kernel_sec_start, kernel_sec_end); -- cgit v1.2.3-73-gaa49b From 9e9b0cf9319b4db143014477b0bc4b39894248f1 Mon Sep 17 00:00:00 2001 From: Harith G Date: Wed, 18 Sep 2024 06:57:53 +0100 Subject: ARM: 9420/1: smp: Fix SMP for xip kernels Fix the physical address calculation of the following to get smp working on xip kernels. - secondary_data needed for secondary cpu bootup. - secondary_startup address passed through psci. - identity mapped code region needed for enabling mmu for secondary cpus. Signed-off-by: Harith George Reviewed-by: Linus Walleij Signed-off-by: Russell King (Oracle) --- arch/arm/kernel/head.S | 4 ++++ arch/arm/kernel/psci_smp.c | 7 +++++++ arch/arm/mm/idmap.c | 7 +++++++ 3 files changed, 18 insertions(+) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 28873cda464f..f22c50d4bd41 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -411,7 +411,11 @@ ENTRY(secondary_startup) /* * Use the page tables supplied from __cpu_up. */ +#ifdef CONFIG_XIP_KERNEL + ldr r3, =(secondary_data + PLAT_PHYS_OFFSET - PAGE_OFFSET) +#else adr_l r3, secondary_data +#endif mov_l r12, __secondary_switched ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE: diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index d4392e177484..3bb0c4dcfc5c 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c @@ -45,8 +45,15 @@ extern void secondary_startup(void); static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle) { if (psci_ops.cpu_on) +#ifdef CONFIG_XIP_KERNEL + return psci_ops.cpu_on(cpu_logical_map(cpu), + ((phys_addr_t)(&secondary_startup) + - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + + CONFIG_XIP_PHYS_ADDR)); +#else return psci_ops.cpu_on(cpu_logical_map(cpu), virt_to_idmap(&secondary_startup)); +#endif return -ENODEV; } diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 448e57c6f653..4a833e89782a 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -84,8 +84,15 @@ static void identity_mapping_add(pgd_t *pgd, const char *text_start, unsigned long addr, end; unsigned long next; +#ifdef CONFIG_XIP_KERNEL + addr = (phys_addr_t)(text_start) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + + CONFIG_XIP_PHYS_ADDR; + end = (phys_addr_t)(text_end) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + + CONFIG_XIP_PHYS_ADDR; +#else addr = virt_to_idmap(text_start); end = virt_to_idmap(text_end); +#endif pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end); prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; -- cgit v1.2.3-73-gaa49b From 4aea16b7cfb76bd3361858ceee6893ef5c9b5570 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 11 Nov 2024 00:17:03 +0100 Subject: ARM: 9434/1: cfi: Fix compilation corner case When enabling expert mode CONFIG_EXPERT and using that power user mode to disable the branch prediction hardening !CONFIG_HARDEN_BRANCH_PREDICTOR, the assembly linker in CLANG notices that some assembly in proc-v7.S does not have corresponding C call sites, i.e. the prototypes in proc-v7-bugs.c are enclosed in ifdef CONFIG_HARDEN_BRANCH_PREDICTOR so this assembly: SYM_TYPED_FUNC_START(cpu_v7_smc_switch_mm) SYM_TYPED_FUNC_START(cpu_v7_hvc_switch_mm) Results in: ld.lld: error: undefined symbol: __kcfi_typeid_cpu_v7_smc_switch_mm >>> referenced by proc-v7.S:94 (.../arch/arm/mm/proc-v7.S:94) >>> arch/arm/mm/proc-v7.o:(.text+0x108) in archive vmlinux.a ld.lld: error: undefined symbol: __kcfi_typeid_cpu_v7_hvc_switch_mm >>> referenced by proc-v7.S:105 (.../arch/arm/mm/proc-v7.S:105) >>> arch/arm/mm/proc-v7.o:(.text+0x124) in archive vmlinux.a Fix this by adding an additional requirement that CONFIG_HARDEN_BRANCH_PREDICTOR has to be enabled to compile these assembly calls. Closes: https://lore.kernel.org/oe-kbuild-all/202411041456.ZsoEiD7T-lkp@intel.com/ Reported-by: kernel test robot Reviewed-by: Nathan Chancellor Signed-off-by: Linus Walleij Signed-off-by: Russell King (Oracle) --- arch/arm/mm/proc-v7.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 5fb9a6aecb00..2cd933342679 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -94,7 +94,7 @@ SYM_TYPED_FUNC_START(cpu_v7_dcache_clean_area) ret lr SYM_FUNC_END(cpu_v7_dcache_clean_area) -#ifdef CONFIG_ARM_PSCI +#if defined(CONFIG_ARM_PSCI) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) .arch_extension sec SYM_TYPED_FUNC_START(cpu_v7_smc_switch_mm) stmfd sp!, {r0 - r3} -- cgit v1.2.3-73-gaa49b From fb5af7d5405bf89a848819d1af007dfc73e9fb57 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Mon, 11 Nov 2024 06:07:40 +0100 Subject: ARM: 9435/1: ARM/nommu: Fix typo "absence" There is a spelling mistake of 'absense' in comments which should be 'absence'. Link: https://lore.kernel.org/all/fca25741-c89f-43ea-95af-5e3232d513fc@arm.com/ Signed-off-by: WangYuli Reviewed-by: Vladimir Murzin Signed-off-by: Russell King (Oracle) --- arch/arm/mm/dma-mapping-nommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c index 97db5397c320..fecac107fd0d 100644 --- a/arch/arm/mm/dma-mapping-nommu.c +++ b/arch/arm/mm/dma-mapping-nommu.c @@ -39,7 +39,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) /* * Cache support for v7m is optional, so can be treated as * coherent if no cache has been detected. Note that it is not - * enough to check if MPU is in use or not since in absense of + * enough to check if MPU is in use or not since in absence of * MPU system memory map is used. */ dev->dma_coherent = cacheid ? coherent : true; -- cgit v1.2.3-73-gaa49b From ca29cfcc4a21083d671522ad384532e28a43f033 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 12 Nov 2024 10:16:13 +0000 Subject: ARM: fix cacheflush with PAN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that the cacheflush syscall got broken when PAN for LPAE was implemented. User access was not enabled around the cache maintenance instructions, causing them to fault. Fixes: 7af5b901e847 ("ARM: 9358/2: Implement PAN for LPAE by TTBR0 page table walks disablement") Reported-by: Michał Pecio Tested-by: Michał Pecio Signed-off-by: Russell King (Oracle) --- arch/arm/kernel/traps.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 480e307501bb..6ea645939573 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -570,6 +570,7 @@ static int bad_syscall(int n, struct pt_regs *regs) static inline int __do_cache_op(unsigned long start, unsigned long end) { + unsigned int ua_flags; int ret; do { @@ -578,7 +579,9 @@ __do_cache_op(unsigned long start, unsigned long end) if (fatal_signal_pending(current)) return 0; + ua_flags = uaccess_save_and_enable(); ret = flush_icache_user_range(start, start + chunk); + uaccess_restore(ua_flags); if (ret) return ret; -- cgit v1.2.3-73-gaa49b