* [PATCH 0/3+2+8] powerpc zImage kexec
@ 2007-04-11 8:28 Milton Miller
2007-04-11 8:29 ` [PATCH HACK kexec-tools-testing] malloc corruption hack Milton Miller
` (12 more replies)
0 siblings, 13 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:28 UTC (permalink / raw)
To: linuxppc-dev, fastboot; +Cc: Paul Mackerras
The patches following this message implement support for creating a
compressed zImage that can be used where a vmlinux image with a
flat device-tree would be. It has been tested with kexec-tools
on 64 bit platforms with upto 8 threads, and with an external
bootloader. that supplies a device tree and initrd.
The patches are:
(1) a series of 3 patches for kexec-tools
(a) a hack to fix memory corruption in the testing tree
(b) a fix for @ha relocations
(c) a major change to the handling of SMP slaves during purgatory
(2) a related patch for increasing the times for slaves to transiton
(3) a convinence patch to expose a retained initrd for testing kexec-reboot
(4) and a series of 8 patches for the zImage wrapper
(a) a debug message
(b) smp handling code
(c) coarse memory allocation for finding malloc pool, vmlinux, etc.
(d) 64 bit support
(e) kexec entrypoint base support
-- or any environment that can supply a flat tree that
fully describes the machine, and wishes to use it to
find memory for the machine.
(f) support for converting older versions of the flat device tree
(g) support for writing to an rtas put-term-char console
(h) alternative example code for using a-f on another palatform.
The kernel series is based on the patches I extracted from the
for-2.6.22 branch of powerpc.git as well as 1, 3, and 4 from my
last series.
I did not include my external payload patch at this point because
I still have to debug the initramfs search code, but the plan
is to allow the base code to find the vmlinux in a compressed cpio.gz
in the initrd area, with the file to decompress being selected by
a property in the device-tree.
Because of the vaired nature of the patches, each has its own CC list.
I ask that the non-bootwrapper patchs and the debug message be queued
now. I expect the last one be discussion only, and the others to
provoke discussion.
I have been running a loop on 4 and 8 thread pSeries boxes of continous
kexecs for several thousand interations now.
Thanks,
milton
kexec-tools:
ppc64-miscount-exlude-hack
ppc64-reloc-ha
ppc64-steal-kernel-slaves
misc:
initrd-debugfs
kexec-slaves-earlier
Patch: [PATCH 1/4] bootwrapper: missing relocation in crt0.S
http://patchwork.ozlabs.org/linuxppc/patch?id=10219
Message ID <boot-3-01.miltonm@bga.com>
Patch: Re: Patch: [PATCH 3/4] bootwrapper: no gzip fixes
http://patchwork.ozlabs.org/linuxppc/patch?id=10223
Message ID <boot-3-03.miltonm@bga.com>
Patch: Re: [PATCH 4/4] bootwrapper: decompress less, check more
http://patchwork.ozlabs.org/linuxppc/patch?id=10232
Message ID <boot-3-04-a.miltonm@bga.com>
boot-exact-debug
boot-marshal-smp
boot-memranges
boot-64
boot-kexec
boot-flat-conv-2-16
boot-rtas
boot-bml.patch
Patch: [RFC] bootwrapper: allow vmlinuz to be an external payload
Submitter Milton Miller
Date 2007-03-28 18:21:03
Message ID <boot-3-05.miltonm@bga.com>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH HACK kexec-tools-testing] malloc corruption hack
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
@ 2007-04-11 8:29 ` Milton Miller
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: correct @ha relocation Milton Miller
` (11 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:29 UTC (permalink / raw)
To: fastboot, Sachin Sant; +Cc: linuxppc-dev, Vivek Goyal
On a system with rtas, a hash table, no pci, and one memory node I
got the following error:
*** glibc detected *** double free or corruption (out): 0x0000000010115800 ***
kexec-reboot: line 9: 2366 Aborted \
./kexec --mem-max=0x20000000 -l /root/vmlinux --devicetreeblob=dtall.dtb
The problem is count_memory_ranges doesn't count what get_devtree_details
will be adding to the exlcude list.
This is a very gross hack to get around the problem, I post it so others
might benifit until the real problem is fixed.
However, I would also like to point out that the code is deficent, as it
is only looking for the properties in specific directories. It should
be looking in all directories for the properties, like the reserve code
building the device tree. TCE (iommu) tables can be attached to any
pci bus. Also, it allows other ranges to be reserved by just changing
the device tree, instead of adding new searches to kexec-tools.
---
Thanks to Sonny for getting a debug envrionment laoded to debug this failure.
--- kexec-tools-testing/kexec/arch/ppc64/kexec-ppc64.c.orig 2007-04-10 22:29:59.000000000 -0500
+++ kexec-tools-testing/kexec/arch/ppc64/kexec-ppc64.c 2007-04-10 22:30:21.000000000 -0500
@@ -124,6 +124,8 @@ static int count_memory_ranges()
}
closedir(dir);
+ max_memory_ranges += 5; /* base exclude ranges - kernel, rtas, etc */
+
return 0;
}
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH kexec-tools] ppc64: correct @ha relocation
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
2007-04-11 8:29 ` [PATCH HACK kexec-tools-testing] malloc corruption hack Milton Miller
@ 2007-04-11 8:30 ` Milton Miller
2007-04-12 3:24 ` Simon Horman
2007-04-12 8:17 ` Mohan Kumar M
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: use kernels slave loop for purgatory Milton Miller
` (10 subsequent siblings)
12 siblings, 2 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:30 UTC (permalink / raw)
To: fastboot, Sachin Sant; +Cc: linuxppc-dev, Vivek Goyal, Simon Horman
The @ha relocation is supposed to account for the @l relocation being
a signed quantity by adding 1 if the msb of @l is set.
The trick of adding 0x8000 stolen from the linux kernel file
arch/powerpc/kernel/module_64.c which credits binutils.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
This relocation is used in v2wrap.S to hold and release the slave cpus.
Without this fix the memory location may be 64k off the initialized variable
which is checked against 0.
--- kexec-tools-testing/kexec/arch/ppc64/kexec-elf-rel-ppc64.c.orig 2007-04-10 22:29:59.000000000 -0500
+++ kexec-tools-testing/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2007-04-10 22:29:59.000000000 -0500
@@ -97,7 +97,7 @@ void machine_apply_elf_rel(struct mem_eh
break;
case R_PPC64_ADDR16_HA:
- *(uint16_t *)location = ((value>>16) & 0xffff);
+ *(uint16_t *)location = (((value+0x8000)>>16) & 0xffff);
break;
case R_PPC64_ADDR16_HIGHEST:
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH kexec-tools] ppc64: use kernels slave loop for purgatory
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
2007-04-11 8:29 ` [PATCH HACK kexec-tools-testing] malloc corruption hack Milton Miller
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: correct @ha relocation Milton Miller
@ 2007-04-11 8:30 ` Milton Miller
2007-04-13 1:34 ` Simon Horman
2007-04-11 8:31 ` [PATCH] export retained initrd in debugfs Milton Miller
` (9 subsequent siblings)
12 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:30 UTC (permalink / raw)
To: fastboot, Sachin Sant; +Cc: linuxppc-dev, Vivek Goyal, Simon Horman
Purgatory doesn't really care about the SMP cpus. But if we leave them
behind, they end up getting lost when the kernel overwrites purgatory or
the previous kernel. The current slave handling in purgatory doesn't
have any handshaking to make sure the cpus have moved on before leaving.
Instead of moving the slave cpus up to purgatory and then back down to
the kernel, just copy bytes 4-255 from the kernel and use it as the
purgatory start / slave hold block.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
I wrote this while debugging a problem in my zImage.kexec smp code.
Since the first instruction is the branch for the master, changing it
to another branch should be safe.
We could copy the kernels original branch to 0 before jumping to the
kernel for completeness.
We could also just compute the branch for the master instead of reading
the code in the original symbol.
--- kexec-tools-testing/purgatory/arch/ppc64/v2wrap.S.orig 2007-04-10 22:29:59.000000000 -0500
+++ kexec-tools-testing/purgatory/arch/ppc64/v2wrap.S 2007-04-10 23:46:11.000000000 -0500
@@ -45,13 +45,22 @@
oris rn,rn,name##@h; \
ori rn,rn,name##@l
-# look a bit like a Linux kernel here ...
+
.machine ppc64
.globl purgatory_start
purgatory_start: b master
- tweq 0,0
+ .org purgatory_start + 0x60 # ABI: slaves start at 60 with r3=phys
+slave: b $
+ .org purgatory_start + 0x100 # ABI: end of copied region
+ .size purgatory_start, . - purgatory_start
+
+#
+# The above 0x100 bytes at purgatory_start are replaced with the
+# code from the kernel (or next stage) by kexec/arch/ppc64/kexec-ppc64.c
+#
+
master:
- or 1,1,1 # low priority to let other thread catchup
+ or 1,1,1 # low priority to let other threads catchup
isync
mr 17,3 # save cpu id to r17
mr 15,4 # save physical address in reg15
@@ -66,25 +75,7 @@ master:
bl .purgatory
nop
- b 81f
- .org purgatory_start + 0x60 # ABI: slaves start at 60 with r3=phys
-slave:
- # load slave spin code address and branch into that
- LOADADDR(6,slave_spin)
- ld 4,0(6)
- mtctr 4
- bctr
-
-spin: .long 1
-slave_spin_code:
- lis 5,spin@ha
- lwz 5,spin@l(5)
- cmpwi 0,5,0
- bne slave_spin_code
- ba 0x60
-
-81: # master continues here
- or 3,3,3 # ok back to high, lets boot
+ or 3,3,3 # ok now to high priority, lets boot
lis 6,0x1
mtctr 6 # delay a bit for slaves to catch up
83: bdnz 83b # before we overwrite 0-100 again
@@ -99,30 +90,12 @@ slave_spin_code:
80:
LOADADDR(6,kernel)
ld 4,0(6) # load the kernel address
-
- addi 5,4,-8 # prepare copy with update form instructions
- li 6,0x100/8
- mtctr 6
- li 6,-8
-85: ldu 7,8(5)
- stdu 7,8(6)
- bdnz 85b
-
li 5,0 # r5 will be 0 for kernel
- dcbst 0,5 # store dcache, flush icache
- dcbst 0,6 # 0 and 0xf8 covers us with 128 byte lines
mtctr 4 # prepare branch too
- sync
- icbi 0,5
- icbi 0,6
- sync
- isync
- lis 6,spin@ha
- li 0,0
- stw 0,spin@l(6)
mr 3,16 # restore dt address
- bctr # start kernel
-
-slave_spin: .llong slave_spin_code
+ lwz 7,0(4) # get the first instruction that we stole
+ stw 7,0(0) # and put it in the slave loop at 0
+ # skip cache flush, do we care?
+ bctr # start kernel
--- kexec-tools-testing/kexec/arch/ppc64/kexec-elf-ppc64.c.orig 2007-04-10 22:29:59.000000000 -0500
+++ kexec-tools-testing/kexec/arch/ppc64/kexec-elf-ppc64.c 2007-04-10 22:29:59.000000000 -0500
@@ -89,6 +89,7 @@ int elf_ppc64_load(int argc, char **argv
unsigned int my_panic_kernel;
unsigned long my_stack, my_backup_start;
unsigned long toc_addr;
+ unsigned int slave_code[256/sizeof (unsigned int)], master_entry;
#define OPT_APPEND (OPT_ARCH_MAX+0)
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
@@ -281,6 +282,15 @@ int elf_ppc64_load(int argc, char **argv
elf_rel_set_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
sizeof(my_dt_offset));
+ /* get slave code from new kernel, put in purgatory */
+ elf_rel_get_symbol(&info->rhdr, "purgatory_start", slave_code,
+ sizeof(slave_code));
+ master_entry = slave_code[0];
+ memcpy(slave_code, info->segment[0].buf, sizeof(slave_code));
+ slave_code[0] = master_entry;
+ elf_rel_set_symbol(&info->rhdr, "purgatory_start", slave_code,
+ sizeof(slave_code));
+
if (info->kexec_flags & KEXEC_ON_CRASH) {
my_panic_kernel = 1;
/* Set panic flag */
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH] export retained initrd in debugfs
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (2 preceding siblings ...)
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: use kernels slave loop for purgatory Milton Miller
@ 2007-04-11 8:31 ` Milton Miller
2007-04-12 6:17 ` Michael Neuling
2007-04-11 8:32 ` [PATCH] kexec: send slaves to new kernel earlier Milton Miller
` (8 subsequent siblings)
12 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:31 UTC (permalink / raw)
To: fastboot, klibc, linuxppc-dev
Export initrd in debugfs when retained.
As a side effect, initrd_start and initrd_end are not cleared when the
initrd is retained.
After this patch, one can then copy the initrd space from debugfs and
pass it to kexec as the initrd, or do something else with it (maybe it
was an initrd not an initramfs).
Signed-off-by: Milton Miller <miltonm@bga.com>
---
This is a lot more reliable than extracting it via dd from /dev/mem.
Currently debugfs doesn't have a getattr even for blobs, so one has
to cp elsewhere before using kexec from kexec-tools.
Index: kernel/init/initramfs.c
===================================================================
--- kernel.orig/init/initramfs.c 2007-03-28 00:12:15.000000000 -0500
+++ kernel/init/initramfs.c 2007-03-28 00:35:56.000000000 -0500
@@ -6,6 +6,7 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/syscalls.h>
+#include <linux/debugfs.h>
static __initdata char *message;
static void __init error(char *x)
@@ -519,7 +520,7 @@ static void __init free_initrd(void)
unsigned long crashk_end = (unsigned long)__va(crashk_res.end);
#endif
if (do_retain_initrd)
- goto skip;
+ return;
#ifdef CONFIG_KEXEC
/*
@@ -588,3 +589,29 @@ static int __init populate_rootfs(void)
return 0;
}
rootfs_initcall(populate_rootfs);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static struct debugfs_blob_wrapper initrd_blob;
+
+static int __init export_initrd(void)
+{
+ struct dentry *d;
+ initrd_blob.data = (char *)initrd_start;
+ initrd_blob.size = initrd_end - initrd_start;
+
+ if (!do_retain_initrd)
+ return 0;
+
+ if (!initrd_start)
+ return 0;
+
+ d = debugfs_create_blob("initrd", S_IFREG, NULL, &initrd_blob);
+
+ if (!d)
+ return 1;
+
+ return 0;
+}
+
+__initcall(export_initrd);
+#endif
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH] kexec: send slaves to new kernel earlier
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (3 preceding siblings ...)
2007-04-11 8:31 ` [PATCH] export retained initrd in debugfs Milton Miller
@ 2007-04-11 8:32 ` Milton Miller
2007-04-11 8:32 ` [PATCH 1/8] boot: more verbose gunzip error message Milton Miller
` (7 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:32 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: fastboot, Vivek Goyal
Copy the code and start the slaves on their journey to next
kernels spin loop as soon as we copy the kexec image into place.
The kernel doesn't know exactly which slaves are spinning in
kexec_wait. This allows us to pass more than max-cpus to the
next kernel. But it also means that we might leave some behind.
Moving the code here means they have the time it takes us to
clear the hash table to wake up and move on. Moving the code
any earlier would reuqire walking the image description to
search for the code, which could span multiple pages.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
I applied this change while searching for the cause of lost cpus. The actual
cause was a sequence error causing the slaves to attempt to execute invalid
instructions, but it showed the result is bouncing off the kernels ISI
handler scribling on low memory.
Index: kernel/arch/powerpc/kernel/misc_64.S
===================================================================
--- kernel.orig/arch/powerpc/kernel/misc_64.S 2007-04-09 02:25:01.000000000 -0500
+++ kernel/arch/powerpc/kernel/misc_64.S 2007-04-09 02:32:05.000000000 -0500
@@ -606,6 +606,19 @@ _GLOBAL(kexec_sequence)
/* turn off mmu */
bl real_mode
+ /* copy 0x100 bytes starting at start to 0 */
+ li r3,0
+ mr r4,r30 /* start, aka phys mem offset */
+ li r5,0x100
+ li r6,0
+ bl .copy_and_flush /* (dest, src, copy limit, start offset) */
+1: /* assume normal blr return */
+
+ /* release other cpus to the new kernel secondary start at 0x60 */
+ mflr r5
+ li r6,1
+ stw r6,kexec_flag-1b(5)
+
/* clear out hardware hash page table and tlb */
ld r5,0(r27) /* deref function descriptor */
mtctr r5
@@ -636,19 +649,6 @@ _GLOBAL(kexec_sequence)
* are the boot cpu ?????
* other device tree differences (prop sizes, va vs pa, etc)...
*/
-
- /* copy 0x100 bytes starting at start to 0 */
- li r3,0
- mr r4,r30
- li r5,0x100
- li r6,0
- bl .copy_and_flush /* (dest, src, copy limit, start offset) */
-1: /* assume normal blr return */
-
- /* release other cpus to the new kernel secondary start at 0x60 */
- mflr r5
- li r6,1
- stw r6,kexec_flag-1b(5)
mr r3,r25 # my phys cpu
mr r4,r30 # start, aka phys mem offset
mtlr 4
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 1/8] boot: more verbose gunzip error message
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (4 preceding siblings ...)
2007-04-11 8:32 ` [PATCH] kexec: send slaves to new kernel earlier Milton Miller
@ 2007-04-11 8:32 ` Milton Miller
2007-04-12 7:46 ` David Gibson
2007-04-11 8:32 ` [PATCH 2/8] bootwrapper: smp support code Milton Miller
` (6 subsequent siblings)
12 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
Change the error message in gunzip_exactly to be more verbose.
Besides the identifier being unrelated to the current function name,
the user had no indication if the corruption was near the beginning
or the end.
Signed-off-by: Milton Miller <miltonm@bga.com>
Index: kernel/arch/powerpc/boot/gunzip_util.c
===================================================================
--- kernel.orig/arch/powerpc/boot/gunzip_util.c 2007-04-10 21:29:49.000000000 -0500
+++ kernel/arch/powerpc/boot/gunzip_util.c 2007-04-10 21:30:15.000000000 -0500
@@ -142,7 +142,8 @@ void gunzip_exactly(struct gunzip_state
len = gunzip_partial(state, dst, dstlen);
if (len < dstlen)
- fatal("gunzip_block: ran out of data\n\r");
+ fatal("\n\rgunzip_exactly: ran out of data!"
+ " Wanted %d, got %d.\n\r", dstlen, len);
}
/**
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 2/8] bootwrapper: smp support code
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (5 preceding siblings ...)
2007-04-11 8:32 ` [PATCH 1/8] boot: more verbose gunzip error message Milton Miller
@ 2007-04-11 8:32 ` Milton Miller
2007-04-11 8:32 ` [PATCH 3/8] bootwrapper: occuppied memory ranges Milton Miller
` (5 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
Add support code to move cpus around, both a spin loop and c code to move
the cpus before uncompressing and copying the kernel to 0.
The low level code is designed to be included in a crt0 because it may
need to be at a fixed location or there may be other entry point
requirements.
This code supports arbitrary cpu identifiers in the 0-1023 range.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
I first had move_slaves_up, then added move_to_here to support loading
at zero where the bss is overwritten by the kernel. After moving
the slave area from the end to the beginning of the decompressed
kernel when it was not at 0, I started getting crashes. At that
point, I wrote checkout_slaves_to_kernel. Debugging checkout_slaves
prompted the kexec-slaves-earlier and kexec-tools purgatory patches.
Note: this works with the 64 bit kernel using head_64.S. The 32 bit
6xx kernel head_32.S needs the 0x60 slave entry point (it currently uses
something closer to 0xC0) and kexec slave shutdown.
Index: kernel/arch/powerpc/boot/marshal_low.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/marshal_low.S 2007-04-09 04:10:00.000000000 -0500
@@ -0,0 +1,103 @@
+/*
+ * 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 (C) 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ *
+ */
+
+#include "ppc_asm.h"
+
+ .text
+ /*
+ * This code is designed to be a kexec entry point block.
+ * That is, it has both code for the master cpu that begins
+ * at offset 0 as linked into the image, and a sequence of
+ * 0x100 bytes that, when copied to address 0, forms the
+ * wait loop for slave cpus. Each slave should have its
+ * unique hardware cpu identifier in r3 before entering
+ * this code.
+ */
+ .globl master
+master: b _zimage_start_plat
+
+ .global slave_wait
+slave_wait:
+ /* r3 cpu id, r4 slaves_wait, r5 cpu bit, r6 cpu mask word offset */
+
+ /* set our bit in the slaves mask */
+98: lwarx r7,r4,r6
+ or r8,r7,r5
+ stwcx. r8,r4,r6
+ bne 98b
+
+ and. r8,r7,r5
+ bnel- err_slave
+
+99: lwz r7,gohere-slave_wait(r4)
+ cmpwi 0,r7,0
+ beq 99b
+ mtctr r7
+ mr r4,r7
+ bctr
+
+
+ .global gohere
+gohere: .long 0 /* when set the slave moves */
+
+
+err_slave:
+ stw r5,slave_error-slave_wait(4) /* no locking */
+ blr
+
+ .globl slave_error /* set when slave detects error */
+slave_error:
+ .long 0
+
+ /*
+ * The slaves may be in 32 or 64 bit mode, we don't care
+ * r3 is the slave cpu number, matching the device tree.
+ */
+ .org master+0x60
+ .globl slave
+slave: bl 1f
+1: mflr r4
+ addi r4,r4,slave_wait-1b /* code assumes r4=slave_wait */
+ li r5,1
+ rlwnm r5,r5,r3,0,31 /* bit within word */
+ rlwinm r6,r3,32-5+2,4,29 /* word in array */
+ addi r6,r6,slaves-slave_wait /* relative to r4, slave_wait */
+ b slave_wait
+
+ .org master+0x80 /* put locked bitmask data in another line */
+ .global slaves
+slaves:
+
+ .globl slaves_end;
+slaves_end = 0f
+
+#if 0
+ /* today, the 32 bit kernel starts slaves at 0xc0
+ * but this limits us to cpu to 512 vs 1024
+ */
+ .org master+0xc0
+0: b slave
+#endif
+
+
+ .org master+0x100 /* we must fit in 0x100 bytes */
+0:
+
Index: kernel/arch/powerpc/boot/marshal.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/marshal.c 2007-04-09 01:48:53.000000000 -0500
@@ -0,0 +1,283 @@
+/*
+ * 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 (C) 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "reg.h"
+
+extern unsigned int gohere[], master[], slave_wait[], slaves[], slaves_end[];
+extern unsigned int slave_error[1];
+extern unsigned int slave_checkout_begin[], slave_checkout_spin[];
+
+static unsigned int slaves_run_here[SMP_SLAVE_SIZE / sizeof(unsigned int)];
+static unsigned int *slaves_were_here = master;
+static unsigned int *slaves_goto_here = master;
+
+/* check_slave_errors
+ * check if the slaves have set the error flag.
+ */
+static void check_slave_errors(unsigned int *slaves_here)
+{
+ unsigned int *error = slave_error - master + slaves_here;
+
+ if (*error) {
+ printf("WARNING: error detected by one or more slave cpus!!\n\r"
+ "WARNING: This probably means you have duplicate cpu ids\n\r");
+ /* exit() */
+ }
+}
+
+/* wait_slaves_moved - wait for the slaves to catch up
+ * Wait until all slaves that checked in the previous location have
+ * checked into the current location. Seperate so we can do other
+ * work while we wait for them to catch up.
+ */
+void wait_slaves_moved(void)
+{
+ int offset = slaves - master;
+ int len = sizeof(slaves_end[0]) * (slaves_end - slaves);
+ int printed = 0;
+ unsigned int *to = slaves_goto_here;
+ unsigned int *from = slaves_were_here;
+
+ from += offset;
+ to += offset;
+
+ if (from == to)
+ return;
+
+ while (memcmp(from, to, len)) {
+ if (!printed) {
+ printf("waiting for slave cpus to move...");
+ printed = 1;
+ HMT_LOW;
+ barrier();
+ }
+ /* check from is superset of to */
+ }
+ if (printed) {
+ HMT_MEDIUM;
+ printf("done.\n\r");
+ }
+
+ slaves_were_here = slaves_goto_here;
+}
+
+/* move_slaves_here - move slaves to a specified address.
+ * Tell slaves to go from their current location to a buffer @addr
+ * of %SMP_SLAVE_SIZE bytes somewhere in memory.
+ */
+void move_slaves_here(void *addr)
+{
+ unsigned int *move_slaves_here = addr;
+ unsigned int *tell_them = gohere - master + slaves_goto_here;
+ unsigned int *goto_here = slave_wait - master + move_slaves_here;
+ unsigned int *wait_here = gohere - master + move_slaves_here;
+
+ if (move_slaves_here == slaves_goto_here)
+ return; /* already there */
+
+ wait_slaves_moved(); /* one move at a time */
+
+ printf("moving slave cpus from %p to %p\n\r", slaves_goto_here,
+ move_slaves_here);
+
+ memcpy(move_slaves_here, master, SMP_SLAVE_SIZE);
+ memset(move_slaves_here + (slaves - master), 0,
+ (slaves_end - slaves) * sizeof(slaves_end[0]));
+ *wait_here = 0;
+
+ flush_cache(move_slaves_here, SMP_SLAVE_SIZE);
+
+ check_slave_errors(slaves_were_here);
+
+ *tell_them = (unsigned int)goto_here;
+ slaves_goto_here = move_slaves_here;
+}
+
+/**
+ * move_slaves_up - move slaves from somewhere low to our bss.
+ * Call before decompressing the kernel to address 0.
+ */
+void move_slaves_up(void)
+{
+ move_slaves_here(slaves_run_here);
+}
+
+/**
+ * slaves_are_low - Assert that the slaves are spinning at 0 and move them
+ * Assert that the slaves are running in a copy of the marshall code
+ * that was copied to address 0. Ask them to go up to our bss, as we
+ * know we have to move them away from 0.
+ */
+void slaves_are_low(void)
+{
+ slaves_goto_here = slaves_were_here = (void *)0;
+ move_slaves_up();
+}
+
+void delay_a_bit(int count)
+{
+ while(count--) {
+ HMT_LOW;
+ barrier();
+ }
+ HMT_MEDIUM;
+}
+
+/**
+ * wait_slave_checkout - wait for slaves to execute checkout store.
+ * Wait for every slave who checked in at slaves_were_here to
+ * perform the stb to @checkout before the branch to self spin loop.
+ */
+static void wait_slave_checkout(char *checkout)
+{
+ unsigned int *end = slaves_end - master + slaves_were_here;
+ unsigned int *from = slaves - master + slaves_were_here;;
+ unsigned int bit;
+ int i, ncpus = 0;
+ char *waiting = "waiting on slaves to go to kernel...";
+
+ for (i=0; from < end; from++)
+ for (bit = 1; bit; i++, bit <<= 1)
+ if (*from & bit) {
+ ncpus++;
+ while (!checkout[i]) {
+ if (waiting) {
+ printf(waiting);
+ waiting = NULL;
+ }
+ HMT_LOW;
+ barrier();
+ }
+ }
+
+ if (waiting == NULL)
+ printf("done.\n\r");
+
+ printf("moved %d slaves to the kernel.\n\r", ncpus);
+}
+
+
+/**
+ * checkout_slaves_to_kernel - send SMP slaves to the kernel
+ * Actively move slaves spinning on @tell_them to 0x60. Since we
+ * don't know what code is there, replace it with our one code that
+ * ends with a byte store and branch to self, with the branch at 0x60.
+ * After the stores complete, we can restore the rest of the line,
+ * floush, then restore the remaining line.
+ */
+static void checkout_slaves_to_kernel(unsigned int *tell_them)
+{
+ int to, spin;
+ unsigned int *from, *low, save[SMP_SLAVE_SIZE/sizeof(unsigned int)];
+ char *checkout;
+
+ checkout = malloc(1024);
+ if (checkout == NULL)
+ fatal("can't malloc slave checkout buffer");
+ memset(checkout, 0, 1024);
+
+ low = (unsigned int *)0;
+ memcpy(save, low, SMP_SLAVE_SIZE);
+
+ to = spin = 0x60 / sizeof(int);
+
+ to++;
+ from = slave_checkout_spin;
+ while (from >= slave_checkout_begin)
+ low[--to] = *from--;
+
+ low[0] = (unsigned int)checkout;
+ flush_cache(low, SMP_SLAVE_SIZE);
+
+ *tell_them = (unsigned int)(low + to);
+
+ wait_slave_checkout(checkout);
+
+ /* at this point, all have completed the store at 0x5c and are at
+ * the branch to self at 0x60. Restore the rest of the vector,
+ * flush cache, then do the final store replacing the spin and
+ * flush again.
+ */
+ low[0] = save[0];
+ for (;to < spin; to++)
+ low[to] = save[to];
+ flush_cache(low, SMP_SLAVE_SIZE);
+ low[to] = save[to];
+ flush_cache(low, SMP_SLAVE_SIZE);
+
+ asm volatile ("b 1f ;\
+ .globl slave_checkout_begin ;\
+ .globl slave_checkout_spin ;\
+slave_checkout_begin: ;\
+ lwz 7,0(0) ;\
+ li 8,1 ;\
+ stbx 8,7,3 ;\
+slave_checkout_spin: ;\
+ b $ ;\
+1:");
+
+
+}
+
+/**
+ * send_slaves_to_kernel - send SMP slaves to the kernel
+ * Send slaves to a new kernel which is uncompressed at address @vmlinux_addr.
+ * Copies the first SMP_SLAVE_SIZE bytes of the image to address 0 and
+ * then tells the slaves to go to 0x60.
+ */
+void send_slaves_to_kernel(void *vmlinux_addr)
+{
+ unsigned int *tell_them = gohere - master + slaves_goto_here;
+
+ if ((unsigned long)slaves_goto_here < SMP_SLAVE_SIZE) {
+ if ((unsigned long)vmlinux_addr < SMP_SLAVE_SIZE)
+ fatal("ERROR: slaves were not marshaled before "
+ "decompressing the kernel to 0!\n");
+ move_slaves_up();
+ send_slaves_to_kernel(vmlinux_addr);
+ return;
+ }
+
+ wait_slaves_moved();
+
+ if (vmlinux_addr) {
+ memcpy((void *)0, vmlinux_addr, SMP_SLAVE_SIZE);
+ flush_cache((void *)0, SMP_SLAVE_SIZE);
+ } else {
+ printf("kernel was decompressed to 0\n\r");
+ }
+ check_slave_errors(slaves_goto_here);
+
+#if 1
+ checkout_slaves_to_kernel(tell_them);
+#else
+ *tell_them = 0x60; /* goto_here */
+
+ /* Since we don't own the new loop, we don't know what acknowledge it
+ * might or might not have. We pause here to in hopes they move away.
+ * If the previous slave location was outside the static kernel size,
+ * then they will probably be ok.
+ */
+ flush_cache(tell_them, 0x4);
+ delay_a_bit(1000000);
+#endif
+}
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-04-09 00:47:06.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-04-09 04:09:38.000000000 -0500
@@ -41,6 +41,7 @@ $(addprefix $(obj)/,$(zlib) main.o): $(a
$(addprefix $(obj)/,$(zlibheader))
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
+ marshal.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c $(zlib)
src-plat := of.c
Index: kernel/arch/powerpc/boot/reg.h
===================================================================
--- kernel.orig/arch/powerpc/boot/reg.h 2007-04-09 00:47:06.000000000 -0500
+++ kernel/arch/powerpc/boot/reg.h 2007-04-09 01:47:13.000000000 -0500
@@ -19,4 +19,9 @@ static inline u32 mfpvr(void)
register void *__stack_pointer asm("r1");
#define get_sp() (__stack_pointer)
+#define HMT_MEDIUM asm volatile("or 2,2,2")
+#define HMT_LOW asm volatile("or 1,1,1")
+#define barrier() asm volatile("":::"memory")
+
+
#endif /* _PPC_BOOT_REG_H */
Index: kernel/arch/powerpc/boot/ops.h
===================================================================
--- kernel.orig/arch/powerpc/boot/ops.h 2007-04-09 00:47:18.000000000 -0500
+++ kernel/arch/powerpc/boot/ops.h 2007-04-09 04:09:38.000000000 -0500
@@ -18,6 +18,7 @@
#define COMMAND_LINE_SIZE 512
#define MAX_PATH_LEN 256
#define MAX_PROP_LEN 256 /* What should this be? */
+#define SMP_SLAVE_SIZE 256 /* Size of SMP slave block, kexec/kernel */
/* Platform specific operations */
struct platform_ops {
@@ -79,7 +80,14 @@ int serial_console_init(void);
int ns16550_console_init(void *devp, struct serial_console_data *scdp);
void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
u32 max_allocs);
-extern void flush_cache(void *, unsigned long);
+void flush_cache(void *, unsigned long);
+
+/* marshal slave cpus around to kernel */
+void move_slaves_up(void);
+void move_slaves_here(void *where);
+void send_slaves_to_kernel(void *vmlinux_addr);
+void slaves_are_low(void);
+void wait_slaves_moved(void);
static inline void *finddevice(const char *name)
{
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/8] bootwrapper: occuppied memory ranges
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (6 preceding siblings ...)
2007-04-11 8:32 ` [PATCH 2/8] bootwrapper: smp support code Milton Miller
@ 2007-04-11 8:32 ` Milton Miller
2007-04-11 8:33 ` [PATCH 4/8] bootwrapper: help for 64 bit cpus Milton Miller
` (4 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
Here is a set of library routines to manage gross memory allocations.
It uses an array in bss to store upto 32 entrys with merging representing
a range of memory below rmo_end (aka end of real mode memory at 0).
To use this code, set rmo_end to the highest address (32 bits) you can
access and wish to manage. Then follow with calls to occupy memory,
followed by calls init_malloc for fine grain allocation.
Also, an optional vmlinux_alloc with hooks into the smp marshaling code.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
Index: kernel/arch/powerpc/boot/memranges.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/memranges.c 2007-04-09 00:53:45.000000000 -0500
@@ -0,0 +1,230 @@
+/*
+ * 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 (C) IBM Corporation 2007
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "flatdevtree.h"
+#include "page.h"
+#include "types.h"
+
+extern char _start[], _end[];
+
+void *rmo_end;
+
+static struct {
+ void *start, *end;
+} ranges[32];
+static int num_ranges;
+
+/**
+ * add_occupied_range - mark a range as occupied
+ * Mark the range from @start to @end as occupied.
+ * Ignore anything above rmo_end.
+ */
+void add_occupied_range(void *start, void *end)
+{
+ int i, j;
+
+ if (start == end)
+ return;
+ if (start > rmo_end)
+ return;
+ if (end > rmo_end)
+ end = rmo_end;
+ if (start > end)
+ fatal("%s: BUG: start %p > end %p\n\r", __FUNCTION__,
+ start, end);
+
+ printf("add %p %p: ", start, end);
+
+ for (i=0; i < num_ranges; i++)
+ if (start <= ranges[i].end)
+ break;
+
+ /* extend and merge any overlapping ranges */
+ if (i < num_ranges && end >= ranges[i].start) {
+ ranges[i].start = min(start, ranges[i].start);
+ for (j=i; j < num_ranges; j++)
+ if (end >= ranges[j].start)
+ end = ranges[j].end;
+ else
+ break;
+ ranges[i].end = end;
+
+ if (j == i + 1) {
+ printf("extending range %d to %p %p\n\r", i,
+ ranges[i].start, ranges[i].end);
+ } else {
+ printf("merged ranges %d to %d now %p %p\n\r", i, j,
+ ranges[i].start, ranges[i].end);
+
+ ++i;
+ memmove(&ranges[i], &ranges[j],
+ (num_ranges - j) * sizeof(ranges[0]));
+ num_ranges -= j-i;
+ }
+ } else {
+ /* insert a new range */
+ if (num_ranges >= ARRAY_SIZE(ranges) - 1)
+ fatal("Too many memory ranges to track\n");
+
+ printf("inserting range %d between %p and %p\n\r",
+ i, i ? ranges[i-1].end : 0,
+ i == num_ranges ? rmo_end : ranges[i].start);
+
+ memmove(&ranges[i+1], &ranges[i],
+ (num_ranges - i) * sizeof(ranges[0]));
+ num_ranges++;
+
+ ranges[i].start = start;
+ ranges[i].end = end;
+ }
+}
+
+/**
+ * add_occupied_range_ulong - mark a range as occupied
+ * Call add_occupied_range_ulong after casting to ulong @start and @end to
+ * void * pointers.
+ */
+void add_occupied_range_ulong(unsigned long start, unsigned long end)
+{
+ add_occupied_range((void *)start, (void *)end);
+}
+
+/**
+ * add_known_ranges - occupy some known regions
+ * call add_occupied_range for the wrapper, loader supplied initrd, and,
+ * if not %NULL, the device tree blob @dt_blob and any reserved memory
+ * ranges therein.
+ */
+void add_known_ranges(struct boot_param_header *dt_blob)
+{
+ unsigned long long rstart, rlen, rend, *rsrv;
+
+ add_occupied_range(_start, _end);
+
+ add_occupied_range_ulong(loader_info.initrd_addr,
+ loader_info.initrd_addr + loader_info.initrd_size);
+
+ if (dt_blob == NULL)
+ return;
+
+ add_occupied_range(dt_blob, (void *)dt_blob + dt_blob->totalsize);
+ /* only support 8-byte reserve map. Only care about < 4G */
+ rsrv = (void *)dt_blob + dt_blob->off_mem_rsvmap;
+ do {
+ rstart = *rsrv++;
+ rlen = *rsrv++;
+ rend = rstart + rlen;
+
+ if (rlen && rstart < UINT_MAX) {
+ if (rend < UINT_MAX)
+ add_occupied_range_ulong(rstart, rend);
+ else
+ add_occupied_range_ulong(rstart, UINT_MAX);
+ }
+ } while (rlen);
+}
+
+/**
+ * ranges_init_malloc - initialize malloc heap in a free memory range.
+ * Call simple_alloc_init using the largest gap between occupied ranges.
+ * Does not consider before the first or after the last range.
+ */
+void ranges_init_malloc(void)
+{
+ int i;
+ unsigned long size = 0;
+ void *heap_start, *heap_end;
+
+ /*
+ * Allow the beginning for the kernel and the end for
+ * other things the platform might want to have reserved.
+ */
+
+ heap_start = NULL; /* avoid gcc warning */
+ for (i=1; i < num_ranges; i++) {
+ unsigned long newsize;
+
+ newsize = ranges[i].start - ranges[i-1].end;
+ if (newsize > size) {
+ size = newsize;
+ heap_start = ranges[i-1].end;
+ }
+ }
+
+ if (size < 4 * 1024 * 1024)
+ fatal("Can't find a sutiable gap (largest 0x%lx)", size);
+
+ printf("putting heap between %p and %p size 0x%lx\n\r", heap_start,
+ heap_start + size, size);
+ heap_end = simple_alloc_init(heap_start, size * 7 / 8,
+ PAGE_SIZE, /* max num alloc */ 4096);
+ if (heap_end > (heap_start + size))
+ fatal("heap alloc overflowed gap (%p)\n\r", heap_end);
+
+ add_occupied_range(heap_start, heap_end);
+}
+
+/**
+ * ranges_vmlinux_alloc - an optonal kernel allocator.
+ * Searches for a location to put the kernel. Ideally at 0, which could
+ * be blocked by a range_add. If not, check if the kernel @size will
+ * overwrite the image, and if so, tack on space for the slaves. Find
+ * space either through malloc() or free space between the occupied
+ * ranges, including after the last range to rmo_end.
+ */
+void *ranges_vmlinux_alloc(unsigned long size)
+{
+ void *addr;
+ int i;
+
+ /* Assume _start to _end is occupied */
+ addr = (void *)0;
+ if (addr + size < ranges[0].start)
+ goto occupy;
+
+ addr = malloc(size);
+ if (addr)
+ goto out;
+
+ for (i=1; i < num_ranges; i++) {
+ if (size < ranges[i].start - ranges[i-1].end)
+ goto occupy_range;
+ }
+ if (size < rmo_end - ranges[i-1].end)
+ goto occupy_range;
+
+ fatal("Unable to find a 0x%lx byte gap for the kernel\n", size);
+
+occupy_range:
+ addr = ranges[i-1].end;
+occupy:
+ add_occupied_range(addr, addr + size);
+out:
+ /*
+ * Assume the kernel will decompress to 0, but don't implicity
+ * create a new gap below the current first range.
+ */
+ if ((unsigned long)ranges[0].end < size)
+ add_occupied_range_ulong(0, size);
+
+ return addr;
+}
Index: kernel/arch/powerpc/boot/ops.h
===================================================================
--- kernel.orig/arch/powerpc/boot/ops.h 2007-04-09 00:49:01.000000000 -0500
+++ kernel/arch/powerpc/boot/ops.h 2007-04-09 00:53:59.000000000 -0500
@@ -20,6 +20,8 @@
#define MAX_PROP_LEN 256 /* What should this be? */
#define SMP_SLAVE_SIZE 256 /* Size of SMP slave block, kexec/kernel */
+struct boot_param_header;
+
/* Platform specific operations */
struct platform_ops {
void (*fixups)(void);
@@ -89,6 +91,14 @@ void send_slaves_to_kernel(void *vmlinux
void slaves_are_low(void);
void wait_slaves_moved(void);
+/* memory ranges */
+extern void *rmo_end;
+void add_occupied_range(void *start, void *end);
+void add_occupied_range_ulong(unsigned long start, unsigned long end);
+void add_known_ranges(struct boot_param_header *dt_blob);
+void ranges_init_malloc(void);
+void *ranges_vmlinux_alloc(unsigned long size);
+
static inline void *finddevice(const char *name)
{
return (dt_ops.finddevice) ? dt_ops.finddevice(name) : NULL;
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-04-09 00:49:01.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-04-09 00:53:45.000000000 -0500
@@ -41,7 +41,7 @@ $(addprefix $(obj)/,$(zlib) main.o): $(a
$(addprefix $(obj)/,$(zlibheader))
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
- marshal.c \
+ marshal.c memranges.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c $(zlib)
src-plat := of.c
Index: kernel/arch/powerpc/boot/types.h
===================================================================
--- kernel.orig/arch/powerpc/boot/types.h 2007-04-09 00:47:05.000000000 -0500
+++ kernel/arch/powerpc/boot/types.h 2007-04-09 00:53:45.000000000 -0500
@@ -1,6 +1,9 @@
#ifndef _TYPES_H_
#define _TYPES_H_
+#define _LIBC_LIMITS_H_ /* don't recurse to system's headers */
+#include <limits.h> /* MAX_UINT, etc */
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef unsigned char u8;
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 4/8] bootwrapper: help for 64 bit cpus
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (7 preceding siblings ...)
2007-04-11 8:32 ` [PATCH 3/8] bootwrapper: occuppied memory ranges Milton Miller
@ 2007-04-11 8:33 ` Milton Miller
2007-04-12 7:43 ` Segher Boessenkool
2007-04-11 8:33 ` [PATCH 5/8] bootwrapper: Add kexec callable zImage wrapper Milton Miller
` (3 subsequent siblings)
12 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
A procedure descriptior for the entry point, and a routine to
clear MSR[SF] if we are running in 64 bit mode via mtmsrd before
calling _zimage_start_lib.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
Index: kernel/arch/powerpc/boot/misc64.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/misc64.S 2007-03-29 03:42:25.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+ * 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 (C) 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ *
+ */
+#include "ppc_asm.h"
+
+
+ .globl _zimage_start_32_64
+_zimage_start_32_64:
+
+ /*
+ * Run code compiled and linked as ELF32 in 32 bit mode.
+ *
+ * Check if the processor is running in 32 bit mode, using
+ * only 32 bit instructions which should be safe on 32 and
+ * 64 bit processors.
+ *
+ * Subtract bottom 32 bits of MSR from full value recording
+ * the result. Since MSR[SF] is in the high word, we will
+ * be not-equal iff in 32 bit mode (MSR[SF] = 0 or 32 bit
+ * processor).
+ */
+ mfmsr r0 /* grab whole msr */
+ rlwinm r8,r0,0,0,31 /* extract bottom word */
+ subf. r8,r8,r0 /* subtract, same? */
+ beq 1f /* yes: we are 32 bit mode */
+
+ /* We are in 64-bit mode. This program must run in 32 bit
+ * mode. Assume we are actually running somewhere in the
+ * low 32 bits of the address space, so we can just turn
+ * off MSR[SF] which is bit 0.
+ */
+ .machine push
+ .machine "ppc64"
+ rldicl r0,r0,0,1
+ sync
+ mtmsrd r0
+ isync
+ .machine pop
+
+1: b _zimage_start_lib
+
+
+ .data
+
+ /* a procedure descriptor used when pretending to be elf64_powerpc */
+ .balign 8
+ .global _zimage_start64
+_zimage_start64:
+ .long 0, _zimage_start /* big endian, supported reloc ppc32 */
+ .quad 0, 0, 0
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-03-29 03:30:20.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-03-29 03:43:17.000000000 -0500
@@ -41,7 +41,7 @@ $(addprefix $(obj)/,$(zlib) main.o): $(a
$(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 misc64.S \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c $(zlib)
src-plat := of.c
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/8] bootwrapper: Add kexec callable zImage wrapper
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (8 preceding siblings ...)
2007-04-11 8:33 ` [PATCH 4/8] bootwrapper: help for 64 bit cpus Milton Miller
@ 2007-04-11 8:33 ` Milton Miller
2007-04-11 8:33 ` [PATCH 6/8] bootwrapper: convert flatdevtree to version 16 Milton Miller
` (2 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
This code creates a 32 bit zImage wrapper for a 32 or 64 bit PowerPC
Linux kernel. This allows you to kexec a zImage (instead of a kernel).
This can reduce the memory needed to reboot, or to provide a common
image for boot and reboot.
It also provides rules to pretend the binary is a 64-bit elf, with
the same calling convention as the 64-bit kernel.
In theory this code should be useable in any envrionment that supplies
a flat device tree to describe the usable memory of the machine.
Limitations:
The memory node off the root with a name starting with "memory" must
contain enough free memory (not in the reserved ranges) in the first
reg range to uncompress the the kenrel with padding.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
Status: Successfully boots from and to a 64 bit kernel when loaded
at 0 and after the kernel _end, when initrds and various other data
reserved are loaded discontigiously above the size of the kernel.
The memory search should be converted to use the address translation
framework and find_node_by_type, although we have a limited malloc
space during the search. That points out the need for a read-only
scan of the tree.
The next patch is needed to call from kexec-tools without supplying
an externally generated flat device tree.
kexec.c is added as a library in the belief that it can be used by
multiple platforms.
I didn't test any serial drivers in this environment. kexec will
clear out the mmu, so relying on initialized translations will fail.
Index: kernel/arch/powerpc/boot/kexec.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/kexec.c 2007-04-10 21:35:03.000000000 -0500
@@ -0,0 +1,255 @@
+/*
+ * 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 (C) IBM Corporation 2007
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ */
+
+#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;
+
+ rc = serial_console_init();
+ if (rc) {
+ /* no console, oh well */
+ }
+}
+
+/* fixme: use find_device_by_type "memory" and xlate_reg */
+static void find_rmo_end(void)
+{
+ unsigned int na, ns, reg[4], *rp;
+ void *devp;
+ int rc;
+
+ devp = finddevice("/");
+ if (!devp)
+ fatal("Ack, device-tree root");
+ rc = getprop(devp, "#address-cells", &na, sizeof(na));
+ if (rc != sizeof(na))
+ fatal("Ack, no #address-cells in root");
+ rc = getprop(devp, "#size-cells", &ns, sizeof(ns));
+ if (rc != sizeof(ns))
+ fatal("Ack, no #size-cells in root");
+ if (!na || !ns || na + ns > ARRAY_SIZE(reg))
+ fatal("#addr-cells or #size-cells unusable");
+ do {
+ devp = finddevice("/memory@0");
+ if (!devp)
+ devp = finddevice("/memory");
+ if (!devp)
+ devp = finddevice("/memory@00000000");
+ if (!devp)
+ devp = finddevice("/memory@0000000000000000");
+ if (!devp)
+ fatal("Ack, can't find memory");
+ rc = getprop(devp, "reg", reg, sizeof(reg));
+ if (rc < (na + ns) * sizeof(int))
+ fatal("Ack, no valid reg property in memory");
+
+ rp = ®[0];
+ while (na--) {
+ if (*rp)
+ continue;
+ rp++;
+ }
+ while (--ns) {
+ if (*rp)
+ continue;
+ rp++;
+ }
+ } while (0);
+
+ rmo_end = (void *)*rp;
+}
+
+static void find_dt_initrd(void)
+{
+ int rc;
+ unsigned long long initrd_start, initrd_end;
+ void *devp;
+
+ devp = finddevice("/chosen");
+ if (! devp) {
+ return;
+ }
+
+ /* The properties had to be 8 bytes until 2.6.22 */
+ rc = getprop(devp, "linux,initrd-start", &initrd_start,
+ sizeof(initrd_start));
+ if (rc < 0)
+ return;
+ if (rc == sizeof(unsigned long)) {
+ unsigned long tmp;
+ memcpy(&tmp, &initrd_start, rc);
+ initrd_start = tmp;
+ } else if (rc != sizeof(initrd_start)) {
+ printf("unexpected length of linux,initrd_start in /chosen!\n\r");
+ return;
+ }
+
+ rc = getprop(devp, "linux,initrd-end", &initrd_end, sizeof(initrd_end));
+ if (rc < 0) {
+ printf("chosen has linux,initrd_start but no linux,initrd_end!\n\r");
+ return;
+ }
+ if (rc == sizeof(unsigned long)) {
+ unsigned long tmp;
+ memcpy(&tmp, &initrd_end, rc);
+ initrd_end = tmp;
+ } else if (rc != sizeof(initrd_end)) {
+ printf("unexpected length of linux,initrd_end in /chosen!\n\r");
+ return;
+ }
+
+ if (!initrd_start)
+ return;
+
+ /* if the initrd is above 4G, its untouchable in 32 bit mode */
+ if (initrd_end <= UINT_MAX && initrd_start < initrd_end) {
+ loader_info.initrd_addr = initrd_start;
+ loader_info.initrd_size = initrd_end - initrd_start;
+ }
+}
+
+/**
+ * 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 early_scan_flat_tree(struct boot_param_header *dt_blob)
+{
+ int rc;
+
+ rc = ft_init(dt_blob, dt_blob->totalsize, 50);
+ if (rc)
+ fatal("couldn't initialize device-tree\n\r");
+
+ find_rmo_end();
+ find_dt_initrd();
+}
+
+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 vmsize)
+{
+ unsigned long size = vmsize;
+ void *addr;
+
+ /*
+ * If we are running where the kernel will decompress itself,
+ * tack some more space onto the allocations and move the slaves
+ * there. This avoids the kernel decompressing before the slaves
+ * catch on that they should move down to 0x60.
+ */
+ if (size > (unsigned long)_start)
+ size += SMP_SLAVE_SIZE;
+
+ addr = ranges_vmlinux_alloc(size);
+
+ if (size > vmsize) {
+ if (addr < (void *)_start) {
+ /*
+ * The kernel will memmove its self down. The extra
+ * space is at the end, make sure it is alligned.
+ * We don't care if the kernel overwrites the first
+ * instruction, that is the master entry point.
+ */
+ vmsize &= ~3UL;
+ move_slaves_here(addr + vmsize);
+ } else {
+ /* nice aligned space at the beginning */
+ move_slaves_here(addr);
+ addr += SMP_SLAVE_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();
+ early_scan_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();
+
+ add_known_ranges(dt_blob);
+ ranges_init_malloc();
+ 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-04-10 21:35:03.000000000 -0500
@@ -0,0 +1,46 @@
+/*
+ * 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 (C) 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ *
+ */
+ /*
+ * 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 platform_init
+platform_init:
+ b kexec_platform_init
+
+
+ .globl _zimage_start_plat
+_zimage_start_plat:
+ b _zimage_start_32_64
Index: kernel/arch/powerpc/boot/wrapper
===================================================================
--- kernel.orig/arch/powerpc/boot/wrapper 2007-04-10 21:28:30.000000000 -0500
+++ kernel/arch/powerpc/boot/wrapper 2007-04-10 21:35:03.000000000 -0500
@@ -133,6 +133,12 @@ pmaccoff)
platformo=$object/of.o
lds=$object/zImage.coff.lds
;;
+kexec)
+ platformo=$object/crt0_kexec.o
+ ;;
+kexec64)
+ platformo="-e _zimage_start64 $object/crt0_kexec.o"
+ ;;
miboot|uboot)
# miboot and U-boot want just the bare bits, not an ELF binary
ext=bin
@@ -216,4 +222,7 @@ pmaccoff)
${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
$object/hack-coff "$ofile"
;;
+kexec64)
+ ${CROSS}objcopy -O elf64-powerpc $ofile
+ ;;
esac
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-04-10 21:34:43.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-04-10 21:35:03.000000000 -0500
@@ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) main.o): $(a
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
marshal.c memranges.c misc64.S \
ns16550.c serial.c simple_alloc.c div64.S util.S \
- gunzip_util.c $(zlib)
+ gunzip_util.c $(zlib) kexec.c
src-plat := of.c
-src-boot := $(src-wlib) $(src-plat) empty.c
+src-plat += crt0_kexec.S
+src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
obj-wlib := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-wlib))))
@@ -122,6 +123,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
@@ -131,6 +135,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
+image-$(CONFIG_KEXEC) += $(kexec-y)
# For 32-bit powermacs, build the COFF and miboot images
# as well as the ELF images.
@@ -138,7 +143,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%, $(image-y))
initrd-y := $(filter-out $(image-y), $(initrd-y))
targets += $(image-y) $(initrd-y)
@@ -172,7 +177,7 @@ install: $(CONFIGURE) $(image-y)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
# anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd
+clean-files += $(image-) $(initrd-) $(kexec-) zImage zImage.initrd
# 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-04-10 21:34:18.000000000 -0500
+++ kernel/arch/powerpc/boot/ops.h 2007-04-10 21:35:03.000000000 -0500
@@ -83,6 +83,7 @@ int ns16550_console_init(void *devp, str
void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
u32 max_allocs);
void flush_cache(void *, unsigned long);
+void kexec_platform_init(struct boot_param_header *dt_blob);
/* marshal slave cpus around to kernel */
void move_slaves_up(void);
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/8] bootwrapper: convert flatdevtree to version 16
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (9 preceding siblings ...)
2007-04-11 8:33 ` [PATCH 5/8] bootwrapper: Add kexec callable zImage wrapper Milton Miller
@ 2007-04-11 8:33 ` Milton Miller
2007-04-11 16:30 ` Scott Wood
2007-04-11 8:34 ` [PATCH 7/8] bootwrapper: rtas support Milton Miller
2007-04-11 8:34 ` [PATCH 8/8] bootwrapper: example sreset marshalling Milton Miller
12 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
kexec-tools still produces a version 2 device tree, while the
libraries in the wrapper only support version 16 and later.
Add a routine to convert a v2 flat device tree to a v16 one inplace
by inserting OF_DT_NOP and chomping full path. Make space for new
headers by moving and then chomping the OF_DT_NOPs.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
Tested on version two and version 3 device-trees. Version 1 code
has not been tested.
Index: kernel/arch/powerpc/boot/flatdevtree_conv.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/flatdevtree_conv.c 2007-04-09 04:10:35.000000000 -0500
@@ -0,0 +1,276 @@
+/*
+ * 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 (C) IBM Corporation 2007
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ */
+#include "flatdevtree.h"
+#include "stdio.h"
+#include "ops.h"
+
+#define MIN_VERSION 2
+#define OUT_VERSION 16
+#define OUT_COMPAT 16
+
+#ifdef NO_CHECK
+static int check_v123_tree(u32 *start, u32 *limit)
+{
+ return 0;
+}
+#else
+/**
+ * check_v123_tree - check integrety of a version 1, 2, or 3 tree
+ * structural checks on device_tree
+ */
+static int check_v123_tree(u32 *start, u32 *limit)
+{
+ u32 len;
+ int depth = 0;
+ u32 *dtp = start;
+
+ while (dtp < limit)
+ switch (*dtp) {
+ case OF_DT_END:
+ if (depth)
+ return -1;
+ return ++dtp - start;
+ case OF_DT_NOP:
+ dtp++;
+ break;
+ case OF_DT_END_NODE:
+ dtp++;
+ depth--;
+ break;
+ case OF_DT_BEGIN_NODE:
+ len = strlen((char *)(++dtp));
+ /* check path is suffix to previous? */
+ dtp += 1 + (len / 4);
+ depth++;
+ break;
+ case OF_DT_PROP:
+ len = dtp[1];
+ dtp += 3;
+ if ((len >= 8) && ((long)dtp & 4))
+ dtp++;
+ dtp += (len + 3) / 4;
+ break;
+ default:
+ return -1;
+ }
+ return -1; /* no OF_DT_END */
+}
+#endif
+
+/**
+ * nop_to_v16
+ * insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 2, or 3.
+ */
+static int nop_to_v16(u32 *dtp)
+{
+ int nops = 0;
+ char *p, *s;
+ int len;
+ u32 *next;
+
+ while (*dtp != OF_DT_END)
+ switch (*dtp) {
+ case OF_DT_BEGIN_NODE:
+ /* v2 & v3 names are full path, v16+ is relative */
+ p = (char *)(++dtp);
+ len = strlen(p);
+ next = dtp + 1 + len / 4;
+
+ for (s = p + len; *s != '/'; s--)
+ if (s == p)
+ fatal("name %s has no '/'", p);
+
+ len -= s++ - p; /* not the slash but the nul */
+ memmove(p, s, len);
+ while (len % 4)
+ p[len++] = '\0';
+ dtp += len / 4;
+ while (dtp != next) {
+ *dtp++ = OF_DT_NOP;
+ nops++;
+ }
+ break;
+ case OF_DT_PROP:
+ /* convert from align_8 to align_4 via prefixing nop */
+ len = dtp[1];
+ if ((len >= 8) && !((long)dtp & 4)) {
+ memmove(dtp+1, dtp, 12);
+ *dtp++ = OF_DT_NOP;
+ nops++;
+ }
+ dtp += 3 + (len + 3)/4;
+ break;
+ default:
+ fatal("%s: unrecognised tag %d at %p\n", __FUNCTION__,
+ *dtp, dtp);
+ case OF_DT_NOP:
+ nops ++;
+ /* fall through */
+ case OF_DT_END_NODE:
+ dtp ++;
+ break;
+ }
+ return nops;
+}
+
+#if MIN_VERSION < 3 || OUT_VERSION > 16
+/**
+ * move_nops_fwd - move nops in a v16 dt_struct to the beginning
+ * @start - device tree starting address
+ * @count - number of %OF_DT_NOP cells to move
+ */
+static void move_nops_fwd(u32 *start, int count)
+{
+ u32 *dtp = start;
+ int len;
+ while (count)
+ switch (*dtp) {
+ case OF_DT_NOP:
+ memmove(start+1,start,(dtp-start) * 4);
+ *start++ = OF_DT_NOP;
+ dtp++;
+ count--;
+ break;
+ case OF_DT_END_NODE:
+ dtp++;
+ break;
+ case OF_DT_BEGIN_NODE:
+ len = strlen((char *)(++dtp));
+ dtp += 1 + len / 4;
+ break;
+ case OF_DT_PROP:
+ len = dtp[1];
+ dtp += 3 + (len + 3) / 4;
+ break;
+ case OF_DT_END:
+ fatal("Not enough nops -- need %d more\n", count);
+ return;
+ default:
+ fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp)
+ }
+}
+#endif
+
+/**
+ * conv_flattree_inplace upgrade the version of a boot_param_header
+ *
+ * converts a v1, 2, 3 device tree (of at least MIN_VERSION)
+ * in place to a v16 one, usable by flatdevtree.c
+ */
+void conv_flattree_inplace(struct boot_param_header *tree)
+{
+ u32 *dtp;
+ u32 need = 0, nops;
+ int slen;
+
+ if (tree->magic != OF_DT_HEADER)
+ fatal("%s: no magic", __FUNCTION__);
+
+ if (tree->last_comp_version > 3)
+ return; /* don't know what to do */
+
+ if (tree->version < MIN_VERSION) {
+ printf("%s: Warning: can't handle version %d tree\n",
+ __FUNCTION__, tree->version);
+ return;
+ }
+
+ if (tree->version < 2)
+ need++; /* boot_cpu_id */
+
+ if (tree->version < 3)
+ need++; /* dt_string_size */
+
+ if (OUT_VERSION > 16)
+ need++; /* dt_struct_size */
+
+ dtp = (void *)tree + tree->off_dt_struct;
+
+ slen = check_v123_tree(dtp, (void *)tree + tree->totalsize);
+ if (slen < 0)
+ fatal("device tree check failed\n");
+
+ nops = nop_to_v16(dtp);
+
+ if (need & 1) /* keep 8 byte alignment of mem reserve */
+ need++;
+
+ if (need > nops)
+ fatal("Didn't find enough space to add new header fields\n\r"
+ "(needed %d found %d tree %p)", need, nops, tree);
+
+ /* ok now compress the dtb struct */
+ move_nops_fwd(dtp, need);
+ dtp += need;
+
+ /*
+ * move mem_rsvmap and dt_strings if they are before dt_struct
+ * onto our nops . Adjust start addresses for the 3 sections.
+ */
+ if ((tree->off_mem_rsvmap < tree->off_dt_struct) ||
+ (tree->off_dt_strings < tree->off_dt_struct)) {
+ int start, end;
+ void *ptr;
+
+ if (tree->off_mem_rsvmap < tree->off_dt_strings)
+ start = tree->off_mem_rsvmap;
+ else
+ start = tree->off_dt_strings;
+
+ end = tree->off_dt_struct;
+ ptr = (void *)tree + start;
+
+ memmove(ptr + 4 * need, ptr, end - start);
+
+ if (tree->off_mem_rsvmap < tree->off_dt_struct)
+ tree->off_mem_rsvmap += 4 * need;
+ if (tree->off_dt_strings < tree->off_dt_struct)
+ tree->off_dt_strings += 4 * need;
+ }
+ tree->off_dt_struct += 4 * need;
+
+ /* ok now we have space to extend the header. */
+ if (tree->version < 2 && MIN_VERSION < 2) {
+ tree->boot_cpuid_phys = 0; /* default, caller can fix */
+ }
+
+ /* calculate size of dt_strings_size */
+ if (tree->version < 3 && MIN_VERSION < 3) {
+ int end = tree->totalsize;
+
+ if (tree->off_dt_strings < tree->off_mem_rsvmap)
+ end = tree->off_mem_rsvmap;
+
+ if ((tree->off_dt_strings < tree->off_dt_struct) &&
+ (end > tree->off_dt_struct))
+ end = tree->off_dt_struct;
+
+ tree->dt_strings_size = end - tree->off_dt_strings;
+ }
+
+#if OUT_VERSION > 16
+ tree->dt_struct_size = 4 * slen;
+#endif
+
+ tree->version = OUT_VERSION;
+ tree->last_comp_version = OUT_COMPAT;
+
+ return;
+}
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-04-09 04:10:34.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-04-09 04:10:35.000000000 -0500
@@ -41,7 +41,7 @@ $(addprefix $(obj)/,$(zlib) main.o): $(a
$(addprefix $(obj)/,$(zlibheader))
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
- marshal.c memranges.c misc64.S \
+ flatdevtree_conv.c marshal.c memranges.c misc64.S \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c $(zlib) kexec.c
src-plat := of.c
Index: kernel/arch/powerpc/boot/ops.h
===================================================================
--- kernel.orig/arch/powerpc/boot/ops.h 2007-04-09 04:10:32.000000000 -0500
+++ kernel/arch/powerpc/boot/ops.h 2007-04-09 04:10:35.000000000 -0500
@@ -76,7 +76,10 @@ struct loader_info {
};
extern struct loader_info loader_info;
+struct boot_param_header;
+
void start(void);
+void conv_flattree_inplace(struct boot_param_header *tree);
int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
int serial_console_init(void);
int ns16550_console_init(void *devp, struct serial_console_data *scdp);
Index: kernel/arch/powerpc/boot/kexec.c
===================================================================
--- kernel.orig/arch/powerpc/boot/kexec.c 2007-04-09 04:10:34.000000000 -0500
+++ kernel/arch/powerpc/boot/kexec.c 2007-04-09 04:10:35.000000000 -0500
@@ -236,6 +236,7 @@ void kexec_platform_init(struct boot_par
move_slaves_up();
setup_initial_heap();
+ conv_flattree_inplace(dt_blob);
early_scan_flat_tree(dt_blob);
/* drivers can malloc and read the tree, but not realloc later
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 7/8] bootwrapper: rtas support
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (10 preceding siblings ...)
2007-04-11 8:33 ` [PATCH 6/8] bootwrapper: convert flatdevtree to version 16 Milton Miller
@ 2007-04-11 8:34 ` Milton Miller
2007-04-11 8:34 ` [PATCH 8/8] bootwrapper: example sreset marshalling Milton Miller
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:34 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
This code provides a console write that calls rtas for the
put-term-char service.
To avoid PIC relocation of the absolute rtas addresses, hide
the actual call in assembly and declare all variables as int.
An instantiated rtas will be protected by a reserve range in
the device tree, so no explicit call to add_occupied_range here.
Signed-off-by: Milton Miller <miltonm@bga.com>
---
I considered making this a client of the serial code, but there are
no hooks to init that layer other than through the stdout property
pointing to a serial type node with a compatable property, which
doesn't match the /rtas node.
Index: kernel/arch/powerpc/boot/rtas.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/rtas.c 2007-04-09 00:56:09.000000000 -0500
@@ -0,0 +1,152 @@
+/*
+ * 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 (C) 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ *
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "flatdevtree.h"
+
+void call_rtas(int args[], int base, int entry);
+
+static void __attribute__((noinline)) use_call_rtas(void)
+{
+ /*
+ * PIC relocation of function pointers happens at call time,
+ * We have an absolute out-of-image address. So tell C they
+ * are just integers, and hide the call as an out-of-file
+ * function.
+ */
+ __asm__ __volatile__(
+ " b 1f \n"
+ " .globl call_rtas\n"
+ " call_rtas: mtctr 5\n"
+ " bctr\n"
+ "1:");
+}
+
+static int rtas_entry;
+static int rtas_base;
+static int rtas_size;
+
+static void find_rtas(void)
+{
+ int rc;
+ void *devp;
+ char *str;
+
+ devp = finddevice("/rtas");
+ if (! devp)
+ return;
+
+ str = "linux,rtas-entry";
+ rc = getprop(devp, str, &rtas_entry, sizeof(rtas_entry));
+ if (rc < 0)
+ return;
+ if (rc != sizeof(rtas_entry))
+ goto fail;
+
+ str = "rtas-size";
+ rc = getprop(devp, str, &rtas_size, sizeof(rtas_size));
+ if (rc < 0)
+ return;
+ if (rc != sizeof(rtas_size))
+ goto fail;
+
+ str = "linux,rtas-base";
+ rc = getprop(devp, str, &rtas_base, sizeof(rtas_base));
+ if (rc < 0) {
+ printf("rtas-size but no linux,rtas-base in /rtas. "
+ "disabling wrapper rtas interface\n\r");
+ rtas_entry = 0;
+ return;
+ }
+
+ if (rc != sizeof(rtas_base))
+ goto fail;
+
+ return;
+
+
+fail:
+ printf("Unexpected length %d of %s property in /rtas.\n\r"
+ "disabling wrapper rtas interface\n\r", rc, str);
+ rtas_entry = 0;
+ return;
+}
+
+static int put_term_char;
+
+static void rtas_put_term_write(char *buf, int len)
+{
+ int i, args[5];
+
+ args[0] = put_term_char;
+ args[1] = 1; /* num inputs */
+ args[2] = 1; /* num outputs */
+
+ for (i=0; i < len; ) {
+ args[3] = buf[i];
+ args[4] = 0;
+
+ call_rtas(args, rtas_base, rtas_entry);
+ if (args[4] == 0) /* SUCCESS */
+ i++;
+ else if (args[4] == -1) /* HARDWARE_ERROR */
+ break;
+ /* else retry */
+ }
+}
+
+int rtas_console_init(void)
+{
+ void *devp;
+ int rc;
+
+
+ devp = finddevice("/rtas");
+ if (!devp)
+ return -1;
+
+ if (!rtas_entry)
+ find_rtas();
+ if (!rtas_entry)
+ return -1;
+
+ rc = getprop(devp, "put-term-char", &put_term_char,
+ sizeof(put_term_char));
+ if (rc == sizeof(put_term_char))
+ console_ops.write = rtas_put_term_write;
+ else
+ put_term_char = -1;
+
+ use_call_rtas();
+
+ return put_term_char == -1 ? -1 : 0;
+}
+
+/* for debug, hard code */
+void use_rtas_console(int entry, int base, int tc)
+{
+ rtas_entry = entry;
+ rtas_base = base;
+ put_term_char = tc;
+ use_call_rtas();
+ console_ops.write = rtas_put_term_write;
+}
Index: kernel/arch/powerpc/boot/ops.h
===================================================================
--- kernel.orig/arch/powerpc/boot/ops.h 2007-04-09 00:55:09.000000000 -0500
+++ kernel/arch/powerpc/boot/ops.h 2007-04-09 00:56:09.000000000 -0500
@@ -87,6 +87,8 @@ void *simple_alloc_init(char *base, u32
u32 max_allocs);
void flush_cache(void *, unsigned long);
void kexec_platform_init(struct boot_param_header *dt_blob);
+int rtas_console_init(void);
+void use_rtas_console(int entry, int base, int tc);
/* marshal slave cpus around to kernel */
void move_slaves_up(void);
Index: kernel/arch/powerpc/boot/kexec.c
===================================================================
--- kernel.orig/arch/powerpc/boot/kexec.c 2007-04-09 00:55:09.000000000 -0500
+++ kernel/arch/powerpc/boot/kexec.c 2007-04-09 00:56:09.000000000 -0500
@@ -33,6 +33,9 @@ static void find_console_from_tree(void)
{
int rc;
+ rc = rtas_console_init();
+ if (!rc)
+ return;
rc = serial_console_init();
if (rc) {
/* no console, oh well */
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-04-09 00:55:09.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-04-09 00:56:09.000000000 -0500
@@ -43,7 +43,7 @@ $(addprefix $(obj)/,$(zlib) main.o): $(a
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
flatdevtree_conv.c marshal.c memranges.c misc64.S \
ns16550.c serial.c simple_alloc.c div64.S util.S \
- gunzip_util.c $(zlib) kexec.c
+ gunzip_util.c $(zlib) kexec.c rtas.c
src-plat := of.c
src-plat += crt0_kexec.S
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 8/8] bootwrapper: example sreset marshalling
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
` (11 preceding siblings ...)
2007-04-11 8:34 ` [PATCH 7/8] bootwrapper: rtas support Milton Miller
@ 2007-04-11 8:34 ` Milton Miller
12 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-11 8:34 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
An example that uses the marshalling code but expects cpus to be
sreset. This reuses the kexec code after finding the device tree
(which is magically available at 31K by whatever means loaded this
code). With the marshalling code is at 0 in the image and
the checks in platform_init, it also works as a kexec target when
left as elf.
---
Status: works with sreset on the tested platform when image data
loaded at 0 and the device tree loaded at 31MB. Works as kexec
called elf image from 64 bit kernel with kexec-supplied device-tree
and initrd. The attached device-tree and initrd cases have not
been tested.
Index: kernel/arch/powerpc/boot/crt0_bml.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/crt0_bml.S 2007-04-09 05:12:35.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006-2007 Milton Miller, IBM Corporation.
+ *
+ * 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 can be either a kexec started image or a sreset initiated
+ * one. kexec-tools purgatory is suppposed to copy from entry
+ * point, but instead copies from image start, so put marshal_low
+ * at address 0.
+ */
+
+ .globl zImage_start
+zImage_start:
+#include "marshal_low.S"
+
+ .org 0x100
+ bl get_cpu_id
+1: mflr 0
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r0,r4,r0
+
+ lis r4,elected_master@ha
+ addi r4,r4,elected_master@l
+ add r4,r4,r0
+2: lwarx r6,r0,r4
+ cmpwi r6,0
+ bge 3f
+ stwcx. r3,r0,r4
+ bne- 2b
+ lwz r6,0(r4)
+
+3: lis r4,cpus_found@ha
+ addi r4,r4,cpus_found@l
+ add r4,r4,r0
+4: lwarx r12,r0,r4
+ addi r12,r12,1
+ stwcx. r12,r0,r4
+ bne- 4b
+
+ cmpw r6,r3
+ bne slave
+
+ mr r4,r0
+ li r5,0
+ b master
+
+
+ .globl _zimage_start_plat
+_zimage_start_plat:
+ b _zimage_start_32_64
+
+ .weak get_cpu_id
+get_cpu_id:
+
+get_pir:
+ mfspr r3,1023 /* SPRN_PIR */
+ blr
+
+ .balign 8
+ .globl elected_master
+elected_master:
+ .long -1
+ .globl cpus_expected
+cpus_expected:
+ .long 8
+ .globl cpus_found
+cpus_found:
+ .long 0
Index: kernel/arch/powerpc/boot/bml.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/bml.c 2007-04-09 04:17:24.000000000 -0500
@@ -0,0 +1,42 @@
+#include "ops.h"
+#include "reg.h"
+#include "flatdevtree.h"
+
+extern struct boot_param_header _dtb_start[], _dtb_end[];
+struct boot_param_header *bml_dt_blob;
+
+extern unsigned int get_cpu_id(void);
+extern unsigned int cpus_found, cpus_expected;
+
+void platform_init(unsigned long boot_cpu_id)
+{
+ if (boot_cpu_id > 1024) {
+ bml_dt_blob = (void *)boot_cpu_id;
+ boot_cpu_id = get_cpu_id();
+ }
+
+ if (!bml_dt_blob)
+ if (_dtb_start != _dtb_end)
+ bml_dt_blob = _dtb_start;
+
+ if (!bml_dt_blob)
+ bml_dt_blob = 31 * 1024 * 1024 + (void *)0;
+
+ if (bml_dt_blob->magic != OF_DT_HEADER)
+ fatal("No device tree at %p\n", bml_dt_blob);
+
+ if (bml_dt_blob->version < 2)
+ conv_flattree_inplace(bml_dt_blob);
+
+ bml_dt_blob->boot_cpuid_phys = boot_cpu_id;
+
+ if (cpus_found && cpus_found < cpus_expected) {
+ HMT_LOW;
+ while (cpus_found < cpus_expected) {
+ barrier();
+ }
+ HMT_MEDIUM;
+ }
+
+ kexec_platform_init(bml_dt_blob);
+}
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile 2007-04-09 04:17:10.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile 2007-04-09 04:17:24.000000000 -0500
@@ -46,6 +46,7 @@ src-wlib := string.S crt0.S stdio.c main
gunzip_util.c $(zlib) kexec.c rtas.c
src-plat := of.c
src-plat += crt0_kexec.S
+src-plat += crt0_bml.S bml.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -124,7 +125,7 @@ quiet_cmd_wrap = WRAP $@
$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
kexec-$(CONFIG_PPC32) += zImage.kexec
-kexec-$(CONFIG_PPC64) += zImage.kexec64
+kexec-$(CONFIG_PPC64) += zImage.kexec64 zImage.bml
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
image-$(CONFIG_PPC_MAPLE) += zImage.pseries
Index: kernel/arch/powerpc/boot/wrapper
===================================================================
--- kernel.orig/arch/powerpc/boot/wrapper 2007-04-09 04:17:10.000000000 -0500
+++ kernel/arch/powerpc/boot/wrapper 2007-04-09 04:17:24.000000000 -0500
@@ -139,6 +139,9 @@ kexec)
kexec64)
platformo="-e _zimage_start64 $object/crt0_kexec.o"
;;
+bml)
+ platformo="$object/crt0_bml.o $object/bml.o"
+ ;;
miboot|uboot)
# miboot and U-boot want just the bare bits, not an ELF binary
ext=bin
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/8] bootwrapper: convert flatdevtree to version 16
2007-04-11 8:33 ` [PATCH 6/8] bootwrapper: convert flatdevtree to version 16 Milton Miller
@ 2007-04-11 16:30 ` Scott Wood
2007-04-12 16:56 ` Milton Miller
0 siblings, 1 reply; 25+ messages in thread
From: Scott Wood @ 2007-04-11 16:30 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
Milton Miller wrote:
> kexec-tools still produces a version 2 device tree, while the
> libraries in the wrapper only support version 16 and later.
>
> Add a routine to convert a v2 flat device tree to a v16 one inplace
> by inserting OF_DT_NOP and chomping full path. Make space for new
> headers by moving and then chomping the OF_DT_NOPs.
Why not fix kexec-tools to generate a version 17 device tree?
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH kexec-tools] ppc64: correct @ha relocation
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: correct @ha relocation Milton Miller
@ 2007-04-12 3:24 ` Simon Horman
2007-04-12 3:57 ` [Fastboot] " Simon Horman
2007-04-12 8:17 ` Mohan Kumar M
1 sibling, 1 reply; 25+ messages in thread
From: Simon Horman @ 2007-04-12 3:24 UTC (permalink / raw)
To: Milton Miller; +Cc: Vivek Goyal, fastboot, linuxppc-dev
On Wed, Apr 11, 2007 at 03:30:00AM -0500, Milton Miller wrote:
>
> The @ha relocation is supposed to account for the @l relocation being
> a signed quantity by adding 1 if the msb of @l is set.
>
> The trick of adding 0x8000 stolen from the linux kernel file
> arch/powerpc/kernel/module_64.c which credits binutils.
This and the following patch seem fine to me.
But I would appreciate a review from someone
a little more ppc savy than I.
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Fastboot] [PATCH kexec-tools] ppc64: correct @ha relocation
2007-04-12 3:24 ` Simon Horman
@ 2007-04-12 3:57 ` Simon Horman
0 siblings, 0 replies; 25+ messages in thread
From: Simon Horman @ 2007-04-12 3:57 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, fastboot
On Thu, Apr 12, 2007 at 12:24:47PM +0900, Simon Horman wrote:
> On Wed, Apr 11, 2007 at 03:30:00AM -0500, Milton Miller wrote:
> >
> > The @ha relocation is supposed to account for the @l relocation being
> > a signed quantity by adding 1 if the msb of @l is set.
> >
> > The trick of adding 0x8000 stolen from the linux kernel file
> > arch/powerpc/kernel/module_64.c which credits binutils.
>
> This and the following patch seem fine to me.
> But I would appreciate a review from someone
> a little more ppc savy than I.
Sorry, I should have been a little clearer.
I was refering to the two kexec-tools patches only.
I'm just getting to the kernel ones.
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] export retained initrd in debugfs
2007-04-11 8:31 ` [PATCH] export retained initrd in debugfs Milton Miller
@ 2007-04-12 6:17 ` Michael Neuling
0 siblings, 0 replies; 25+ messages in thread
From: Michael Neuling @ 2007-04-12 6:17 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, klibc, fastboot
This needs to goto lkml
In message <boot-4-misc-01.miltonm@bga.com> you wrote:
> Export initrd in debugfs when retained.
>
> As a side effect, initrd_start and initrd_end are not cleared when the
> initrd is retained.
>
> After this patch, one can then copy the initrd space from debugfs and
> pass it to kexec as the initrd, or do something else with it (maybe it
> was an initrd not an initramfs).
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> This is a lot more reliable than extracting it via dd from /dev/mem.
>
> Currently debugfs doesn't have a getattr even for blobs, so one has
> to cp elsewhere before using kexec from kexec-tools.
>
> Index: kernel/init/initramfs.c
> ===================================================================
> --- kernel.orig/init/initramfs.c 2007-03-28 00:12:15.000000000 -0500
> +++ kernel/init/initramfs.c 2007-03-28 00:35:56.000000000 -0500
> @@ -6,6 +6,7 @@
> #include <linux/delay.h>
> #include <linux/string.h>
> #include <linux/syscalls.h>
> +#include <linux/debugfs.h>
>
> static __initdata char *message;
> static void __init error(char *x)
> @@ -519,7 +520,7 @@ static void __init free_initrd(void)
> unsigned long crashk_end = (unsigned long)__va(crashk_res.end);
> #endif
> if (do_retain_initrd)
> - goto skip;
> + return;
>
> #ifdef CONFIG_KEXEC
> /*
> @@ -588,3 +589,29 @@ static int __init populate_rootfs(void)
> return 0;
> }
> rootfs_initcall(populate_rootfs);
> +
> +#ifdef CONFIG_BLK_DEV_INITRD
> +static struct debugfs_blob_wrapper initrd_blob;
> +
> +static int __init export_initrd(void)
> +{
> + struct dentry *d;
> + initrd_blob.data = (char *)initrd_start;
> + initrd_blob.size = initrd_end - initrd_start;
> +
> + if (!do_retain_initrd)
> + return 0;
> +
> + if (!initrd_start)
> + return 0;
> +
> + d = debugfs_create_blob("initrd", S_IFREG, NULL, &initrd_blob);
> +
> + if (!d)
> + return 1;
> +
> + return 0;
> +}
> +
> +__initcall(export_initrd);
> +#endif
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 4/8] bootwrapper: help for 64 bit cpus
2007-04-11 8:33 ` [PATCH 4/8] bootwrapper: help for 64 bit cpus Milton Miller
@ 2007-04-12 7:43 ` Segher Boessenkool
2007-04-12 8:49 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 25+ messages in thread
From: Segher Boessenkool @ 2007-04-12 7:43 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
> + /* We are in 64-bit mode. This program must run in 32 bit
> + * mode. Assume we are actually running somewhere in the
> + * low 32 bits of the address space, so we can just turn
> + * off MSR[SF] which is bit 0.
> + */
> + .machine push
> + .machine "ppc64"
> + rldicl r0,r0,0,1
> + sync
> + mtmsrd r0
> + isync
> + .machine pop
I'm not sure this actually works on all CPUs --
aren't you supposed to use rfid for this?
Segher
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/8] boot: more verbose gunzip error message
2007-04-11 8:32 ` [PATCH 1/8] boot: more verbose gunzip error message Milton Miller
@ 2007-04-12 7:46 ` David Gibson
0 siblings, 0 replies; 25+ messages in thread
From: David Gibson @ 2007-04-12 7:46 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras
On Wed, Apr 11, 2007 at 03:32:36AM -0500, Milton Miller wrote:
> Change the error message in gunzip_exactly to be more verbose.
>
> Besides the identifier being unrelated to the current function name,
> the user had no indication if the corruption was near the beginning
> or the end.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
--
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
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH kexec-tools] ppc64: correct @ha relocation
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: correct @ha relocation Milton Miller
2007-04-12 3:24 ` Simon Horman
@ 2007-04-12 8:17 ` Mohan Kumar M
2007-04-13 1:35 ` Simon Horman
1 sibling, 1 reply; 25+ messages in thread
From: Mohan Kumar M @ 2007-04-12 8:17 UTC (permalink / raw)
To: Milton Miller; +Cc: Simon Horman, Vivek Goyal, fastboot, linuxppc-dev
On Wed, Apr 11, 2007 at 03:30:00AM -0500, Milton Miller wrote:
>
> The @ha relocation is supposed to account for the @l relocation being
> a signed quantity by adding 1 if the msb of @l is set.
>
> The trick of adding 0x8000 stolen from the linux kernel file
> arch/powerpc/kernel/module_64.c which credits binutils.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
>
Acked-by: Mohan Kumar M <mohan@in.ibm.com>
Cross checked with PPC64 ELF ABI also.
> ---
> This relocation is used in v2wrap.S to hold and release the slave cpus.
> Without this fix the memory location may be 64k off the initialized variable
> which is checked against 0.
>
>
> --- kexec-tools-testing/kexec/arch/ppc64/kexec-elf-rel-ppc64.c.orig 2007-04-10 22:29:59.000000000 -0500
> +++ kexec-tools-testing/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2007-04-10 22:29:59.000000000 -0500
> @@ -97,7 +97,7 @@ void machine_apply_elf_rel(struct mem_eh
> break;
>
> case R_PPC64_ADDR16_HA:
> - *(uint16_t *)location = ((value>>16) & 0xffff);
> + *(uint16_t *)location = (((value+0x8000)>>16) & 0xffff);
> break;
>
> case R_PPC64_ADDR16_HIGHEST:
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 4/8] bootwrapper: help for 64 bit cpus
2007-04-12 7:43 ` Segher Boessenkool
@ 2007-04-12 8:49 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 25+ messages in thread
From: Benjamin Herrenschmidt @ 2007-04-12 8:49 UTC (permalink / raw)
To: Segher Boessenkool
Cc: linuxppc-dev, Paul Mackerras, Milton Miller, David Gibson
On Thu, 2007-04-12 at 09:43 +0200, Segher Boessenkool wrote:
> > + /* We are in 64-bit mode. This program must run in 32 bit
> > + * mode. Assume we are actually running somewhere in the
> > + * low 32 bits of the address space, so we can just turn
> > + * off MSR[SF] which is bit 0.
> > + */
> > + .machine push
> > + .machine "ppc64"
> > + rldicl r0,r0,0,1
> > + sync
> > + mtmsrd r0
> > + isync
> > + .machine pop
>
> I'm not sure this actually works on all CPUs --
> aren't you supposed to use rfid for this?
Not for 32/64 bits switches afaik... as long as your PC is known to
fit in 32 bits, you don't generate an implicit branch.
Ben.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/8] bootwrapper: convert flatdevtree to version 16
2007-04-11 16:30 ` Scott Wood
@ 2007-04-12 16:56 ` Milton Miller
0 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2007-04-12 16:56 UTC (permalink / raw)
To: Scott Wood; +Cc: ppcdev, Fastboot, David Gibson
On Apr 11, 2007, at 11:30 AM, Scott Wood wrote:
> Milton Miller wrote:
>> kexec-tools still produces a version 2 device tree, while the
>> libraries in the wrapper only support version 16 and later.
>> Add a routine to convert a v2 flat device tree to a v16 one inplace
>> by inserting OF_DT_NOP and chomping full path. Make space for new
>> headers by moving and then chomping the OF_DT_NOPs.
>
> Why not fix kexec-tools to generate a version 17 device tree?
>
Because that would prevent kexec-tools from starting a kernel
between
[PATCH] ppc64: Make early processor spinup based on physical ids
author olof <olof>
Thu, 25 Nov 2004 23:59:21 +0000 (23:59 +0000)
commit e1b47549d1588ccea1fa5726eb430aae4e80f8ed
(linux-bkcvs, 2.6.9 or so) and
[PATCH] flattened device tree changes
author Benjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 9 Aug 2005 08:36:34 +0000 (10:36 +0200)
committer Paul Mackerras <paulus@samba.org>
Mon, 29 Aug 2005 00:53:31 +0000 (10:53 +1000)
commit 34153fa3af45d84f3221d9b67ba2ab7e8a220d28
(2.6.14)
Admittedly they don't all support kexec from them, but they
can be kexeced into. ppc64 kexec support was merged
here:
[PATCH] ppc64: kexec support for ppc64
author R Sharada <sharada@in.ibm.com>
Sat, 25 Jun 2005 21:58:10 +0000 (14:58 -0700)
committer Linus Torvalds <torvalds@ppc970.osdl.org>
Sat, 25 Jun 2005 23:24:51 +0000 (16:24 -0700)
commit fce0d5740322b98b863f9e609f5a9bd4c06703af
(2.6.13)
That, and I didn't want to make changes to the code that
may be replaced with some other library later.
We could move this from kexec_platform_init to crt0_kexec.S
platform_init so it becomes platform dependent if you want
to support them.
Are there embedded firmwares that hove old device trees?
milton
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH kexec-tools] ppc64: use kernels slave loop for purgatory
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: use kernels slave loop for purgatory Milton Miller
@ 2007-04-13 1:34 ` Simon Horman
0 siblings, 0 replies; 25+ messages in thread
From: Simon Horman @ 2007-04-13 1:34 UTC (permalink / raw)
To: Milton Miller; +Cc: Vivek Goyal, fastboot, linuxppc-dev
On Wed, Apr 11, 2007 at 03:30:38AM -0500, Milton Miller wrote:
>
> Purgatory doesn't really care about the SMP cpus. But if we leave them
> behind, they end up getting lost when the kernel overwrites purgatory or
> the previous kernel. The current slave handling in purgatory doesn't
> have any handshaking to make sure the cpus have moved on before leaving.
>
> Instead of moving the slave cpus up to purgatory and then back down to
> the kernel, just copy bytes 4-255 from the kernel and use it as the
> purgatory start / slave hold block.
>
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
Thanks, applied.
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH kexec-tools] ppc64: correct @ha relocation
2007-04-12 8:17 ` Mohan Kumar M
@ 2007-04-13 1:35 ` Simon Horman
0 siblings, 0 replies; 25+ messages in thread
From: Simon Horman @ 2007-04-13 1:35 UTC (permalink / raw)
To: Mohan Kumar M; +Cc: linuxppc-dev, Vivek Goyal, fastboot, Milton Miller
On Thu, Apr 12, 2007 at 01:47:16PM +0530, Mohan Kumar M wrote:
> On Wed, Apr 11, 2007 at 03:30:00AM -0500, Milton Miller wrote:
> >
> > The @ha relocation is supposed to account for the @l relocation being
> > a signed quantity by adding 1 if the msb of @l is set.
> >
> > The trick of adding 0x8000 stolen from the linux kernel file
> > arch/powerpc/kernel/module_64.c which credits binutils.
> >
> > Signed-off-by: Milton Miller <miltonm@bga.com>
> >
> Acked-by: Mohan Kumar M <mohan@in.ibm.com>
>
>
> Cross checked with PPC64 ELF ABI also.
Thanks Milton. Thanks Mohan. I've applied this to kexec-tools-testing.
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2007-04-13 1:38 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-11 8:28 [PATCH 0/3+2+8] powerpc zImage kexec Milton Miller
2007-04-11 8:29 ` [PATCH HACK kexec-tools-testing] malloc corruption hack Milton Miller
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: correct @ha relocation Milton Miller
2007-04-12 3:24 ` Simon Horman
2007-04-12 3:57 ` [Fastboot] " Simon Horman
2007-04-12 8:17 ` Mohan Kumar M
2007-04-13 1:35 ` Simon Horman
2007-04-11 8:30 ` [PATCH kexec-tools] ppc64: use kernels slave loop for purgatory Milton Miller
2007-04-13 1:34 ` Simon Horman
2007-04-11 8:31 ` [PATCH] export retained initrd in debugfs Milton Miller
2007-04-12 6:17 ` Michael Neuling
2007-04-11 8:32 ` [PATCH] kexec: send slaves to new kernel earlier Milton Miller
2007-04-11 8:32 ` [PATCH 1/8] boot: more verbose gunzip error message Milton Miller
2007-04-12 7:46 ` David Gibson
2007-04-11 8:32 ` [PATCH 2/8] bootwrapper: smp support code Milton Miller
2007-04-11 8:32 ` [PATCH 3/8] bootwrapper: occuppied memory ranges Milton Miller
2007-04-11 8:33 ` [PATCH 4/8] bootwrapper: help for 64 bit cpus Milton Miller
2007-04-12 7:43 ` Segher Boessenkool
2007-04-12 8:49 ` Benjamin Herrenschmidt
2007-04-11 8:33 ` [PATCH 5/8] bootwrapper: Add kexec callable zImage wrapper Milton Miller
2007-04-11 8:33 ` [PATCH 6/8] bootwrapper: convert flatdevtree to version 16 Milton Miller
2007-04-11 16:30 ` Scott Wood
2007-04-12 16:56 ` Milton Miller
2007-04-11 8:34 ` [PATCH 7/8] bootwrapper: rtas support Milton Miller
2007-04-11 8:34 ` [PATCH 8/8] bootwrapper: example sreset marshalling Milton Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).