[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 1/3] xen/ppc: Set up a basic C environment
On 22/06/2023 9:57 pm, Shawn Anastasio wrote: > Update ppc64/head.S to set up an initial boot stack, zero the .bss > section, and jump to C. > > Also 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 (see next commit). > > Signed-off-by: Shawn Anastasio <sanastasio@xxxxxxxxxxxxxxxxxxxxx> Thankyou for making this change - it definitely simplifies things. > --- > xen/arch/ppc/Makefile | 1 + > xen/arch/ppc/include/asm/asm-defns.h | 36 ++++++++++++++++++ > xen/arch/ppc/ppc64/head.S | 55 ++++++++++++++++++---------- > xen/arch/ppc/setup.c | 13 +++++++ > 4 files changed, 85 insertions(+), 20 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..fdbcd730d0 100644 > --- a/xen/arch/ppc/Makefile > +++ b/xen/arch/ppc/Makefile > @@ -1,4 +1,5 @@ > 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..3db2063a39 > --- /dev/null > +++ b/xen/arch/ppc/include/asm/asm-defns.h > @@ -0,0 +1,36 @@ > +/* 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; > + > +/* > + * 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/ppc64/head.S b/xen/arch/ppc/ppc64/head.S > index 2fcefb40d8..a7db5b7de2 100644 > --- a/xen/arch/ppc/ppc64/head.S > +++ b/xen/arch/ppc/ppc64/head.S > @@ -1,30 +1,45 @@ > /* 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 initial stack */ > + LOAD_IMM64(%r1, cpu0_boot_stack) > + li %r11, 0 > + std %r11, 0(%r1) I've done a bit of reading around, and it's rather sad that things prior to Power10 don't have PC-relative addressing. So the LOAD_IMM64()'s do look necessary for the stack and bss. I guess that means we can't be sensibly be position independent in head.S? Also, why store 0 onto the stack ? > + > + /* clear .bss */ > + LOAD_IMM64(%r14, __bss_start) > + LOAD_IMM64(%r15, __bss_end) > +1: > + std %r11, 0(%r14) > + addi %r14, %r14, 8 > + cmpld %r14, %r15 > + blt 1b This loop is correct, except for the corner case of this patch alone, where the BSS is empty and this will write one word out-of-bounds. For RISC-V, we put a temporary "char bss_tmp;" in setup.c, and I suggest you do the same here, deleting it at a later point when there's real data in the bss. > + > + /* call the C entrypoint */ > + LOAD_IMM64(%r12, start_xen) > + mtctr %r12 > + bctrl Why is this a LOAD_IMM64(), and not just: b start_xen ? From the same reading around, PPC64 seems to have +/- 32M addressing for branches, and the entire x86 hypervisor (.init included) is within 3M. > + > + /* should never return */ > + trap > > .size start, . - start > .type start, %function > + > + .section .init.data, "aw", @progbits > + > + /* Early init stack */ > + .p2align 4 > +cpu0_boot_stack_bottom: > + .space STACK_SIZE > +cpu0_boot_stack: > + .space STACK_FRAME_OVERHEAD Why the extra space beyond the stack? Also, I'd put cpu0_boot_stack in C, and just LOAD_IMM64(x, cpu0_boot_stack + STACK_SIZE) > diff --git a/xen/arch/ppc/setup.c b/xen/arch/ppc/setup.c > new file mode 100644 > index 0000000000..4d1b72fa23 > --- /dev/null > +++ b/xen/arch/ppc/setup.c > @@ -0,0 +1,13 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +#include <xen/init.h> > + > +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 */ > + asm volatile("or %r31, %r31, %r31"); Is there something magic about the OR instruction, or something magic about %r31? For a RISC architecture, this seems subtle. ~Andrew
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |