summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdgar E. Iglesias <edgar.iglesias@axis.com>2008-09-04 16:08:50 +0200
committerSimon Horman <horms@verge.net.au>2008-10-08 17:09:19 +1100
commitb039510932e5b3d9691a5d423c34f7ebb14e5175 (patch)
tree289c9eb2b92235b717132688d00476363cbf23be
parent800fe37b7931cb11c47c88bf1fd69aa096d3cebe (diff)
downloadkexec-tools-b039510932e5b3d9691a5d423c34f7ebb14e5175.tar.gz
cris: Add CRISv32 support
Hello, I hope this is the correct list to which to send these patches. Comments are very welcome. Thanks, Edgar From: Edgar E. Iglesias <edgar.iglesias@axis.com> Add a CRISv32 port. Initially only the elf filetype is supported. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@axis.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rwxr-xr-xconfig/config.sub2
-rw-r--r--configure.ac3
-rw-r--r--kexec/Makefile1
-rw-r--r--kexec/arch/cris/Makefile13
-rw-r--r--kexec/arch/cris/cris-setup-simple.S31
-rw-r--r--kexec/arch/cris/include/arch/options.h11
-rw-r--r--kexec/arch/cris/kexec-cris.c121
-rw-r--r--kexec/arch/cris/kexec-cris.h17
-rw-r--r--kexec/arch/cris/kexec-elf-cris.c136
-rw-r--r--kexec/arch/cris/kexec-elf-rel-cris.c42
-rw-r--r--kexec/kexec-syscall.h1
11 files changed, 377 insertions, 1 deletions
diff --git a/config/config.sub b/config/config.sub
index ac6de98..4812c82 100755
--- a/config/config.sub
+++ b/config/config.sub
@@ -457,7 +457,7 @@ case $basic_machine in
crds | unos)
basic_machine=m68k-crds
;;
- cris | cris-* | etrax*)
+ cris | cris-* | etrax* | crisv32 | crisv32-* | etraxfs*)
basic_machine=cris-axis
;;
crx)
diff --git a/configure.ac b/configure.ac
index 5351d53..ff3b304 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,9 @@ case $target_cpu in
mips|mipsel )
ARCH="mips"
;;
+ crisv32 )
+ ARCH="cris"
+ ;;
ia64|x86_64|alpha )
ARCH="$target_cpu"
;;
diff --git a/kexec/Makefile b/kexec/Makefile
index 99949c4..45787ac 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -48,6 +48,7 @@ include $(srcdir)/kexec/arch/arm/Makefile
include $(srcdir)/kexec/arch/i386/Makefile
include $(srcdir)/kexec/arch/ia64/Makefile
include $(srcdir)/kexec/arch/mips/Makefile
+include $(srcdir)/kexec/arch/cris/Makefile
include $(srcdir)/kexec/arch/ppc/Makefile
include $(srcdir)/kexec/arch/ppc64/Makefile
include $(srcdir)/kexec/arch/s390/Makefile
diff --git a/kexec/arch/cris/Makefile b/kexec/arch/cris/Makefile
new file mode 100644
index 0000000..6e60ed1
--- /dev/null
+++ b/kexec/arch/cris/Makefile
@@ -0,0 +1,13 @@
+cris_KEXEC_SRCS = kexec/arch/cris/kexec-cris.c
+cris_KEXEC_SRCS += kexec/arch/cris/kexec-elf-cris.c
+cris_KEXEC_SRCS += kexec/arch/cris/cris-setup-simple.S
+cris_KEXEC_SRCS += kexec/arch/cris/kexec-elf-rel-cris.c
+
+cris_ADD_BUFFER =
+cris_ADD_SEGMENT =
+cris_VIRT_TO_PHYS =
+
+dist += kexec/arch/cris/Makefile $(cris_KEXEC_SRCS) \
+ kexec/arch/cris/kexec-criss.h \
+ kexec/arch/cris/include/arch/options.h
+
diff --git a/kexec/arch/cris/cris-setup-simple.S b/kexec/arch/cris/cris-setup-simple.S
new file mode 100644
index 0000000..764f188
--- /dev/null
+++ b/kexec/arch/cris/cris-setup-simple.S
@@ -0,0 +1,31 @@
+/*
+ * cris-setup-simple.S - code to execute before stepping into the new kernel.
+ * Copyright (C) 2008 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+ .data
+ .globl cris_trampoline
+cris_trampoline:
+ .balign 4
+ lapc cris_regframe, $sp
+ moveq 0, $r0
+ move $r0, $pid
+
+ movem [$sp+], $r14
+ jump $r0
+ nop
+
+ .globl cris_regframe
+cris_regframe:
+ .balign 4
+ .fill 16, 4, 0
+cris_trampoline_end:
+
+ .globl cris_trampoline_size
+cris_trampoline_size:
+ .long cris_trampoline_end - cris_trampoline
+
diff --git a/kexec/arch/cris/include/arch/options.h b/kexec/arch/cris/include/arch/options.h
new file mode 100644
index 0000000..bc5f706
--- /dev/null
+++ b/kexec/arch/cris/include/arch/options.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_MIPS_OPTIONS_H
+#define KEXEC_ARCH_MIPS_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_MIPS_OPTIONS_H */
diff --git a/kexec/arch/cris/kexec-cris.c b/kexec/arch/cris/kexec-cris.c
new file mode 100644
index 0000000..540ec6f
--- /dev/null
+++ b/kexec/arch/cris/kexec-cris.c
@@ -0,0 +1,121 @@
+/*
+ * kexec-cris.c
+ * Copyright (C) 2008 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-cris.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 memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges, unsigned long kexec_flags)
+{
+ int memory_ranges = 0;
+
+ memory_range[memory_ranges].start = 0x40000000;
+ memory_range[memory_ranges].end = 0x41000000;
+ memory_range[memory_ranges].type = RANGE_RAM;
+ memory_ranges++;
+
+ memory_range[memory_ranges].start = 0xc0000000;
+ memory_range[memory_ranges].end = 0xc1000000;
+ memory_range[memory_ranges].type = RANGE_RAM;
+ memory_ranges++;
+
+ *range = memory_range;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+struct file_type file_type[] = {
+ {"elf-cris", elf_cris_probe, elf_cris_load, elf_cris_usage},
+};
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+void arch_usage(void)
+{
+}
+
+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;
+
+ 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;
+}
+
+const struct arch_map_entry arches[] = {
+ { "cris", KEXEC_ARCH_CRIS },
+ { "crisv32", KEXEC_ARCH_CRIS },
+ { 0 },
+};
+
+int arch_compat_trampoline(struct kexec_info *info)
+{
+ return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+}
+
+int is_crashkernel_mem_reserved(void)
+{
+ return 1;
+}
+
+unsigned long virt_to_phys(unsigned long addr)
+{
+ return (addr) & 0x7fffffff;
+}
+
+/*
+ * add_segment() should convert base to a physical address on superh,
+ * while the default is just to work with base as is */
+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
+ unsigned long base, size_t memsz)
+{
+ add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
+}
+
+/*
+ * add_buffer() should convert base to a physical address on superh,
+ * while the default is just to work with base as is */
+unsigned long add_buffer(struct kexec_info *info, const void *buf,
+ unsigned long bufsz, unsigned long memsz,
+ unsigned long buf_align, unsigned long buf_min,
+ unsigned long buf_max, int buf_end)
+{
+ return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
+ buf_min, buf_max, buf_end, 1);
+}
+
diff --git a/kexec/arch/cris/kexec-cris.h b/kexec/arch/cris/kexec-cris.h
new file mode 100644
index 0000000..6af49ef
--- /dev/null
+++ b/kexec/arch/cris/kexec-cris.h
@@ -0,0 +1,17 @@
+#ifndef KEXEC_CRIS_H
+#define KEXEC_CRIS_H
+
+extern unsigned char setup_simple_start[];
+extern uint32_t setup_simple_size;
+
+extern struct {
+ uint32_t spr8;
+ uint32_t spr9;
+} setup_simple_regs;
+
+int elf_cris_probe(const char *buf, off_t len);
+int elf_cris_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_cris_usage(void);
+
+#endif /* KEXEC_CRIS_H */
diff --git a/kexec/arch/cris/kexec-elf-cris.c b/kexec/arch/cris/kexec-elf-cris.c
new file mode 100644
index 0000000..bb40398
--- /dev/null
+++ b/kexec/arch/cris/kexec-elf-cris.c
@@ -0,0 +1,136 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2008 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * Based on x86 implementation,
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-elf-boot.h"
+#include <arch/options.h>
+#include "kexec-cris.h"
+
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+
+int elf_cris_probe(const char *buf, off_t len)
+{
+ struct mem_ehdr ehdr;
+ int result;
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
+ if (result < 0)
+ goto out;
+
+ /* Verify the architecuture specific bits */
+ if (ehdr.e_machine != EM_CRIS) {
+ result = -1;
+ goto out;
+ }
+
+ result = 0;
+ out:
+ free_elf_info(&ehdr);
+ return result;
+}
+
+void elf_cris_usage(void)
+{
+ printf(" --append=STRING Set the kernel command line to STRING\n"
+ );
+}
+
+#define CRAMFS_MAGIC 0x28cd3d45
+#define JHEAD_MAGIC 0x1FF528A6
+#define JHEAD_SIZE 8
+#define RAM_INIT_MAGIC 0x56902387
+#define COMMAND_LINE_MAGIC 0x87109563
+#define NAND_BOOT_MAGIC 0x9a9db001
+
+int elf_cris_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct mem_ehdr ehdr;
+ char *command_line;
+ unsigned int *trampoline_buf;
+ unsigned long trampoline_base;
+ int opt;
+ extern void cris_trampoline(void);
+ extern unsigned long cris_trampoline_size;
+ extern struct regframe_t {
+ unsigned int regs[16];
+ } cris_regframe;
+
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0, 0, 0, 0 },
+ };
+
+ static const char short_options[] = KEXEC_OPT_STR "";
+
+ /*
+ * Parse the command line arguments
+ */
+ command_line = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ }
+ }
+
+ /* Load the ELF executable */
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
+
+ cris_regframe.regs[0] = virt_to_phys(ehdr.e_entry);
+ cris_regframe.regs[8] = RAM_INIT_MAGIC;
+ cris_regframe.regs[12] = NAND_BOOT_MAGIC;
+
+ trampoline_buf = xmalloc(cris_trampoline_size);
+ trampoline_base = add_buffer_virt(info,
+ trampoline_buf,
+ cris_trampoline_size,
+ cris_trampoline_size,
+ 4, 0, elf_max_addr(&ehdr), 1);
+ memcpy(trampoline_buf,
+ cris_trampoline, cris_trampoline_size);
+ info->entry = trampoline_base;
+ return 0;
+}
diff --git a/kexec/arch/cris/kexec-elf-rel-cris.c b/kexec/arch/cris/kexec-elf-rel-cris.c
new file mode 100644
index 0000000..c4427cc
--- /dev/null
+++ b/kexec/arch/cris/kexec-elf-rel-cris.c
@@ -0,0 +1,42 @@
+/*
+ * kexec-elf-rel-cris.c - kexec Elf relocation routines
+ * Copyright (C) 2008 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * derived from ../ppc/kexec-elf-rel-ppc.c
+ * Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+*/
+
+#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_CRIS) {
+ 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) {
+
+ default:
+ die("Unknown rela relocation: %lu\n", r_type);
+ break;
+ }
+ return;
+}
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index 4535716..c367790 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -92,6 +92,7 @@ static inline long kexec_reboot(void)
#define KEXEC_ARCH_SH (42 << 16)
#define KEXEC_ARCH_MIPS_LE (10 << 16)
#define KEXEC_ARCH_MIPS ( 8 << 16)
+#define KEXEC_ARCH_CRIS (76 << 16)
#define KEXEC_MAX_SEGMENTS 16