diff --git a/kexec-tools-ppc64-memory-ranges-dynamic.diff b/kexec-tools-ppc64-memory-ranges-dynamic.diff new file mode 100644 index 0000000..220bf79 --- /dev/null +++ b/kexec-tools-ppc64-memory-ranges-dynamic.diff @@ -0,0 +1,187 @@ +From d182ce5434c7b66569118db0ccfe63e5d8a03687 Mon Sep 17 00:00:00 2001 +From: Maxim Uvarov +Date: Wed, 15 Oct 2008 12:46:24 +0400 +Subject: [PATCH] ppc64: kexec memory ranges dynamic allocation + +Do not count max_memory_range for allocation. Increase allocation buffers +when it is needed. This actually allows us to avoid a lot of troubles with +various device-tree files. + +Signed-off-by: Maxim Uvarov +Signed-off-by: Simon Horman + +diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c +index 069a9fc..f60c9ec 100644 +--- a/kexec/arch/ppc64/kexec-ppc64.c ++++ b/kexec/arch/ppc64/kexec-ppc64.c +@@ -96,96 +96,46 @@ err1: + + } + +-static int count_dyn_reconf_memory_ranges(void) ++static int realloc_memory_ranges() + { +- char device_tree[] = "/proc/device-tree/"; +- char fname[128]; +- char buf[32]; +- FILE *file; +- +- strcpy(fname, device_tree); +- strcat(fname, "ibm,dynamic-reconfiguration-memory/ibm,lmb-size"); +- if ((file = fopen(fname, "r")) == NULL) { +- perror(fname); +- return -1; +- } ++ size_t memory_range_len; + +- if (fread(buf, 1, 8, file) < 0) { +- perror(fname); +- fclose(file); +- return -1; +- } +- +- lmb_size = ((uint64_t *)buf)[0]; +- fclose(file); ++ max_memory_ranges++; ++ memory_range_len = sizeof(struct memory_range) * max_memory_ranges; + +- /* Get number of lmbs from ibm,dynamic-memory */ +- strcpy(fname, device_tree); +- strcat(fname, "ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory"); +- if ((file = fopen(fname, "r")) == NULL) { +- perror(fname); +- return -1; +- } +- /* +- * first 4 bytes provide number of entries(lmbs) +- */ +- if (fread(buf, 1, 4, file) < 0) { +- perror(fname); +- fclose(file); +- return -1; +- } +- num_of_lmbs = ((unsigned int *)buf)[0]; +- max_memory_ranges += num_of_lmbs; +- fclose(file); ++ memory_range = (struct memory_range *) realloc(memory_range, memory_range_len); ++ if (!memory_range) ++ goto err; + +- return 0; +-} ++ base_memory_range = (struct memory_range *) realloc(memory_range, memory_range_len); ++ if (!base_memory_range) ++ goto err; + +-/* +- * Count the memory nodes under /proc/device-tree and populate the +- * max_memory_ranges variable. This variable replaces MAX_MEMORY_RANGES +- * macro used earlier. +- */ +-static int count_memory_ranges(void) +-{ +- char device_tree[256] = "/proc/device-tree/"; +- struct dirent *dentry; +- DIR *dir; ++ exclude_range = (struct memory_range *) realloc(exclude_range, memory_range_len); ++ if (!exclude_range) ++ goto err; + +- if ((dir = opendir(device_tree)) == NULL) { +- perror(device_tree); +- return -1; +- } ++ usablemem_rgns.ranges = (struct memory_range *) ++ realloc(usablemem_rgns.ranges, memory_range_len); ++ if (!(usablemem_rgns.ranges)) ++ goto err; + +- while ((dentry = readdir(dir)) != NULL) { +- if (!strncmp(dentry->d_name, +- "ibm,dynamic-reconfiguration-memory", 35)){ +- if (count_dyn_reconf_memory_ranges() != 0) +- return -1; +- continue; +- } ++ return 0; + +- if (strncmp(dentry->d_name, "memory@", 7) && +- strcmp(dentry->d_name, "memory") && +- strncmp(dentry->d_name, "pci@", 4)) +- continue; +- max_memory_ranges++; +- } +- /* need to add extra region for retained initrd */ +- if (reuse_initrd) { +- max_memory_ranges++; +- } ++err: ++ fprintf(stderr, "memory range structure re-allocation failure\n"); ++ return -1; ++} + +- closedir(dir); + +- return 0; +-} + static void add_base_memory_range(uint64_t start, uint64_t end) + { + base_memory_range[nr_memory_ranges].start = start; + base_memory_range[nr_memory_ranges].end = end; + base_memory_range[nr_memory_ranges].type = RANGE_RAM; + nr_memory_ranges++; ++ if (nr_memory_ranges >= max_memory_ranges) ++ realloc_memory_ranges(); + + dbgprintf("%016llx-%016llx : %x\n", + base_memory_range[nr_memory_ranges-1].start, +@@ -300,8 +250,8 @@ static int get_base_ranges(void) + return -1; + } + if (nr_memory_ranges >= max_memory_ranges) { +- fclose(file); +- break; ++ if (realloc_memory_ranges() < 0) ++ break; + } + start = ((uint64_t *)buf)[0]; + end = start + ((uint64_t *)buf)[1]; +@@ -396,6 +346,8 @@ static int get_devtree_details(unsigned long kexec_flags) + exclude_range[i].start = 0x0UL; + exclude_range[i].end = kernel_end; + i++; ++ if (i >= max_memory_ranges) ++ realloc_memory_ranges(); + + if (kexec_flags & KEXEC_ON_CRASH) { + memset(fname, 0, sizeof(fname)); +@@ -470,6 +422,8 @@ static int get_devtree_details(unsigned long kexec_flags) + exclude_range[i].start = htab_base; + exclude_range[i].end = htab_base + htab_size; + i++; ++ if (i >= max_memory_ranges) ++ realloc_memory_ranges(); + + /* reserve the initrd_start and end locations. */ + if (reuse_initrd) { +@@ -545,6 +499,8 @@ static int get_devtree_details(unsigned long kexec_flags) + exclude_range[i].start = rtas_base; + exclude_range[i].end = rtas_base + rtas_size; + i++; ++ if (i >= max_memory_ranges) ++ realloc_memory_ranges(); + if (kexec_flags & KEXEC_ON_CRASH) + add_usable_mem_rgns(rtas_base, rtas_size); + } /* rtas */ +@@ -741,8 +697,9 @@ out: + int get_memory_ranges(struct memory_range **range, int *ranges, + unsigned long kexec_flags) + { +- if (count_memory_ranges()) +- return -1; ++ /* allocate memory_range dynamically */ ++ max_memory_ranges = 1; ++ + if (alloc_memory_ranges()) + return -1; + if (setup_memory_ranges(kexec_flags)) diff --git a/kexec-tools.changes b/kexec-tools.changes index 2707e38..af67072 100644 --- a/kexec-tools.changes +++ b/kexec-tools.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Wed Jan 07 14:30:47 CET 2009 - bwalle@suse.de + +- Allocate memory ranges dynamically on PPC64 (bnc #460752). + ------------------------------------------------------------------- Tue Dec 09 17:10:10 CET 2008 - bwalle@suse.de diff --git a/kexec-tools.spec b/kexec-tools.spec index 6fb78ef..dabd031 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -1,7 +1,7 @@ # # spec file for package kexec-tools (Version 2.0.0) # -# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -29,7 +29,7 @@ PreReq: %insserv_prereq %fillup_prereq AutoReqProv: on Summary: Tools for fast kernel loading Version: 2.0.0 -Release: 48 +Release: 49 Source: %{name}-%{version}.tar.bz2 Source1: kexec-bootloader Source2: kexec-bootloader.8.txt @@ -52,6 +52,7 @@ Patch13: %{name}-xen-static.diff Patch14: %{name}-proc-iomem-xen.diff Patch15: %{name}-parse-iomem-single-warning.diff Patch16: %{name}-exclude-gart.diff +Patch17: %{name}-ppc64-memory-ranges-dynamic.diff Url: http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/ BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: zlib-devel @@ -98,6 +99,7 @@ Authors: %patch14 -p1 %patch15 -p1 %patch16 -p1 +%patch17 -p1 %build %{?suse_update_config -f} @@ -165,6 +167,8 @@ install -m 0755 kexec.init ${RPM_BUILD_ROOT}/etc/init.d/kexec %endif %changelog +* Wed Jan 07 2009 bwalle@suse.de +- Allocate memory ranges dynamically on PPC64 (bnc #460752). * Tue Dec 09 2008 bwalle@suse.de - Exclude GART memory from regions that must be written to the dump file (bnc #457612).