|
|
|
@ -47,8 +47,10 @@ static struct fadump_mem_struct fdm; |
|
|
|
|
static const struct fadump_mem_struct *fdm_active; |
|
|
|
|
|
|
|
|
|
static DEFINE_MUTEX(fadump_mutex); |
|
|
|
|
struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES]; |
|
|
|
|
struct fad_crash_memory_ranges *crash_memory_ranges; |
|
|
|
|
int crash_memory_ranges_size; |
|
|
|
|
int crash_mem_ranges; |
|
|
|
|
int max_crash_mem_ranges; |
|
|
|
|
|
|
|
|
|
/* Scan the Firmware Assisted dump configuration details. */ |
|
|
|
|
int __init early_init_dt_scan_fw_dump(unsigned long node, |
|
|
|
@ -843,38 +845,88 @@ static int __init process_fadump(const struct fadump_mem_struct *fdm_active) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void fadump_add_crash_memory(unsigned long long base, |
|
|
|
|
static void free_crash_memory_ranges(void) |
|
|
|
|
{ |
|
|
|
|
kfree(crash_memory_ranges); |
|
|
|
|
crash_memory_ranges = NULL; |
|
|
|
|
crash_memory_ranges_size = 0; |
|
|
|
|
max_crash_mem_ranges = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Allocate or reallocate crash memory ranges array in incremental units |
|
|
|
|
* of PAGE_SIZE. |
|
|
|
|
*/ |
|
|
|
|
static int allocate_crash_memory_ranges(void) |
|
|
|
|
{ |
|
|
|
|
struct fad_crash_memory_ranges *new_array; |
|
|
|
|
u64 new_size; |
|
|
|
|
|
|
|
|
|
new_size = crash_memory_ranges_size + PAGE_SIZE; |
|
|
|
|
pr_debug("Allocating %llu bytes of memory for crash memory ranges\n", |
|
|
|
|
new_size); |
|
|
|
|
|
|
|
|
|
new_array = krealloc(crash_memory_ranges, new_size, GFP_KERNEL); |
|
|
|
|
if (new_array == NULL) { |
|
|
|
|
pr_err("Insufficient memory for setting up crash memory ranges\n"); |
|
|
|
|
free_crash_memory_ranges(); |
|
|
|
|
return -ENOMEM; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
crash_memory_ranges = new_array; |
|
|
|
|
crash_memory_ranges_size = new_size; |
|
|
|
|
max_crash_mem_ranges = (new_size / |
|
|
|
|
sizeof(struct fad_crash_memory_ranges)); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline int fadump_add_crash_memory(unsigned long long base, |
|
|
|
|
unsigned long long end) |
|
|
|
|
{ |
|
|
|
|
if (base == end) |
|
|
|
|
return; |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if (crash_mem_ranges == max_crash_mem_ranges) { |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
ret = allocate_crash_memory_ranges(); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n", |
|
|
|
|
crash_mem_ranges, base, end - 1, (end - base)); |
|
|
|
|
crash_memory_ranges[crash_mem_ranges].base = base; |
|
|
|
|
crash_memory_ranges[crash_mem_ranges].size = end - base; |
|
|
|
|
crash_mem_ranges++; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void fadump_exclude_reserved_area(unsigned long long start, |
|
|
|
|
static int fadump_exclude_reserved_area(unsigned long long start, |
|
|
|
|
unsigned long long end) |
|
|
|
|
{ |
|
|
|
|
unsigned long long ra_start, ra_end; |
|
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
|
|
ra_start = fw_dump.reserve_dump_area_start; |
|
|
|
|
ra_end = ra_start + fw_dump.reserve_dump_area_size; |
|
|
|
|
|
|
|
|
|
if ((ra_start < end) && (ra_end > start)) { |
|
|
|
|
if ((start < ra_start) && (end > ra_end)) { |
|
|
|
|
fadump_add_crash_memory(start, ra_start); |
|
|
|
|
fadump_add_crash_memory(ra_end, end); |
|
|
|
|
ret = fadump_add_crash_memory(start, ra_start); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
ret = fadump_add_crash_memory(ra_end, end); |
|
|
|
|
} else if (start < ra_start) { |
|
|
|
|
fadump_add_crash_memory(start, ra_start); |
|
|
|
|
ret = fadump_add_crash_memory(start, ra_start); |
|
|
|
|
} else if (ra_end < end) { |
|
|
|
|
fadump_add_crash_memory(ra_end, end); |
|
|
|
|
ret = fadump_add_crash_memory(ra_end, end); |
|
|
|
|
} |
|
|
|
|
} else |
|
|
|
|
fadump_add_crash_memory(start, end); |
|
|
|
|
ret = fadump_add_crash_memory(start, end); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int fadump_init_elfcore_header(char *bufp) |
|
|
|
@ -914,10 +966,11 @@ static int fadump_init_elfcore_header(char *bufp) |
|
|
|
|
* Traverse through memblock structure and setup crash memory ranges. These |
|
|
|
|
* ranges will be used create PT_LOAD program headers in elfcore header. |
|
|
|
|
*/ |
|
|
|
|
static void fadump_setup_crash_memory_ranges(void) |
|
|
|
|
static int fadump_setup_crash_memory_ranges(void) |
|
|
|
|
{ |
|
|
|
|
struct memblock_region *reg; |
|
|
|
|
unsigned long long start, end; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
pr_debug("Setup crash memory ranges.\n"); |
|
|
|
|
crash_mem_ranges = 0; |
|
|
|
@ -928,7 +981,9 @@ static void fadump_setup_crash_memory_ranges(void) |
|
|
|
|
* specified during fadump registration. We need to create a separate |
|
|
|
|
* program header for this chunk with the correct offset. |
|
|
|
|
*/ |
|
|
|
|
fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); |
|
|
|
|
ret = fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
for_each_memblock(memory, reg) { |
|
|
|
|
start = (unsigned long long)reg->base; |
|
|
|
@ -948,8 +1003,12 @@ static void fadump_setup_crash_memory_ranges(void) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* add this range excluding the reserved dump area. */ |
|
|
|
|
fadump_exclude_reserved_area(start, end); |
|
|
|
|
ret = fadump_exclude_reserved_area(start, end); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -1072,6 +1131,7 @@ static int register_fadump(void) |
|
|
|
|
{ |
|
|
|
|
unsigned long addr; |
|
|
|
|
void *vaddr; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If no memory is reserved then we can not register for firmware- |
|
|
|
@ -1080,7 +1140,9 @@ static int register_fadump(void) |
|
|
|
|
if (!fw_dump.reserve_dump_area_size) |
|
|
|
|
return -ENODEV; |
|
|
|
|
|
|
|
|
|
fadump_setup_crash_memory_ranges(); |
|
|
|
|
ret = fadump_setup_crash_memory_ranges(); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len); |
|
|
|
|
/* Initialize fadump crash info header. */ |
|
|
|
@ -1158,6 +1220,7 @@ void fadump_cleanup(void) |
|
|
|
|
} else if (fw_dump.dump_registered) { |
|
|
|
|
/* Un-register Firmware-assisted dump if it was registered. */ |
|
|
|
|
fadump_unregister_dump(&fdm); |
|
|
|
|
free_crash_memory_ranges(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|