summaryrefslogtreecommitdiffstats
path: root/stand/powerpc/kboot/kerneltramp.S
diff options
context:
space:
mode:
Diffstat (limited to 'stand/powerpc/kboot/kerneltramp.S')
-rw-r--r--stand/powerpc/kboot/kerneltramp.S55
1 files changed, 55 insertions, 0 deletions
diff --git a/stand/powerpc/kboot/kerneltramp.S b/stand/powerpc/kboot/kerneltramp.S
new file mode 100644
index 0000000..a394c95
--- /dev/null
+++ b/stand/powerpc/kboot/kerneltramp.S
@@ -0,0 +1,55 @@
+/*
+ * This is the analog to the kexec "purgatory" code
+ *
+ * The goal here is to call the actual kernel entry point with the arguments it
+ * expects when kexec calls into it with no arguments. The value of the kernel
+ * entry point and arguments r3-r7 are copied into the trampoline text (which
+ * can be executed from any address) at bytes 8-32. kexec begins execution
+ * of APs at 0x60 bytes past the entry point, executing in a copy relocated
+ * to the absolute address 0x60. Here we implement a loop waiting on the release
+ * of a lock by the kernel at 0x40.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+
+ .globl CNAME(kerneltramp),CNAME(szkerneltramp)
+CNAME(kerneltramp):
+ mflr %r9
+ bl 2f
+ .space 24 /* branch address, r3-r7 */
+
+. = kerneltramp + 0x40 /* AP spinlock */
+ .long 0
+
+. = kerneltramp + 0x60 /* AP entry point */
+ li %r3,0x40
+1: lwz %r1,0(%r3)
+ cmpwi %r1,0
+ beq 1b
+
+ /* Jump into CPU reset */
+ li %r0,0x100
+ icbi 0,%r0
+ isync
+ sync
+ ba 0x100
+
+2: /* Continuation of kerneltramp */
+ mflr %r8
+ mtlr %r9
+ lwz %r3,0(%r8)
+ mtctr %r3
+ lwz %r3,4(%r8)
+ lwz %r4,8(%r8)
+ lwz %r5,12(%r8)
+ lwz %r6,16(%r8)
+ lwz %r7,20(%r8)
+ bctr
+
+endkerneltramp:
+
+ .data
+CNAME(szkerneltramp):
+ .long endkerneltramp - CNAME(kerneltramp)
OpenPOWER on IntegriCloud