On Thursday 09 August 2007 14:35:30 Ralf Baechle wrote: Hi, > I recently noticed the kernel part was fairly broken, did (if ever) only > work for 32-bit machines. I fixed what I could but I don't have the > necessary test setup. See > > http://www.linux-mips.org/git?p=linux.git;a=commit;h=bb73f9d8ee3133800da546 >832ca7f09d3f27695e My appologies for this, I should have taken more care about 64 bit portability when writing this code. I have also been trying to address the cache problem in the kexec code. please see the attached patch. I now use __flush_cache_all(), since flush_cache_all() is mostly a noop on r4k if cpu_has_dc_aliases evaluates to 0 (and it is the case on the MIPS cpu I have access to). To avoid caching problem in the relocation code, I disable the cache in KSEG0 (using the K0 field in CP0 CONFIG register) before jumping to the relocation code. I don't know how clean this solution is, but this avoids having to add non-portable cache flush code to relocate_kernel.S. Regards, Signed-off-by: Nicolas Schichan <nschichan@xxxxxxxxxx> --- linux/arch/mips/kernel/machine_kexec.c (revision 5939) +++ linux/arch/mips/kernel/machine_kexec.c (revision 5941) @@ -50,8 +50,10 @@ reboot_code_buffer = (unsigned long)page_address(image->control_code_page); + printk(KERN_INFO "reboot code is at %08lx\n", reboot_code_buffer); + kexec_start_address = image->start; - kexec_indirection_page = phys_to_virt(image->head & PAGE_MASK); + kexec_indirection_page = (long)phys_to_virt(image->head & PAGE_MASK); memcpy((void*)reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); @@ -75,11 +77,17 @@ */ local_irq_disable(); - flush_icache_range(reboot_code_buffer, - reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE); + __flush_cache_all(); + flush_icache_all(); - printk("Will call new kernel at %08x\n", image->start); - printk("Bye ...\n"); - flush_cache_all(); + /* + * avoid cache operation related headache in + * relocate_kernel.S: disable caches in kseg0, the new kernel + * will take care to re-enable cache in kseg0. + */ + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + + printk(KERN_INFO "Will call new kernel at %08lx\n", image->start); + printk(KERN_INFO "Bye ...\n"); ((void (*)(void))reboot_code_buffer)(); } -- Nicolas Schichan