arm64: Ensure the secondary CPUs have safe ASIDBits size
authorSuzuki K Poulose <suzuki.poulose@arm.com>
Tue, 23 Feb 2016 10:31:45 +0000 (10:31 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Thu, 25 Feb 2016 10:33:06 +0000 (10:33 +0000)
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>
arch/arm64/include/asm/mmu_context.h
arch/arm64/kernel/cpufeature.c
arch/arm64/mm/context.c

index a00f7cf35bbd4d80ce045bfeb0cbb6bd061aeaaa..b1892a0dbcb0f8d7b52aeccd11f89418421712e8 100644 (file)
@@ -203,4 +203,6 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 #define deactivate_mm(tsk,mm)  do { } while (0)
 #define activate_mm(prev,next) switch_mm(prev, next, NULL)
 
+void verify_cpu_asid_bits(void);
+
 #endif
index 282a4f852dd19f8138bb9e3a0665f7210e20de4b..b7fa75fc0fa921e8f6d12e476c3183a6dabe5330 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
 #include <asm/cpu_ops.h>
+#include <asm/mmu_context.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 
@@ -872,6 +873,15 @@ static u64 __raw_read_system_reg(u32 sys_id)
        }
 }
 
+/*
+ * Check for CPU features that are used in early boot
+ * based on the Boot CPU value.
+ */
+static void check_early_cpu_features(void)
+{
+       verify_cpu_asid_bits();
+}
+
 /*
  * Run through the enabled system capabilities and enable() it on this CPU.
  * The capabilities were decided based on the available CPUs at the boot time.
@@ -885,6 +895,8 @@ void verify_local_cpu_capabilities(void)
        int i;
        const struct arm64_cpu_capabilities *caps;
 
+       check_early_cpu_features();
+
        /*
         * If we haven't computed the system capabilities, there is nothing
         * to verify.
index 21f9f1ea14f7c70d6cb20a8ce7a6a2e154bb756e..6b5783f6eb0ea3888acce991fb97088a32e7ea19 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <asm/cpufeature.h>
 #include <asm/mmu_context.h>
+#include <asm/smp.h>
 #include <asm/tlbflush.h>
 
 static u32 asid_bits;
@@ -62,6 +63,23 @@ static u32 get_cpu_asid_bits(void)
        return asid;
 }
 
+/* Check if the current cpu's ASIDBits is compatible with asid_bits */
+void verify_cpu_asid_bits(void)
+{
+       u32 asid = get_cpu_asid_bits();
+
+       if (asid < asid_bits) {
+               /*
+                * We cannot decrease the ASID size at runtime, so panic if we support
+                * fewer ASID bits than the boot CPU.
+                */
+               pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n",
+                               smp_processor_id(), asid, asid_bits);
+               update_cpu_boot_status(CPU_PANIC_KERNEL);
+               cpu_park_loop();
+       }
+}
+
 static void flush_context(unsigned int cpu)
 {
        int i;