[PATCH 3/3] Use get_memory_ranges() on x86-64.
Bernhard Walle
bwalle at suse.de
Mon Jul 7 10:43:42 EDT 2008
Because the get_memory_ranges() function was the same on i386 and x86_64, and
because that /sys/firmware/memmap interface should also be used for x86_64
without *new* code duplication, that part was moved out in a new file called
kexec-x86-common.c. That file only contains the memory map parsing for both the
"old" /proc/iomem interface and the new /sys/firmware/memmap interface.
That file is now built for i386 and x86_64.
Signed-off-by: Bernhard Walle <bwalle at suse.de>
---
kexec/arch/i386/Makefile | 1 +
kexec/arch/i386/kexec-x86-common.c | 207 ++++++++++++++++++++++++++++++++++++
kexec/arch/i386/kexec-x86.c | 175 ------------------------------
kexec/arch/x86_64/Makefile | 1 +
kexec/arch/x86_64/kexec-x86_64.c | 83 --------------
5 files changed, 209 insertions(+), 258 deletions(-)
create mode 100644 kexec/arch/i386/kexec-x86-common.c
diff --git a/kexec/arch/i386/Makefile b/kexec/arch/i386/Makefile
index f2d9636..d52a2f5 100644
--- a/kexec/arch/i386/Makefile
+++ b/kexec/arch/i386/Makefile
@@ -2,6 +2,7 @@
# kexec i386 (linux booting linux)
#
i386_KEXEC_SRCS = kexec/arch/i386/kexec-x86.c
+i386_KEXEC_SRCS += kexec/arch/i386/kexec-x86-common.c
i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-x86.c
i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-rel-x86.c
i386_KEXEC_SRCS += kexec/arch/i386/kexec-bzImage.c
diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c
new file mode 100644
index 0000000..4533425
--- /dev/null
+++ b/kexec/arch/i386/kexec-x86-common.c
@@ -0,0 +1,207 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm at xmission.com)
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "../../firmware_memmap.h"
+#include "kexec-x86.h"
+
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/**
+ * The old /proc/iomem parsing code.
+ *
+ * @param[out] range pointer that will be set to an array that holds the
+ * memory ranges
+ * @param[out] ranges number of ranges valid in @p range
+ *
+ * @return 0 on success, any other value on failure.
+ */
+static int get_memory_ranges_proc_iomem(struct memory_range **range, int *ranges)
+{
+ const char *iomem= proc_iomem();
+ int memory_ranges = 0;
+ char line[MAX_LINE];
+ FILE *fp;
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ iomem, strerror(errno));
+ return -1;
+ }
+ while(fgets(line, sizeof(line), fp) != 0) {
+ unsigned long long start, end;
+ char *str;
+ int type;
+ int consumed;
+ int count;
+ if (memory_ranges >= MAX_MEMORY_RANGES)
+ break;
+ count = sscanf(line, "%Lx-%Lx : %n",
+ &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+ end = end + 1;
+#if 0
+ printf("%016Lx-%016Lx : %s",
+ start, end, str);
+#endif
+ if (memcmp(str, "System RAM\n", 11) == 0) {
+ type = RANGE_RAM;
+ }
+ else if (memcmp(str, "reserved\n", 9) == 0) {
+ type = RANGE_RESERVED;
+ }
+ else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
+ type = RANGE_ACPI;
+ }
+ else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
+ type = RANGE_ACPI_NVS;
+ }
+ else {
+ continue;
+ }
+ memory_range[memory_ranges].start = start;
+ memory_range[memory_ranges].end = end;
+ memory_range[memory_ranges].type = type;
+#if 0
+ printf("%016Lx-%016Lx : %x\n",
+ start, end, type);
+#endif
+ memory_ranges++;
+ }
+ fclose(fp);
+ *range = memory_range;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+/**
+ * Calls the architecture independent get_firmware_memmap_ranges() to parse
+ * /sys/firmware/memmap and then do some x86 only modifications.
+ *
+ * @param[out] range pointer that will be set to an array that holds the
+ * memory ranges
+ * @param[out] ranges number of ranges valid in @p range
+ *
+ * @return 0 on success, any other value on failure.
+ */
+static int get_memory_ranges_sysfs(struct memory_range **range, int *ranges)
+{
+ int ret;
+ size_t range_number = MAX_MEMORY_RANGES;
+
+ ret = get_firmware_memmap_ranges(memory_range, &range_number);
+ if (ret != 0) {
+ fprintf(stderr, "Parsing the /sys/firmware memory map failed. "
+ "Falling back to /proc/iomem.\n");
+ return get_memory_ranges_proc_iomem(range, ranges);
+ }
+
+ *range = memory_range;
+ *ranges = range_number;
+
+ return 0;
+}
+
+/**
+ * Return a sorted list of memory ranges.
+ *
+ * If we have the /sys/firmware/memmap interface, then use that. If not,
+ * or if parsing of that fails, use /proc/iomem as fallback.
+ *
+ * @param[out] range pointer that will be set to an array that holds the
+ * memory ranges
+ * @param[out] ranges number of ranges valid in @p range
+ * @param[in] kexec_flags the kexec_flags to determine if we load a normal
+ * or a crashdump kernel
+ *
+ * @return 0 on success, any other value on failure.
+ */
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
+{
+ int ret, i;
+
+ if (have_sys_firmware_memmap())
+ ret = get_memory_ranges_sysfs(range, ranges);
+ else
+ ret = get_memory_ranges_proc_iomem(range, ranges);
+
+ /*
+ * both get_memory_ranges_sysfs() and get_memory_ranges_proc_iomem()
+ * have already printed an error message, so fail silently here
+ */
+ if (ret != 0)
+ return ret;
+
+ /* Don't report the interrupt table as ram */
+ for (i = 0; i < *ranges; i++) {
+ if ((*range)[i].type == RANGE_RAM &&
+ ((*range)[i].start < 0x100)) {
+ (*range)[i].start = 0x100;
+ break;
+ }
+ }
+
+ /*
+ * Redefine the memory region boundaries if kernel
+ * exports the limits and if it is panic kernel.
+ * Override user values only if kernel exported values are
+ * subset of user defined values.
+ */
+ if (kexec_flags & KEXEC_ON_CRASH) {
+ unsigned long long start, end;
+
+ ret = parse_iomem_single("Crash kernel\n", &start, &end);
+ if (ret != 0) {
+ fprintf(stderr, "parse_iomem_single failed.\n");
+ return -1;
+ }
+
+ if (start > mem_min)
+ mem_min = start;
+ if (end < mem_max)
+ mem_max = end;
+ }
+
+ /* just set 0 to 1 to enable printing for debugging */
+#if 0
+ {
+ int i;
+ printf("MEMORY RANGES\n");
+ for (i = 0; i < *ranges; i++) {
+ printf("%016Lx-%016Lx (%d)\n", (*range)[i].start,
+ (*range)[i].end, (*range)[i].type);
+ }
+ }
+#endif
+
+ return ret;
+}
+
+
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
index d5b6737..d33a14b 100644
--- a/kexec/arch/i386/kexec-x86.c
+++ b/kexec/arch/i386/kexec-x86.c
@@ -33,181 +33,6 @@
#include "crashdump-x86.h"
#include <arch/options.h>
-static struct memory_range memory_range[MAX_MEMORY_RANGES];
-
-/**
- * The old /proc/iomem parsing code.
- *
- * @param[out] range pointer that will be set to an array that holds the
- * memory ranges
- * @param[out] ranges number of ranges valid in @p range
- *
- * @return 0 on success, any other value on failure.
- */
-static int get_memory_ranges_proc_iomem(struct memory_range **range, int *ranges)
-{
- const char *iomem= proc_iomem();
- int memory_ranges = 0;
- char line[MAX_LINE];
- FILE *fp;
- fp = fopen(iomem, "r");
- if (!fp) {
- fprintf(stderr, "Cannot open %s: %s\n",
- iomem, strerror(errno));
- return -1;
- }
- while(fgets(line, sizeof(line), fp) != 0) {
- unsigned long long start, end;
- char *str;
- int type;
- int consumed;
- int count;
- if (memory_ranges >= MAX_MEMORY_RANGES)
- break;
- count = sscanf(line, "%Lx-%Lx : %n",
- &start, &end, &consumed);
- if (count != 2)
- continue;
- str = line + consumed;
- end = end + 1;
-#if 0
- printf("%016Lx-%016Lx : %s",
- start, end, str);
-#endif
- if (memcmp(str, "System RAM\n", 11) == 0) {
- type = RANGE_RAM;
- }
- else if (memcmp(str, "reserved\n", 9) == 0) {
- type = RANGE_RESERVED;
- }
- else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
- type = RANGE_ACPI;
- }
- else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
- type = RANGE_ACPI_NVS;
- }
- else {
- continue;
- }
- memory_range[memory_ranges].start = start;
- memory_range[memory_ranges].end = end;
- memory_range[memory_ranges].type = type;
-#if 0
- printf("%016Lx-%016Lx : %x\n",
- start, end, type);
-#endif
- memory_ranges++;
- }
- fclose(fp);
- *range = memory_range;
- *ranges = memory_ranges;
- return 0;
-}
-
-/**
- * Calls the architecture independent get_firmware_memmap_ranges() to parse
- * /sys/firmware/memmap and then do some x86 only modifications.
- *
- * @param[out] range pointer that will be set to an array that holds the
- * memory ranges
- * @param[out] ranges number of ranges valid in @p range
- *
- * @return 0 on success, any other value on failure.
- */
-static int get_memory_ranges_sysfs(struct memory_range **range, int *ranges)
-{
- int ret;
- size_t range_number = MAX_MEMORY_RANGES;
-
- ret = get_firmware_memmap_ranges(memory_range, &range_number);
- if (ret != 0) {
- fprintf(stderr, "Parsing the /sys/firmware memory map failed. "
- "Falling back to /proc/iomem.\n");
- return get_memory_ranges_proc_iomem(range, ranges);
- }
-
- *range = memory_range;
- *ranges = range_number;
-
- return 0;
-}
-
-/**
- * Return a sorted list of memory ranges.
- *
- * If we have the /sys/firmware/memmap interface, then use that. If not,
- * or if parsing of that fails, use /proc/iomem as fallback.
- *
- * @param[out] range pointer that will be set to an array that holds the
- * memory ranges
- * @param[out] ranges number of ranges valid in @p range
- * @param[in] kexec_flags the kexec_flags to determine if we load a normal
- * or a crashdump kernel
- *
- * @return 0 on success, any other value on failure.
- */
-int get_memory_ranges(struct memory_range **range, int *ranges,
- unsigned long kexec_flags)
-{
- int ret, i;
-
- if (have_sys_firmware_memmap())
- ret = get_memory_ranges_sysfs(range, ranges);
- else
- ret = get_memory_ranges_proc_iomem(range, ranges);
-
- /*
- * both get_memory_ranges_sysfs() and get_memory_ranges_proc_iomem()
- * have already printed an error message, so fail silently here
- */
- if (ret != 0)
- return ret;
-
- /* Don't report the interrupt table as ram */
- for (i = 0; i < *ranges; i++) {
- if ((*range)[i].type == RANGE_RAM &&
- ((*range)[i].start < 0x100)) {
- (*range)[i].start = 0x100;
- break;
- }
- }
-
- /*
- * Redefine the memory region boundaries if kernel
- * exports the limits and if it is panic kernel.
- * Override user values only if kernel exported values are
- * subset of user defined values.
- */
- if (kexec_flags & KEXEC_ON_CRASH) {
- unsigned long long start, end;
-
- ret = parse_iomem_single("Crash kernel\n", &start, &end);
- if (ret != 0) {
- fprintf(stderr, "parse_iomem_single failed.\n");
- return -1;
- }
-
- if (start > mem_min)
- mem_min = start;
- if (end < mem_max)
- mem_max = end;
- }
-
- /* just set 0 to 1 to enable printing for debugging */
-#if 0
- {
- int i;
- printf("MEMORY RANGES\n");
- for (i = 0; i < *ranges; i++) {
- printf("%016Lx-%016Lx (%d)\n", (*range)[i].start,
- (*range)[i].end, (*range)[i].type);
- }
- }
-#endif
-
- return ret;
-}
-
struct file_type file_type[] = {
{ "multiboot-x86", multiboot_x86_probe, multiboot_x86_load,
multiboot_x86_usage },
diff --git a/kexec/arch/x86_64/Makefile b/kexec/arch/x86_64/Makefile
index c59c41f..7ca3e7e 100644
--- a/kexec/arch/x86_64/Makefile
+++ b/kexec/arch/x86_64/Makefile
@@ -7,6 +7,7 @@ x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-multiboot-x86.c
x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-beoboot-x86.c
x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-nbi.c
x86_64_KEXEC_SRCS += kexec/arch/i386/x86-linux-setup.c
+x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-x86-common.c
x86_64_KEXEC_SRCS += kexec/arch/x86_64/crashdump-x86_64.c
x86_64_KEXEC_SRCS += kexec/arch/x86_64/kexec-x86_64.c
x86_64_KEXEC_SRCS += kexec/arch/x86_64/kexec-elf-x86_64.c
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
index d0b3e90..9973815 100644
--- a/kexec/arch/x86_64/kexec-x86_64.c
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -32,89 +32,6 @@
#include "crashdump-x86_64.h"
#include <arch/options.h>
-#define MAX_MEMORY_RANGES 64
-static struct memory_range memory_range[MAX_MEMORY_RANGES];
-
-/* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges,
- unsigned long kexec_flags)
-{
- const char *iomem= proc_iomem();
- int memory_ranges = 0;
- char line[MAX_LINE];
- FILE *fp;
- fp = fopen(iomem, "r");
- if (!fp) {
- fprintf(stderr, "Cannot open %s: %s\n",
- iomem, strerror(errno));
- return -1;
- }
- while(fgets(line, sizeof(line), fp) != 0) {
- unsigned long long start, end;
- char *str;
- int type;
- int consumed;
- int count;
- if (memory_ranges >= MAX_MEMORY_RANGES)
- break;
- count = sscanf(line, "%Lx-%Lx : %n",
- &start, &end, &consumed);
- if (count != 2)
- continue;
- str = line + consumed;
- end = end + 1;
-#ifdef DEBUG
- printf("%016Lx-%016Lx : %s",
- start, end, str);
-#endif
- if (memcmp(str, "System RAM\n", 11) == 0) {
- type = RANGE_RAM;
- }
- else if (memcmp(str, "reserved\n", 9) == 0) {
- type = RANGE_RESERVED;
- }
- else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
- type = RANGE_ACPI;
- }
- else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
- type = RANGE_ACPI_NVS;
- }
- else if (memcmp(str, "Crash kernel\n", 13) == 0) {
- /* Redefine the memory region boundaries if kernel
- * exports the limits and if it is panic kernel.
- * Override user values only if kernel exported
- * values are subset of user defined values.
- */
- if (kexec_flags & KEXEC_ON_CRASH) {
- if (start > mem_min)
- mem_min = start;
- if (end < mem_max)
- mem_max = end;
- }
- continue;
- }
- else {
- continue;
- }
- /* Don't report the interrupt table as ram */
- if (type == RANGE_RAM && (start < 0x100)) {
- start = 0x100;
- }
- memory_range[memory_ranges].start = start;
- memory_range[memory_ranges].end = end;
- memory_range[memory_ranges].type = type;
-#ifdef DEBUG
- printf("%016Lx-%016Lx : %x\n",
- start, end, type);
-#endif
- memory_ranges++;
- }
- fclose(fp);
- *range = memory_range;
- *ranges = memory_ranges;
- return 0;
-}
-
struct file_type file_type[] = {
{ "elf-x86_64", elf_x86_64_probe, elf_x86_64_load, elf_x86_64_usage },
{ "multiboot-x86", multiboot_x86_probe, multiboot_x86_load,
--
1.5.6
More information about the kexec
mailing list