Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: Ensure the secondary CPUs have safe ASIDBits size

Adds a hook for checking whether a secondary CPU has the
features used already by the kernel during early boot, based
on the boot CPU and plugs in the check for ASID size.

The ID_AA64MMFR0_EL1:ASIDBits determines the size of the mm context
id and is used in the early boot to make decisions. The value is
picked up from the Boot CPU and cannot be delayed until other CPUs
are up. If a secondary CPU has a smaller size than that of the Boot
CPU, things will break horribly and the usual SANITY check is not good
enough to prevent the system from crashing. So, crash the system with
enough information.

Cc: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Suzuki K Poulose and committed by
Catalin Marinas
13f417f3 038dc9c6

+32
+2
arch/arm64/include/asm/mmu_context.h
··· 203 203 #define deactivate_mm(tsk,mm) do { } while (0) 204 204 #define activate_mm(prev,next) switch_mm(prev, next, NULL) 205 205 206 + void verify_cpu_asid_bits(void); 207 + 206 208 #endif
+12
arch/arm64/kernel/cpufeature.c
··· 24 24 #include <asm/cpu.h> 25 25 #include <asm/cpufeature.h> 26 26 #include <asm/cpu_ops.h> 27 + #include <asm/mmu_context.h> 27 28 #include <asm/processor.h> 28 29 #include <asm/sysreg.h> 29 30 ··· 874 873 } 875 874 876 875 /* 876 + * Check for CPU features that are used in early boot 877 + * based on the Boot CPU value. 878 + */ 879 + static void check_early_cpu_features(void) 880 + { 881 + verify_cpu_asid_bits(); 882 + } 883 + 884 + /* 877 885 * Run through the enabled system capabilities and enable() it on this CPU. 878 886 * The capabilities were decided based on the available CPUs at the boot time. 879 887 * Any new CPU should match the system wide status of the capability. If the ··· 894 884 { 895 885 int i; 896 886 const struct arm64_cpu_capabilities *caps; 887 + 888 + check_early_cpu_features(); 897 889 898 890 /* 899 891 * If we haven't computed the system capabilities, there is nothing
+18
arch/arm64/mm/context.c
··· 24 24 25 25 #include <asm/cpufeature.h> 26 26 #include <asm/mmu_context.h> 27 + #include <asm/smp.h> 27 28 #include <asm/tlbflush.h> 28 29 29 30 static u32 asid_bits; ··· 61 60 } 62 61 63 62 return asid; 63 + } 64 + 65 + /* Check if the current cpu's ASIDBits is compatible with asid_bits */ 66 + void verify_cpu_asid_bits(void) 67 + { 68 + u32 asid = get_cpu_asid_bits(); 69 + 70 + if (asid < asid_bits) { 71 + /* 72 + * We cannot decrease the ASID size at runtime, so panic if we support 73 + * fewer ASID bits than the boot CPU. 74 + */ 75 + pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n", 76 + smp_processor_id(), asid, asid_bits); 77 + update_cpu_boot_status(CPU_PANIC_KERNEL); 78 + cpu_park_loop(); 79 + } 64 80 } 65 81 66 82 static void flush_context(unsigned int cpu)