KEXEC: add support for (and enable) KEXEC with RAM CONSOLE

file:53994e46fabef78f6213f0987b0f447029f8a23a -> file:581d8bce8c0b9c7ac39894239989bce236ea8ef1
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2026,6 +2026,36 @@ config ATAGS_PROC
Should the atags used to boot the kernel be exported in an "atags"
file in procfs. Useful with kexec.
+config KEXEC_HARDBOOT
+ bool "Support hard booting to a kexec kernel"
+ depends on KEXEC
+ help
+ Allows hard booting (i.e., with a full hardware reboot) to a kernel
+ previously loaded in memory by kexec. This works around the problem of
+ soft-booted kernel hangs due to improper device shutdown and/or
+ reinitialization. Support is comprised of two components:
+
+ First, a "hardboot" flag is added to the kexec syscall to force a hard
+ reboot in relocate_new_kernel() (which requires machine-specific assembly
+ code). This also requires the kexec userspace tool to load the kexec'd
+ kernel in memory region left untouched by the bootloader (i.e., not
+ explicitly cleared and not overwritten by the boot kernel). Just prior
+ to reboot, the kexec kernel arguments are stashed in a machine-specific
+ memory page that must also be preserved. Note that this hardboot page
+ need not be reserved during regular kernel execution.
+
+ Second, the zImage decompresor of the boot (bootloader-loaded) kernel is
+ modified to check the hardboot page for fresh kexec arguments, and if
+ present, attempts to jump to the kexec'd kernel preserved in memory.
+
+ Note that hardboot support is only required in the boot kernel and any
+ kernel capable of performing a hardboot kexec. It is _not_ required by a
+ kexec'd kernel.
+
+config KEXEC_HB_PAGE_ADDR
+ hex "Kexec hardboot page address"
+ depends on KEXEC_HARDBOOT
+
config CRASH_DUMP
bool "Build kdump crash kernel (EXPERIMENTAL)"
depends on EXPERIMENTAL
file:2cd81c8a5ea67de8ba936034ce7c7e05678cd1c2 -> file:ee5ddfc8466ab3686efc6c837dd41d452ebc881f
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -5,6 +5,7 @@
#
OBJS =
+plus_sec := $(call as-instr,.arch_extension sec,+sec)
# Ensure that mmcif loader code appears early in the image
# to minimise that number of bocks that have to be read in
@@ -15,14 +16,26 @@ OBJS += mmcif-sh7372.o
endif
endif
-AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
-HEAD = head.o
-OBJS += misc.o decompress.o
+AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
+AFLAGS_head.o += -Wa,-march=armv7-a$(plus_sec)
+HEAD = head.o
+
+AFLAGS_misc.o +=-Wa,-march=armv7-a$(plus_sec)
+MISC = misc.o
+
+AFLAGS_decompress.o += -Wa,-march=armv7-a$(plus_sec)
+DECOMPRESS = decompress.o
+
FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
+#AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
+#HEAD = head.o
+#OBJS += misc.o decompress.o
+#FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
+
# string library code (-Os is enforced to keep it much smaller)
OBJS += string.o
-CFLAGS_string.o := -Os
+CFLAGS_string.o := -O3
#
# Architecture dependencies
@@ -86,6 +99,7 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/
suffix_$(CONFIG_KERNEL_GZIP) = gzip
suffix_$(CONFIG_KERNEL_LZO) = lzo
suffix_$(CONFIG_KERNEL_LZMA) = lzma
+suffix_$(CONFIG_KERNEL_XZ) = xzkern
# Borrowed libfdt files for the ATAG compatibility mode
@@ -106,10 +120,10 @@ endif
targets := vmlinux vmlinux.lds \
piggy.$(suffix_y) piggy.$(suffix_y).o \
- lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
+ lib1funcs.o lib1funcs.S font.o font.c head.o misc.o decompress.o $(OBJS)
# Make sure files are removed during clean
-extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
+extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern lib1funcs.S $(libfdt) $(libfdt_hdrs)
ifeq ($(CONFIG_FUNCTION_TRACER),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -117,7 +131,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CF
endif
ccflags-y := -fpic -fno-builtin -I$(obj)
-asflags-y := -Wa,-march=all
+asflags-y := -Wa,-march=armv7-a$(plus_sec)
# Supply kernel BSS size to the decompressor via a linker symbol.
SIZEBIN := $(if $(shell which $(CROSS_COMPILE)size),$(CROSS_COMPILE)size,size)
@@ -130,6 +144,9 @@ endif
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
LDFLAGS_vmlinux += --be8
endif
+ifneq ($(PARAMS_PHYS),)
+LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS)
+endif
# ?
LDFLAGS_vmlinux += -p
# Report unresolved symbol references
@@ -140,6 +157,7 @@ LDFLAGS_vmlinux += -X
LDFLAGS_vmlinux += -T
# For __aeabi_uidivmod
+AFLAGS_lib1funcs.o +=-Wa,-march=armv7-a$(plus_sec)
lib1funcs = $(obj)/lib1funcs.o
$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
@@ -157,12 +175,19 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed
[ -z "$$bad_syms" ] || \
( echo "following symbols must have non local/private scope:" >&2; \
echo "$$bad_syms" >&2; rm -f $@; false )
+# For __aeabi_llsl
+AFLAGS_ashldi3.o +=-Wa,-march=armv7-a$(plus_sec)
+ashldi3 = $(obj)/ashldi3.o
+
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S FORCE
+ $(call cmd,shipped)
-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
- $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/$(MISC) $(obj)/$(DECOMPRESS) $(obj)/piggy.$(suffix_y).o \
+ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
$(call if_changed,ld)
@$(check_for_bad_syms)
+AFLAGS_piggy.$(suffix_y).o += -Wa,-march=armv7-a$(plus_sec)
$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
$(call if_changed,$(suffix_y))
@@ -175,3 +200,4 @@ $(obj)/font.c: $(FONTC)
$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
@sed "$(SEDFLAGS)" < $< > $@
+
file:7f35d0c291297a311da7c78fa410ccff3c080d7e -> file:005f490cc2ad673d0ba19368d22743da489b39bf
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -9,6 +9,11 @@
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
+#include <asm/memory.h>
+
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/kexec.h>
+#endif
/*
* Debugging stuff
@@ -141,7 +146,31 @@ start:
.word _edata @ zImage end address
THUMB( .thumb )
1: mov r7, r1 @ save architecture ID
- mov r8, r2 @ save atags pointer
+ teq r0, #0 @ Check for kexec_boot_atags.
+ movne r8, r0 @ Save kexec_boot_tags.
+ moveq r8, r2 @ save atags pointer
+
+#ifdef CONFIG_KEXEC_HARDBOOT
+ /* Check hardboot page for a kexec kernel. */
+ ldr r3, =KEXEC_HB_PAGE_ADDR
+ ldr r0, [r3]
+ ldr r1, =KEXEC_HB_PAGE_MAGIC
+ teq r0, r1
+ bne not_booting_other
+
+ /* Clear hardboot page magic to avoid boot loop. */
+ mov r0, #0
+ str r0, [r3]
+
+ /* Load boot arguments and jump to kexec kernel. */
+ ldr r0, [r3, #12] @ kexec_boot_atags (r2: boot_atags)
+ ldr r1, [r3, #8] @ kexec_mach_type
+ ldr pc, [r3, #4] @ kexec_start_address
+
+ .ltorg
+
+not_booting_other:
+#endif
#ifndef __ARM_ARCH_2__
/*
@@ -463,6 +492,41 @@ not_relocated: mov r0, #0
add r2, sp, #0x10000 @ 64k max
mov r3, r7
bl decompress_kernel
+
+/* Copy the kernel tagged list (atags):
+ *
+ * The kernel requires atags to be located in a direct-mapped region,
+ * usually below the kernel in the first 16 kB of RAM. If they're above
+ * (the start of) the kernel, they need to be copied to a suitable
+ * location, e.g., the machine-defined params_phys.
+ *
+ * Still need to make sure that the copied tags don't overwrite either the
+ * kernel or decompressor code (or rather, the remainder of it since
+ * everything up to here has already been executed).
+ *
+ * r4: zreladdr (kernel start)
+ * r8: atags */
+
+ /* Don't need to copy atags if they're already below the kernel. */
+ cmp r8, r4
+ blo call_kernel
+
+ /* r1: min(zreladdr, pc) */
+ mov r1, pc
+ cmp r4, r1
+ movlo r1, r4
+
+ /* Compute max space for atags, if max <= 0 don't copy. */
+ ldr r0, =params_phys @ dest
+ subs r2, r1, r0 @ max = min(zreladdr, pc) - dest
+ bls call_kernel
+
+ /* Copy atags to params_phys. */
+ mov r1, r8 @ src
+ bl copy_atags
+ mov r8, r0
+
+call_kernel:
bl cache_clean_flush
bl cache_off
mov r0, #0 @ must be zero
@@ -470,6 +534,8 @@ not_relocated: mov r0, #0
mov r2, r8 @ restore atags pointer
mov pc, r4 @ call kernel
+ .ltorg
+
.align 2
.type LC0, #object
LC0: .word LC0 @ r1
@@ -581,9 +647,14 @@ __setup_mmu: sub r3, r4, #16384 @ Page
* bits for the RAM area only.
*/
mov r0, r3
+#if defined(PLAT_PHYS_OFFSET) && defined(END_MEM)
+ ldr r9, =PLAT_PHYS_OFFSET @ start of RAM
+ ldr r10, =END_MEM @ end of RAM
+#else
mov r9, r0, lsr #18
mov r9, r9, lsl #18 @ start of RAM
add r10, r9, #0x10000000 @ a reasonable RAM size
+#endif
mov r1, #0x12
orr r1, r1, #3 << 10
add r2, r3, #16384
file:8e2a8fca5ed205bcbfda7faafa1eb0d7628a863b -> file:112edaedf350be6cf1f1154878320e6dcf1fb534
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -21,6 +21,8 @@ unsigned int __machine_arch_type;
#include <linux/compiler.h> /* for inline */
#include <linux/types.h>
#include <linux/linkage.h>
+#include <asm/setup.h>
+#include <asm/string.h>
static void putstr(const char *ptr);
extern void error(char *x);
@@ -152,3 +154,25 @@ decompress_kernel(unsigned long output_s
else
putstr(" done, booting the kernel.\n");
}
+
+const struct tag *copy_atags(struct tag *dest, const struct tag *src,
+ size_t max)
+{
+ struct tag *tag;
+ size_t size;
+
+ /* Find the last tag (ATAG_NONE). */
+ for_each_tag(tag, (struct tag *)src)
+ continue;
+
+ /* Include the last tag in copy. */
+ size = (char *)tag - (char *)src + sizeof(struct tag_header);
+
+ /* If there's not enough room, just use original and hope it works. */
+ if (size > max)
+ return src;
+
+ memcpy(dest, src, size);
+
+ return dest;
+}
file:c2b9b4bdec00dec88b0b81094c659780c5c63b95 -> file:632bc1504dde5a287929a5f1e19c7a9553708685
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -17,6 +17,11 @@
#define KEXEC_ARM_ATAGS_OFFSET 0x1000
#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
+#ifdef CONFIG_KEXEC_HARDBOOT
+#define KEXEC_HB_PAGE_ADDR UL(CONFIG_KEXEC_HB_PAGE_ADDR)
+#define KEXEC_HB_PAGE_MAGIC 0x4a5db007
+#endif
+
#ifndef __ASSEMBLY__
/**
@@ -53,6 +58,10 @@ static inline void crash_setup_regs(stru
/* Function pointer to optional machine-specific reinitialization */
extern void (*kexec_reinit)(void);
+#ifdef CONFIG_KEXEC_HARDBOOT
+extern void (*kexec_hardboot_hook)(void);
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_KEXEC */
file:601ef74450000008c43c1f2e26cc47a18d1f9de8 -> file:d9d14c990a598e466849153dc9597818c7cad0f5
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -12,6 +12,7 @@
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
+#include <asm/mmu_writeable.h>
extern const unsigned char relocate_new_kernel[];
extern const unsigned int relocate_new_kernel_size;
@@ -23,6 +24,11 @@ extern unsigned long kexec_indirection_p
extern unsigned long kexec_mach_type;
extern unsigned long kexec_boot_atags;
+#ifdef CONFIG_KEXEC_HARDBOOT
+extern unsigned long kexec_hardboot;
+void (*kexec_hardboot_hook)(void);
+#endif
+
static atomic_t waiting_for_crash_ipi;
/*
@@ -96,10 +102,13 @@ void machine_kexec(struct kimage *image)
reboot_code_buffer = page_address(image->control_code_page);
/* Prepare parameters for reboot_code_buffer*/
- kexec_start_address = image->start;
- kexec_indirection_page = page_list;
- kexec_mach_type = machine_arch_type;
- kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
+ mem_text_write_kernel_word(&kexec_start_address, image->start);
+ mem_text_write_kernel_word(&kexec_indirection_page, page_list);
+ mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type);
+ mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET);
+#ifdef CONFIG_KEXEC_HARDBOOT
+ mem_text_write_kernel_word(&kexec_hardboot, image->hardboot);
+#endif
/* copy our kernel relocation code to the control code page */
memcpy(reboot_code_buffer,
@@ -115,6 +124,13 @@ void machine_kexec(struct kimage *image)
local_irq_disable();
local_fiq_disable();
setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+
+#ifdef CONFIG_KEXEC_HARDBOOT
+ if (image->hardboot && kexec_hardboot_hook)
+ /* Run any final machine-specific shutdown code. */
+ kexec_hardboot_hook();
+#endif
+
flush_cache_all();
outer_flush_all();
outer_disable();
file:e72150048b07cee2bef954beb74b840edb2b4228(deleted)
--- a/arch/arm/kernel/machine_kexec.c.rej
+++ /dev/null
@@ -1,12 +0,0 @@
---- arch/arm/kernel/machine_kexec.c
-+++ arch/arm/kernel/machine_kexec.c
-@@ -106,6 +111,9 @@
- mem_text_write_kernel_word(&kexec_indirection_page, page_list);
- mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type);
- mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET);
-+#ifdef CONFIG_KEXEC_HARDBOOT
-+ mem_text_write_kernel_word(&kexec_hardboot, image->hardboot);
-+#endif
-
- /* copy our kernel relocation code to the control code page */
- memcpy(reboot_code_buffer,
file:9cf4cbf8f95b8ca9eef1baf1d8f49054999304f8 -> file:5efe59c49c7cac7d01fdd8baa881389cc635818d
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -4,6 +4,13 @@
#include <asm/kexec.h>
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/memory.h>
+#ifdef CONFIG_ARCH_MSM8960
+#include <mach/msm_iomap.h>
+#endif
+#endif
+
.globl relocate_new_kernel
relocate_new_kernel:
@@ -52,6 +59,12 @@ relocate_new_kernel:
b 0b
2:
+#ifdef CONFIG_KEXEC_HARDBOOT
+ ldr r0, kexec_hardboot
+ teq r0, #0
+ bne hardboot
+#endif
+
/* Jump to relocated kernel */
mov lr,r1
mov r0,#0
@@ -59,6 +72,35 @@ relocate_new_kernel:
ldr r2,kexec_boot_atags
mov pc,lr
+#ifdef CONFIG_KEXEC_HARDBOOT
+hardboot:
+ /* Stash boot arguments in hardboot page:
+ * 0: KEXEC_HB_PAGE_MAGIC
+ * 4: kexec_start_address
+ * 8: kexec_mach_type
+ * 12: kexec_boot_atags */
+ ldr r0, =KEXEC_HB_PAGE_ADDR
+ str r1, [r0, #4]
+ ldr r1, kexec_mach_type
+ str r1, [r0, #8]
+ ldr r1, kexec_boot_atags
+ str r1, [r0, #12]
+ ldr r1, =KEXEC_HB_PAGE_MAGIC
+ str r1, [r0]
+
+#ifdef CONFIG_ARCH_MSM8960
+ /* Hard reset via PMIC, decompressor jumps to kernel. */
+ ldr r0, =MSM8960_TLMM_PHYS
+ mov r1, #0
+ str r1, [r0, #0x820] @ PSHOLD_CTL_SU
+loop: b loop
+#else
+#error "No reboot method defined for hardboot."
+#endif
+
+ .ltorg
+#endif
+
.align
.globl kexec_start_address
@@ -78,6 +120,12 @@ kexec_mach_type:
kexec_boot_atags:
.long 0x0
+#ifdef CONFIG_KEXEC_HARDBOOT
+ .globl kexec_hardboot
+kexec_hardboot:
+ .long 0x0
+#endif
+
relocate_new_kernel_end:
.globl relocate_new_kernel_size
file:987c4a0bb0eacf565fadc8aedff632e7dad2abb6 -> file:e8d5431cc8b7402739b38cd394b7e6ffbc110929
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -904,6 +904,13 @@ config PHYS_OFFSET
default "0x40200000" if ARCH_MSM8X60
default "0x10000000"
+config HAVE_END_MEM
+ bool "Specify highest physical RAM address at compile time"
+
+config END_MEM
+ hex "Highest physical address where system RAM resides"
+ depends on HAVE_END_MEM
+
config KERNEL_PMEM_EBI_REGION
bool "Enable in-kernel PMEM region for EBI"
default y if ARCH_MSM8X60
file:bc15a010e7fc958ae5743424513302f4aaec72e6 -> file:9ec9c70a4132858a617a511aab8dce89bed8d63d
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -34,6 +34,7 @@ endif
# MSM8960
zreladdr-$(CONFIG_ARCH_MSM8960) := 0x80208000
+params_phys-$(CONFIG_ARCH_MSM8960) := 0x80200100
# MSM8930
zreladdr-$(CONFIG_ARCH_MSM8930) := 0x80208000
file:ed26af6d6498c4c8b238ea9b47f585db5de5df11 -> file:4694508bbb84406798888c3a87713b61aa025a32
--- a/arch/arm/mach-msm/board-m2_spr.c
+++ b/arch/arm/mach-msm/board-m2_spr.c
@@ -172,6 +172,9 @@
#include <linux/sec_jack.h>
#endif
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/kexec.h>
+#endif
#ifdef CONFIG_TOUCHSCREEN_MMS144
struct tsp_callbacks *charger_callbacks;
struct tsp_callbacks {
@@ -1029,6 +1032,25 @@ static int __init ext_display_setup(char
}
early_param("ext_display", ext_display_setup);
+/* Exclude the last 4 kB to preserve the kexec hardboot page. */
+#ifdef CONFIG_ANDROID_RAM_CONSOLE
+#define RAM_CONSOLE_START 0xfff00000
+#define RAM_CONSOLE_SIZE (SZ_1M-SZ_4K)
+
+static struct resource ram_console_resource[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ram_console_device = {
+ .name = "ram_console",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ram_console_resource),
+ .resource = ram_console_resource,
+};
+#endif
+
unsigned int address = 0xea000000;
unsigned int size = 0x100000;
@@ -1054,6 +1076,17 @@ static void __init msm8960_reserve(void)
ret = memblock_remove(address, size);
BUG_ON(ret);
}
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE
+ if (memblock_remove(RAM_CONSOLE_START, RAM_CONSOLE_SIZE) == 0) {
+ ram_console_resource[0].start = RAM_CONSOLE_START;
+ ram_console_resource[0].end = RAM_CONSOLE_START+RAM_CONSOLE_SIZE-1;
+ }
+#endif
+
+#ifdef CONFIG_KEXEC_HARDBOOT
+ memblock_remove(KEXEC_HB_PAGE_ADDR, SZ_4K);
+#endif
}
static int msm8960_change_memory_power(u64 start, u64 size,
@@ -4416,6 +4449,9 @@ static struct platform_device *m2_spr_de
#ifdef CONFIG_VIBETONZ
&vibetonz_device,
#endif /* CONFIG_VIBETONZ */
+#ifdef CONFIG_ANDROID_RAM_CONSOLE
+ &ram_console_device,
+#endif
};
static void __init msm8960_i2c_init(void)
@@ -5279,7 +5315,7 @@ static void __init samsung_m2_spr_init(v
}
-MACHINE_START(M2_SPR, "SAMSUNG M2_SPR")
+MACHINE_START(M2_SPR, "AnThRaXed SAMSUNG M2_SPR")
.map_io = msm8960_map_io,
.reserve = msm8960_reserve,
.init_irq = msm8960_init_irq,
file:b1e806f61725f45c5d96f00f15f94aa16511044e -> file:6879c73bdad14639e06443d0f403669b574b37f0
--- a/arch/arm/mach-msm/board-m2_vzw.c
+++ b/arch/arm/mach-msm/board-m2_vzw.c
@@ -172,6 +172,9 @@
#include <linux/sec_jack.h>
#endif
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/kexec.h>
+#endif
#ifdef CONFIG_TOUCHSCREEN_MMS144
struct tsp_callbacks *charger_callbacks;
struct tsp_callbacks {
@@ -1051,6 +1054,25 @@ static int __init ext_display_setup(char
}
early_param("ext_display", ext_display_setup);
+/* Exclude the last 4 kB to preserve the kexec hardboot page. */
+#ifdef CONFIG_ANDROID_RAM_CONSOLE
+#define RAM_CONSOLE_START 0xfff00000
+#define RAM_CONSOLE_SIZE (SZ_1M-SZ_4K)
+
+static struct resource ram_console_resource[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ram_console_device = {
+ .name = "ram_console",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ram_console_resource),
+ .resource = ram_console_resource,
+};
+#endif
+
unsigned int address = 0xea000000;
unsigned int size = 0x100000;
@@ -1076,6 +1098,17 @@ static void __init msm8960_reserve(void)
ret = memblock_remove(address, size);
BUG_ON(ret);
}
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE
+ if (memblock_remove(RAM_CONSOLE_START, RAM_CONSOLE_SIZE) == 0) {
+ ram_console_resource[0].start = RAM_CONSOLE_START;
+ ram_console_resource[0].end = RAM_CONSOLE_START+RAM_CONSOLE_SIZE-1;
+ }
+#endif
+
+#ifdef CONFIG_KEXEC_HARDBOOT
+ memblock_remove(KEXEC_HB_PAGE_ADDR, SZ_4K);
+#endif
}
static int msm8960_change_memory_power(u64 start, u64 size,
@@ -4465,6 +4498,9 @@ static struct platform_device *m2_vzw_de
#ifdef CONFIG_VIBETONZ
&vibetonz_device,
#endif /* CONFIG_VIBETONZ */
+#ifdef CONFIG_ANDROID_RAM_CONSOLE
+ &ram_console_device,
+#endif
};
static void __init msm8960_i2c_init(void)
file:259636478b9f88f5ac184f00178e253a8b6d9fac -> file:b6394c350a065c7b5b82195452c8abcb7681a1af
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -19,6 +19,9 @@
/* physical offset of RAM */
#define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
+#ifdef CONFIG_HAVE_END_MEM
+#define END_MEM UL(CONFIG_END_MEM)
+#endif
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 28
file:0e237ba9e59c49c10ebf2d1ca31d79e88da4109c -> file:303073c9a3e43d64b87dd44bbb6114210d949131
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -40,6 +40,10 @@
#include "msm_watchdog.h"
#include "timer.h"
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/kexec.h>
+#endif
+
#define WDT0_RST 0x38
#define WDT0_EN 0x40
#define WDT0_BARK_TIME 0x4C
@@ -271,11 +275,6 @@ void arch_reset(char mode, const char *c
__raw_writel(0x77665507, restart_reason);
printk(KERN_NOTICE "peripheral_hw_reset C777!!!!\n");
#endif
-#ifdef CONFIG_SEC_L1_DCACHE_PANIC_CHK
- } else if (!strncmp(cmd, "l1_dcache_reset", 15)) {
- __raw_writel(0x77665588, restart_reason);
- printk(KERN_NOTICE "l1_dcache_reset !!!!\n");
-#endif
} else if (!strncmp(cmd, "download", 8)) {
__raw_writel(0x12345671, restart_reason);
} else if (!strncmp(cmd, "sud", 3)) {
@@ -284,11 +283,6 @@ void arch_reset(char mode, const char *c
} else if (!strncmp(cmd, "debug", 5) /* set debug leve */
&& !kstrtoul(cmd + 5, 0, &value)) {
__raw_writel(0xabcd0000 | value, restart_reason);
-#ifdef CONFIG_SEC_SSR_DEBUG_LEVEL_CHK
- } else if (!strncmp(cmd, "cpdebug", 7) /* set cp debug level */
- && !kstrtoul(cmd + 7, 0, &value)) {
- __raw_writel(0xfedc0000 | value, restart_reason);
-#endif
} else if (!strncmp(cmd, "nvbackup", 8)) {
__raw_writel(0x77665511, restart_reason);
} else if (!strncmp(cmd, "nvrestore", 9)) {
@@ -339,6 +333,18 @@ static struct notifier_block dload_reboo
};
#endif
+#ifdef CONFIG_KEXEC_HARDBOOT
+void msm_kexec_hardboot(void)
+{
+ /* Set PM8XXX PMIC to reset on power off. */
+ pm8xxx_reset_pwr_off(1);
+
+ /* Reboot with the recovery kernel since the boot kernel decompressor may
+ * not support the hardboot jump. */
+ __raw_writel(0x77665502, restart_reason);
+}
+#endif
+
static int __init msm_restart_init(void)
{
int rc;
@@ -364,6 +370,9 @@ static int __init msm_restart_init(void)
restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR;
#endif
pm_power_off = msm_power_off;
+#ifdef CONFIG_KEXEC_HARDBOOT
+ kexec_hardboot_hook = msm_kexec_hardboot;
+#endif
if (pmic_reset_irq != 0) {
rc = request_any_context_irq(pmic_reset_irq,
file:61d429bf16a97ac80cc8eb612eef6eec5db2b651 -> file:21f300605397cc0c35ccd95c2c725c563c332cf2
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -100,6 +100,9 @@ struct kimage {
#define KEXEC_TYPE_DEFAULT 0
#define KEXEC_TYPE_CRASH 1
unsigned int preserve_context : 1;
+#ifdef CONFIG_KEXEC_HARDBOOT
+ unsigned int hardboot : 1;
+#endif
#ifdef ARCH_HAS_KIMAGE_ARCH
struct kimage_arch arch;
@@ -166,6 +169,9 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_ON_CRASH 0x00000001
#define KEXEC_PRESERVE_CONTEXT 0x00000002
+#ifdef CONFIG_KEXEC_HARDBOOT
+#define KEXEC_HARDBOOT 0x00000004
+#endif
#define KEXEC_ARCH_MASK 0xffff0000
/* These values match the ELF architecture values.
@@ -184,10 +190,14 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_ARCH_MIPS ( 8 << 16)
/* List of defined/legal kexec flags */
-#ifndef CONFIG_KEXEC_JUMP
-#define KEXEC_FLAGS KEXEC_ON_CRASH
-#else
+#if defined(CONFIG_KEXEC_JUMP) && defined(CONFIG_KEXEC_HARDBOOT)
+#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT | KEXEC_HARDBOOT)
+#elif defined(CONFIG_KEXEC_JUMP)
#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)
+#elif defined(CONFIG_KEXEC_HARDBOOT)
+#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_HARDBOOT)
+#else
+#define KEXEC_FLAGS (KEXEC_ON_CRASH)
#endif
#define VMCOREINFO_BYTES (4096)
file:8d814cbc810950700113fc32b0bcaf8750265118 -> file:b9ee0ab889876055afbfa472dc2c56bcb63b19ed
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1005,6 +1005,10 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon
if (flags & KEXEC_PRESERVE_CONTEXT)
image->preserve_context = 1;
+#ifdef CONFIG_KEXEC_HARDBOOT
+ if (flags & KEXEC_HARDBOOT)
+ image->hardboot = 1;
+#endif
result = machine_kexec_prepare(image);
if (result)
goto out;