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@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/kexec > -- Regards, Florian