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.
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.
opal_fadump_update_config(fadump_conf, opal_fdm);
- return addr;
+ return dest_addr;
}
static u64 opal_fadump_get_metadata_size(void)