On Tuesday 14 August 2007 11:47:38 Ralf Baechle wrote: Hi, > flush_icache_all() is a nop except on VIVT caches. Anyway, following a > __flush_cache_all it's pointless unless you want to flush caches a little > harder. The updated patch only uses __flush_cache_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); > > And that line is the kernel's one way ticket to hell on some platforms. > > There is a hazard barrier missing here. Just for my culture, could you please specify which kind of barrier macro should I use here ? should it be a back_to_back_c0_hazard() ? > Only KSEG0 (or CKSEG0 in 64-bit parlance) is affected by changing Config.K0 > field. But 64-bit kernels do not necessarily run in one of the 32-bit > compatibility segments (R8000 doesn't but that's an academic counter > example) - if they exist at all there is no guarantee that there is any RAM > mapped in them (IP30 and others). > > On IP27 the kernel will run in CKSEG0 and if you switch that to 0 it'll > mean BRIDGE ASIC will start looking at the uncached attribute which will be > defaulted to 0 meaning that in CKSEG0 the CPU will no longer address RAM > but the ECC and Backdoor Directory information. > > Basically it boils down to be very, very careful about cache modes > on MIPS. What the kernel does on bootup only happens to work because for > all the platforms that have potencial issues with the change of the CCA > for KSEG0 we know that Linux will set the CCA to the same value that is > already in that field. So that mode switch is sort of useless for most > platforms except a few where firmware doesn't initialize Config0.K0. Ok, updated patch does not try to disable caching in KSEG0 using Config0.K0. Hoewever I so feel a bit unsafe now because D-Cache is not wrote-back and I-Cache is not invalidated in relocate_kernel.S, before jumping to the new kernel. This happens to work on my board, but I think that it is mostly because of luck. Maybe using KSEG1 or XKPHYS (not sure about this one, I am not familiar with 64bit mips) when fixing the indirection list addresses should be safer. However, updated patch follows. Regards. Signed-off-by: Nicolas Schichan <nschichan@xxxxxxxxxx> --- linux/arch/mips/kernel/machine_kexec.c (revision 5975) +++ linux/arch/mips/kernel/machine_kexec.c (revision 5976) @@ -78,11 +78,8 @@ */ local_irq_disable(); - flush_icache_range(reboot_code_buffer, - reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE); - printk("Will call new kernel at %08lx\n", image->start); printk("Bye ...\n"); - flush_cache_all(); + __flush_cache_all(); ((noretfun_t) reboot_code_buffer)(); } -- Nicolas Schichan