[SLOF] [PATCH] OF: Add a separate direct kernel loading word

Jordan Niethe jniethe5 at gmail.com
Wed Jul 13 13:38:03 AEST 2022

On Tue, Jul 12, 2022 at 11:49 PM Segher Boessenkool
<segher at kernel.crashing.org> wrote:
> Hi!
> On Tue, Jul 12, 2022 at 10:46:24AM +1000, Jordan Niethe wrote:
> > Currently, go-64 is used for booting a kernel from qemu (i.e. -kernel).
> > However, there is an expectation from users that this should be able to
> > boot not just vmlinux kernels but things like Zimages too.
> >
> > The bootwrapper of a BE zImage is a 32-bit ELF. Attempting to load that
> > with go-64 means that it will be ran with MSR_SF set (64-bit mode). This
> > crashes early in boot (usually due to what should be 32-bit operations
> > being done with 64-bit registers eventually leading to an incorrect
> > address being generated and branched to).
> In PowerPC, all operations are done the same in SF=0 and SF=1 modes,
> except:
>   - For addressing storage, the high 32 bits are ignored if SF=0;
>   - For bdz and bdnz (bc with BO[2]=1) the high 32 bits are ignored;
>   - For integer record form instructions ("dot instructions"), the high
>     32 bits are ignored.
> Everything else is done exactly the same with SF=0 -- the high 32 bits
> of everything are set in exactly the same way, for example.
> In practice, what bites you is the first item, when doing table jumps:
> it ends up jumping to 0xffffffff12345678 instead of 0x0000000012345678
> when running 32-bit code with SF=1.  You get about two million
> instructions into yaboot before it blows up, for example :-)  Dot insns
> are very common, but you do end up with the result properly (sign-)
> extended most of the time :-)

Ah ok, it is the first case happening. For example, here the crash
comes after going to $0000000104002f24
when it should be going to $0000000004002f24. Like this:

=> 0x4002cd8:    add     r7,r7,r5
2: /x $r7 = 0xffff566c
3: /x $r5 = 0x400d8b8
(gdb) stepi
1: x/i $pc
=> 0x4002cdc:    mtctr   r7
2: /x $r7 = 0x104002f24
3: /x $r5 = 0x400d8b8
(gdb) stepi
1: x/i $pc
=> 0x4002ce0:    bctr
2: /x $r7 = 0x104002f24
3: /x $r5 = 0x400d8b8

> > Note that our 64-bit payloads are prepared to enter with MSR_SF cleared
> > and set it themselves very early.
> >
> > Add a new word named go-direct that will execute any simple payload
> > in-place and will enter with MSR_SF cleared. This allows booting a BE
> > zImage from qemu with -machine kernel-addr=0.
> Ouch.  So you run 64-bit programs in 32-bit mode as well, just hoping
> they will deal with it?  Not a good idea :-(  Current Linux is fine with
> it, but are other payloads, including future Linux?

In SLOF when using -kernel from qemu it already doesn't do the
"Preparing ELF-Format Programs for Execution" things (it runs it in
place, always enters the client BE).
So I thought these "-kernel" payloads weren't being treated as ELFs
but as the kind of client program described in the PowerPC Processor
Binding for 1275 (Section 8.2.1 Initial Register Values).
That seemed to indicate that a client program will be entered in
32-bit mode. So I thought it might be ok to do...

> "init-program" is supposed to set the MSR state correctly (in ciregs
> >srr1), based on the ELF headers (and btw the same is true for the LE
> flag etc).  A little ELF parsing is needed.

When booting from memory with the -kernel option, qemu has already
loaded the kernel into memory and tells SLOF where to jump into?
SLOF is not looking at the ELF at all in this case is it?


> Hope this helps,
> Segher

More information about the SLOF mailing list