Skip to content

Instantly share code, notes, and snippets.

@Tasssadar
Last active January 7, 2022 17:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Tasssadar/6733940 to your computer and use it in GitHub Desktop.
Save Tasssadar/6733940 to your computer and use it in GitHub Desktop.
Kexec-hardboot for HTC One (M7)
From 074ac0e9087ab1ecf95bba019787b4aa4b82bef6 Mon Sep 17 00:00:00 2001
From: Vojtech Bocek <vbocek@gmail.com>
Date: Fri, 27 Sep 2013 20:47:54 +0200
Subject: [PATCH] Implement kexec-hardboot
"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."
More info in /arch/arm/Kconfig.
Original author: Mike Kasick <mike@kasick.org>
Vojtech Bocek <vbocek@gmail.com>:
I've ported it to M7, it is based of my flo port, which is based of
my grouper port, which is based of Asus TF201 patches ported by
Jens Andersen <jens.andersen@gmail.com>.
I've moved atags copying from guest to the host kernel, which means there
is no need to patch the guest kernel, assuming the --mem-min in kexec call
is within the first 256MB of System RAM, otherwise it will take a long time
to load. I've also fixed /proc/atags entry, which would give the kexec-tools
userspace binary only the first 1024 bytes of atags,
see arch/arm/kernel/atags.c for more details.
Other than that, memory-reservation code for the hardboot page and
some assembler to do the watchdog reset on MSM chip are new for this device.
M7 also needed bigger BOOT_PARAMS_SIZE, because it has more atags.
Modified kexec-tools binary is required. See:
https://lkml.org/lkml/2013/9/27/517
https://github.com/Tasssadar/kexec-tools/commit/c6844e1ddb13a6b60cfefcb01c3843da97d6174c
https://github.com/Tasssadar/kexec-tools/commit/210c3b8a4aab69778d93d08b7ff2bfd9c1146cef
Signed-off-by: Vojtech Bocek <vbocek@gmail.com>
---
arch/arm/Kconfig | 26 +++++++++
arch/arm/boot/compressed/head.S | 96 +++++++++++++++++++++++++++++++++
arch/arm/include/asm/kexec.h | 8 +++
arch/arm/kernel/atags.c | 53 +++++++++++-------
arch/arm/kernel/machine_kexec.c | 22 ++++++--
arch/arm/kernel/relocate_kernel.S | 55 +++++++++++++++++++
arch/arm/mach-msm/Makefile | 2 +-
arch/arm/mach-msm/board-m7.c | 12 ++++-
arch/arm/mach-msm/include/mach/memory.h | 10 ++++
arch/arm/mach-msm/restart-apq8064.c | 19 +++++++
include/linux/kexec.h | 19 +++++--
kernel/kexec.c | 4 ++
12 files changed, 299 insertions(+), 27 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 216e16e..8c28690 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2219,6 +2219,32 @@ 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 CRASH_DUMP
bool "Build kdump crash kernel (EXPERIMENTAL)"
depends on EXPERIMENTAL
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 136d1de..e904d26 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -10,6 +10,11 @@
*/
#include <linux/linkage.h>
+#ifdef CONFIG_KEXEC_HARDBOOT
+ #include <asm/kexec.h>
+ #include <asm/memory.h>
+#endif
+
/*
* Debugging stuff
*
@@ -135,6 +140,97 @@ start:
1: mov r7, r1 @ save architecture ID
mov 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]
+
+/* 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.
+ *
+ * The assumption is that the tags will only be "out of place" if the
+ * decompressor code is also, so copying is implemented only in the "won't
+ * overwrite" case (which should be fixed). 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).
+ *
+ * Vojtech Bocek <vbocek@gmail.com>: I've moved atags copying from guest
+ * kernel to the host and rewrote it from C to assembler in order to remove
+ * the need for guest kernel to be patched. I don't know assembler very well,
+ * so it doesn't look very good and I have no idea if I didn't accidentally
+ * break something, causing problems down the road. It's worked every time
+ * and I didn't notice any problems so far though.
+ *
+ * r4: zreladdr (kernel start)
+ * r8: kexec_boot_atags
+ * r2: boot_atags */
+ ldr r8, [r3, #12] @ kexec_boot_atags (r2: boot_atags)
+ ldr r4, =zreladdr @ zreladdr
+
+ /* No need to copy atags if they're already below kernel */
+ cmp r8, r4
+ blo no_atags_cpy
+
+ /* r0: min(zreladdr, pc) */
+ mov r0, pc
+ cmp r4, r0
+ movlo r0, r4
+
+ /* Compute max space for atags, if max <= 0 don't copy. */
+ subs r5, r0, r2 @ max = min(zreladdr, pc) - dest
+ bls no_atags_cpy
+
+ /* Copy atags to params_phys. */
+ /* r8 src, r2 dest, r5 max */
+
+ ldr r0, [r8] @ first tag size
+ cmp r0, #0
+ moveq r4, #8
+ beq catags_empty
+ mov r4, r8
+
+catags_foreach:
+ lsl r0, r0, #2 @ Multiply by 4
+ ldr r0, [r4, r0]! @ Load next tag size to r0 and address to r4
+ cmp r0, #0
+ bne catags_foreach
+
+ rsb r4, r8, r4 @ r4 -= r8 (get only size)
+ add r4, r4, #8 @ add size of the last tag
+catags_empty:
+ cmp r5, r4 @ if(max <= size)
+ bcc no_atags_cpy
+
+ mov r5, #0 @ iterator
+catags_cpy:
+ ldr r0, [r8, r5]
+ str r0, [r2, r5]
+ add r5, r5, #4
+ cmp r5, r4
+ blo catags_cpy
+
+no_atags_cpy:
+ /* Load boot arguments and jump to kexec kernel. */
+ ldr r1, [r3, #8] @ kexec_mach_type
+ ldr pc, [r3, #4] @ kexec_start_address
+
+ .ltorg
+
+not_booting_other:
+#endif
+
#ifndef __ARM_ARCH_2__
/*
* Booting from Angel - need to enter SVC mode and disable
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index c2b9b4b..564c55b 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -17,6 +17,10 @@
#define KEXEC_ARM_ATAGS_OFFSET 0x1000
#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
+#ifdef CONFIG_KEXEC_HARDBOOT
+ #define KEXEC_HB_PAGE_MAGIC 0x4a5db007
+#endif
+
#ifndef __ASSEMBLY__
/**
@@ -53,6 +57,10 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
/* 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 */
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
index 42a1a14..a950e09 100644
--- a/arch/arm/kernel/atags.c
+++ b/arch/arm/kernel/atags.c
@@ -4,30 +4,46 @@
#include <asm/types.h>
#include <asm/page.h>
+/*
+ * [PATCH] Backport arch/arm/kernel/atags.c from 3.10
+ *
+ * There is a bug in older kernels, causing kexec-tools binary to
+ * only read first 1024 bytes from /proc/atags. I guess the bug is
+ * somewhere in /fs/proc/, since I don't think the callback in atags.c
+ * does something wrong. It might affect all procfs files using that
+ * old read callback instead of fops. Doesn't matter though, since it
+ * was accidentally fixed when 3.10 removed it.
+ *
+ * This might have no particular effect on real devices, because the
+ * atags _might_ be organized "just right", but it might be very hard
+ * to track down on a device where it causes problems.
+ *
+ */
+
struct buffer {
size_t size;
char data[];
};
-static int
-read_buffer(char* page, char** start, off_t off, int count,
- int* eof, void* data)
-{
- struct buffer *buffer = (struct buffer *)data;
-
- if (off >= buffer->size) {
- *eof = 1;
- return 0;
- }
-
- count = min((int) (buffer->size - off), count);
+static struct buffer* atags_buffer = NULL;
- memcpy(page, &buffer->data[off], count);
-
- return count;
+static ssize_t atags_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ // These are introduced in kernel 3.10. I don't want to backport
+ // the whole chunk, and other things (ram_console) use static
+ // variable to keep data too, so I guess it's okay.
+ //struct buffer *b = PDE_DATA(file_inode(file));
+ struct buffer *b = atags_buffer;
+ return simple_read_from_buffer(buf, count, ppos, b->data, b->size);
}
-#define BOOT_PARAMS_SIZE 1536
+static const struct file_operations atags_fops = {
+ .read = atags_read,
+ .llseek = default_llseek,
+};
+
+#define BOOT_PARAMS_SIZE 16384 // 16kb
static char __initdata atags_copy[BOOT_PARAMS_SIZE];
void __init save_atags(const struct tag *tags)
@@ -66,12 +82,13 @@ static int __init init_atags_procfs(void)
b->size = size;
memcpy(b->data, atags_copy, size);
- tags_entry = create_proc_read_entry("atags", 0400,
- NULL, read_buffer, b);
+ tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b);
if (!tags_entry)
goto nomem;
+ atags_buffer = b;
+
return 0;
nomem:
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index dfcdb9f..05a6f2a 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -14,6 +14,7 @@
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
#include <asm/system_misc.h>
+#include <asm/mmu_writeable.h>
extern const unsigned char relocate_new_kernel[];
extern const unsigned int relocate_new_kernel_size;
@@ -22,6 +23,10 @@ extern unsigned long kexec_start_address;
extern unsigned long kexec_indirection_page;
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;
@@ -119,10 +124,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,
@@ -136,5 +144,11 @@ void machine_kexec(struct kimage *image)
if (kexec_reinit)
kexec_reinit();
+#ifdef CONFIG_KEXEC_HARDBOOT
+ /* Run any final machine-specific shutdown code. */
+ if (image->hardboot && kexec_hardboot_hook)
+ kexec_hardboot_hook();
+#endif
+
soft_restart(reboot_code_buffer_phys);
}
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index d0cdedf..f534293 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -4,6 +4,15 @@
#include <asm/kexec.h>
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/memory.h>
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ #include <mach/iomap.h>
+#elif defined(CONFIG_ARCH_APQ8064)
+ #include <mach/msm_iomap.h>
+#endif
+#endif
+
.globl relocate_new_kernel
relocate_new_kernel:
@@ -52,6 +61,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
@@ -60,6 +75,40 @@ relocate_new_kernel:
ARM( mov pc, lr )
THUMB( bx 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]
+
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ ldr r0, =TEGRA_PMC_BASE
+ ldr r1, [r0]
+ orr r1, r1, #0x10
+ str r1, [r0]
+loop: b loop
+#elif defined(CONFIG_ARCH_APQ8064)
+ /* Restart using the PMIC chip, see mach-msm/restart.c */
+ ldr r0, =APQ8064_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
@@ -79,6 +128,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
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index a9ce174..19456d7 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -8,7 +8,7 @@ obj-y += clock.o clock-voter.o clock-dummy.o
obj-y += modem_notifier.o subsystem_map.o
obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
-obj-$(CONFIG_KEXEC) += msm_kexec.o
+#obj-$(CONFIG_KEXEC) += msm_kexec.o
obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o
ifndef CONFIG_ARCH_MSM8X60
diff --git a/arch/arm/mach-msm/board-m7.c b/arch/arm/mach-msm/board-m7.c
index b33c07d..86e11b7 100644
--- a/arch/arm/mach-msm/board-m7.c
+++ b/arch/arm/mach-msm/board-m7.c
@@ -588,7 +588,6 @@ static void __init apq8064_reserve_fixed_area(unsigned long fixed_area_size)
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
int ret;
-
if (fixed_area_size > MAX_FIXED_AREA_SIZE)
panic("fixed area size is larger than %dM\n",
MAX_FIXED_AREA_SIZE >> 20);
@@ -5386,6 +5385,17 @@ static void __init m7_common_init(void)
static void __init m7_allocate_memory_regions(void)
{
+#ifdef CONFIG_KEXEC_HARDBOOT
+ // Reserve space for hardboot page at the end of first system ram block
+ struct membank* bank = &meminfo.bank[0];
+ phys_addr_t start = bank->start + bank->size - SZ_1M;
+ int ret = memblock_remove(start, SZ_1M);
+ if(!ret)
+ pr_info("Hardboot page reserved at 0x%X\n", start);
+ else
+ pr_err("Failed to reserve space for hardboot page at 0x%X!\n", start);
+#endif
+
m7_allocate_fb_region();
}
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index cafdc9a..2c57145 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -19,6 +19,16 @@
#define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
+#if defined(CONFIG_KEXEC_HARDBOOT)
+#if defined(CONFIG_MACH_APQ8064_FLO)
+#define KEXEC_HB_PAGE_ADDR UL(0x88C00000)
+#elif defined(CONFIG_MACH_M7_UL)
+#define KEXEC_HB_PAGE_ADDR UL(0x88B00000)
+#else
+#error "Adress for kexec hardboot page not defined"
+#endif
+#endif
+
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 28
diff --git a/arch/arm/mach-msm/restart-apq8064.c b/arch/arm/mach-msm/restart-apq8064.c
index f63c57e..48368ef 100644
--- a/arch/arm/mach-msm/restart-apq8064.c
+++ b/arch/arm/mach-msm/restart-apq8064.c
@@ -41,6 +41,10 @@
#include "timer.h"
#include <mach/htc_restart_handler.h>
+#ifdef CONFIG_KEXEC_HARDBOOT
+#include <asm/kexec.h>
+#endif
+
#define WDT0_RST 0x38
#define WDT0_EN 0x40
#define WDT0_BARK_TIME 0x4C
@@ -387,6 +391,17 @@ void msm_restart(char mode, const char *cmd)
printk(KERN_ERR "Restarting has failed\n");
}
+#ifdef CONFIG_KEXEC_HARDBOOT
+static void msm_kexec_hardboot_hook(void)
+{
+ // Set PMIC to restart-on-poweroff
+ pm8xxx_reset_pwr_off(1);
+
+ turn_off_mdm_power();
+ turn_off_qsc_power();
+}
+#endif
+
static int __init msm_restart_init(void)
{
int rc;
@@ -413,6 +428,10 @@ static int __init msm_restart_init(void)
pr_warn("no pmic restart interrupt specified\n");
}
+#ifdef CONFIG_KEXEC_HARDBOOT
+ kexec_hardboot_hook = msm_kexec_hardboot_hook;
+#endif
+
return 0;
}
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index dddb8d8..3062740 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -101,6 +101,10 @@ struct kimage {
#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;
#endif
@@ -167,6 +171,11 @@ 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
#define KEXEC_ARCH_DEFAULT ( 0 << 16)
@@ -181,10 +190,14 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_ARCH_MIPS_LE (10 << 16)
#define KEXEC_ARCH_MIPS ( 8 << 16)
-#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)
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 4e2e472..aef7893 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1004,6 +1004,10 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
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;
--
1.8.4.rc3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment