Currently, there is only one crash kernel region on arm64, we add
another region "crash kernel low" used for crash dump kernel devices.

To do this, we add DT property "linux,low-memory-range" to crash
dump kernel's dtb to pass the low region.

Signed-off-by: Chen Zhou <chenzho...@huawei.com>
---
For "support reserving crashkernel above 4G on arm64 kdump", we need to
modify the kexec-tools.

I will post patch series "[PATCH v6 0/4] support reserving crashkernel
above 4G on arm64 kdump". This version is much different from the previous
one and the kexec-tools part neeed to be modified.

Changes since [v1]:
- Add another DT property "linux,low-memory-range" to crash dump kernel's
dtb to pass the low region instead of reusing "linux,usable-memory-range".

[1]: http://lists.infradead.org/pipermail/kexec/2019-April/022792.html
---
 kexec/arch/arm64/crashdump-arm64.c | 29 +++++++++++++++++++++++++++--
 kexec/arch/arm64/crashdump-arm64.h |  2 ++
 kexec/arch/arm64/iomem.h           |  1 +
 kexec/arch/arm64/kexec-arm64.c     | 27 +++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/arm64/crashdump-arm64.c 
b/kexec/arch/arm64/crashdump-arm64.c
index 4fd7aa8..a8be036 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -39,6 +39,14 @@ struct memory_ranges usablemem_rgns = {
        .ranges = &crash_reserved_mem,
 };
 
+/* memory range reserved for crashkernel low, optional */
+struct memory_range crash_reserved_low_mem;
+struct memory_ranges lowmem_rgns = {
+       .size = 0,
+       .max_size = 1,
+       .ranges = &crash_reserved_low_mem,
+};
+
 struct memory_range elfcorehdr_mem;
 
 static struct crash_elf_info elf_info = {
@@ -89,7 +97,10 @@ static int iomem_range_callback(void *UNUSED(data), int 
UNUSED(nr),
                                char *str, unsigned long long base,
                                unsigned long long length)
 {
-       if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0)
+       if (strncmp(str, CRASH_KERNEL_LOW, strlen(CRASH_KERNEL_LOW)) == 0)
+               return mem_regions_add(&lowmem_rgns,
+                               base, length, RANGE_RAM);
+       else if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0)
                return mem_regions_add(&usablemem_rgns,
                                       base, length, RANGE_RAM);
        else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
@@ -129,7 +140,7 @@ static int crash_get_memory_ranges(void)
        if (!usablemem_rgns.size)
                kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
 
-       /* allow only a single region for crash dump kernel */
+       /* allow only a single usablemem region for crash dump kernel */
        if (usablemem_rgns.size != 1)
                return -EINVAL;
 
@@ -141,6 +152,20 @@ static int crash_get_memory_ranges(void)
                return -ENOMEM;
        }
 
+       /* lowmem region for crash dump kernel is optional, at most one region 
*/
+       if (lowmem_rgns.size > 1)
+               return -EINVAL;
+
+       if (lowmem_rgns.size) {
+               dbgprint_mem_range("Reserved low memory range", 
&crash_reserved_low_mem,
+                               1);
+
+               if (mem_regions_exclude(&system_memory_rgns, 
&crash_reserved_low_mem)) {
+                       fprintf(stderr,
+                                       "Error: Number of crash memory ranges 
excedeed the max limit\n");
+                       return -ENOMEM;
+               }
+       }
        /*
         * Make sure that the memory regions are sorted.
         */
diff --git a/kexec/arch/arm64/crashdump-arm64.h 
b/kexec/arch/arm64/crashdump-arm64.h
index 880b83a..f185534 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -18,6 +18,8 @@
 
 extern struct memory_ranges usablemem_rgns;
 extern struct memory_range crash_reserved_mem;
+extern struct memory_ranges lowmem_rgns;
+extern struct memory_range crash_reserved_low_mem;
 extern struct memory_range elfcorehdr_mem;
 
 extern int load_crashdump_segments(struct kexec_info *info);
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
index d4864bb..45d7953 100644
--- a/kexec/arch/arm64/iomem.h
+++ b/kexec/arch/arm64/iomem.h
@@ -4,6 +4,7 @@
 #define SYSTEM_RAM             "System RAM\n"
 #define KERNEL_CODE            "Kernel code\n"
 #define KERNEL_DATA            "Kernel data\n"
+#define CRASH_KERNEL_LOW       "Crash kernel (low)\n"
 #define CRASH_KERNEL           "Crash kernel\n"
 #define IOMEM_RESERVED         "reserved\n"
 
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index eb3a3a3..dddec23 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -38,6 +38,7 @@
 #define PROP_SIZE_CELLS "#size-cells"
 #define PROP_ELFCOREHDR "linux,elfcorehdr"
 #define PROP_USABLE_MEM_RANGE "linux,usable-memory-range"
+#define PROP_LOW_MEM_RANGE "linux,low-memory-range"
 
 #define PAGE_OFFSET_36 ((0xffffffffffffffffUL) << 36)
 #define PAGE_OFFSET_39 ((0xffffffffffffffffUL) << 39)
@@ -466,12 +467,24 @@ static int setup_2nd_dtb(struct dtb *dtb, char 
*command_line, int on_crash)
                goto on_error;
        }
 
+       if (lowmem_rgns.size) {
+               if (!cells_size_fitted(address_cells, size_cells,
+                                       &crash_reserved_low_mem)) {
+                       fprintf(stderr, "kexec: low memory range doesn't fit 
cells-size.\n");
+                       result = -EINVAL;
+                       goto on_error;
+               }
+       }
+
        /* duplicate dt blob */
        range_len = sizeof(uint32_t) * (address_cells + size_cells);
        new_size = fdt_totalsize(dtb->buf)
                + fdt_prop_len(PROP_ELFCOREHDR, range_len)
                + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len);
 
+       if (lowmem_rgns.size)
+               new_size += fdt_prop_len(PROP_LOW_MEM_RANGE, range_len);
+
        new_buf = xmalloc(new_size);
        result = fdt_open_into(dtb->buf, new_buf, new_size);
        if (result) {
@@ -575,6 +588,20 @@ static int setup_2nd_dtb(struct dtb *dtb, char 
*command_line, int on_crash)
                        result = -EINVAL;
                        goto on_error;
                }
+
+               /* add linux,low-memory-range */
+               if (lowmem_rgns.size) {
+                       nodeoffset = fdt_path_offset(new_buf, "/chosen");
+                       result = fdt_setprop_range(new_buf, nodeoffset,
+                                       PROP_LOW_MEM_RANGE, 
&crash_reserved_low_mem,
+                                       address_cells, size_cells);
+                       if (result) {
+                               dbgprintf("%s: fdt_setprop failed: %s\n", 
__func__,
+                                               fdt_strerror(result));
+                               result = -EINVAL;
+                               goto on_error;
+                       }
+               }
        }
 
        fdt_pack(new_buf);
-- 
2.7.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to