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@raptorengineering.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Shawn Anastasio authored and Jan Beulich committed 2023-07-24 14:29:15 +02:00
1 parent 0c683baa67
commit 3a4e6f67bc
5 files changed
+79 -20

No files matched your search

+2
View File
@@ -1,5 +1,7 @@
obj-$(CONFIG_PPC64) += ppc64/
obj-y += setup.o
$(TARGET): $(TARGET)-syms
cp -f $< $@
+40
View File
@@ -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 */
+1 -1
View File
@@ -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 */
+17 -19
View File
@@ -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 */
FIXUP_ENDIAN
/* Now that the endianness is confirmed, continue */
1: b 1b
/* 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
+19
View File
@@ -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();
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.