This code creates a 32 bit zImage wrapper for a 32 or 64 bit PowerPC
Linux kernel.  This allows you to kexec a zImage with its compressed
vmlinux instead of the uncompressed vmlinux elf.  The code is also
packaged as a 64 bit elf for use by kexec-tools on 64 bit kernels.

Limitations:
Note: the device-tree generated by kexec-tools is currently version 2,
not the version 16 supported by the boot code base.

Signed-off-by: Milton Miller <[EMAIL PROTECTED]>
---
find_rmo_end moved to memranges as find_rma_end.
early_scan_flat_tree replaced with calls to its pieces in
kexec_platform_init
rediff wrapper, Makefile, ops.h

Index: kernel/arch/powerpc/boot/kexec.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/kexec.c    2007-09-21 04:52:46.000000000 -0500
@@ -0,0 +1,122 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corporation 2007
+ *
+ * Authors: Milton Miller <[EMAIL PROTECTED]>
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "flatdevtree.h"
+#include "page.h"
+#include "types.h"
+
+extern char _start[];
+extern char _end[];
+
+BSS_STACK(16*1024);
+
+static void find_console_from_tree(void)
+{
+       int rc = -1;
+
+       if (rc) {
+               /* no console, oh well */
+       }
+}
+
+/**
+ * setup_initial_heap - setup a small heap in the bss
+ * Using a preallocated heap, setup for scanning the device tree.
+ * Intended for the initial read while the tree will remain read-only so
+ * a minimal malloc and search limit can be used.  This way we don't have
+ * lots of data or bss to clear.
+ */
+static void setup_initial_heap(void)
+{
+       static char initial_heap[8*1024];
+       void *heap_end;
+
+       heap_end = simple_alloc_init(initial_heap,
+                       sizeof(initial_heap) * 7 / 8,
+                       sizeof(long), 64);
+
+       if (heap_end - sizeof(initial_heap) > (void *)&initial_heap[0])
+               fatal("Initial heap too big\n\r");
+}
+
+static void init_flat_tree(struct boot_param_header *dt_blob)
+{
+       int rc;
+
+       rc = ft_init(dt_blob, dt_blob->totalsize, /* max_finddevice */ 1024);
+       if (rc)
+               fatal("Unable to initialize device_tree library!\n\r");
+}
+
+static void *saved_vmlinux_addr;
+
+static void *kexec_vmlinux_alloc(unsigned long size)
+{
+       void *addr;
+
+       addr = ranges_vmlinux_alloc(size);
+
+       saved_vmlinux_addr = addr;
+       return addr;
+}
+
+static void kexec_fixups(void)
+{
+       wait_slaves_moved();
+}
+
+static unsigned long (*finalize_chain)(void);
+
+static unsigned long kexec_finalize(void)
+{
+       send_slaves_to_kernel(saved_vmlinux_addr);
+
+       return finalize_chain();
+}
+
+void kexec_platform_init(struct boot_param_header *dt_blob)
+{
+       slaves_are_low();
+       move_slaves_up();
+
+       setup_initial_heap();
+       init_flat_tree(dt_blob);
+       /*
+        * drivers can malloc and read the tree, but not realloc later
+        * or modify the tree now.
+        */
+       if (!console_ops.write)
+               find_console_from_tree();
+
+       find_rma_end();
+       dt_find_initrd();
+       add_known_ranges(dt_blob);
+       ranges_init_malloc();
+
+       /* now that we have a malloc region, start over from the flat tree */
+       init_flat_tree(dt_blob);
+
+       platform_ops.vmlinux_alloc = kexec_vmlinux_alloc;
+       platform_ops.fixups = kexec_fixups;
+       finalize_chain = dt_ops.finalize;
+       dt_ops.finalize = kexec_finalize;
+}
Index: kernel/arch/powerpc/boot/crt0_kexec.S
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/crt0_kexec.S       2007-09-21 04:52:46.000000000 
-0500
@@ -0,0 +1,45 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <[EMAIL PROTECTED]>
+ *
+ */
+       /*
+        * The kernel calls out to the first image with
+        * r3 = boot cpu, r4 = entrypoint, r5 = 0
+        *
+        * kexec-tools purgatory calls this as it would a linux kernel:
+        * r3 = boot block, r4 = entrypoint, r5 = 0
+        *
+        * The boot block boot_cpu field has been filled in.
+        *
+        * kexec-tools and its purgatory are suppposed to copy SMP_SLAVE_SIZE
+        * bytes from the from entry point, but aparently instead it copies
+        * from the image start.
+        */
+       .globl _zimage_start
+_zimage_start:
+
+#include "marshal_low.S"
+
+       .globl  _zimage_start_plat
+_zimage_start_plat:
+       b       _zimage_start_lib
+
+       .globl  platform_init
+platform_init:
+       b       kexec_platform_init
Index: kernel/arch/powerpc/boot/wrapper
===================================================================
--- kernel.orig/arch/powerpc/boot/wrapper       2007-09-21 04:51:31.000000000 
-0500
+++ kernel/arch/powerpc/boot/wrapper    2007-09-21 04:52:46.000000000 -0500
@@ -133,6 +133,12 @@ coff)
     platformo=$object/of.o
     lds=$object/zImage.coff.lds
     ;;
+kexec)
+    platformo=$object/crt0_kexec.o
+    ;;
+kexec64)
+    platformo="-e _zimage_start_64 $object/crt0_kexec.o"
+    ;;
 miboot|uboot)
     # miboot and U-boot want just the bare bits, not an ELF binary
     ext=bin
@@ -190,6 +196,9 @@ uboot)
     fi
     exit 0
     ;;
+kexec64)
+    ${CROSS}objcopy -O elf64-powerpc $ofile
+    ;;
 esac
 
 addsec() {
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile      2007-09-21 04:52:44.000000000 
-0500
+++ kernel/arch/powerpc/boot/Makefile   2007-09-21 04:52:46.000000000 -0500
@@ -42,12 +42,12 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
        $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix 
$(obj)/,$(zlibheader))
 
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
-               marshal.c memranges.c \
+               marshal.c memranges.c kexec.c \
                ns16550.c serial.c simple_alloc.c div64.S util.S \
                gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
                4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
                cpm-serial.c stdlib.c
-src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
+src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \
                cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
                ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
                cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c
@@ -128,6 +128,9 @@ quiet_cmd_wrap      = WRAP    $@
       cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
                $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
 
+kexec-$(CONFIG_PPC32)                  += zImage.kexec
+kexec-$(CONFIG_PPC64)                  += zImage.kexec64
+
 image-$(CONFIG_PPC_PSERIES)            += zImage.pseries
 image-$(CONFIG_PPC_MAPLE)              += zImage.pseries
 image-$(CONFIG_PPC_IBM_CELL_BLADE)     += zImage.pseries
@@ -140,6 +143,7 @@ image-$(CONFIG_PPC_HOLLY)           += zImage.hol
 image-$(CONFIG_PPC_PRPMC2800)          += zImage.prpmc2800
 image-$(CONFIG_PPC_ISERIES)            += zImage.iseries
 image-$(CONFIG_DEFAULT_UIMAGE)         += uImage
+image-$(CONFIG_KEXEC)                  += $(kexec-y)
 
 ifneq ($(CONFIG_DEVICE_TREE),"")
 image-$(CONFIG_PPC_8xx)                        += cuImage.8xx
@@ -158,7 +162,7 @@ ifeq ($(CONFIG_PPC32),y)
 image-$(CONFIG_PPC_PMAC)       += zImage.coff zImage.miboot
 endif
 
-initrd-  := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
+initrd-  := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-) $(kexec-))
 initrd-y := $(patsubst zImage%, zImage.initrd%, \
                $(patsubst treeImage%, treeImage.initrd%, $(image-y)))
 initrd-y := $(filter-out $(image-y), $(initrd-y))
@@ -227,7 +231,7 @@ install: $(CONFIGURE) $(addprefix $(obj)
 
 # anything not in $(targets)
 clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* 
\
-       otheros.bld
+       otheros.bld $(kexec-)
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin
Index: kernel/arch/powerpc/boot/ops.h
===================================================================
--- kernel.orig/arch/powerpc/boot/ops.h 2007-09-21 04:52:44.000000000 -0500
+++ kernel/arch/powerpc/boot/ops.h      2007-09-21 04:52:46.000000000 -0500
@@ -95,6 +95,7 @@ void move_slaves_here(void *where);
 void send_slaves_to_kernel(void *vmlinux_addr);
 void slaves_are_low(void);
 void wait_slaves_moved(void);
+void kexec_platform_init(struct boot_param_header *dt_blob);
 
 int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long 
*size);
 int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long 
*xlated_addr);
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to