linux-mips
[Top] [All Lists]

Re: kexec - not happening on mipsel?

To: Ralf Baechle <ralf@linux-mips.org>
Subject: Re: kexec - not happening on mipsel?
From: Nicolas Schichan <nschichan@freebox.fr>
Date: Fri, 10 Aug 2007 18:57:15 +0200
Cc: Andrew Sharp <andy.sharp@onstor.com>, linux-mips@linux-mips.org
In-reply-to: <20070809123530.GA14183@linux-mips.org>
Organization: Freebox
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <20070808170846.7d395891@ripper.onstor.net> <20070808184120.40b6b5d5@ripper.onstor.net> <20070809123530.GA14183@linux-mips.org>
Sender: linux-mips-bounce@linux-mips.org
User-agent: KMail/1.9.6
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@freebox.fr>

--- 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

<Prev in Thread] Current Thread [Next in Thread>