blob: 5a9496024e2a164884fbaaa47fc6a9be40b7062f [file] [log] [blame]
/* 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