summaryrefslogtreecommitdiff
path: root/src/arch/ppc64/bootblock_crt0.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/ppc64/bootblock_crt0.S')
-rw-r--r--src/arch/ppc64/bootblock_crt0.S92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/arch/ppc64/bootblock_crt0.S b/src/arch/ppc64/bootblock_crt0.S
new file mode 100644
index 0000000000..3988583bee
--- /dev/null
+++ b/src/arch/ppc64/bootblock_crt0.S
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Early initialization code for POWER8/POWER9.
+ */
+
+#define FIXUP_ENDIAN \
+ tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
+ b $+44; /* Skip trampoline if endian is good */ \
+ .long 0xa600607d; /* mfmsr r11 */ \
+ .long 0x01006b69; /* xori r11,r11,1 */ \
+ .long 0x00004039; /* li r10,0 */ \
+ .long 0x6401417d; /* mtmsrd r10,1 */ \
+ .long 0x05009f42; /* bcl 20,31,$+4 */ \
+ .long 0xa602487d; /* mflr r10 */ \
+ .long 0x14004a39; /* addi r10,r10,20 */ \
+ .long 0xa6035a7d; /* mtsrr0 r10 */ \
+ .long 0xa6037b7d; /* mtsrr1 r11 */ \
+ .long 0x2400004c /* rfid */
+
+/* Load an immediate 64-bit value into a register */
+#define LOAD_IMM64(r, e) \
+ lis r,(e)@highest; \
+ ori r,r,(e)@higher; \
+ rldicr r,r, 32, 31; \
+ oris r,r, (e)@h; \
+ ori r,r, (e)@l;
+
+.section ".text._start", "ax", %progbits
+.globl _start
+_start:
+ /* QEMU with hb-mode=on starts at address 0x10, while hardware at 0x0 */
+ nop
+ nop
+ nop
+ nop
+ FIXUP_ENDIAN
+
+ /* Set program priority to medium */
+ or %r2, %r2, %r2
+
+ /* Stack */
+ lis %r1, _estack@ha
+ addi %r1, %r1, _estack@l
+
+ /* Clear .bss section */
+ /* Currently not needed, .bss is zeroed in the file. If it were to be
+ * used, make sure that .bss is 128B aligned (size of cache line),
+ * otherwise dcbz will clear (part of) .opd section! */
+/*
+ lis %r5, _bss@ha
+ addi %r5, %r5, _bss@l
+ lis %r6, _ebss@ha
+ addi %r6, %r6, _ebss@l
+ addi %r6, %r6, -1
+1:
+ dcbz 0, %r5
+ addi %r5, %r5, 128
+ cmpld cr7, %r5, %r6
+ blt cr7, 1b
+*/
+
+ /* This is tested by checkstack() just before jumping to payload */
+ LOAD_IMM64(%r3, 0xDEADBEEFDEADBEEF)
+ lis %r5, _stack@ha
+ addi %r5, %r5, _stack@l
+ subi %r5, %r5, 8
+ sub %r4, %r1, %r5
+ sradi %r4, %r4, 3 /* Divide by 8 */
+ mtctr %r4
+1:
+ stdu %r3, 8(%r5)
+ bc 25, 0, 1b
+
+ /* Enable floating point and vector operations */
+ /* Vector operations are sometimes generated for code like
+ * 'uint8_t x[32] = {0}', this results in an exception when vector
+ * registers (VEC) are not enabled. VSX (vector-scalar extension) is
+ * also enabled, there is no reason not to. Floating point must also be
+ * enabled for VSX.
+ */
+ mfmsr %r3
+ ori %r3, %r3, 0x2000 /* FP = 1 */
+ oris %r3, %r3, 0x0280 /* VEC = 1, VSX = 1 */
+ mtmsr %r3
+
+ /* Load official procedure descriptor address for main() */
+ lis %r12, main@ha
+ addi %r12, %r12, main@l
+
+ /* Load TOC pointer and jump to main() */
+ ld %r2, 8(%r12)
+ b main