Currently the init_thread_union contains both the stack and the thread_info of the init thread. The current kernel relocation code makes use of this such that the C code can update the thread_info in r28, and then the asm can manipulate that value to find the value for the SP in the new image. Once CONFIG_THREAD_INFO_IN_TASK is activated, this will no longer be possible since the task struct held in r28 will be separate from the stack. In preparation for this, change relocate_kernel to just prepare the new image, and return the applied offset. The assembly code in kernel_entry can then perform the necessary steps to set up the state for the relocated image just as it did for the initial image. Signed-off-by: Matt Redfearn <matt.redfearn@xxxxxxxx> --- arch/mips/kernel/head.S | 16 ++++++++-------- arch/mips/kernel/relocate.c | 20 ++++++-------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index d1bb506adc10..0fcb3e048ece 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -142,20 +142,20 @@ dtb_found: /* Copy kernel and apply the relocations */ jal relocate_kernel - /* Repoint the sp into the new kernel image */ - PTR_LI sp, _THREAD_SIZE - 32 - PT_SIZE - PTR_ADDU sp, $28 + /* relocate_kernel returns the offset applied, apply it to ti & sp */ + PTR_ADDU $28, v0 + PTR_ADDU sp, v0 + set_saved_sp sp, t0, t1 - PTR_SUBU sp, 4 * SZREG # init stack pointer /* - * relocate_kernel returns the entry point either - * in the relocated kernel or the original if for - * some reason relocation failed - jump there now + * Find start_kernel in relocated image and jump there * with instruction hazard barrier because of the * newly sync'd icache. */ - jr.hb v0 + PTR_LA t0, start_kernel + PTR_ADDU t0, v0 + jr.hb t0 #else j start_kernel #endif diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index cbf4cc0b0b6c..6c9a8e5c1652 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -294,15 +294,13 @@ static inline int __init relocation_addr_valid(void *loc_new) return 1; } -void *__init relocate_kernel(void) +int __init relocate_kernel(void) { void *loc_new; unsigned long kernel_length; unsigned long bss_length; long offset = 0; int res = 1; - /* Default to original kernel entry point */ - void *kernel_entry = start_kernel; void *fdt = NULL; /* Get the command line */ @@ -359,14 +357,14 @@ void *__init relocate_kernel(void) /* Perform relocations on the new kernel */ res = do_relocations(&_text, loc_new, offset); if (res < 0) - goto out; + return 0; /* Sync the caches ready for execution of new kernel */ sync_icache(loc_new, kernel_length); res = relocate_exception_table(offset); if (res < 0) - goto out; + return 0; /* * The original .bss has already been cleared, and @@ -390,16 +388,10 @@ void *__init relocate_kernel(void) * resident in memory and ready to be executed. */ if (plat_post_relocation(offset)) - goto out; - - /* The current thread is now within the relocated image */ - __current_thread_info = RELOCATED(&init_thread_union); - - /* Return the new kernel's entry point */ - kernel_entry = RELOCATED(start_kernel); + return 0; } -out: - return kernel_entry; + + return offset; } /* -- 2.7.4