[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v5 2/4] xen/ppc: Set up a basic C environment



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@xxxxxxxxxxxxxxxxxxxxx>
---
 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

diff --git a/xen/arch/ppc/Makefile b/xen/arch/ppc/Makefile
index 98220648af..530fba2121 100644
--- a/xen/arch/ppc/Makefile
+++ b/xen/arch/ppc/Makefile
@@ -1,5 +1,7 @@
 obj-$(CONFIG_PPC64) += ppc64/
 
+obj-y += setup.o
+
 $(TARGET): $(TARGET)-syms
        cp -f $< $@
 
diff --git a/xen/arch/ppc/include/asm/asm-defns.h 
b/xen/arch/ppc/include/asm/asm-defns.h
new file mode 100644
index 0000000000..6ea35f6edb
--- /dev/null
+++ b/xen/arch/ppc/include/asm/asm-defns.h
@@ -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 */
diff --git a/xen/arch/ppc/include/asm/config.h 
b/xen/arch/ppc/include/asm/config.h
index b9a6814f00..01ca5d0803 100644
--- a/xen/arch/ppc/include/asm/config.h
+++ b/xen/arch/ppc/include/asm/config.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 */
diff --git a/xen/arch/ppc/ppc64/head.S b/xen/arch/ppc/ppc64/head.S
index 2fcefb40d8..49b3066396 100644
--- a/xen/arch/ppc/ppc64/head.S
+++ b/xen/arch/ppc/ppc64/head.S
@@ -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
diff --git a/xen/arch/ppc/setup.c b/xen/arch/ppc/setup.c
new file mode 100644
index 0000000000..9e90a6179a
--- /dev/null
+++ b/xen/arch/ppc/setup.c
@@ -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();
+}
-- 
2.30.2




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.