arm64: smp: Rework early feature mismatched detection
authorWill Deacon <will.deacon@arm.com>
Mon, 10 Dec 2018 14:21:13 +0000 (14:21 +0000)
committerWill Deacon <will.deacon@arm.com>
Mon, 10 Dec 2018 18:42:18 +0000 (18:42 +0000)
Rather than add additional variables to detect specific early feature
mismatches with secondary CPUs, we can instead dedicate the upper bits
of the CPU boot status word to flag specific mismatches.

This allows us to communicate both granule and VA-size mismatches back
to the primary CPU without the need for additional book-keeping.

Tested-by: Steve Capper <steve.capper@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
arch/arm64/include/asm/smp.h
arch/arm64/kernel/head.S
arch/arm64/kernel/smp.c

index f82b447bd34f03c94998a5ac105fb9adeb1ee7b0..1895561839a98a5b72f3e42808b0ff3056211bb4 100644 (file)
 #define __ASM_SMP_H
 
 /* Values for secondary_data.status */
+#define CPU_STUCK_REASON_SHIFT         (8)
+#define CPU_BOOT_STATUS_MASK           ((1U << CPU_STUCK_REASON_SHIFT) - 1)
 
-#define CPU_MMU_OFF            (-1)
-#define CPU_BOOT_SUCCESS       (0)
+#define CPU_MMU_OFF                    (-1)
+#define CPU_BOOT_SUCCESS               (0)
 /* The cpu invoked ops->cpu_die, synchronise it with cpu_kill */
-#define CPU_KILL_ME            (1)
+#define CPU_KILL_ME                    (1)
 /* The cpu couldn't die gracefully and is looping in the kernel */
-#define CPU_STUCK_IN_KERNEL    (2)
+#define CPU_STUCK_IN_KERNEL            (2)
 /* Fatal system error detected by secondary CPU, crash the system */
-#define CPU_PANIC_KERNEL       (3)
+#define CPU_PANIC_KERNEL               (3)
+
+#define CPU_STUCK_REASON_52_BIT_VA     (1U << CPU_STUCK_REASON_SHIFT)
+#define CPU_STUCK_REASON_NO_GRAN       (2U << CPU_STUCK_REASON_SHIFT)
 
 #ifndef __ASSEMBLY__
 
index 6b70dd625f0198a280ff9d10eaa0141cd1fca2c4..eaa68ce6a06db8897c7fc658bdd4b11524ae8107 100644 (file)
@@ -809,13 +809,8 @@ ENTRY(__cpu_secondary_check52bitva)
        and     x0, x0, #(0xf << ID_AA64MMFR2_LVA_SHIFT)
        cbnz    x0, 2f
 
-       adr_l   x0, va52mismatch
-       mov     w1, #1
-       strb    w1, [x0]
-       dmb     sy
-       dc      ivac, x0        // Invalidate potentially stale cache line
-
-       update_early_cpu_boot_status CPU_STUCK_IN_KERNEL, x0, x1
+       update_early_cpu_boot_status \
+               CPU_STUCK_IN_KERNEL | CPU_STUCK_REASON_52_BIT_VA, x0, x1
 1:     wfe
        wfi
        b       1b
@@ -826,7 +821,8 @@ ENDPROC(__cpu_secondary_check52bitva)
 
 __no_granule_support:
        /* Indicate that this CPU can't boot and is stuck in the kernel */
-       update_early_cpu_boot_status CPU_STUCK_IN_KERNEL, x1, x2
+       update_early_cpu_boot_status \
+               CPU_STUCK_IN_KERNEL | CPU_STUCK_REASON_NO_GRAN, x1, x2
 1:
        wfe
        wfi
index 1ff18f5fbecb26949a00e14778dbbd0a8ae0d690..4e3bfbde829a803f996af2128c641e48c66d326e 100644 (file)
@@ -108,7 +108,6 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle)
 }
 
 static DECLARE_COMPLETION(cpu_running);
-bool va52mismatch __ro_after_init;
 
 int __cpu_up(unsigned int cpu, struct task_struct *idle)
 {
@@ -138,10 +137,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 
                if (!cpu_online(cpu)) {
                        pr_crit("CPU%u: failed to come online\n", cpu);
-
-                       if (IS_ENABLED(CONFIG_ARM64_USER_VA_BITS_52) && va52mismatch)
-                               pr_crit("CPU%u: does not support 52-bit VAs\n", cpu);
-
                        ret = -EIO;
                }
        } else {
@@ -156,7 +151,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
                if (status == CPU_MMU_OFF)
                        status = READ_ONCE(__early_cpu_boot_status);
 
-               switch (status) {
+               switch (status & CPU_BOOT_STATUS_MASK) {
                default:
                        pr_err("CPU%u: failed in unknown state : 0x%lx\n",
                                        cpu, status);
@@ -170,6 +165,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
                        pr_crit("CPU%u: may not have shut down cleanly\n", cpu);
                case CPU_STUCK_IN_KERNEL:
                        pr_crit("CPU%u: is stuck in kernel\n", cpu);
+                       if (status & CPU_STUCK_REASON_52_BIT_VA)
+                               pr_crit("CPU%u: does not support 52-bit VAs\n", cpu);
+                       if (status & CPU_STUCK_REASON_NO_GRAN)
+                               pr_crit("CPU%u: does not support %luK granule \n", cpu, PAGE_SIZE / SZ_1K);
                        cpus_stuck_in_kernel++;
                        break;
                case CPU_PANIC_KERNEL: