diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c index b53007e82190ce07ec7128fc254b1b34c1246ceb..a4b96a7a5d6c424ef45a30506558d26bf49baf49 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.c +++ b/arch/powerpc/platforms/powernv/opal-fadump.c @@ -26,6 +26,8 @@ static int opal_fadump_unregister(struct fw_dump *fadump_conf); static void opal_fadump_update_config(struct fw_dump *fadump_conf, const struct opal_fadump_mem_struct *fdm) { + pr_debug("Boot memory regions count: %d\n", fdm->region_cnt); + /* * The destination address of the first boot memory region is the * destination address of boot memory regions. @@ -48,16 +50,34 @@ static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm) static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf) { - u64 addr = fadump_conf->reserve_dump_area_start; + int max_copy_size, cur_size, size; + u64 src_addr, dest_addr; opal_fdm = __va(fadump_conf->kernel_metadata); opal_fadump_init_metadata(opal_fdm); - opal_fdm->region_cnt = 1; - opal_fdm->rgn[0].src = 0; - opal_fdm->rgn[0].dest = addr; - opal_fdm->rgn[0].size = fadump_conf->boot_memory_size; - addr += fadump_conf->boot_memory_size; + /* + * Firmware supports 32-bit field for size. Align it to PAGE_SIZE + * and request firmware to copy multiple kernel boot memory regions. + */ + max_copy_size = _ALIGN_DOWN(U32_MAX, PAGE_SIZE); + + /* Boot memory regions */ + src_addr = 0; + dest_addr = fadump_conf->reserve_dump_area_start; + size = fadump_conf->boot_memory_size; + while (size) { + cur_size = size > max_copy_size ? max_copy_size : size; + + opal_fdm->rgn[opal_fdm->region_cnt].src = src_addr; + opal_fdm->rgn[opal_fdm->region_cnt].dest = dest_addr; + opal_fdm->rgn[opal_fdm->region_cnt].size = cur_size; + + opal_fdm->region_cnt++; + dest_addr += cur_size; + src_addr += cur_size; + size -= cur_size; + } /* * Kernel metadata is passed to f/w and retrieved in capture kerenl. @@ -68,7 +88,7 @@ static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf) opal_fadump_update_config(fadump_conf, opal_fdm); - return addr; + return dest_addr; } static u64 opal_fadump_get_metadata_size(void)