From: mb Date: Thu, 17 Nov 2011 14:57:34 +0000 (+0000) Subject: omap24xx: Add basic kexec fixes. X-Git-Url: http://git.rohieb.name/openwrt.git/commitdiff_plain/fd34842997e021a4370d61b394b9fb050555fe09 omap24xx: Add basic kexec fixes. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@29232 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- diff --git a/target/linux/omap24xx/patches-3.1/210-omap2-kexec-rewrite.patch b/target/linux/omap24xx/patches-3.1/210-omap2-kexec-rewrite.patch new file mode 100644 index 000000000..fe3224ab5 --- /dev/null +++ b/target/linux/omap24xx/patches-3.1/210-omap2-kexec-rewrite.patch @@ -0,0 +1,2415 @@ +Index: linux-3.1.1/arch/arm/Kconfig +=================================================================== +--- linux-3.1.1.orig/arch/arm/Kconfig 2011-11-17 15:36:08.005974898 +0100 ++++ linux-3.1.1/arch/arm/Kconfig 2011-11-17 15:36:47.117577734 +0100 +@@ -1876,7 +1876,7 @@ config XIP_PHYS_ADDR + + config KEXEC + bool "Kexec system call (EXPERIMENTAL)" +- depends on EXPERIMENTAL ++ depends on EXPERIMENTAL && (!SMP || HOTPLUG_CPU) + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot +Index: linux-3.1.1/arch/arm/include/asm/idmap.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.1.1/arch/arm/include/asm/idmap.h 2011-11-17 15:36:47.121577693 +0100 +@@ -0,0 +1,11 @@ ++#ifndef __ASM_IDMAP_H ++#define __ASM_IDMAP_H ++ ++#include ++ ++/* Tag a function as requiring to be executed via an identity mapping. */ ++#define __idmap __section(.idmap.text) noinline notrace ++ ++void setup_mm_for_reboot(void); ++ ++#endif /* __ASM_IDMAP_H */ +Index: linux-3.1.1/arch/arm/include/asm/mach/arch.h +=================================================================== +--- linux-3.1.1.orig/arch/arm/include/asm/mach/arch.h 2011-11-17 15:36:08.601968818 +0100 ++++ linux-3.1.1/arch/arm/include/asm/mach/arch.h 2011-11-17 15:36:47.121577693 +0100 +@@ -30,10 +30,10 @@ struct machine_desc { + unsigned int video_start; /* start of video RAM */ + unsigned int video_end; /* end of video RAM */ + +- unsigned int reserve_lp0 :1; /* never has lp0 */ +- unsigned int reserve_lp1 :1; /* never has lp1 */ +- unsigned int reserve_lp2 :1; /* never has lp2 */ +- unsigned int soft_reboot :1; /* soft reboot */ ++ unsigned char reserve_lp0 :1; /* never has lp0 */ ++ unsigned char reserve_lp1 :1; /* never has lp1 */ ++ unsigned char reserve_lp2 :1; /* never has lp2 */ ++ char restart_mode; /* default restart mode */ + void (*fixup)(struct machine_desc *, + struct tag *, char **, + struct meminfo *); +@@ -46,6 +46,7 @@ struct machine_desc { + #ifdef CONFIG_MULTI_IRQ_HANDLER + void (*handle_irq)(struct pt_regs *); + #endif ++ void (*restart)(char, const char *); + }; + + /* +Index: linux-3.1.1/arch/arm/include/asm/system.h +=================================================================== +--- linux-3.1.1.orig/arch/arm/include/asm/system.h 2011-11-17 15:36:08.613968696 +0100 ++++ linux-3.1.1/arch/arm/include/asm/system.h 2011-11-17 15:36:47.121577693 +0100 +@@ -107,7 +107,7 @@ extern void __show_regs(struct pt_regs * + extern int cpu_architecture(void); + extern void cpu_init(void); + +-void arm_machine_restart(char mode, const char *cmd); ++void soft_restart(unsigned long); + extern void (*arm_pm_restart)(char str, const char *cmd); + + #define UDBG_UNDEFINED (1 << 0) +Index: linux-3.1.1/arch/arm/kernel/machine_kexec.c +=================================================================== +--- linux-3.1.1.orig/arch/arm/kernel/machine_kexec.c 2011-11-17 15:36:08.409970777 +0100 ++++ linux-3.1.1/arch/arm/kernel/machine_kexec.c 2011-11-17 15:36:47.121577693 +0100 +@@ -12,12 +12,11 @@ + #include + #include + #include ++#include + + extern const unsigned char relocate_new_kernel[]; + extern const unsigned int relocate_new_kernel_size; + +-extern void setup_mm_for_reboot(char mode); +- + extern unsigned long kexec_start_address; + extern unsigned long kexec_indirection_page; + extern unsigned long kexec_mach_type; +@@ -111,14 +110,6 @@ void machine_kexec(struct kimage *image) + + if (kexec_reinit) + kexec_reinit(); +- local_irq_disable(); +- local_fiq_disable(); +- setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ +- flush_cache_all(); +- outer_flush_all(); +- outer_disable(); +- cpu_proc_fin(); +- outer_inv_all(); +- flush_cache_all(); +- cpu_reset(reboot_code_buffer_phys); ++ ++ soft_restart(reboot_code_buffer_phys); + } +Index: linux-3.1.1/arch/arm/kernel/process.c +=================================================================== +--- linux-3.1.1.orig/arch/arm/kernel/process.c 2011-11-17 15:36:08.433970532 +0100 ++++ linux-3.1.1/arch/arm/kernel/process.c 2011-11-17 15:36:47.121577693 +0100 +@@ -57,7 +57,7 @@ static const char *isa_modes[] = { + "ARM" , "Thumb" , "Jazelle", "ThumbEE" + }; + +-extern void setup_mm_for_reboot(char mode); ++extern void setup_mm_for_reboot(void); + + static volatile int hlt_counter; + +@@ -92,40 +92,64 @@ static int __init hlt_setup(char *__unus + __setup("nohlt", nohlt_setup); + __setup("hlt", hlt_setup); + +-void arm_machine_restart(char mode, const char *cmd) ++extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); ++typedef void (*phys_reset_t)(unsigned long); ++ ++/* ++ * A temporary stack to use for CPU reset. This is static so that we ++ * don't clobber it with the identity mapping. When running with this ++ * stack, any references to the current task *will not work* so you ++ * should really do as little as possible before jumping to your reset ++ * code. ++ */ ++#define SOFT_RESTART_STACK_WORDS 32 ++static u32 soft_restart_stack[SOFT_RESTART_STACK_WORDS]; ++ ++static void __soft_restart(void *addr) + { +- /* Disable interrupts first */ +- local_irq_disable(); +- local_fiq_disable(); ++ phys_reset_t phys_reset; + +- /* +- * Tell the mm system that we are going to reboot - +- * we may need it to insert some 1:1 mappings so that +- * soft boot works. +- */ +- setup_mm_for_reboot(mode); ++ /* Take out a flat memory mapping. */ ++ setup_mm_for_reboot(); + +- /* Clean and invalidate caches */ ++ /* Clean and invalidate caches. */ + flush_cache_all(); + +- /* Turn off caching */ ++ /* Turn off caching. */ + cpu_proc_fin(); + + /* Push out any further dirty data, and ensure cache is empty */ + flush_cache_all(); + +- /* +- * Now call the architecture specific reboot code. +- */ +- arch_reset(mode, cmd); +- +- /* +- * Whoops - the architecture was unable to reboot. +- * Tell the user! +- */ +- mdelay(1000); +- printk("Reboot failed -- System halted\n"); +- while (1); ++ /* Switch to the identity mapping. */ ++ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); ++ phys_reset((unsigned long)addr); ++ ++ /* Should never get here. */ ++ BUG(); ++} ++ ++void soft_restart(unsigned long addr) ++{ ++ u32 *stack = soft_restart_stack + SOFT_RESTART_STACK_WORDS; ++ ++ /* Disable interrupts first */ ++ local_irq_disable(); ++ local_fiq_disable(); ++ ++ /* Disable the L2 if we're the last man standing. */ ++ if (num_online_cpus() == 1) ++ outer_disable(); ++ ++ /* Change to the new stack and continue with the reset. */ ++ call_with_stack(__soft_restart, (void *)addr, (void *)stack); ++ ++ /* Should never get here. */ ++ BUG(); ++} ++ ++static void null_restart(char mode, const char *cmd) ++{ + } + + /* +@@ -134,7 +158,7 @@ void arm_machine_restart(char mode, cons + void (*pm_power_off)(void); + EXPORT_SYMBOL(pm_power_off); + +-void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; ++void (*arm_pm_restart)(char str, const char *cmd) = null_restart; + EXPORT_SYMBOL_GPL(arm_pm_restart); + + static void do_nothing(void *unused) +@@ -250,7 +274,15 @@ void machine_power_off(void) + void machine_restart(char *cmd) + { + machine_shutdown(); ++ + arm_pm_restart(reboot_mode, cmd); ++ ++ /* Give a grace period for failure to restart of 1s */ ++ mdelay(1000); ++ ++ /* Whoops - the platform was unable to reboot. Tell the user! */ ++ printk("Reboot failed -- System halted\n"); ++ while (1); + } + + void __show_regs(struct pt_regs *regs) +Index: linux-3.1.1/arch/arm/kernel/setup.c +=================================================================== +--- linux-3.1.1.orig/arch/arm/kernel/setup.c 2011-11-17 15:36:08.429970573 +0100 ++++ linux-3.1.1/arch/arm/kernel/setup.c 2011-11-17 15:36:47.121577693 +0100 +@@ -890,8 +890,8 @@ void __init setup_arch(char **cmdline_p) + machine_desc = mdesc; + machine_name = mdesc->name; + +- if (mdesc->soft_reboot) +- reboot_setup("s"); ++ if (mdesc->restart_mode) ++ reboot_setup(&mdesc->restart_mode); + + init_mm.start_code = (unsigned long) _text; + init_mm.end_code = (unsigned long) _etext; +@@ -910,6 +910,9 @@ void __init setup_arch(char **cmdline_p) + paging_init(mdesc); + request_standard_resources(mdesc); + ++ if (mdesc->restart) ++ arm_pm_restart = mdesc->restart; ++ + unflatten_device_tree(); + + #ifdef CONFIG_SMP +Index: linux-3.1.1/arch/arm/kernel/smp.c +=================================================================== +--- linux-3.1.1.orig/arch/arm/kernel/smp.c 2011-11-17 15:36:08.417970695 +0100 ++++ linux-3.1.1/arch/arm/kernel/smp.c 2011-11-17 15:36:47.121577693 +0100 +@@ -558,6 +558,10 @@ static void ipi_cpu_stop(unsigned int cp + local_fiq_disable(); + local_irq_disable(); + ++#ifdef CONFIG_HOTPLUG_CPU ++ platform_cpu_kill(cpu); ++#endif ++ + while (1) + cpu_relax(); + } +Index: linux-3.1.1/arch/arm/kernel/vmlinux.lds.S +=================================================================== +--- linux-3.1.1.orig/arch/arm/kernel/vmlinux.lds.S 2011-11-17 15:36:08.421970654 +0100 ++++ linux-3.1.1/arch/arm/kernel/vmlinux.lds.S 2011-11-17 15:36:47.121577693 +0100 +@@ -91,6 +91,7 @@ SECTIONS + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT ++ IDMAP_TEXT + #ifdef CONFIG_MMU + *(.fixup) + #endif +Index: linux-3.1.1/arch/arm/lib/Makefile +=================================================================== +--- linux-3.1.1.orig/arch/arm/lib/Makefile 2011-11-17 15:36:08.593968900 +0100 ++++ linux-3.1.1/arch/arm/lib/Makefile 2011-11-17 15:36:47.121577693 +0100 +@@ -13,7 +13,8 @@ lib-y := backtrace.o changebit.o csumip + testchangebit.o testclearbit.o testsetbit.o \ + ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ + ucmpdi2.o lib1funcs.o div64.o \ +- io-readsb.o io-writesb.o io-readsl.o io-writesl.o ++ io-readsb.o io-writesb.o io-readsl.o io-writesl.o \ ++ call_with_stack.o + + mmu-y := clear_user.o copy_page.o getuser.o putuser.o + +Index: linux-3.1.1/arch/arm/lib/call_with_stack.S +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.1.1/arch/arm/lib/call_with_stack.S 2011-11-17 15:36:47.121577693 +0100 +@@ -0,0 +1,44 @@ ++/* ++ * arch/arm/lib/call_with_stack.S ++ * ++ * Copyright (C) 2011 ARM Ltd. ++ * Written by Will Deacon ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++ ++/* ++ * void call_with_stack(void (*fn)(void *), void *arg, void *sp) ++ * ++ * Change the stack to that pointed at by sp, then invoke fn(arg) with ++ * the new stack. ++ */ ++ENTRY(call_with_stack) ++ str sp, [r2, #-4]! ++ str lr, [r2, #-4]! ++ ++ mov sp, r2 ++ mov r2, r0 ++ mov r0, r1 ++ ++ adr lr, BSYM(1f) ++ mov pc, r2 ++ ++1: ldr lr, [sp] ++ ldr sp, [sp, #4] ++ mov pc, lr ++ENDPROC(call_with_stack) +Index: linux-3.1.1/arch/arm/mach-omap2/board-2430sdp.c +=================================================================== +--- linux-3.1.1.orig/arch/arm/mach-omap2/board-2430sdp.c 2011-11-17 15:36:08.137973551 +0100 ++++ linux-3.1.1/arch/arm/mach-omap2/board-2430sdp.c 2011-11-17 15:36:47.121577693 +0100 +@@ -34,7 +34,7 @@ + #include + + #include +-#include ++#include "common.h" + #include + #include + #include +@@ -264,4 +264,5 @@ MACHINE_START(OMAP_2430SDP, "OMAP2430 sd + .init_irq = omap2_init_irq, + .init_machine = omap_2430sdp_init, + .timer = &omap2_timer, ++ .restart = omap_prcm_restart, + MACHINE_END +Index: linux-3.1.1/arch/arm/mach-omap2/board-3430sdp.c +=================================================================== +--- linux-3.1.1.orig/arch/arm/mach-omap2/board-3430sdp.c 2011-11-17 15:36:08.125973674 +0100 ++++ linux-3.1.1/arch/arm/mach-omap2/board-3430sdp.c 2011-11-17 15:36:47.121577693 +0100 +@@ -33,7 +33,7 @@ + #include + #include + #include +-#include ++#include "common.h" + #include + #include + #include