diff options
Diffstat (limited to 'src/arch/ppc64/bootblock_crt0.S')
-rw-r--r-- | src/arch/ppc64/bootblock_crt0.S | 92 |
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 |