arm64: enforce x1|x2|x3 == 0 upon kernel entry as per boot protocol
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 17 Mar 2015 09:55:12 +0000 (10:55 +0100)
committerWill Deacon <will.deacon@arm.com>
Thu, 19 Mar 2015 19:46:02 +0000 (19:46 +0000)
According to the arm64 boot protocol, registers x1 to x3 should be
zero upon kernel entry, and non-zero values are reserved for future
use. This future use is going to be problematic if we never enforce
the current rules, so start enforcing them now, by emitting a warning
if non-zero values are detected.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
arch/arm64/kernel/head.S
arch/arm64/kernel/setup.c

index f5ac337f959874e06f35ef1ce9c0141ca9858ac5..1fdf42041f42a1f293052c75f09644c75b4af755 100644 (file)
@@ -233,7 +233,7 @@ section_table:
 #endif
 
 ENTRY(stext)
-       mov     x21, x0                         // x21=FDT
+       bl      preserve_boot_args
        bl      el2_setup                       // Drop to EL1, w20=cpu_boot_mode
        adrp    x24, __PHYS_OFFSET
        bl      set_cpu_boot_mode_flag
@@ -252,6 +252,23 @@ ENTRY(stext)
        b       __cpu_setup                     // initialise processor
 ENDPROC(stext)
 
+/*
+ * Preserve the arguments passed by the bootloader in x0 .. x3
+ */
+preserve_boot_args:
+       mov     x21, x0                         // x21=FDT
+
+       adr_l   x0, boot_args                   // record the contents of
+       stp     x21, x1, [x0]                   // x0 .. x3 at kernel entry
+       stp     x2, x3, [x0, #16]
+
+       dmb     sy                              // needed before dc ivac with
+                                               // MMU off
+
+       add     x1, x0, #0x20                   // 4 x 8 bytes
+       b       __inval_cache_range             // tail call
+ENDPROC(preserve_boot_args)
+
 /*
  * Determine validity of the x21 FDT pointer.
  * The dtb must be 8-byte aligned and live in the first 512M of memory.
index 1783b38cf4c0feb8ac3a64a0b0e3293ab8f7b6c9..51ef97274b52ac342a6c760aa60cd90665a7e705 100644 (file)
@@ -115,6 +115,11 @@ void __init early_print(const char *str, ...)
        printk("%s", buf);
 }
 
+/*
+ * The recorded values of x0 .. x3 upon kernel entry.
+ */
+u64 __cacheline_aligned boot_args[4];
+
 void __init smp_setup_processor_id(void)
 {
        u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
@@ -412,6 +417,12 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
+       if (boot_args[1] || boot_args[2] || boot_args[3]) {
+               pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n"
+                       "\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n"
+                       "This indicates a broken bootloader or old kernel\n",
+                       boot_args[1], boot_args[2], boot_args[3]);
+       }
 }
 
 static int __init arm64_device_init(void)