!12 fix issue about iomem file that contains too many contens. As a result , the kdump service failed
From: @zhangruifang2020 Reviewed-by: @xiezhipeng1 Signed-off-by: @xiezhipeng1
This commit is contained in:
commit
45b5f4492f
@ -0,0 +1,244 @@
|
|||||||
|
From f736104f533290b4ce6fbfbca74abde9ffd3888c Mon Sep 17 00:00:00 2001
|
||||||
|
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
||||||
|
Date: Wed, 18 Dec 2019 11:42:31 -0500
|
||||||
|
Subject: [PATCH] arm64: kexec: allocate memory space avoiding reserved regions
|
||||||
|
|
||||||
|
On UEFI/ACPI-only system, some memory regions, including but not limited
|
||||||
|
to UEFI memory map and ACPI tables, must be preserved across kexec'ing.
|
||||||
|
Otherwise, they can be corrupted and result in early failure in booting
|
||||||
|
a new kernel.
|
||||||
|
|
||||||
|
In recent kernels, /proc/iomem now has an extended file format like:
|
||||||
|
|
||||||
|
40000000-5871ffff : System RAM
|
||||||
|
41800000-426affff : Kernel code
|
||||||
|
426b0000-42aaffff : reserved
|
||||||
|
42ab0000-42c64fff : Kernel data
|
||||||
|
54400000-583fffff : Crash kernel
|
||||||
|
58590000-585effff : reserved
|
||||||
|
58700000-5871ffff : reserved
|
||||||
|
58720000-58b5ffff : reserved
|
||||||
|
58b60000-5be3ffff : System RAM
|
||||||
|
58b61000-58b61fff : reserved
|
||||||
|
|
||||||
|
where the "reserved" entries at the top level or under System RAM (and
|
||||||
|
its descendant resources) are ones of such kind and should not be regarded
|
||||||
|
as usable memory ranges where several free spaces for loading kexec data
|
||||||
|
will be allocated.
|
||||||
|
|
||||||
|
With this patch, get_memory_ranges() will handle this format of file
|
||||||
|
correctly. Note that, for safety, unknown regions, in addition to
|
||||||
|
"reserved" ones, will also be excluded.
|
||||||
|
|
||||||
|
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
||||||
|
Tested-by: Bhupesh Sharma <bhsharma@redhat.com>
|
||||||
|
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
|
||||||
|
Signed-off-by: Simon Horman <horms@verge.net.au>
|
||||||
|
---
|
||||||
|
kexec/arch/arm64/kexec-arm64.c | 153 ++++++++++++++++++++-------------
|
||||||
|
1 file changed, 94 insertions(+), 59 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
|
||||||
|
index 6ad3b0a..45ebc54 100644
|
||||||
|
--- a/kexec/arch/arm64/kexec-arm64.c
|
||||||
|
+++ b/kexec/arch/arm64/kexec-arm64.c
|
||||||
|
@@ -10,7 +10,9 @@
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <libfdt.h>
|
||||||
|
#include <limits.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <linux/elf-em.h>
|
||||||
|
#include <elf.h>
|
||||||
|
@@ -29,6 +31,7 @@
|
||||||
|
#include "fs2dt.h"
|
||||||
|
#include "iomem.h"
|
||||||
|
#include "kexec-syscall.h"
|
||||||
|
+#include "mem_regions.h"
|
||||||
|
#include "arch/options.h"
|
||||||
|
|
||||||
|
#define ROOT_NODE_ADDR_CELLS_DEFAULT 1
|
||||||
|
@@ -905,19 +908,33 @@ int get_phys_base_from_pt_load(unsigned long *phys_offset)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool to_be_excluded(char *str)
|
||||||
|
+{
|
||||||
|
+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) ||
|
||||||
|
+ !strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) ||
|
||||||
|
+ !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) ||
|
||||||
|
+ !strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)))
|
||||||
|
+ return false;
|
||||||
|
+ else
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
- * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem.
|
||||||
|
+ * get_memory_ranges - Try to get the memory ranges from
|
||||||
|
+ * /proc/iomem.
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
-static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
|
||||||
|
- unsigned long long base, unsigned long long length)
|
||||||
|
+int get_memory_ranges(struct memory_range **range, int *ranges,
|
||||||
|
+ unsigned long kexec_flags)
|
||||||
|
{
|
||||||
|
- int ret;
|
||||||
|
unsigned long phys_offset = UINT64_MAX;
|
||||||
|
- struct memory_range *r;
|
||||||
|
-
|
||||||
|
- if (nr >= KEXEC_SEGMENT_MAX)
|
||||||
|
- return -1;
|
||||||
|
+ FILE *fp;
|
||||||
|
+ const char *iomem = proc_iomem();
|
||||||
|
+ char line[MAX_LINE], *str;
|
||||||
|
+ unsigned long long start, end;
|
||||||
|
+ int n, consumed;
|
||||||
|
+ struct memory_ranges memranges;
|
||||||
|
+ struct memory_range *last, excl_range;
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
if (!try_read_phys_offset_from_kcore) {
|
||||||
|
/* Since kernel version 4.19, 'kcore' contains
|
||||||
|
@@ -951,17 +968,72 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
|
||||||
|
try_read_phys_offset_from_kcore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- r = (struct memory_range *)data + nr;
|
||||||
|
+ fp = fopen(iomem, "r");
|
||||||
|
+ if (!fp)
|
||||||
|
+ die("Cannot open %s\n", iomem);
|
||||||
|
+
|
||||||
|
+ memranges.ranges = NULL;
|
||||||
|
+ memranges.size = memranges.max_size = 0;
|
||||||
|
+
|
||||||
|
+ while (fgets(line, sizeof(line), fp) != 0) {
|
||||||
|
+ n = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed);
|
||||||
|
+ if (n != 2)
|
||||||
|
+ continue;
|
||||||
|
+ str = line + consumed;
|
||||||
|
+
|
||||||
|
+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) {
|
||||||
|
+ ret = mem_regions_alloc_and_add(&memranges,
|
||||||
|
+ start, end - start + 1, RANGE_RAM);
|
||||||
|
+ if (ret) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "Cannot allocate memory for ranges\n");
|
||||||
|
+ fclose(fp);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)))
|
||||||
|
- r->type = RANGE_RAM;
|
||||||
|
- else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED)))
|
||||||
|
- r->type = RANGE_RESERVED;
|
||||||
|
- else
|
||||||
|
- return 1;
|
||||||
|
+ dbgprintf("%s:+[%d] %016llx - %016llx\n", __func__,
|
||||||
|
+ memranges.size - 1,
|
||||||
|
+ memranges.ranges[memranges.size - 1].start,
|
||||||
|
+ memranges.ranges[memranges.size - 1].end);
|
||||||
|
+ } else if (to_be_excluded(str)) {
|
||||||
|
+ if (!memranges.size)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Note: mem_regions_exclude() doesn't guarantee
|
||||||
|
+ * that the ranges are sorted out, but as long as
|
||||||
|
+ * we cope with /proc/iomem, we only operate on
|
||||||
|
+ * the last entry and so it is safe.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
- r->start = base;
|
||||||
|
- r->end = base + length - 1;
|
||||||
|
+ /* The last System RAM range */
|
||||||
|
+ last = &memranges.ranges[memranges.size - 1];
|
||||||
|
+
|
||||||
|
+ if (last->end < start)
|
||||||
|
+ /* New resource outside of System RAM */
|
||||||
|
+ continue;
|
||||||
|
+ if (end < last->start)
|
||||||
|
+ /* Already excluded by parent resource */
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ excl_range.start = start;
|
||||||
|
+ excl_range.end = end;
|
||||||
|
+ ret = mem_regions_alloc_and_exclude(&memranges, &excl_range);
|
||||||
|
+ if (ret) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "Cannot allocate memory for ranges (exclude)\n");
|
||||||
|
+ fclose(fp);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
+ dbgprintf("%s:- %016llx - %016llx\n",
|
||||||
|
+ __func__, start, end);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fclose(fp);
|
||||||
|
+
|
||||||
|
+ *range = memranges.ranges;
|
||||||
|
+ *ranges = memranges.size;
|
||||||
|
|
||||||
|
/* As a fallback option, we can try determining the PHYS_OFFSET
|
||||||
|
* value from the '/proc/iomem' entries as well.
|
||||||
|
@@ -982,52 +1054,15 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
|
||||||
|
* between the user-space and kernel space 'PHYS_OFFSET'
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
- set_phys_offset(r->start, "iomem");
|
||||||
|
-
|
||||||
|
- dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start,
|
||||||
|
- r->end, str);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/**
|
||||||
|
- * get_memory_ranges_iomem - Try to get the memory ranges from
|
||||||
|
- * /proc/iomem.
|
||||||
|
- */
|
||||||
|
+ if (memranges.size)
|
||||||
|
+ set_phys_offset(memranges.ranges[0].start, "iomem");
|
||||||
|
|
||||||
|
-static int get_memory_ranges_iomem(struct memory_range *array,
|
||||||
|
- unsigned int *count)
|
||||||
|
-{
|
||||||
|
- *count = kexec_iomem_for_each_line(NULL,
|
||||||
|
- get_memory_ranges_iomem_cb, array);
|
||||||
|
-
|
||||||
|
- if (!*count) {
|
||||||
|
- dbgprintf("%s: failed: No RAM found.\n", __func__);
|
||||||
|
- return EFAILED;
|
||||||
|
- }
|
||||||
|
+ dbgprint_mem_range("System RAM ranges;",
|
||||||
|
+ memranges.ranges, memranges.size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/**
|
||||||
|
- * get_memory_ranges - Try to get the memory ranges some how.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
-int get_memory_ranges(struct memory_range **range, int *ranges,
|
||||||
|
- unsigned long kexec_flags)
|
||||||
|
-{
|
||||||
|
- static struct memory_range array[KEXEC_SEGMENT_MAX];
|
||||||
|
- unsigned int count;
|
||||||
|
- int result;
|
||||||
|
-
|
||||||
|
- result = get_memory_ranges_iomem(array, &count);
|
||||||
|
-
|
||||||
|
- *range = result ? NULL : array;
|
||||||
|
- *ranges = result ? 0 : count;
|
||||||
|
-
|
||||||
|
- return result;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int arch_compat_trampoline(struct kexec_info *info)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
From cf977b1af9ec67fabcc6a625589c49c52d07b11d Mon Sep 17 00:00:00 2001
|
||||||
|
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
||||||
|
Date: Wed, 18 Dec 2019 11:42:30 -0500
|
||||||
|
Subject: [PATCH] kexec: add variant helper functions for handling memory
|
||||||
|
regions
|
||||||
|
|
||||||
|
mem_regions_alloc_and_add() and mem_regions_alloc_and_exclude() are
|
||||||
|
functionally equivalent to, respectively, mem_regions_add() and
|
||||||
|
mem_regions_exclude() except the formers will re-allocate memory
|
||||||
|
dynamically when no more entries are available in 'ranges' array.
|
||||||
|
|
||||||
|
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
||||||
|
Tested-by: Bhupesh Sharma <bhsharma@redhat.com>
|
||||||
|
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
|
||||||
|
Signed-off-by: Simon Horman <horms@verge.net.au>
|
||||||
|
---
|
||||||
|
kexec/mem_regions.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
kexec/mem_regions.h | 7 +++++++
|
||||||
|
2 files changed, 49 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
|
||||||
|
index 50c8abc..ad7d3f1 100644
|
||||||
|
--- a/kexec/mem_regions.c
|
||||||
|
+++ b/kexec/mem_regions.c
|
||||||
|
@@ -125,3 +125,45 @@ int mem_regions_exclude(struct memory_ranges *ranges,
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#define KEXEC_MEMORY_RANGES 16
|
||||||
|
+
|
||||||
|
+int mem_regions_alloc_and_add(struct memory_ranges *ranges,
|
||||||
|
+ unsigned long long base,
|
||||||
|
+ unsigned long long length, int type)
|
||||||
|
+{
|
||||||
|
+ void *new_ranges;
|
||||||
|
+
|
||||||
|
+ if (ranges->size >= ranges->max_size) {
|
||||||
|
+ new_ranges = realloc(ranges->ranges,
|
||||||
|
+ sizeof(struct memory_range) *
|
||||||
|
+ (ranges->max_size + KEXEC_MEMORY_RANGES));
|
||||||
|
+ if (!new_ranges)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ ranges->ranges = new_ranges;
|
||||||
|
+ ranges->max_size += KEXEC_MEMORY_RANGES;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return mem_regions_add(ranges, base, length, type);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mem_regions_alloc_and_exclude(struct memory_ranges *ranges,
|
||||||
|
+ const struct memory_range *range)
|
||||||
|
+{
|
||||||
|
+ void *new_ranges;
|
||||||
|
+
|
||||||
|
+ /* for safety, we should have at least one free entry in ranges */
|
||||||
|
+ if (ranges->size >= ranges->max_size) {
|
||||||
|
+ new_ranges = realloc(ranges->ranges,
|
||||||
|
+ sizeof(struct memory_range) *
|
||||||
|
+ (ranges->max_size + KEXEC_MEMORY_RANGES));
|
||||||
|
+ if (!new_ranges)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ ranges->ranges = new_ranges;
|
||||||
|
+ ranges->max_size += KEXEC_MEMORY_RANGES;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return mem_regions_exclude(ranges, range);
|
||||||
|
+}
|
||||||
|
diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
|
||||||
|
index ae9e972..e306d67 100644
|
||||||
|
--- a/kexec/mem_regions.h
|
||||||
|
+++ b/kexec/mem_regions.h
|
||||||
|
@@ -12,4 +12,11 @@ int mem_regions_exclude(struct memory_ranges *ranges,
|
||||||
|
int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
|
||||||
|
unsigned long long length, int type);
|
||||||
|
|
||||||
|
+int mem_regions_alloc_and_exclude(struct memory_ranges *ranges,
|
||||||
|
+ const struct memory_range *range);
|
||||||
|
+
|
||||||
|
+int mem_regions_alloc_and_add(struct memory_ranges *ranges,
|
||||||
|
+ unsigned long long base,
|
||||||
|
+ unsigned long long length, int type);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Name: kexec-tools
|
Name: kexec-tools
|
||||||
Version: 2.0.20
|
Version: 2.0.20
|
||||||
Release: 2
|
Release: 3
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
Summary: The kexec/kdump userspace component
|
Summary: The kexec/kdump userspace component
|
||||||
URL: https://www.kernel.org/
|
URL: https://www.kernel.org/
|
||||||
@ -69,24 +69,27 @@ Requires: systemd-udev%{?_isa}
|
|||||||
|
|
||||||
%undefine _hardened_build
|
%undefine _hardened_build
|
||||||
|
|
||||||
Patch6000: kexec-tools-2.0.20-fix-broken-multiboot2-buliding-for-i386.patch
|
Patch0: kexec-tools-2.0.20-fix-broken-multiboot2-buliding-for-i386.patch
|
||||||
|
|
||||||
Patch6001: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch
|
Patch1: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch
|
||||||
Patch6002: kexec-tools-2.0.20-makedumpfile-Remove-duplicated-variable-declarations.patch
|
Patch2: kexec-tools-2.0.20-makedumpfile-Remove-duplicated-variable-declarations.patch
|
||||||
Patch6003: kexec-tools-2.0.20-Remove-duplicated-variable-declarations.patch
|
Patch3: kexec-tools-2.0.20-Remove-duplicated-variable-declarations.patch
|
||||||
Patch6004: kexec-tools-2.0.20-makedumpfile-Introduce-check-params-option.patch
|
Patch4: kexec-tools-2.0.20-makedumpfile-Introduce-check-params-option.patch
|
||||||
|
|
||||||
|
Patch5: kexec-add-variant-helper-functions-for-handling-memory-regions.patch
|
||||||
|
Patch6: arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch
|
||||||
|
|
||||||
%ifarch aarch64
|
%ifarch aarch64
|
||||||
Patch9000: arm64-support-more-than-one-crash-kernel-regions.patch
|
Patch7: arm64-support-more-than-one-crash-kernel-regions.patch
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
Patch9001: add-secure-compile-options-for-makedumpfile.patch
|
Patch8: add-secure-compile-options-for-makedumpfile.patch
|
||||||
|
|
||||||
Patch9002: bugfix-get-the-paddr-of-mem_section-return-error-address.patch
|
Patch9: bugfix-get-the-paddr-of-mem_section-return-error-address.patch
|
||||||
Patch9003: fix-header-offset-overflow-when-large-pfn.patch
|
Patch10: fix-header-offset-overflow-when-large-pfn.patch
|
||||||
Patch9004: kexec-Add-quick-kexec-support.patch
|
Patch11: kexec-Add-quick-kexec-support.patch
|
||||||
%ifarch aarch64
|
%ifarch aarch64
|
||||||
Patch9005: kexec-Quick-kexec-implementation-for-arm64.patch
|
Patch12: kexec-Quick-kexec-implementation-for-arm64.patch
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@ -110,18 +113,24 @@ mkdir -p -m755 kcp
|
|||||||
tar -z -x -v -f %{SOURCE9}
|
tar -z -x -v -f %{SOURCE9}
|
||||||
tar -z -x -v -f %{SOURCE19}
|
tar -z -x -v -f %{SOURCE19}
|
||||||
|
|
||||||
%{lua:for i=0,4 do print(string.format("%%patch600%u -p1\n", i)) end}
|
%patch0 -p1
|
||||||
|
%patch1 -p1
|
||||||
|
%patch2 -p1
|
||||||
|
%patch3 -p1
|
||||||
|
%patch4 -p1
|
||||||
|
%patch5 -p1
|
||||||
|
%patch6 -p1
|
||||||
|
|
||||||
%ifarch aarch64
|
%ifarch aarch64
|
||||||
%patch9000 -p1
|
%patch7 -p1
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%patch9001 -p1
|
%patch8 -p1
|
||||||
%patch9002 -p1
|
%patch9 -p1
|
||||||
%patch9003 -p1
|
%patch10 -p1
|
||||||
%patch9004 -p1
|
%patch11 -p1
|
||||||
%ifarch aarch64
|
%ifarch aarch64
|
||||||
%patch9005 -p1
|
%patch12 -p1
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
@ -309,6 +318,12 @@ done
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Sep 10 2020 zhangruifang2020 <xdzhangruifang@163.com> - 2.0.20-3
|
||||||
|
- Type:bugfix
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:fix issue about iomem file that contains too many contens.As a result,the kdump service failed.
|
||||||
|
|
||||||
* Thu Aug 13 2020 snoweay <snoweay@163.com> - 2.0.20-2
|
* Thu Aug 13 2020 snoweay <snoweay@163.com> - 2.0.20-2
|
||||||
- Add support for quick kexec
|
- Add support for quick kexec
|
||||||
kexec: Add quick kexec support
|
kexec: Add quick kexec support
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user