Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 48897
b: refs/heads/master
c: c587e4a
h: refs/heads/master
i:
  48895: ce2f884
v: v3
  • Loading branch information
Richard Purdie authored and Russell King committed Feb 16, 2007
1 parent ee8ba31 commit e748ac5
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3b581f5485c180016a6c36c4c7007e21c53f8a63
refs/heads/master: c587e4a6a4d808fd2a1c4e7fb2d5a3a31e300d23
14 changes: 14 additions & 0 deletions trunk/arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,20 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.

config KEXEC
bool "Kexec system call (EXPERIMENTAL)"
depends on EXPERIMENTAL
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
but it is indepedent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.

It is an ongoing process to be certain the hardware in a machine
is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging
support.

endmenu

if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o

obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/kernel/calls.S
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@
CALL(sys_move_pages)
/* 345 */ CALL(sys_getcpu)
CALL(sys_ni_syscall) /* eventually epoll_pwait */
CALL(sys_kexec_load)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
Expand Down
78 changes: 78 additions & 0 deletions trunk/arch/arm/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* machine_kexec.c - handle transition of Linux booting another kernel
*/

#include <linux/mm.h>
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>

const extern unsigned char relocate_new_kernel[];
const extern 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;

/*
* Provide a dummy crash_notes definition while crash dump arrives to arm.
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
*/

int machine_kexec_prepare(struct kimage *image)
{
return 0;
}

void machine_kexec_cleanup(struct kimage *image)
{
}

void machine_shutdown(void)
{
}

void machine_crash_shutdown(struct pt_regs *regs)
{
}

void machine_kexec(struct kimage *image)
{
unsigned long page_list;
unsigned long reboot_code_buffer_phys;
void *reboot_code_buffer;


page_list = image->head & PAGE_MASK;

/* we need both effective and real address here */
reboot_code_buffer_phys =
page_to_pfn(image->control_code_page) << PAGE_SHIFT;
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;

/* copy our kernel relocation code to the control code page */
memcpy(reboot_code_buffer,
relocate_new_kernel, relocate_new_kernel_size);


flush_icache_range((unsigned long) reboot_code_buffer,
(unsigned long) reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
printk(KERN_INFO "Bye!\n");

cpu_proc_fin();
setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
cpu_reset(reboot_code_buffer_phys);
}
74 changes: 74 additions & 0 deletions trunk/arch/arm/kernel/relocate_kernel.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* relocate_kernel.S - put the kernel image in place to boot
*/

#include <asm/kexec.h>

.globl relocate_new_kernel
relocate_new_kernel:

ldr r0,kexec_indirection_page
ldr r1,kexec_start_address


0: /* top, read another word for the indirection page */
ldr r3, [r0],#4

/* Is it a destination page. Put destination address to r4 */
tst r3,#1,0
beq 1f
bic r4,r3,#1
b 0b
1:
/* Is it an indirection page */
tst r3,#2,0
beq 1f
bic r0,r3,#2
b 0b
1:

/* are we done ? */
tst r3,#4,0
beq 1f
b 2f

1:
/* is it source ? */
tst r3,#8,0
beq 0b
bic r3,r3,#8
mov r6,#1024
9:
ldr r5,[r3],#4
str r5,[r4],#4
subs r6,r6,#1
bne 9b
b 0b

2:
/* Jump to relocated kernel */
mov lr,r1
mov r0,#0
ldr r1,kexec_mach_type
mov r2,#0
mov pc,lr

.globl kexec_start_address
kexec_start_address:
.long 0x0

.globl kexec_indirection_page
kexec_indirection_page:
.long 0x0

.globl kexec_mach_type
kexec_mach_type:
.long 0x0

relocate_new_kernel_end:

.globl relocate_new_kernel_size
relocate_new_kernel_size:
.long relocate_new_kernel_end - relocate_new_kernel


30 changes: 30 additions & 0 deletions trunk/include/asm-arm/kexec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef _ARM_KEXEC_H
#define _ARM_KEXEC_H

#ifdef CONFIG_KEXEC

/* Maximum physical address we can use pages from */
#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
/* Maximum address we can reach in physical address mode */
#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
/* Maximum address we can use for the control code buffer */
#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE

#define KEXEC_CONTROL_CODE_SIZE 4096

#define KEXEC_ARCH KEXEC_ARCH_ARM

#ifndef __ASSEMBLY__

#define MAX_NOTE_BYTES 1024

struct kimage;
/* Provide a dummy definition to avoid build failures. */
static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) { }

#endif /* __ASSEMBLY__ */

#endif /* CONFIG_KEXEC */

#endif /* _ARM_KEXEC_H */
1 change: 1 addition & 0 deletions trunk/include/asm-arm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@
#define __NR_move_pages (__NR_SYSCALL_BASE+344)
#define __NR_getcpu (__NR_SYSCALL_BASE+345)
/* 346 for epoll_pwait */
#define __NR_sys_kexec_load (__NR_SYSCALL_BASE+347)

/*
* The following SWIs are ARM private.
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/kexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_ARCH_PPC (20 << 16)
#define KEXEC_ARCH_PPC64 (21 << 16)
#define KEXEC_ARCH_IA_64 (50 << 16)
#define KEXEC_ARCH_ARM (40 << 16)
#define KEXEC_ARCH_S390 (22 << 16)
#define KEXEC_ARCH_SH (42 << 16)
#define KEXEC_ARCH_MIPS_LE (10 << 16)
Expand Down

0 comments on commit e748ac5

Please sign in to comment.