/* SPDX-License-Identifier: GPL-2.0-only */ /* * Early initialization code for POWER8/POWER9. */ #include <cpu/power/spr.h> #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 /* Store FDT address provided by QEMU in %r3 to pass it later to * payload */ mtspr SPR_HSPRG0, %r3 /* 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