aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/ppc64/Makefile.inc3
-rw-r--r--src/arch/ppc64/bootblock.S10
-rw-r--r--src/arch/ppc64/bootblock_crt0.S92
3 files changed, 94 insertions, 11 deletions
diff --git a/src/arch/ppc64/Makefile.inc b/src/arch/ppc64/Makefile.inc
index 13b61673bd..8ccd62bfab 100644
--- a/src/arch/ppc64/Makefile.inc
+++ b/src/arch/ppc64/Makefile.inc
@@ -9,7 +9,8 @@ ppc64_asm_flags =
################################################################################
ifeq ($(CONFIG_ARCH_BOOTBLOCK_PPC64),y)
-bootblock-y = bootblock.S stages.c
+bootblock-y = bootblock_crt0.S
+bootblock-y += arch_timer.c
bootblock-y += boot.c
bootblock-y += rom_media.c
bootblock-y += \
diff --git a/src/arch/ppc64/bootblock.S b/src/arch/ppc64/bootblock.S
deleted file mode 100644
index b443f056d1..0000000000
--- a/src/arch/ppc64/bootblock.S
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Early initialization code for POWER8.
- */
-
-.section ".text._start", "ax", %progbits
-.globl _start
-.org 0x100, 0xff
-_start:
- b _start
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