diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 07:58:09 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 07:58:09 -1000 |
| commit | 5b6eaf4aeba0aab8cc757d79102aa9662d148f97 (patch) | |
| tree | b6ad7d0f455a40d0297b01357fc2f44680240bc3 /arch/arm/kernel | |
| parent | aad73b807cd1a5bff9c5277e8a42e75bbdc8adab (diff) | |
| parent | 01330dac0fa7c16ef0f3da39757e9509653a2e3f (diff) | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
Pull ARM updates from Russell King:
- remove supersection support
- set "current" earlier to avoid KASAN issues
- fix a couple of corner cases in the alignment handler
- fix wrong free function in iommu allocation path
- cacheinfo updates
- properly align hugetlb mappings
- always set endianness on xscale
- fix clang backtracer
- avoid replacing active_asids if already 0
* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux:
ARM: 9493/1: asid: Do not replace active_asids if already 0
ARM: 9490/1: backtrace-clang: fix wrong sp usage for unwinding
ARM: 9482/5: decompressor: always set endianess on xscale
ARM: 9524/1: mm: align hugetlb mappings to the huge page size
ARM: 9523/1: topology: allocate the cacheinfo early on the boot CPU
ARM: 9522/1: cacheinfo: guard the CLIDR read in populate_cache_leaves()
ARM: 9521/1: cacheinfo: count external caches in early_cache_level()
ARM: 9520/1: cacheinfo: avoid out-of-bounds write in populate_cache_leaves()
ARM: 9519/1: dma-mapping: Fix wrong free function in __iommu_alloc_simple() error path
ARM: 9492/1: alignment: fix LSR #32 and ASR #32 offset decoding
ARM: 9491/1: alignment: restore uaccess state on emulation fault
ARM: 9488/1: smp: set current pointer in assembly before jumping into C
ARM: 9486/1: set !LPAE MAX_PHYSMEM_BITS to 32 and remove supersection mappings
Diffstat (limited to 'arch/arm/kernel')
| -rw-r--r-- | arch/arm/kernel/cacheinfo.c | 49 | ||||
| -rw-r--r-- | arch/arm/kernel/efi.c | 13 | ||||
| -rw-r--r-- | arch/arm/kernel/head-nommu.S | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/head.S | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/smp.c | 15 | ||||
| -rw-r--r-- | arch/arm/kernel/topology.c | 13 |
6 files changed, 55 insertions, 37 deletions
diff --git a/arch/arm/kernel/cacheinfo.c b/arch/arm/kernel/cacheinfo.c index e1469b641780..993c8a134786 100644 --- a/arch/arm/kernel/cacheinfo.c +++ b/arch/arm/kernel/cacheinfo.c @@ -80,19 +80,21 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, this_leaf->type = type; } -static int detect_cache_level(unsigned int *level_p, unsigned int *leaves_p) +static bool clidr_present(void) { - unsigned int ctype, level, leaves; - u32 ctr, format; - /* CLIDR is not present before ARMv7/v7m */ if (cpu_architecture() < CPU_ARCH_ARMv7) - return -EOPNOTSUPP; + return false; /* Don't try reading CLIDR if CTR declares old format */ - ctr = read_cpuid_cachetype(); - format = FIELD_GET(CTR_FORMAT_MASK, ctr); - if (format != CTR_FORMAT_ARMV7) + return FIELD_GET(CTR_FORMAT_MASK, read_cpuid_cachetype()) == CTR_FORMAT_ARMV7; +} + +static int detect_cache_level(unsigned int *level_p, unsigned int *leaves_p) +{ + unsigned int ctype, level, leaves; + + if (!clidr_present()) return -EOPNOTSUPP; for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { @@ -111,13 +113,6 @@ static int detect_cache_level(unsigned int *level_p, unsigned int *leaves_p) return 0; } -int early_cache_level(unsigned int cpu) -{ - struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); - - return detect_cache_level(&this_cpu_ci->num_levels, &this_cpu_ci->num_leaves); -} - int init_cache_level(unsigned int cpu) { unsigned int level, leaves; @@ -146,26 +141,32 @@ int init_cache_level(unsigned int cpu) return 0; } +int early_cache_level(unsigned int cpu) +{ + return init_cache_level(cpu); +} + int populate_cache_leaves(unsigned int cpu) { unsigned int level, idx; enum cache_type type; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); - struct cacheinfo *this_leaf = this_cpu_ci->info_list; - unsigned int arch = cpu_architecture(); + struct cacheinfo *infos = this_cpu_ci->info_list; - /* CLIDR is not present before ARMv7/v7m */ - if (arch < CPU_ARCH_ARMv7) - return -EOPNOTSUPP; + /* The device tree can describe caches CLIDR cannot fill in. */ + if (!clidr_present()) + return -ENOENT; for (idx = 0, level = 1; level <= this_cpu_ci->num_levels && - idx < this_cpu_ci->num_leaves; idx++, level++) { + idx < this_cpu_ci->num_leaves; level++) { type = get_cache_type(level); if (type == CACHE_TYPE_SEPARATE) { - ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level); - ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level); + if (idx + 1 >= this_cpu_ci->num_leaves) + break; + ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level); + ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level); } else { - ci_leaf_init(this_leaf++, type, level); + ci_leaf_init(&infos[idx++], type, level); } } diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c index 6f9ec7d28a71..c14275257a8a 100644 --- a/arch/arm/kernel/efi.c +++ b/arch/arm/kernel/efi.c @@ -6,6 +6,7 @@ #include <linux/efi.h> #include <linux/memblock.h> #include <linux/screen_info.h> +#include <linux/sizes.h> #include <asm/efi.h> #include <asm/mach/map.h> @@ -55,6 +56,18 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) }; /* + * Non-LPAE page tables cannot map EFI runtime regions extending + * beyond the 32-bit physical address space. + */ + if (!IS_ENABLED(CONFIG_ARM_LPAE) && + (md->phys_addr >= SZ_4G || + md->num_pages > (SZ_4G - md->phys_addr) / EFI_PAGE_SIZE)) { + pr_warn("EFI runtime region at 0x%llx exceeds 32-bit physical address space\n", + md->phys_addr); + return -ERANGE; + } + + /* * Order is important here: memory regions may have all of the * bits below set (and usually do), so we check them in order of * preference. diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index b9d6818f1ee1..f80bbfbd3a6f 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -116,6 +116,7 @@ ENTRY(secondary_startup) ldr r7, __secondary_data @ reload r7 ldr sp, [r7, #12] @ set up the stack pointer ldr r0, [r7, #16] @ set up task pointer + set_current r0, r1 mov fp, #0 b secondary_start_kernel ENDPROC(secondary_startup) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f22c50d4bd41..a22403a629ef 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -442,6 +442,7 @@ ENTRY(__secondary_switched) adr_l r7, secondary_data + 12 @ get secondary_data.stack ldr sp, [r7] ldr r0, [r7, #4] @ get secondary_data.task + set_current r0, r1 mov fp, #0 b secondary_start_kernel ENDPROC(__secondary_switched) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b5fb4697bc3f..a9f4600fe4d0 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -371,12 +371,9 @@ void __noreturn arch_cpu_idle_dead(void) */ __asm__("mov sp, %0\n" " mov fp, #0\n" - " mov r0, %1\n" " b secondary_start_kernel" : - : "r" (task_stack_page(current) + THREAD_SIZE - 8), - "r" (current) - : "r0"); + : "r" (task_stack_page(current) + THREAD_SIZE - 8)); unreachable(); } @@ -397,23 +394,15 @@ static void smp_store_cpu_info(unsigned int cpuid) check_cpu_icache_size(cpuid); } -static void set_current(struct task_struct *cur) -{ - /* Set TPIDRURO */ - asm("mcr p15, 0, %0, c13, c0, 3" :: "r"(cur) : "memory"); -} - /* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void secondary_start_kernel(struct task_struct *task) +asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu; - set_current(task); - secondary_biglittle_init(); /* diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 2336ee2aa44a..e6b50cd43ce5 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -12,6 +12,7 @@ */ #include <linux/arch_topology.h> +#include <linux/cacheinfo.h> #include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/cpumask.h> @@ -238,8 +239,20 @@ topology_populated: */ void __init init_cpu_topology(void) { + int cpu, ret; + reset_cpu_topology(); smp_wmb(); parse_dt_topology(); + + for_each_possible_cpu(cpu) { + ret = fetch_cache_info(cpu); + if (!ret) + continue; + /* CPUs without a usable CLIDR return -EOPNOTSUPP. */ + if (ret != -ENOENT && ret != -EOPNOTSUPP) + pr_err("Early cacheinfo failed, ret = %d\n", ret); + return; + } } |
