@@ -1,5 +1,7 @@
obj-$(CONFIG_PPC64) += ppc64/
+obj-y += setup.o
+
$(TARGET): $(TARGET)-syms
cp -f $< $@
new file mode 100644
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _ASM_PPC_ASM_DEFNS_H
+#define _ASM_PPC_ASM_DEFNS_H
+
+/*
+ * Load a 64-bit immediate value into the specified GPR.
+ */
+#define LOAD_IMM64(reg, val) \
+ lis reg, (val) @highest; \
+ ori reg, reg, (val) @higher; \
+ rldicr reg, reg, 32, 31; \
+ oris reg, reg, (val) @h; \
+ ori reg, reg, (val) @l;
+
+#define LOAD_IMM32(reg, val) \
+ lis reg, (val) @h; \
+ ori reg, reg, (val) @l; \
+
+/*
+ * Depending on how we were booted, the CPU could be running in either
+ * Little Endian or Big Endian mode. The following trampoline from Linux
+ * cleverly uses an instruction that encodes to a NOP if the CPU's
+ * endianness matches the assumption of the assembler (LE, in our case)
+ * or a branch to code that performs the endian switch in the other case.
+ */
+#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 */
+
+#endif /* _ASM_PPC_ASM_DEFNS_H */
@@ -43,7 +43,7 @@
#define SMP_CACHE_BYTES (1 << 6)
-#define STACK_ORDER 2
+#define STACK_ORDER 0
#define STACK_SIZE (PAGE_SIZE << STACK_ORDER)
/* 288 bytes below the stack pointer must be preserved by interrupt handlers */
@@ -1,30 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <asm/asm-defns.h>
+
.section .text.header, "ax", %progbits
ENTRY(start)
/*
- * Depending on how we were booted, the CPU could be running in either
- * Little Endian or Big Endian mode. The following trampoline from Linux
- * cleverly uses an instruction that encodes to a NOP if the CPU's
- * endianness matches the assumption of the assembler (LE, in our case)
- * or a branch to code that performs the endian switch in the other case.
+ * NOTE: argument registers (r3-r9) must be preserved until the C entrypoint
*/
- 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 */
-
- /* Now that the endianness is confirmed, continue */
-1: b 1b
+ FIXUP_ENDIAN
+
+ /* set up the TOC pointer */
+ LOAD_IMM32(%r2, .TOC.)
+
+ /* set up the initial stack */
+ LOAD_IMM32(%r1, cpu0_boot_stack)
+ li %r11, 0
+ stdu %r11, -STACK_FRAME_OVERHEAD(%r1)
+
+ /* call the C entrypoint */
+ bl start_xen
+
+ /* should never return */
+ trap
.size start, . - start
.type start, %function
new file mode 100644
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <xen/init.h>
+
+/* Xen stack for bringing up the first CPU. */
+unsigned char __initdata cpu0_boot_stack[STACK_SIZE] __aligned(STACK_SIZE);
+
+/* Macro to adjust thread priority for hardware multithreading */
+#define HMT_very_low() asm volatile ( "or %r31, %r31, %r31" )
+
+void __init noreturn start_xen(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6,
+ unsigned long r7)
+{
+ for ( ; ; )
+ /* Set current hardware thread to very low priority */
+ HMT_very_low();
+
+ unreachable();
+}
Update ppc64/head.S to set up an initial boot stack, zero the .bss section, and jump to C. The required setup is done using 32-bit immediate address loads for now, but they will be changed to TOC-relative loads once the position-independent code model is enabled. Additionally, move the cpu0_boot_stack declaration to setup.c and change STACK_ORDER from 2 to 0. For now, ppc64 is using 64k pages and thus the larger STACK_ORDER is unnecessary. Finally, refactor the endian fixup trampoline into its own macro, since it will need to be used in multiple places, including every time we make a call into firmware. Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com> --- xen/arch/ppc/Makefile | 2 ++ xen/arch/ppc/include/asm/asm-defns.h | 40 ++++++++++++++++++++++++++++ xen/arch/ppc/include/asm/config.h | 2 +- xen/arch/ppc/ppc64/head.S | 38 +++++++++++++------------- xen/arch/ppc/setup.c | 19 +++++++++++++ 5 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 xen/arch/ppc/include/asm/asm-defns.h create mode 100644 xen/arch/ppc/setup.c