Before the introduction of proper init-program contexts, OpenBIOS used a simple assembler call_elf() function to execute the guest kernel directly.
Switch over to using proper contexts via arch_init_program() which enables us to remove the legacy call_elf() completely.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/ppc/qemu/kernel.h | 1 - arch/ppc/qemu/main.c | 11 ++++++++++- arch/ppc/qemu/switch.S | 43 ------------------------------------------- 3 files changed, 10 insertions(+), 45 deletions(-)
diff --git a/arch/ppc/qemu/kernel.h b/arch/ppc/qemu/kernel.h index 3e25a56..0ded835 100644 --- a/arch/ppc/qemu/kernel.h +++ b/arch/ppc/qemu/kernel.h @@ -23,7 +23,6 @@ extern void exit( int status ) __attribute__ ((noreturn)); extern void flush_icache_range( char *start, char *stop ); extern void flush_dcache_range( char *start, char *stop ); extern char of_rtas_start[], of_rtas_end[]; -extern void call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry );
/* methods.c */ extern void node_methods_init( const char *cpuname ); diff --git a/arch/ppc/qemu/main.c b/arch/ppc/qemu/main.c index 44b1666..3c76e41 100644 --- a/arch/ppc/qemu/main.c +++ b/arch/ppc/qemu/main.c @@ -24,6 +24,8 @@ #include "kernel.h" #include "drivers/drivers.h" #include "libopenbios/ofmem.h" +#include "libopenbios/initprogram.h" +#include "context.h" #define NO_QEMU_PROTOS #include "arch/common/fw_cfg.h"
@@ -45,6 +47,7 @@ static void check_preloaded_kernel(void) unsigned long kernel_image, kernel_size; unsigned long initrd_image, initrd_size; const char * kernel_cmdline; + volatile struct context *ctx = __context;
kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); if (kernel_size) { @@ -61,7 +64,13 @@ static void check_preloaded_kernel(void) ph = find_dev("/chosen"); set_property(ph, "bootargs", strdup(kernel_cmdline), strlen(kernel_cmdline) + 1); } - call_elf(initrd_image, initrd_size, kernel_image); + + arch_init_program(); + ctx->regs[REG_R3] = initrd_image; + ctx->regs[REG_R4] = initrd_size; + ctx->pc = kernel_image; + + start_elf(); } }
diff --git a/arch/ppc/qemu/switch.S b/arch/ppc/qemu/switch.S index f1b120d..32a7bbf 100644 --- a/arch/ppc/qemu/switch.S +++ b/arch/ppc/qemu/switch.S @@ -17,49 +17,6 @@ #endif #endif
- /* According to IEEE 1275, PPC bindings: - * - * MSR = FP, ME + (DR|IR) - * r1 = stack (32 K + 32 bytes link area above) - * r5 = client interface handler - * r6 = address of client program arguments (unused) - * r7 = length of client program arguments (unused) - * - * Yaboot and Linux use r3 and r4 for initrd address and size - */ - - /* void call_elf( arg1, arg2, entry ) */ -_GLOBAL(call_elf): - mflr r0 - PPC_STLU r1, -STACKFRAME_MINSIZE(r1) - PPC_STL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1) - mtlr r5 - LOAD_REG_IMMEDIATE(r8, saved_stack) // save our stack pointer - PPC_STL r1,0(r8) - mfsdr1 r1 - addi r1, r1, -32768 /* - 32 KiB exception stack */ - addis r1, r1, -1 /* - 64 KiB stack */ - LOAD_REG_IMMEDIATE(r5, of_client_callback) // r5 = callback - li r6,0 // r6 = address of client program arguments (unused) - li r7,0 // r7 = length of client program arguments (unused) - li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR - MTMSRD(r0) - blrl - -#ifdef CONFIG_PPC64 - /* Restore SF bit */ - LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR) - MTMSRD(r0) -#endif - LOAD_REG_IMMEDIATE(r8, saved_stack) // restore stack pointer - mr r1,r8 - PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1) - mtlr r0 - addi r1, r1, STACKFRAME_MINSIZE - // XXX: should restore r12-r31 etc.. - // we should not really come here though - blrl - /* * Switch execution context * This saves registers in the stack, then