summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/start.S27
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm64/kernel/start.S b/arch/arm64/kernel/start.S
index 6ee9941..3cf58d2 100644
--- a/arch/arm64/kernel/start.S
+++ b/arch/arm64/kernel/start.S
@@ -222,6 +222,24 @@ park:
wfe
b 1b
2:
+ /* interrupts masked at release, the manual's boot state */
+ msr daifset, #0xf
+ /*
+ * every PE must read the same virtual counter. whatever
+ * ran before this loader could have left a per cpu offset
+ * in the virtual counter view, the kernel has no way to
+ * repair that itself. CNTVOFF_EL2 is writable at EL2 and
+ * the write holds for the EL1 virtual timer the kernel
+ * runs on. below EL2 it is out of reach, the reset value
+ * is the best a lower EL can do.
+ */
+ mrs x4, CurrentEL
+ lsr x4, x4, #2
+ cmp x4, #2
+ b.lt 3f
+ msr cntvoff_el2, xzr
+ isb
+3:
mov x0, xzr /* secondaries enter with x0-x3 zero */
mov x1, xzr
mov x2, xzr
@@ -396,6 +414,15 @@ exc_serr:
mov x1, #0
mov x2, lr
bl exc_report
+ /*
+ * an SError while this loader runs means the machine is
+ * broken. handing the kernel a cpu that already lost is
+ * worse than stopping: report, then drive the reset domain
+ * the same way PSCI SYSTEM_RESET does. the reset call does
+ * not return, the park below is the fallback if a reset
+ * domain ignores the request.
+ */
+ bl tb_system_reset
ldp x29, x30, [sp], #16
b park