From patchwork Wed Oct 22 20:39:17 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milton Miller X-Patchwork-Id: 5379 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id C3A4C476E3 for ; Thu, 23 Oct 2008 07:43:50 +1100 (EST) X-Original-To: linuxppc-dev@ozlabs.org Delivered-To: linuxppc-dev@ozlabs.org Received: from sullivan.realtime.net (sullivan.realtime.net [205.238.132.226]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3DD8E474CF for ; Thu, 23 Oct 2008 07:39:33 +1100 (EST) Received: from sullivan.realtime.net (localhost [127.0.0.1]) by sullivan.realtime.net (8.13.1/8.9.3) with ESMTP id m9MKdIFw020555; Wed, 22 Oct 2008 15:39:18 -0500 (CDT) (envelope-from miltonm@sullivan.realtime.net) Received: (from miltonm@localhost) by sullivan.realtime.net (8.13.1/8.12.7/Submit) id m9MKdHXj020551; Wed, 22 Oct 2008 15:39:17 -0500 (CDT) Date: Wed, 22 Oct 2008 15:39:17 -0500 (CDT) From: Milton Miller To: Simon Horman Subject: [PATCH 2/2 kexec-tools] ppc64: segemments are sorted Message-id: In-Reply-To: Cc: linuxppc-dev@ozlabs.org, Simon Horman , kexec@lists.infradead.org, Paul Mackerras X-BeenThere: linuxppc-dev@ozlabs.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org Every time add_segment is called, the segments are sorted. If the first hole in memory is not big enough for the kernel then something besides the kernel may be at Signed-off-by: Milton Miller --- Found during custom environment testing with several reserved blocks of memory, not the usual case. Index: kexec-tools/kexec/arch/ppc64/kexec-elf-ppc64.c =================================================================== --- kexec-tools.orig/kexec/arch/ppc64/kexec-elf-ppc64.c 2008-10-22 06:14:48.000000000 -0500 +++ kexec-tools/kexec/arch/ppc64/kexec-elf-ppc64.c 2008-10-22 06:14:54.000000000 -0500 @@ -86,7 +86,7 @@ int elf_ppc64_load(int argc, char **argv size_t size; uint64_t *rsvmap_ptr; struct bootblock *bb_ptr; - unsigned int nr_segments, i; + unsigned int i; int result, opt; uint64_t my_kernel, my_dt_offset; unsigned int my_panic_kernel; @@ -187,7 +187,7 @@ int elf_ppc64_load(int argc, char **argv if (size > phdr->p_memsz) size = phdr->p_memsz; - hole_addr = (uint64_t)locate_hole(info, size, 0, 0, + my_kernel = hole_addr = (uint64_t)locate_hole(info, size, 0, 0, max_addr, 1); ehdr.e_phdr[0].p_paddr = hole_addr; result = elf_exec_load(&ehdr, info); @@ -233,12 +233,10 @@ int elf_ppc64_load(int argc, char **argv return -1; } seg_buf = (unsigned char *)slurp_file(ramdisk, &seg_size); - add_buffer(info, seg_buf, seg_size, seg_size, 0, 0, max_addr, 1); - hole_addr = (uintptr_t) - info->segment[info->nr_segments-1].mem; + hole_addr = add_buffer(info, seg_buf, seg_size, seg_size, + 0, 0, max_addr, 1); initrd_base = hole_addr; - initrd_size = (uint64_t) - info->segment[info->nr_segments-1].memsz; + initrd_size = seg_size; } /* ramdisk */ if (devicetreeblob) { @@ -248,16 +246,18 @@ int elf_ppc64_load(int argc, char **argv /* Grab device tree from buffer */ blob_buf = (unsigned char *)slurp_file(devicetreeblob, &blob_size); - add_buffer(info, blob_buf, blob_size, blob_size, 0, 0, - max_addr, -1); + my_dt_offset = add_buffer(info, blob_buf, blob_size, blob_size, + 0, 0, max_addr, -1); + seg_buf = blob_buf; + seg_size = blob_size; } else { /* create from fs2dt */ seg_buf = NULL; seg_size = 0; create_flatten_tree(info, (unsigned char **)&seg_buf, (unsigned long *)&seg_size,cmdline); - add_buffer(info, seg_buf, seg_size, seg_size, + my_dt_offset = add_buffer(info, seg_buf, seg_size, seg_size, 0, 0, max_addr, -1); } @@ -265,27 +265,20 @@ int elf_ppc64_load(int argc, char **argv * find last entry (both 0) in the reserve mem list. Assume DT * entry is before this one */ - bb_ptr = (struct bootblock *)( - (unsigned char *)info->segment[(info->nr_segments)-1].buf); - rsvmap_ptr = (uint64_t *)( - (unsigned char *)info->segment[(info->nr_segments)-1].buf + - bb_ptr->off_mem_rsvmap); + bb_ptr = (struct bootblock *)(seg_buf); + rsvmap_ptr = (uint64_t *) + (((char *)seg_buf) + bb_ptr->off_mem_rsvmap); while (*rsvmap_ptr || *(rsvmap_ptr+1)) rsvmap_ptr += 2; rsvmap_ptr -= 2; - *rsvmap_ptr = (uintptr_t)( - info->segment[(info->nr_segments)-1].mem); + *rsvmap_ptr = my_dt_offset; rsvmap_ptr++; *rsvmap_ptr = (uint64_t)bb_ptr->totalsize; - nr_segments = info->nr_segments; - /* Set kernel */ - my_kernel = (uintptr_t)info->segment[0].mem; elf_rel_set_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel)); /* Set dt_offset */ - my_dt_offset = (uintptr_t)info->segment[nr_segments-1].mem; elf_rel_set_symbol(&info->rhdr, "dt_offset", &my_dt_offset, sizeof(my_dt_offset)); @@ -293,7 +286,7 @@ int elf_ppc64_load(int argc, char **argv 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)); + memcpy(slave_code, phdr->p_data, sizeof(slave_code)); slave_code[0] = master_entry; elf_rel_set_symbol(&info->rhdr, "purgatory_start", slave_code, sizeof(slave_code)); @@ -366,7 +359,7 @@ int elf_ppc64_load(int argc, char **argv fprintf(stderr, "purgatory size is %zu\n", purgatory_size); #endif - for (i = 0; i < nr_segments; i++) + for (i = 0; i < info->nr_segments; i++) fprintf(stderr, "segment[%d].mem:%p memsz:%zu\n", i, info->segment[i].mem, info->segment[i].memsz);