Google
  Web www.spinics.net

ARM KEXEC support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


There are two patches attached
"kexec-arm-support.patch" is 2.6.11.6 kernel patch (with the latest kexec patch series from http://www.xmission.com/~ebiederm/files/kexec/ applied).
"kexec-tools-arm-support.patch" - patch for kexec-tools-1.101. Only elf file booting is implemented, I've tested with arch/ar/boot/compressed/vmlinux (kernel patch modifies link address of this file)


I've tested these patches on IXPD2801 platform (~ 100 kexec consecutive reboots was successful).

There is no syscall assigned to sys_kexec_load, so I just take one of free. Is it possible to assing number for it (as in x86 and ppc) ?

Thanks,
Maxim
diff -Naur kexec-tools-1.101.noarm/configure kexec-tools-1.101/configure
--- kexec-tools-1.101.noarm/configure	2005-02-16 15:37:44.000000000 +0300
+++ kexec-tools-1.101/configure	2005-04-01 17:49:02.632764816 +0400
@@ -1384,12 +1384,16 @@
 	powerpc )
 		host_cpu="ppc"
 		;;
+	arm* )
+		host_cpu="arm"
+		;;
 	* )
 		host_cpu="$host_cpu"
 		;;
 esac
 case $host_cpu in
-	i386|ppc|x86_64|alpha|ppc64|ia64)
+	i386|ppc|x86_64|alpha|ppc64|ia64|arm)
+	
 		;;
 	* )
 		{ { echo "$as_me:$LINENO: error:  unsupported architecture $host_cpu" >&5
diff -Naur kexec-tools-1.101.noarm/kexec/arch/arm/include/arch/options.h kexec-tools-1.101/kexec/arch/arm/include/arch/options.h
--- kexec-tools-1.101.noarm/kexec/arch/arm/include/arch/options.h	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/kexec/arch/arm/include/arch/options.h	2005-04-01 17:49:02.633764664 +0400
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_ARM_OPTIONS_H
+#define KEXEC_ARCH_ARM_OPTIONS_H
+
+#define OPT_ARCH_MAX   (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+	KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_ARM_OPTIONS_H */
diff -Naur kexec-tools-1.101.noarm/kexec/arch/arm/kexec-arm.c kexec-tools-1.101/kexec/arch/arm/kexec-arm.c
--- kexec-tools-1.101.noarm/kexec/arch/arm/kexec-arm.c	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/kexec/arch/arm/kexec-arm.c	2005-04-01 17:57:36.716612192 +0400
@@ -0,0 +1,154 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * modified from kexec-ppc.c
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-arm.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+#define MAX_LINE 160
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/* Return a sorted list of available memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+	const char iomem[]= "/proc/iomem";
+	int memory_ranges = 0;
+	char line[MAX_LINE];
+	FILE *fp;
+	fp = fopen(iomem, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s: %s\n", 
+			iomem, strerror(errno));
+		return -1;
+	}
+
+	while(fgets(line, sizeof(line), fp) != 0) {
+		unsigned long long start, end;
+		char *str;
+		int type;
+		int consumed;
+		int count;
+		if (memory_ranges >= MAX_MEMORY_RANGES)
+			break;
+		count = sscanf(line, "%Lx-%Lx : %n",
+			&start, &end, &consumed);
+		if (count != 2) 
+			continue;
+		str = line + consumed;
+		end = end + 1;
+#if 0 
+		printf("%016Lx-%016Lx : %s",
+			start, end, str);
+#endif
+		if (memcmp(str, "System RAM\n", 11) == 0) {
+			type = RANGE_RAM;
+		} 
+		else if (memcmp(str, "reserved\n", 9) == 0) {
+			type = RANGE_RESERVED;
+		}
+		else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
+			type = RANGE_ACPI;
+		}
+		else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
+			type = RANGE_ACPI_NVS;
+		}
+		else {
+			continue;
+		}
+
+		memory_range[memory_ranges].start = start;
+		memory_range[memory_ranges].end = end;
+		memory_range[memory_ranges].type = type;
+#if 0
+		printf("%016Lx-%016Lx : %x\n",
+			start, end, type);
+#endif
+		memory_ranges++;
+	}
+	fclose(fp);
+	*range = memory_range;
+	*ranges = memory_ranges;
+	return 0;
+}
+
+/* Supported file types and callbacks */
+struct file_type file_type[] = {
+       {"vmlinux", elf_arm_probe, elf_arm_load, elf_arm_usage},
+};
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+
+void arch_usage(void)
+{
+}
+
+static struct {
+} arch_options = {
+};
+int arch_process_options(int argc, char **argv)
+{
+	static const struct option options[] = {
+		KEXEC_ARCH_OPTIONS
+		{ 0, 			0, NULL, 0 },
+	};
+	static const char short_options[] = KEXEC_ARCH_OPT_STR;
+	int opt;
+	unsigned long value;
+	char *end;
+
+	opterr = 0; /* Don't complain about unrecognized options here */
+	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+		switch(opt) {
+		default:
+			break;
+		}
+	}
+	/* Reset getopt for the next pass; called in other source modules */
+	opterr = 1;
+	optind = 1;
+	return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+	int result;
+	struct utsname utsname;
+	result = uname(&utsname);
+	if (result < 0) {
+		fprintf(stderr, "uname failed: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	if (strncmp(utsname.machine, "arm",3) == 0)
+	{
+		/* For compatibility with older patches 
+		 * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_ARM here.
+		 */
+		*flags |= KEXEC_ARCH_DEFAULT;
+	}
+	else {
+		fprintf(stderr, "Unsupported machine type: %s\n",
+			utsname.machine);
+		return -1;
+	}
+	return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+}
+
diff -Naur kexec-tools-1.101.noarm/kexec/arch/arm/kexec-arm.h kexec-tools-1.101/kexec/arch/arm/kexec-arm.h
--- kexec-tools-1.101.noarm/kexec/arch/arm/kexec-arm.h	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/kexec/arch/arm/kexec-arm.h	2005-04-01 17:53:35.915219568 +0400
@@ -0,0 +1,9 @@
+#ifndef KEXEC_ARM_H
+#define KEXEC_ARM_H
+
+int elf_arm_probe(const char *buf, off_t len);
+int elf_arm_load(int argc, char **argv, const char *buf, off_t len,
+	struct kexec_info *info);
+void elf_arm_usage(void);
+
+#endif /* KEXEC_ARM_H */
diff -Naur kexec-tools-1.101.noarm/kexec/arch/arm/kexec-elf-arm.c kexec-tools-1.101/kexec/arch/arm/kexec-elf-arm.c
--- kexec-tools-1.101.noarm/kexec/arch/arm/kexec-elf-arm.c	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/kexec/arch/arm/kexec-elf-arm.c	2005-04-01 17:56:14.987036976 +0400
@@ -0,0 +1,65 @@
+/*
+ * modified from kexec-elf-ppc.c
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <ip_checksum.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "kexec-arm.h"
+#include <arch/options.h>
+
+static const int probe_debug = 0;
+
+int elf_arm_probe(const char *buf, off_t len)
+{
+
+	struct mem_ehdr ehdr;
+	int result;
+	result = build_elf_exec_info(buf, len, &ehdr);
+	if (result < 0) {
+		goto out;
+	}
+	
+	/* Verify the architecuture specific bits */
+	if (ehdr.e_machine != EM_ARM) {
+		/* for a different architecture */
+		if (probe_debug) {
+			fprintf(stderr, "Not for this architecture.\n");
+		}
+		result = -1;
+		goto out;
+	}
+	result = 0;
+ out:
+	free_elf_info(&ehdr);
+	return result;
+}
+
+void elf_arm_usage(void)
+{
+}
+
+int elf_arm_load(int argc, char **argv,	const char *buf, off_t len, 
+	struct kexec_info *info)
+{
+ 	struct mem_ehdr ehdr;
+ 
+	elf_exec_build_load(info, &ehdr, buf, len);
+
+	info->entry = (void*)ehdr.e_entry;
+	return 0;
+
+}
diff -Naur kexec-tools-1.101.noarm/kexec/arch/arm/kexec-elf-rel-arm.c kexec-tools-1.101/kexec/arch/arm/kexec-elf-rel-arm.c
--- kexec-tools-1.101.noarm/kexec/arch/arm/kexec-elf-rel-arm.c	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/kexec/arch/arm/kexec-elf-rel-arm.c	2005-04-01 17:49:02.634764512 +0400
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+	if (ehdr->ei_data != ELFDATA2MSB) {
+		return 0;
+	}
+	if (ehdr->ei_class != ELFCLASS32) {
+		return 0;
+	}
+	if (ehdr->e_machine != EM_ARM) 
+	{
+		return 0;
+	}
+	return 1;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+	void *location, unsigned long address, unsigned long value)
+{
+	switch(r_type) {
+	case R_ARM_ABS32:
+		*((uint32_t *)location) += value;
+		break;
+	case R_ARM_REL32:
+		*((uint32_t *)location) += value - address;
+		break;
+	default:
+		die("Unknown rel relocation: %lu\n", r_type);
+		break;
+	}
+}
diff -Naur kexec-tools-1.101.noarm/kexec/arch/arm/Makefile kexec-tools-1.101/kexec/arch/arm/Makefile
--- kexec-tools-1.101.noarm/kexec/arch/arm/Makefile	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/kexec/arch/arm/Makefile	2005-04-01 17:52:16.156344760 +0400
@@ -0,0 +1,8 @@
+#
+# kexec arm (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/arm/kexec-elf-rel-arm.c
+KEXEC_C_SRCS+= kexec/arch/arm/kexec-elf-arm.c 
+KEXEC_C_SRCS+= kexec/arch/arm/kexec-arm.c 
+
+KEXEC_S_SRCS+=
diff -Naur kexec-tools-1.101.noarm/kexec/kexec-syscall.h kexec-tools-1.101/kexec/kexec-syscall.h
--- kexec-tools-1.101.noarm/kexec/kexec-syscall.h	2005-01-06 09:59:50.000000000 +0300
+++ kexec-tools-1.101/kexec/kexec-syscall.h	2005-04-01 17:49:02.635764360 +0400
@@ -37,6 +37,9 @@
 #ifdef __x86_64__
 #define __NR_kexec_load		246
 #endif
+#ifdef __arm__
+#define __NR_kexec_load		189  /* this value should be fixed */
+#endif
 #ifndef __NR_kexec_load
 #error Unknown processor architecture.  Needs a kexec_load syscall number.
 #endif
@@ -67,6 +70,7 @@
 #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_MAX_SEGMENTS 8
 
diff -Naur kexec-tools-1.101.noarm/purgatory/arch/arm/include/limits.h kexec-tools-1.101/purgatory/arch/arm/include/limits.h
--- kexec-tools-1.101.noarm/purgatory/arch/arm/include/limits.h	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/purgatory/arch/arm/include/limits.h	2005-04-01 17:49:02.636764208 +0400
@@ -0,0 +1,58 @@
+#ifndef LIMITS_H
+#define LIMITS_H	1
+
+
+/* Number of bits in a `char' */
+#define CHAR_BIT	8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN	(-128)
+#define SCHAR_MAX	127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX	255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN	SCHAR_MIN
+#define CHAR_MAX	SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN	(-32768)
+#define SHRT_MAX	32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX	65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN		(-INT_MAX - 1)
+#define INT_MAX		2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX	4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN		(-INT_MAX - 1)
+#define INT_MAX		2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX	4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX	2147483647L
+#define LONG_MIN	(-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX	4294967295UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX	9223372036854775807LL
+#define LLONG_MIN	(-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX	18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff -Naur kexec-tools-1.101.noarm/purgatory/arch/arm/include/stdint.h kexec-tools-1.101/purgatory/arch/arm/include/stdint.h
--- kexec-tools-1.101.noarm/purgatory/arch/arm/include/stdint.h	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/purgatory/arch/arm/include/stdint.h	2005-04-01 17:49:02.636764208 +0400
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long      size_t;
+
+typedef unsigned char      uint8_t;
+typedef unsigned short     uint16_t;
+typedef unsigned int       uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char        int8_t;
+typedef signed short       int16_t;
+typedef signed int         int32_t;
+typedef signed long long   int64_t;
+
+#endif /* STDINT_H */
diff -Naur kexec-tools-1.101.noarm/purgatory/arch/arm/Makefile kexec-tools-1.101/purgatory/arch/arm/Makefile
--- kexec-tools-1.101.noarm/purgatory/arch/arm/Makefile	1970-01-01 03:00:00.000000000 +0300
+++ kexec-tools-1.101/purgatory/arch/arm/Makefile	2005-04-01 17:51:21.630633928 +0400
@@ -0,0 +1,7 @@
+#
+# Purgatory arm
+#
+
+PURGATORY_S_SRCS += 
+PURGATORY_C_SRCS += 
+
Source: MontaVista Software, Inc.
MR: 11054
Type: Enhancement
Disposition: MontaVista
Keywords: 
Signed-off-by: Maxim Syrchin <msyrchin@ru.mvista.com>
Description:
        Kexec code specific for arm platform:
	- kexec_sys_load syscall added;
	- code to prepare and relocate kernel;

Index: linux-2.6.11.6/arch/arm/kernel/calls.S
===================================================================
--- linux-2.6.11.6.orig/arch/arm/kernel/calls.S
+++ linux-2.6.11.6/arch/arm/kernel/calls.S
@@ -203,7 +203,7 @@
 		.long	sys_sigaltstack_wrapper
 		.long	sys_sendfile
 		.long	sys_ni_syscall
-		.long	sys_ni_syscall
+		.long	sys_kexec_load	/* FIX ME !!!! */
 /* 190 */	.long	sys_vfork_wrapper
 		.long	sys_getrlimit
 		.long	sys_mmap2
Index: linux-2.6.11.6/arch/arm/boot/compressed/Makefile
===================================================================
--- linux-2.6.11.6.orig/arch/arm/boot/compressed/Makefile
+++ linux-2.6.11.6/arch/arm/boot/compressed/Makefile
@@ -66,10 +66,16 @@
 ifeq ($(CONFIG_ZBOOT_ROM),y)
 ZTEXTADDR	:= $(CONFIG_ZBOOT_ROM_TEXT)
 ZBSSADDR	:= $(CONFIG_ZBOOT_ROM_BSS)
+else  
+ifeq ($(CONFIG_KEXEC) ,y)
+ZTEXTADDR	:= $(CONFIG_KEXEC_IMAGE_OFFSET)
+ZBSSADDR	:= ALIGN(4)
 else
 ZTEXTADDR	:= 0
 ZBSSADDR	:= ALIGN(4)
 endif
+endif
+
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
Index: linux-2.6.11.6/arch/arm/Kconfig
===================================================================
--- linux-2.6.11.6.orig/arch/arm/Kconfig
+++ linux-2.6.11.6/arch/arm/Kconfig
@@ -257,6 +257,31 @@
 	depends on CPU_XSCALE && !XSCALE_PMU_TIMER
 	default y
 
+
+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.
+
+          The name comes from the similiarity to the exec system call.
+
+          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.  As of this writing the exact hardware interface is
+          strongly in flux, so no good recommendation can be made.
+
+config KEXEC_IMAGE_OFFSET
+	hex "Physical address where the compressed kernel image is loaded"
+	depends on KEXEC
+	default 0x8000
+	help
+	  this offset is used to link arch/arm/boot/compressed/vmlinux.
+
 endmenu
 
 menu "General setup"
Index: linux-2.6.11.6/include/asm-arm/unistd.h
===================================================================
--- linux-2.6.11.6.orig/include/asm-arm/unistd.h
+++ linux-2.6.11.6/include/asm-arm/unistd.h
@@ -214,7 +214,7 @@
 #define __NR_sigaltstack		(__NR_SYSCALL_BASE+186)
 #define __NR_sendfile			(__NR_SYSCALL_BASE+187)
 					/* 188 reserved */
-					/* 189 reserved */
+#define __NR_sys_kexec_load             (__NR_SYSCALL_BASE+189)			/* 189 was reserved, temporarily use it for sys_kexec_load */
 #define __NR_vfork			(__NR_SYSCALL_BASE+190)
 #define __NR_ugetrlimit			(__NR_SYSCALL_BASE+191)	/* SuS compliant getrlimit */
 #define __NR_mmap2			(__NR_SYSCALL_BASE+192)
Index: linux-2.6.11.6/arch/arm/kernel/machine_kexec.c
===================================================================
--- /dev/null
+++ linux-2.6.11.6/arch/arm/kernel/machine_kexec.c
@@ -0,0 +1,69 @@
+/*
+ * 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>
+
+typedef NORET_TYPE void (*relocate_new_kernel_t) (unsigned long
+						  indirection_page,
+						  unsigned long
+						  reboot_code_buffer,
+						  unsigned long start_address) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+int machine_kexec_prepare(struct kimage *image)
+{
+	return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(void)
+{
+}
+
+void machine_kexec(struct kimage *image)
+{
+	unsigned long page_list;
+	unsigned long reboot_code_buffer_phys;
+	void *reboot_code_buffer;
+	relocate_new_kernel_t rnk;
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	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);
+
+	/* copy our kernel relocation code to the control code page */
+	memcpy(reboot_code_buffer,
+	       relocate_new_kernel, relocate_new_kernel_size);
+
+	flush_icache_range(reboot_code_buffer,
+			   reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+	printk(KERN_INFO "Bye!\n");
+
+	/* now call reboot code  */
+	rnk = (relocate_new_kernel_t) reboot_code_buffer;
+	(*rnk) (page_list, reboot_code_buffer_phys, image->start);
+}
Index: linux-2.6.11.6/include/asm-arm/kexec.h
===================================================================
--- /dev/null
+++ linux-2.6.11.6/include/asm-arm/kexec.h
@@ -0,0 +1,25 @@
+#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__
+
+struct kimage;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ARM_KEXEC_H */
Index: linux-2.6.11.6/arch/arm/kernel/relocate_kernel.S
===================================================================
--- /dev/null
+++ linux-2.6.11.6/arch/arm/kernel/relocate_kernel.S
@@ -0,0 +1,89 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ */
+
+#include <asm/kexec.h>
+                                                                                
+	/*
+	 * Must be relocatable PIC code callable as a C function.
+	 */
+	.globl relocate_new_kernel
+relocate_new_kernel:
+	/* r0 = indirection_page   */
+	/* r1 = reboot_code_buffer */
+	/* r2 = start_address      */
+
+
+	add lr,r1,#(do_relocate-relocate_new_kernel)
+	
+	/* Here we disable address translations and interrupts */
+	
+	mov	r5,#0x00d3                 /* F_BIT|I_BIT|SVC_MODE */
+	msr	cpsr_c,r5                  /* reset CPSR */
+	mrc	p15,0,r5,c1,c0,0           /* ctrl register */
+	bic	r5,r5,#0x0086              /* ........B....CA. */
+	bic	r5,r5,#0x1900              /* ...IZ..S........ */
+	mcr	p15,0,r5,c1,c0,0           /* ctrl register */
+	mcr	p15,0,r5,c7,c7,0           /* I,D caches+BTB go bye-bye */
+	bic	r5,r5,#0x0001              /* ...............M */
+	mcr	p15,0,r5,c1,c0,0           /* ctrl register */
+
+        /*
+         * CAUTION: MMU turned off from this point. We count on the pipeline
+         * already containing those two last instructions to survive.
+         */
+
+	mcr	p15,0,r5,c8,c7,0           /* invalidate I & D TLBs */
+	mov	pc,lr
+
+do_relocate:
+	nop
+	nop
+	nop
+	
+
+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 pc,r2
+
+
+relocate_new_kernel_end:
+
+	.globl relocate_new_kernel_size
+relocate_new_kernel_size:	
+	.long relocate_new_kernel_end - relocate_new_kernel
+
Index: linux-2.6.11.6/arch/arm/kernel/Makefile
===================================================================
--- linux-2.6.11.6.orig/arch/arm/kernel/Makefile
+++ linux-2.6.11.6/arch/arm/kernel/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o
 obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
Index: linux-2.6.11.6/include/linux/kexec.h
===================================================================
--- linux-2.6.11.6.orig/include/linux/kexec.h
+++ linux-2.6.11.6/include/linux/kexec.h
@@ -115,6 +115,7 @@
 #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_FLAGS    (KEXEC_ON_CRASH)  /* List of defined/legal kexec flags */
 
-------------------------------------------------------------------
Subscription options: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:       http://www.arm.linux.org.uk/armlinux/mlfaq.php
Etiquette: http://www.arm.linux.org.uk/armlinux/mletiquette.php

[Site Home]     [Linux Arm]     [Fedora ARM]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [PDAs]     [Linux]     [Linux Book List]     [Linux MIPS]     [Yosemite Campsites]     [Photos]

Add to Google Google PageRank Checking tool