diff options
author | Chen Zhou <chenzhou10@huawei.com> | 2022-01-10 18:20:08 +0800 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2022-01-14 15:52:06 +0100 |
commit | b5a34a20984c4ad27cc5054d9957af8130b42a50 (patch) | |
tree | af3af3c4ba448fb236324bc476b6f2f48107b4a7 /kexec/arch/arm64/crashdump-arm64.c | |
parent | 186e7b0752d8fce1618fa37519671c834c46340e (diff) |
arm64: support more than one crash kernel regions
When crashkernel is reserved above 4G in memory, kernel should
reserve some amount of low memory for swiotlb and some DMA buffers.
So there may be two crash kernel regions, one is below 4G, the other
is above 4G.
Currently, there is only one crash kernel region on arm64, and pass
"linux,usable-memory-range = <BASE SIZE>" property to crash dump
kernel.
Now, we pass "linux,usable-memory-range = <BASE1 SIZE1 BASE2 SIZE2>"
to crash dump kernel to support two crash kernel regions and load crash
kernel high. Make the low memory region as the second range "BASE2 SIZE2"
to keep compatibility with existing user-space and older kdump kernels.
Signed-off-by: Chen Zhou <chenzhou10@huawei.com>
Co-developed-by: Zhen Lei <thunder.leizhen@huawei.com>
Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec/arch/arm64/crashdump-arm64.c')
-rw-r--r-- | kexec/arch/arm64/crashdump-arm64.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c index a02019a..d0f2253 100644 --- a/kexec/arch/arm64/crashdump-arm64.c +++ b/kexec/arch/arm64/crashdump-arm64.c @@ -27,11 +27,11 @@ static struct memory_ranges system_memory_rgns; /* memory range reserved for crashkernel */ -struct memory_range crash_reserved_mem; +struct memory_range crash_reserved_mem[CRASH_MAX_RESERVED_RANGES]; struct memory_ranges usablemem_rgns = { .size = 0, - .max_size = 1, - .ranges = &crash_reserved_mem, + .max_size = CRASH_MAX_RESERVED_RANGES, + .ranges = crash_reserved_mem, }; struct memory_range elfcorehdr_mem; @@ -119,7 +119,7 @@ int is_crashkernel_mem_reserved(void) if (!usablemem_rgns.size) kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); - return crash_reserved_mem.start != crash_reserved_mem.end; + return usablemem_rgns.size; } /* @@ -133,6 +133,8 @@ int is_crashkernel_mem_reserved(void) */ static int crash_get_memory_ranges(void) { + int i; + /* * First read all memory regions that can be considered as * system memory including the crash area. @@ -140,16 +142,19 @@ 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 */ - if (usablemem_rgns.size != 1) + /* allow one or two regions for crash dump kernel */ + if (!usablemem_rgns.size) return -EINVAL; - dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1); + dbgprint_mem_range("Reserved memory range", + usablemem_rgns.ranges, usablemem_rgns.size); - if (mem_regions_alloc_and_exclude(&system_memory_rgns, - &crash_reserved_mem)) { - fprintf(stderr, "Cannot allocate memory for ranges\n"); - return -ENOMEM; + for (i = 0; i < usablemem_rgns.size; i++) { + if (mem_regions_alloc_and_exclude(&system_memory_rgns, + &crash_reserved_mem[i])) { + fprintf(stderr, "Cannot allocate memory for ranges\n"); + return -ENOMEM; + } } /* @@ -210,7 +215,8 @@ int load_crashdump_segments(struct kexec_info *info) return EFAILED; elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0, - crash_reserved_mem.start, crash_reserved_mem.end, + crash_reserved_mem[usablemem_rgns.size - 1].start, + crash_reserved_mem[usablemem_rgns.size - 1].end, -1, 0); elfcorehdr_mem.start = elfcorehdr; @@ -228,21 +234,23 @@ int load_crashdump_segments(struct kexec_info *info) * virt_to_phys() in add_segment(). * So let's fix up those values for later use so the memory base * (arm64_mm.phys_offset) will be correctly replaced with - * crash_reserved_mem.start. + * crash_reserved_mem[usablemem_rgns.size - 1].start. */ void fixup_elf_addrs(struct mem_ehdr *ehdr) { struct mem_phdr *phdr; int i; - ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start; + ehdr->e_entry += -arm64_mem.phys_offset + + crash_reserved_mem[usablemem_rgns.size - 1].start; for (i = 0; i < ehdr->e_phnum; i++) { phdr = &ehdr->e_phdr[i]; if (phdr->p_type != PT_LOAD) continue; phdr->p_paddr += - (-arm64_mem.phys_offset + crash_reserved_mem.start); + (-arm64_mem.phys_offset + + crash_reserved_mem[usablemem_rgns.size - 1].start); } } @@ -251,11 +259,11 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) if (!usablemem_rgns.size) kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); - if (!crash_reserved_mem.end) + if (!usablemem_rgns.size) return -1; - *start = crash_reserved_mem.start; - *end = crash_reserved_mem.end; + *start = crash_reserved_mem[usablemem_rgns.size - 1].start; + *end = crash_reserved_mem[usablemem_rgns.size - 1].end; return 0; } |