summaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-22 07:58:09 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-22 07:58:09 -1000
commit5b6eaf4aeba0aab8cc757d79102aa9662d148f97 (patch)
treeb6ad7d0f455a40d0297b01357fc2f44680240bc3 /arch/arm/kernel
parentaad73b807cd1a5bff9c5277e8a42e75bbdc8adab (diff)
parent01330dac0fa7c16ef0f3da39757e9509653a2e3f (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.c49
-rw-r--r--arch/arm/kernel/efi.c13
-rw-r--r--arch/arm/kernel/head-nommu.S1
-rw-r--r--arch/arm/kernel/head.S1
-rw-r--r--arch/arm/kernel/smp.c15
-rw-r--r--arch/arm/kernel/topology.c13
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;
+ }
}