On Fri, Sep 21, 2007 at 06:04:58PM -0500, Milton Miller wrote: > > 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[];
Don't need these externs any more, they're in the headers. > + > +BSS_STACK(16*1024); > + > +static void find_console_from_tree(void) > +{ > + int rc = -1; > + > + if (rc) { > + /* no console, oh well */ > + } Um... pointless function...? > +} > + > +/** > + * 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); Ow, yuck, no. The finalize callback is for finalizing the device tree, don't abuse it for SMP entry. It's a new thing that needs to be done, so create a new callback for it. > + > + 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" Arg. Again, just because it happens to fit is not a good reason to abuse platformo - which, obviously enough, s meant to contain the .o file for the platform - to also contain flags. > + ;; > 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); This platform specific function should not poluute ops.h. > > 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 > -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev