[PATCH] MIPS: kexec mips64 XLR 732 support
Florian Fainelli
florian at openwrt.org
Tue Dec 29 10:13:32 EST 2009
Hi,
On Tuesday 29 December 2009 16:02:38 wilbur.chan wrote:
> This patch works on mips64 xlr732 , which has 8 cores up to 32 threads.
> derived from Maxim Syrchin's patch at
> http://lists.infradead.org/pipermail/kexec/2008-June/001909.html
It would help if you cross-posted to linux-mips so that more people can review
your patch.
I do not see the point in adding support to kexec for a SoC which is not
supported by mainline linux-mips kernel.
Please make sure that support for mips64 in kexec and linux-mips hits
mainline, then add your XLR specific to the existing mips64 kexec
infrastructure as I am sure some code can be easily shared.
Thank you.
>
> Notice:
> (I)
> In my code,xlr kernel needs to call functions in bootloader when booting,
> so xlr bootloader is supposed to determin whether in first booting or
> second. (II)
> As xlr kernel choosed CPU0 for special purpose when booting,I simply
> bind kexec on CPU0.
> (III)
> Becasue non-zero CPUs have different kernel entry with respect to
> CPU0,they wait util CPU0 set flags at 0xa6000000.
>
>
> Signed-off-by: wilbur <chen.yu10 at zte.com.cn>
>
> --- machine_kexec.c 2007-08-05 00:11:13.000000000 +0800
> +++ patch.machine_kexec.c 2009-12-29 14:31:32.000000000 +0800
> @@ -13,12 +13,28 @@
> #include <asm/cacheflush.h>
> #include <asm/page.h>
>
> +#ifdef CONFIG_RMI_PHOENIX
> +#define KEXEC_FLAG_VAL 184790
> +#define KEXEC_FLAG_POS 0xa6000000
> +#define KEXEC_SECONDFUNC_POS 0xa6000004
> +#define V_CPUS 31
> +#endif
> extern const unsigned char relocate_new_kernel[];
> +#ifdef CONFIG_RMI_PHOENIX
> +extern const unsigned char kexec_smp_wait[];
> +#endif
> extern const unsigned int relocate_new_kernel_size;
>
> extern unsigned long kexec_start_address;
> extern unsigned long kexec_indirection_page;
>
> +#ifdef CONFIG_RMI_PHOENIX
> +extern unsigned long kexec_fw_arg0;
> +extern unsigned long kexec_fw_arg1;
> +extern unsigned long kexec_fw_arg2;
> +extern unsigned long kexec_fw_arg3;
> +extern unsigned long fw_arg0,fw_arg1,fw_arg2,fw_arg3;
> +#endif
> int
> machine_kexec_prepare(struct kimage *kimage)
> {
> @@ -33,7 +49,70 @@
> void
> machine_shutdown(void)
> {
> + #ifdef CONFIG_RMI_PHOENIX
> + default_machine_kexec_shutdown();
> + #endif
> }
> +#ifdef CONFIG_RMI_PHOENIX
> +unsigned long relocated_kexec_smp_wait;
> +atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
> +int main_cpu = -1;
> +static cpumask_t cpus_in_kexec = CPU_MASK_NONE;
> +void machine_shutdown_secondary(void *ignore)
> +{
> + int cpu = smp_processor_id();
> +
> + if (!cpu_online(cpu))
> + return;
> +
> + local_irq_disable();
> + uint64_t eimr=0;
> + write_64bit_cp0_eimr(eimr);
> +
> +
> +
> + /*
> + * clear flags and secondary funtion before wait
> + */
> + *(unsigned long*)KEXEC_FLAG_POS =0;
> + *(unsigned long*)KEXEC_SECONDFUNC_POS =0;
> +
> + cpu_set(cpu, cpus_in_kexec);
> +
> + while(!atomic_read(&kexec_ready_to_reboot)) {
> + cpu_relax();
> + }
> +
> + ((void (*)(void)) relocated_kexec_smp_wait)();
> + /* NOTREACHED */
> +}
> +static void machine_kexec_prepare_cpus(void)
> +{
> +
> + unsigned int msecs;
> + smp_call_function (machine_shutdown_secondary, NULL, 0, 0);
> + smp_wmb();
> + /*
> + * FIXME: Until we will have the way to stop other CPUSs reliabally,
> + * the crash CPU will send an IPI and wait for other CPUs to
> + * respond.
> + * Delay of at least 10 seconds.
> + */
> +
> + msecs = 10000;
> + while ((cpus_weight(cpus_in_kexec) < V_CPUS) && (--msecs > 0)) {
> + cpu_relax();
> + mdelay(1);
> + }
> +
> +}
> +void default_machine_kexec_shutdown()
> +{
> + machine_kexec_prepare_cpus();
> +}
> +
> +#endif
>
> void
> machine_crash_shutdown(struct pt_regs *regs)
> @@ -50,7 +129,13 @@
> reboot_code_buffer =
> (unsigned long)page_address(image->control_code_page);
>
> - kexec_start_address = image->start;
> + kexec_start_address = (unsigned long) phys_to_virt(image->start);
> + #ifdef CONFIG_RMI_PHOENIX
> + kexec_fw_arg0 = fw_arg0;
> + kexec_fw_arg1 = fw_arg1;
> + kexec_fw_arg2 = fw_arg2;
> + kexec_fw_arg3 = fw_arg3;
> + #endif
> kexec_indirection_page = phys_to_virt(image->head & PAGE_MASK);
>
> memcpy((void*)reboot_code_buffer, relocate_new_kernel,
> @@ -75,10 +160,23 @@
> */
> local_irq_disable();
>
> - flush_icache_range(reboot_code_buffer,
> - reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
>
> - printk("Will call new kernel at %08x\n", image->start);
> +
> + #ifdef CONFIG_RMI_PHOENIX
> + pic_and_control(0xfffffbff);
> + /* All secondary cpus now may jump to kexec_wait cycle */
> + relocated_kexec_smp_wait = reboot_code_buffer +
> + (kexec_smp_wait - relocate_new_kernel);
> + smp_wmb();
> + atomic_set(&kexec_ready_to_reboot,1);
> + pic_irt_timer_maskall();
> + pic_irt_uart0_0_and(0x0);
> + pic_irt_uart0_1_and(0x0);
> + uart_int_and(0x0);
> + uint64_t eimr=0;
> + write_64bit_cp0_eimr(eimr);
> + #endif
> + printk("Will call new kernel at %08x\n", kexec_start_address);
> printk("Bye ...\n");
> flush_cache_all();
> ((void (*)(void))reboot_code_buffer)();
>
> --- relocate_kernel.S 2007-08-05 00:11:13.000000000 +0800
> +++ patch.relocate_kernel.S 2009-12-29 14:25:27.873991800 +0800
> @@ -14,12 +14,21 @@
> #include <asm/stackframe.h>
> #include <asm/addrspace.h>
>
> +#ifdef CONFIG_RMI_PHOENIX
> +#define KEXEC_FLAG_POS 0xa6000000
> +#define KEXEC_SECONDFUNC_POS 0xa6000004
> +#endif
> .globl relocate_new_kernel
> relocate_new_kernel:
>
> PTR_L s0, kexec_indirection_page
> PTR_L s1, kexec_start_address
> -
> +#ifdef CONFIG_RMI_PHOENIX
> + PTR_L t0, kexec_fw_arg0
> + PTR_L t1, kexec_fw_arg1
> + PTR_L t2, kexec_fw_arg2
> + PTR_L t3, kexec_fw_arg3
> +#endif
> process_entry:
> PTR_L s2, (s0)
> PTR_ADD s0, s0, SZREG
> @@ -62,9 +71,39 @@
> b process_entry
>
> done:
> +#ifdef CONFIG_RMI_PHOENIX
> + move a0, t0
> + move a1, t1
> + move a2, t2
> + move a3, t3
> /* jump to kexec_start_address */
> - j s1
> + jr s1
> +#endif
> +
> +
>
> +#ifdef CONFIG_RMI_PHOENIX
> + .globl kexec_smp_wait
> +kexec_smp_wait:
> + /*
> + * wait util CPU0 set flag at 0xa6000000, then jump to
> secondary_function stored in 0xa6000004
> + *
> + */
> +
> + /*
> + * FIXME
> + */
> +20: li s2,KEXEC_FLAG_POS
> + REG_L s5, (s2)
> + beqz s5, 20b
> +
> + /*
> + * ok , we can jump to second kernel
> + */
> + li s2,KEXEC_SECONDFUNC_POS
> + REG_L s6, (s2)
> + jr s6
> +#endif
> .globl kexec_start_address
> kexec_start_address:
> .long 0x0
> @@ -73,6 +112,25 @@
> kexec_indirection_page:
> .long 0x0
>
> +#ifdef CONFIG_RMI_PHOENIX
> + .globl kexec_fw_arg0
> +kexec_fw_arg0:
> + .long 0x0
> +
> +
> + .globl kexec_fw_arg1
> +kexec_fw_arg1:
> + .long 0x0
> +
> + .globl kexec_fw_arg2
> +kexec_fw_arg2:
> + .long 0x0
> +
> + .globl kexec_fw_arg3
> +kexec_fw_arg3:
> + .long 0x0
> +
> +#endif
> relocate_new_kernel_end:
>
> .globl relocate_new_kernel_size
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
>
--
Regards, Florian
More information about the kexec
mailing list