diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2015-03-17 05:55:12 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-03-19 15:46:02 -0400 |
commit | da9c177de88679c2948dc9a5e2325b0dff4677b9 (patch) | |
tree | 1ef1c5f3698aea6230899127fb1583ab55faa53c | |
parent | 6f4d57fa7021efbf135cfa068d56bc5035edffa1 (diff) |
arm64: enforce x1|x2|x3 == 0 upon kernel entry as per boot protocol
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>
-rw-r--r-- | arch/arm64/kernel/head.S | 19 | ||||
-rw-r--r-- | arch/arm64/kernel/setup.c | 11 |
2 files changed, 29 insertions, 1 deletions
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index f5ac337f9598..1fdf42041f42 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S | |||
@@ -233,7 +233,7 @@ section_table: | |||
233 | #endif | 233 | #endif |
234 | 234 | ||
235 | ENTRY(stext) | 235 | ENTRY(stext) |
236 | mov x21, x0 // x21=FDT | 236 | bl preserve_boot_args |
237 | bl el2_setup // Drop to EL1, w20=cpu_boot_mode | 237 | bl el2_setup // Drop to EL1, w20=cpu_boot_mode |
238 | adrp x24, __PHYS_OFFSET | 238 | adrp x24, __PHYS_OFFSET |
239 | bl set_cpu_boot_mode_flag | 239 | bl set_cpu_boot_mode_flag |
@@ -253,6 +253,23 @@ ENTRY(stext) | |||
253 | ENDPROC(stext) | 253 | ENDPROC(stext) |
254 | 254 | ||
255 | /* | 255 | /* |
256 | * Preserve the arguments passed by the bootloader in x0 .. x3 | ||
257 | */ | ||
258 | preserve_boot_args: | ||
259 | mov x21, x0 // x21=FDT | ||
260 | |||
261 | adr_l x0, boot_args // record the contents of | ||
262 | stp x21, x1, [x0] // x0 .. x3 at kernel entry | ||
263 | stp x2, x3, [x0, #16] | ||
264 | |||
265 | dmb sy // needed before dc ivac with | ||
266 | // MMU off | ||
267 | |||
268 | add x1, x0, #0x20 // 4 x 8 bytes | ||
269 | b __inval_cache_range // tail call | ||
270 | ENDPROC(preserve_boot_args) | ||
271 | |||
272 | /* | ||
256 | * Determine validity of the x21 FDT pointer. | 273 | * Determine validity of the x21 FDT pointer. |
257 | * The dtb must be 8-byte aligned and live in the first 512M of memory. | 274 | * The dtb must be 8-byte aligned and live in the first 512M of memory. |
258 | */ | 275 | */ |
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 1783b38cf4c0..51ef97274b52 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
@@ -115,6 +115,11 @@ void __init early_print(const char *str, ...) | |||
115 | printk("%s", buf); | 115 | printk("%s", buf); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | ||
119 | * The recorded values of x0 .. x3 upon kernel entry. | ||
120 | */ | ||
121 | u64 __cacheline_aligned boot_args[4]; | ||
122 | |||
118 | void __init smp_setup_processor_id(void) | 123 | void __init smp_setup_processor_id(void) |
119 | { | 124 | { |
120 | u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; | 125 | u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; |
@@ -412,6 +417,12 @@ void __init setup_arch(char **cmdline_p) | |||
412 | conswitchp = &dummy_con; | 417 | conswitchp = &dummy_con; |
413 | #endif | 418 | #endif |
414 | #endif | 419 | #endif |
420 | if (boot_args[1] || boot_args[2] || boot_args[3]) { | ||
421 | pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n" | ||
422 | "\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n" | ||
423 | "This indicates a broken bootloader or old kernel\n", | ||
424 | boot_args[1], boot_args[2], boot_args[3]); | ||
425 | } | ||
415 | } | 426 | } |
416 | 427 | ||
417 | static int __init arm64_device_init(void) | 428 | static int __init arm64_device_init(void) |