diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-fadump.c | 54 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-fadump.h | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/rtas-fadump.c | 11 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/rtas-fadump.h | 5 |
4 files changed, 45 insertions, 30 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c index 006648e4d5e6..d361d37d975f 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.c +++ b/arch/powerpc/platforms/powernv/opal-fadump.c @@ -115,19 +115,28 @@ static void opal_fadump_update_config(struct fw_dump *fadump_conf, static void opal_fadump_get_config(struct fw_dump *fadump_conf, const struct opal_fadump_mem_struct *fdm) { + unsigned long base, size, last_end, hole_size; int i; if (!fadump_conf->dump_active) return; + last_end = 0; + hole_size = 0; fadump_conf->boot_memory_size = 0; pr_debug("Boot memory regions:\n"); for (i = 0; i < fdm->region_cnt; i++) { - pr_debug("\t%d. base: 0x%llx, size: 0x%llx\n", - (i + 1), fdm->rgn[i].src, fdm->rgn[i].size); + base = fdm->rgn[i].src; + size = fdm->rgn[i].size; + pr_debug("\t[%03d] base: 0x%lx, size: 0x%lx\n", i, base, size); - fadump_conf->boot_memory_size += fdm->rgn[i].size; + fadump_conf->boot_mem_addr[i] = base; + fadump_conf->boot_mem_sz[i] = size; + fadump_conf->boot_memory_size += size; + hole_size += (base - last_end); + + last_end = base + size; } /* @@ -160,6 +169,8 @@ static void opal_fadump_get_config(struct fw_dump *fadump_conf, pr_warn("WARNING: If the unsaved regions contain kernel pages, the vmcore will be corrupted.\n"); } + fadump_conf->boot_mem_top = (fadump_conf->boot_memory_size + hole_size); + fadump_conf->boot_mem_regs_cnt = fdm->region_cnt; opal_fadump_update_config(fadump_conf, fdm); } @@ -174,33 +185,20 @@ static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm) static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf) { - int max_copy_size, cur_size, size; - u64 src_addr, dest_addr; + u64 addr = fadump_conf->reserve_dump_area_start; + int i; opal_fdm = __va(fadump_conf->kernel_metadata); opal_fadump_init_metadata(opal_fdm); - /* - * 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; + for (i = 0; i < fadump_conf->boot_mem_regs_cnt; i++) { + opal_fdm->rgn[i].src = fadump_conf->boot_mem_addr[i]; + opal_fdm->rgn[i].dest = addr; + opal_fdm->rgn[i].size = fadump_conf->boot_mem_sz[i]; opal_fdm->region_cnt++; - dest_addr += cur_size; - src_addr += cur_size; - size -= cur_size; + addr += fadump_conf->boot_mem_sz[i]; } /* @@ -212,7 +210,7 @@ static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf) opal_fadump_update_config(fadump_conf, opal_fdm); - return dest_addr; + return addr; } static u64 opal_fadump_get_metadata_size(void) @@ -254,7 +252,7 @@ static int opal_fadump_setup_metadata(struct fw_dump *fadump_conf) * by a kernel that intends to preserve crash'ed kernel's memory. */ ret = opal_mpipl_register_tag(OPAL_MPIPL_TAG_BOOT_MEM, - fadump_conf->boot_memory_size); + fadump_conf->boot_mem_top); if (ret != OPAL_SUCCESS) { pr_err("Failed to set boot memory tag!\n"); err = -EPERM; @@ -670,6 +668,12 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) fadump_conf->fadump_supported = 1; /* + * Firmware supports 32-bit field for size. Align it to PAGE_SIZE + * and request firmware to copy multiple kernel boot memory regions. + */ + fadump_conf->max_copy_size = _ALIGN_DOWN(U32_MAX, PAGE_SIZE); + + /* * Check if dump has been initiated on last reboot. */ prop = of_get_flat_dt_prop(dn, "mpipl-boot", NULL); diff --git a/arch/powerpc/platforms/powernv/opal-fadump.h b/arch/powerpc/platforms/powernv/opal-fadump.h index e630cb0f108f..f1e9ecf548c5 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.h +++ b/arch/powerpc/platforms/powernv/opal-fadump.h @@ -27,9 +27,6 @@ */ #define OPAL_FADUMP_VERSION 0x1 -/* Maximum number of memory regions kernel supports */ -#define OPAL_FADUMP_MAX_MEM_REGS 128 - /* * OPAL FADump kernel metadata * @@ -42,7 +39,7 @@ struct opal_fadump_mem_struct { u16 region_cnt; /* number of regions */ u16 registered_regions; /* Regions registered for MPIPL */ u64 fadumphdr_addr; - struct opal_mpipl_region rgn[OPAL_FADUMP_MAX_MEM_REGS]; + struct opal_mpipl_region rgn[FADUMP_MAX_MEM_REGS]; } __packed; /* diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.c b/arch/powerpc/platforms/pseries/rtas-fadump.c index a525180c1f0f..70c3013fdd07 100644 --- a/arch/powerpc/platforms/pseries/rtas-fadump.c +++ b/arch/powerpc/platforms/pseries/rtas-fadump.c @@ -42,7 +42,13 @@ static void rtas_fadump_update_config(struct fw_dump *fadump_conf, static void rtas_fadump_get_config(struct fw_dump *fadump_conf, const struct rtas_fadump_mem_struct *fdm) { - fadump_conf->boot_memory_size = be64_to_cpu(fdm->rmr_region.source_len); + fadump_conf->boot_mem_addr[0] = + be64_to_cpu(fdm->rmr_region.source_address); + fadump_conf->boot_mem_sz[0] = be64_to_cpu(fdm->rmr_region.source_len); + fadump_conf->boot_memory_size = fadump_conf->boot_mem_sz[0]; + + fadump_conf->boot_mem_top = fadump_conf->boot_memory_size; + fadump_conf->boot_mem_regs_cnt = 1; /* * Start address of reserve dump area (permanent reservation) for @@ -499,6 +505,9 @@ void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) fadump_conf->ops = &rtas_fadump_ops; fadump_conf->fadump_supported = 1; + /* Firmware supports 64-bit value for size, align it to pagesize. */ + fadump_conf->max_copy_size = _ALIGN_DOWN(U64_MAX, PAGE_SIZE); + /* * The 'ibm,kernel-dump' rtas node is present only if there is * dump data waiting for us. diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.h b/arch/powerpc/platforms/pseries/rtas-fadump.h index 6602ff69e10d..fd59bd7ca9c3 100644 --- a/arch/powerpc/platforms/pseries/rtas-fadump.h +++ b/arch/powerpc/platforms/pseries/rtas-fadump.h @@ -69,6 +69,11 @@ struct rtas_fadump_mem_struct { /* Kernel dump sections */ struct rtas_fadump_section cpu_state_data; struct rtas_fadump_section hpte_region; + + /* + * TODO: Extend multiple boot memory regions support in the kernel + * for this platform. + */ struct rtas_fadump_section rmr_region; }; |