[RFC PATCH 1/3] powerpc/pseries/fadump: add support for multiple boot memory regions
Aditya Gupta
adityag at linux.ibm.com
Sun Dec 17 19:41:17 AEDT 2023
Hi sourabh,
On 06/12/23 01:48, Hari Bathini wrote:
> From: Sourabh Jain <sourabhjain at linux.ibm.com>
>
> Currently, fadump on pseries assumes a single boot memory region even
> though f/w supports more than one boot memory region. Add support for
> more boot memory regions to make the implementation flexible for any
> enhancements that introduce other region types. For this, rtas memory
> structure for fadump is updated to have multiple boot memory regions
> instead of just one. Additionally, methods responsible for creating
> the fadump memory structure during both the first and second kernel
> boot have been modified to take these multiple boot memory regions
> into account. Also, a new callback has been added to the fadump_ops
> structure to get the maximum boot memory regions supported by the
> platform.
>
> Signed-off-by: Sourabh Jain <sourabhjain at linux.ibm.com>
> Signed-off-by: Hari Bathini <hbathini at linux.ibm.com>
> ---
> arch/powerpc/include/asm/fadump-internal.h | 2 +-
> arch/powerpc/kernel/fadump.c | 27 +-
> arch/powerpc/platforms/powernv/opal-fadump.c | 8 +
> arch/powerpc/platforms/pseries/rtas-fadump.c | 258 ++++++++++++-------
> arch/powerpc/platforms/pseries/rtas-fadump.h | 26 +-
> 5 files changed, 199 insertions(+), 122 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/fadump-internal.h b/arch/powerpc/include/asm/fadump-internal.h
> index 27f9e11eda28..b3956c400519 100644
> --- a/arch/powerpc/include/asm/fadump-internal.h
> +++ b/arch/powerpc/include/asm/fadump-internal.h
> @@ -129,6 +129,7 @@ struct fadump_ops {
> struct seq_file *m);
> void (*fadump_trigger)(struct fadump_crash_info_header *fdh,
> const char *msg);
> + int (*fadump_max_boot_mem_rgns)(void);
> };
>
> /* Helper functions */
> @@ -136,7 +137,6 @@ s32 __init fadump_setup_cpu_notes_buf(u32 num_cpus);
> void fadump_free_cpu_notes_buf(void);
> u32 *__init fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs);
> void __init fadump_update_elfcore_header(char *bufp);
> -bool is_fadump_boot_mem_contiguous(void);
> bool is_fadump_reserved_mem_contiguous(void);
>
> #else /* !CONFIG_PRESERVE_FA_DUMP */
> diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
> index d14eda1e8589..757681658dda 100644
> --- a/arch/powerpc/kernel/fadump.c
> +++ b/arch/powerpc/kernel/fadump.c
> @@ -222,28 +222,6 @@ static bool is_fadump_mem_area_contiguous(u64 d_start, u64 d_end)
> return ret;
> }
>
> -/*
> - * Returns true, if there are no holes in boot memory area,
> - * false otherwise.
> - */
> -bool is_fadump_boot_mem_contiguous(void)
> -{
> - unsigned long d_start, d_end;
> - bool ret = false;
> - int i;
> -
> - for (i = 0; i < fw_dump.boot_mem_regs_cnt; i++) {
> - d_start = fw_dump.boot_mem_addr[i];
> - d_end = d_start + fw_dump.boot_mem_sz[i];
> -
> - ret = is_fadump_mem_area_contiguous(d_start, d_end);
> - if (!ret)
> - break;
> - }
> -
> - return ret;
> -}
> -
> /*
> * Returns true, if there are no holes in reserved memory area,
> * false otherwise.
> @@ -389,10 +367,11 @@ static unsigned long __init get_fadump_area_size(void)
> static int __init add_boot_mem_region(unsigned long rstart,
> unsigned long rsize)
> {
> + int max_boot_mem_rgns = fw_dump.ops->fadump_max_boot_mem_rgns();
> int i = fw_dump.boot_mem_regs_cnt++;
>
> - if (fw_dump.boot_mem_regs_cnt > FADUMP_MAX_MEM_REGS) {
> - fw_dump.boot_mem_regs_cnt = FADUMP_MAX_MEM_REGS;
> + if (fw_dump.boot_mem_regs_cnt > max_boot_mem_rgns) {
> + fw_dump.boot_mem_regs_cnt = max_boot_mem_rgns;
> return 0;
> }
>
> diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c
> index 964f464b1b0e..fa26c21a08d9 100644
> --- a/arch/powerpc/platforms/powernv/opal-fadump.c
> +++ b/arch/powerpc/platforms/powernv/opal-fadump.c
> @@ -615,6 +615,13 @@ static void opal_fadump_trigger(struct fadump_crash_info_header *fdh,
> pr_emerg("No backend support for MPIPL!\n");
> }
>
> +/* FADUMP_MAX_MEM_REGS or lower */
> +static int opal_fadump_max_boot_mem_rgns(void)
> +{
> + return FADUMP_MAX_MEM_REGS;
> +
> +}
> +
> static struct fadump_ops opal_fadump_ops = {
> .fadump_init_mem_struct = opal_fadump_init_mem_struct,
> .fadump_get_metadata_size = opal_fadump_get_metadata_size,
> @@ -627,6 +634,7 @@ static struct fadump_ops opal_fadump_ops = {
> .fadump_process = opal_fadump_process,
> .fadump_region_show = opal_fadump_region_show,
> .fadump_trigger = opal_fadump_trigger,
> + .fadump_max_boot_mem_rgns = opal_fadump_max_boot_mem_rgns,
> };
>
> void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
> diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.c b/arch/powerpc/platforms/pseries/rtas-fadump.c
> index b5853e9fcc3c..1b05b4cefdfd 100644
> --- a/arch/powerpc/platforms/pseries/rtas-fadump.c
> +++ b/arch/powerpc/platforms/pseries/rtas-fadump.c
> @@ -29,9 +29,6 @@ static const struct rtas_fadump_mem_struct *fdm_active;
> static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
> const struct rtas_fadump_mem_struct *fdm)
> {
> - fadump_conf->boot_mem_dest_addr =
> - be64_to_cpu(fdm->rmr_region.destination_address);
> -
> fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr +
> fadump_conf->boot_memory_size);
> }
> @@ -43,20 +40,52 @@ static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
> static void __init rtas_fadump_get_config(struct fw_dump *fadump_conf,
> const struct rtas_fadump_mem_struct *fdm)
> {
> - 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];
> + unsigned long base, size, last_end, hole_size;
>
> - fadump_conf->boot_mem_top = fadump_conf->boot_memory_size;
> - fadump_conf->boot_mem_regs_cnt = 1;
> + last_end = 0;
> + hole_size = 0;
> + fadump_conf->boot_memory_size = 0;
> + fadump_conf->boot_mem_regs_cnt = 0;
> + pr_debug("Boot memory regions:\n");
> + for (int i = 0; i < be16_to_cpu(fdm->header.dump_num_sections); i++) {
> + int type = be16_to_cpu(fdm->rgn[i].source_data_type);
>
> - /*
> - * Start address of reserve dump area (permanent reservation) for
> - * re-registering FADump after dump capture.
> - */
> - fadump_conf->reserve_dump_area_start =
> - be64_to_cpu(fdm->cpu_state_data.destination_address);
> + switch (type) {
> + case RTAS_FADUMP_CPU_STATE_DATA:
> + u64 addr = be64_to_cpu(fdm->rgn[i].destination_address);
This caused a compiler error on my system:
arch/powerpc/platforms/pseries/rtas-fadump.c: In function
‘rtas_fadump_get_config’:
arch/powerpc/platforms/pseries/rtas-fadump.c:56:4: error: a label can
only be part of a statement and a declaration is not a statement
u64 addr = be64_to_cpu(fdm->rgn[i].destination_address);
^~~
Probably the 'addr' local variable needs to be in it's own local scope.
Adding the case block in brackets {} solved the error for me.
Rest of the code looks good to me. I will also try to test the patch
series later.
Thanks,
Aditya Gupta
> +
> + fadump_conf->cpu_state_dest_vaddr = (u64)__va(addr);
> + /*
> + * Start address of reserve dump area (permanent reservation) for
> + * re-registering FADump after dump capture.
> + */
> + fadump_conf->reserve_dump_area_start = addr;
> + break;
> + case RTAS_FADUMP_HPTE_REGION:
> + /* Not processed currently. */
> + break;
> + case RTAS_FADUMP_REAL_MODE_REGION:
> + base = be64_to_cpu(fdm->rgn[i].source_address);
> + size = be64_to_cpu(fdm->rgn[i].source_len);
> + pr_debug("\t[%03d] base: 0x%lx, size: 0x%lx\n", i, base, size);
> + if (!base) {
> + fadump_conf->boot_mem_dest_addr =
> + be64_to_cpu(fdm->rgn[i].destination_address);
> + }
> +
> + fadump_conf->boot_mem_addr[fadump_conf->boot_mem_regs_cnt] = base;
> + fadump_conf->boot_mem_sz[fadump_conf->boot_mem_regs_cnt] = size;
> + fadump_conf->boot_memory_size += size;
> + hole_size += (base - last_end);
> + last_end = base + size;
> + fadump_conf->boot_mem_regs_cnt++;
> + break;
> + default:
> + pr_warn("Section type %d unsupported on this kernel. Ignoring!\n", type);
> + break;
> + }
> + }
> + fadump_conf->boot_mem_top = fadump_conf->boot_memory_size + hole_size;
>
> rtas_fadump_update_config(fadump_conf, fdm);
> }
> @@ -64,16 +93,15 @@ static void __init rtas_fadump_get_config(struct fw_dump *fadump_conf,
> static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
> {
> u64 addr = fadump_conf->reserve_dump_area_start;
> + u16 sec_cnt = 0;
>
> memset(&fdm, 0, sizeof(struct rtas_fadump_mem_struct));
> addr = addr & PAGE_MASK;
>
> fdm.header.dump_format_version = cpu_to_be32(0x00000001);
> - fdm.header.dump_num_sections = cpu_to_be16(3);
> fdm.header.dump_status_flag = 0;
> fdm.header.offset_first_dump_section =
> - cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct,
> - cpu_state_data));
> + cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct, rgn));
>
> /*
> * Fields for disk dump option.
> @@ -89,25 +117,22 @@ static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
>
> /* Kernel dump sections */
> /* cpu state data section. */
> - fdm.cpu_state_data.request_flag =
> - cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
> - fdm.cpu_state_data.source_data_type =
> - cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
> - fdm.cpu_state_data.source_address = 0;
> - fdm.cpu_state_data.source_len =
> - cpu_to_be64(fadump_conf->cpu_state_data_size);
> - fdm.cpu_state_data.destination_address = cpu_to_be64(addr);
> + fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
> + fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
> + fdm.rgn[sec_cnt].source_address = 0;
> + fdm.rgn[sec_cnt].source_len = cpu_to_be64(fadump_conf->cpu_state_data_size);
> + fdm.rgn[sec_cnt].destination_address = cpu_to_be64(addr);
> addr += fadump_conf->cpu_state_data_size;
> + sec_cnt++;
>
> /* hpte region section */
> - fdm.hpte_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
> - fdm.hpte_region.source_data_type =
> - cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
> - fdm.hpte_region.source_address = 0;
> - fdm.hpte_region.source_len =
> - cpu_to_be64(fadump_conf->hpte_region_size);
> - fdm.hpte_region.destination_address = cpu_to_be64(addr);
> + fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
> + fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
> + fdm.rgn[sec_cnt].source_address = 0;
> + fdm.rgn[sec_cnt].source_len = cpu_to_be64(fadump_conf->hpte_region_size);
> + fdm.rgn[sec_cnt].destination_address = cpu_to_be64(addr);
> addr += fadump_conf->hpte_region_size;
> + sec_cnt++;
>
> /*
> * Align boot memory area destination address to page boundary to
> @@ -115,15 +140,20 @@ static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
> */
> addr = PAGE_ALIGN(addr);
>
> - /* RMA region section */
> - fdm.rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
> - fdm.rmr_region.source_data_type =
> - cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
> - fdm.rmr_region.source_address = cpu_to_be64(0);
> - fdm.rmr_region.source_len = cpu_to_be64(fadump_conf->boot_memory_size);
> - fdm.rmr_region.destination_address = cpu_to_be64(addr);
> - addr += fadump_conf->boot_memory_size;
> + /* First boot memory region destination address */
> + fadump_conf->boot_mem_dest_addr = addr;
> + for (int i = 0; i < fadump_conf->boot_mem_regs_cnt; i++) {
> + /* Boot memory regions */
> + fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
> + fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
> + fdm.rgn[sec_cnt].source_address = cpu_to_be64(fadump_conf->boot_mem_addr[i]);
> + fdm.rgn[sec_cnt].source_len = cpu_to_be64(fadump_conf->boot_mem_sz[i]);
> + fdm.rgn[sec_cnt].destination_address = cpu_to_be64(addr);
> + addr += fadump_conf->boot_mem_sz[i];
> + sec_cnt++;
> + }
>
> + fdm.header.dump_num_sections = cpu_to_be16(sec_cnt);
> rtas_fadump_update_config(fadump_conf, &fdm);
>
> return addr;
> @@ -136,14 +166,21 @@ static u64 rtas_fadump_get_bootmem_min(void)
>
> static int rtas_fadump_register(struct fw_dump *fadump_conf)
> {
> - unsigned int wait_time;
> + unsigned int wait_time, fdm_size;
> int rc, err = -EIO;
>
> + /*
> + * Platform requires the exact size of the Dump Memory Structure.
> + * Avoid including any unused rgns in the calculation, as this
> + * could result in a parameter error (-3) from the platform.
> + */
> + fdm_size = sizeof(struct rtas_fadump_section_header);
> + fdm_size += be16_to_cpu(fdm.header.dump_num_sections) * sizeof(struct rtas_fadump_section);
> +
> /* TODO: Add upper time limit for the delay */
> do {
> rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
> - NULL, FADUMP_REGISTER, &fdm,
> - sizeof(struct rtas_fadump_mem_struct));
> + NULL, FADUMP_REGISTER, &fdm, fdm_size);
>
> wait_time = rtas_busy_delay_time(rc);
> if (wait_time)
> @@ -161,9 +198,7 @@ static int rtas_fadump_register(struct fw_dump *fadump_conf)
> pr_err("Failed to register. Hardware Error(%d).\n", rc);
> break;
> case -3:
> - if (!is_fadump_boot_mem_contiguous())
> - pr_err("Can't have holes in boot memory area.\n");
> - else if (!is_fadump_reserved_mem_contiguous())
> + if (!is_fadump_reserved_mem_contiguous())
> pr_err("Can't have holes in reserved memory area.\n");
>
> pr_err("Failed to register. Parameter Error(%d).\n", rc);
> @@ -316,11 +351,9 @@ static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf)
> u32 num_cpus, *note_buf;
> int i, rc = 0, cpu = 0;
> struct pt_regs regs;
> - unsigned long addr;
> void *vaddr;
>
> - addr = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
> - vaddr = __va(addr);
> + vaddr = (void *)fadump_conf->cpu_state_dest_vaddr;
>
> reg_header = vaddr;
> if (be64_to_cpu(reg_header->magic_number) !=
> @@ -395,24 +428,48 @@ static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf)
> static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
> {
> struct fadump_crash_info_header *fdh;
> - int rc = 0;
> + int i, rc = 0;
>
> if (!fdm_active || !fadump_conf->fadumphdr_addr)
> return -EINVAL;
>
> - /* Check if the dump data is valid. */
> - if ((be16_to_cpu(fdm_active->header.dump_status_flag) ==
> - RTAS_FADUMP_ERROR_FLAG) ||
> - (fdm_active->cpu_state_data.error_flags != 0) ||
> - (fdm_active->rmr_region.error_flags != 0)) {
> - pr_err("Dump taken by platform is not valid\n");
> - return -EINVAL;
> - }
> - if ((fdm_active->rmr_region.bytes_dumped !=
> - fdm_active->rmr_region.source_len) ||
> - !fdm_active->cpu_state_data.bytes_dumped) {
> - pr_err("Dump taken by platform is incomplete\n");
> - return -EINVAL;
> + /* Check all regions. */
> + for (i = 0; i < be16_to_cpu(fdm_active->header.dump_num_sections); i++) {
> + int type = be16_to_cpu(fdm_active->rgn[i].source_data_type);
> +
> + switch (type) {
> + case RTAS_FADUMP_CPU_STATE_DATA:
> + case RTAS_FADUMP_HPTE_REGION:
> + case RTAS_FADUMP_REAL_MODE_REGION:
> + if (fdm_active->rgn[i].error_flags != 0) {
> + pr_err("Dump taken by platform is not valid (%d)\n", i);
> + rc = -EINVAL;
> + }
> + if (fdm_active->rgn[i].bytes_dumped != fdm_active->rgn[i].source_len) {
> + pr_err("Dump taken by platform is incomplete (%d)\n", i);
> + rc = -EINVAL;
> + }
> + if (rc) {
> + pr_warn("Region type: %u src addr: 0x%llx dest addr: 0x%llx\n",
> + be16_to_cpu(fdm_active->rgn[i].source_data_type),
> + be64_to_cpu(fdm_active->rgn[i].source_address),
> + be64_to_cpu(fdm_active->rgn[i].destination_address));
> + return rc;
> + }
> + break;
> + default:
> + /*
> + * If the first/crashed kernel added a new region type that the
> + * second/fadump kernel doesn't recognize, skip it and process
> + * assuming backward compatibility.
> + */
> + pr_warn("Unknown region found: type: %u src addr: 0x%llx dest addr: 0x%llx\n",
> + be16_to_cpu(fdm_active->rgn[i].source_data_type),
> + be64_to_cpu(fdm_active->rgn[i].source_address),
> + be64_to_cpu(fdm_active->rgn[i].destination_address));
> + break;
> + }
> +
> }
>
> /* Validate the fadump crash info header */
> @@ -439,7 +496,6 @@ static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
> static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
> struct seq_file *m)
> {
> - const struct rtas_fadump_section *cpu_data_section;
> const struct rtas_fadump_mem_struct *fdm_ptr;
>
> if (fdm_active)
> @@ -447,27 +503,42 @@ static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
> else
> fdm_ptr = &fdm;
>
> - cpu_data_section = &(fdm_ptr->cpu_state_data);
> - seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
> - be64_to_cpu(cpu_data_section->destination_address),
> - be64_to_cpu(cpu_data_section->destination_address) +
> - be64_to_cpu(cpu_data_section->source_len) - 1,
> - be64_to_cpu(cpu_data_section->source_len),
> - be64_to_cpu(cpu_data_section->bytes_dumped));
> -
> - seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
> - be64_to_cpu(fdm_ptr->hpte_region.destination_address),
> - be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
> - be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
> - be64_to_cpu(fdm_ptr->hpte_region.source_len),
> - be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
> -
> - seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
> - be64_to_cpu(fdm_ptr->rmr_region.source_address),
> - be64_to_cpu(fdm_ptr->rmr_region.destination_address));
> - seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
> - be64_to_cpu(fdm_ptr->rmr_region.source_len),
> - be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
> +
> + for (int i = 0; i < be16_to_cpu(fdm_ptr->header.dump_num_sections); i++) {
> + int type = be16_to_cpu(fdm_ptr->rgn[i].source_data_type);
> +
> + switch (type) {
> + case RTAS_FADUMP_CPU_STATE_DATA:
> + seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
> + be64_to_cpu(fdm_ptr->rgn[i].destination_address),
> + be64_to_cpu(fdm_ptr->rgn[i].destination_address) +
> + be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1,
> + be64_to_cpu(fdm_ptr->rgn[i].source_len),
> + be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped));
> + break;
> + case RTAS_FADUMP_HPTE_REGION:
> + seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
> + be64_to_cpu(fdm_ptr->rgn[i].destination_address),
> + be64_to_cpu(fdm_ptr->rgn[i].destination_address) +
> + be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1,
> + be64_to_cpu(fdm_ptr->rgn[i].source_len),
> + be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped));
> + break;
> + case RTAS_FADUMP_REAL_MODE_REGION:
> + seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
> + be64_to_cpu(fdm_ptr->rgn[i].source_address),
> + be64_to_cpu(fdm_ptr->rgn[i].destination_address));
> + seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
> + be64_to_cpu(fdm_ptr->rgn[i].source_len),
> + be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped));
> + break;
> + default:
> + seq_printf(m, "Unknown region type %d : Src: %#016llx, Dest: %#016llx, ",
> + type, be64_to_cpu(fdm_ptr->rgn[i].source_address),
> + be64_to_cpu(fdm_ptr->rgn[i].destination_address));
> + break;
> + }
> + }
>
> /* Dump is active. Show preserved area start address. */
> if (fdm_active) {
> @@ -483,6 +554,20 @@ static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh,
> rtas_os_term((char *)msg);
> }
>
> +/* FADUMP_MAX_MEM_REGS or lower */
> +static int rtas_fadump_max_boot_mem_rgns(void)
> +{
> + /*
> + * Version 1 of Kernel Assisted Dump Memory Structure (PAPR) supports 10 sections.
> + * With one each section taken for CPU state data & HPTE respectively, 8 sections
> + * can be used for boot memory regions.
> + *
> + * If new region(s) is(are) defined, maximum boot memory regions will decrease
> + * proportionally.
> + */
> + return RTAS_FADUMP_MAX_BOOT_MEM_REGS;
> +}
> +
> static struct fadump_ops rtas_fadump_ops = {
> .fadump_init_mem_struct = rtas_fadump_init_mem_struct,
> .fadump_get_bootmem_min = rtas_fadump_get_bootmem_min,
> @@ -492,6 +577,7 @@ static struct fadump_ops rtas_fadump_ops = {
> .fadump_process = rtas_fadump_process,
> .fadump_region_show = rtas_fadump_region_show,
> .fadump_trigger = rtas_fadump_trigger,
> + .fadump_max_boot_mem_rgns = rtas_fadump_max_boot_mem_rgns,
> };
>
> void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
> diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.h b/arch/powerpc/platforms/pseries/rtas-fadump.h
> index fd59bd7ca9c3..6740f4981bb8 100644
> --- a/arch/powerpc/platforms/pseries/rtas-fadump.h
> +++ b/arch/powerpc/platforms/pseries/rtas-fadump.h
> @@ -29,6 +29,15 @@
> /* Dump status flag */
> #define RTAS_FADUMP_ERROR_FLAG 0x2000
>
> +/*
> + * The Firmware Assisted Dump Memory structure supports a maximum of 10 sections
> + * in the dump memory structure. Presently, first two sections are used for
> + * CPU and HPTE data, while the remaining eight sections can be used for
> + * boot memory regions.
> + */
> +#define MAX_SECTIONS 10
> +#define RTAS_FADUMP_MAX_BOOT_MEM_REGS 8
> +
> /* Kernel Dump section info */
> struct rtas_fadump_section {
> __be32 request_flag;
> @@ -61,20 +70,15 @@ struct rtas_fadump_section_header {
> * Firmware Assisted dump memory structure. This structure is required for
> * registering future kernel dump with power firmware through rtas call.
> *
> - * No disk dump option. Hence disk dump path string section is not included.
> + * In version 1, the platform permits one section header, dump-disk path
> + * and ten sections.
> + *
> + * Note: No disk dump option. Hence disk dump path string section is not
> + * included.
> */
> struct rtas_fadump_mem_struct {
> struct rtas_fadump_section_header header;
> -
> - /* 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;
> + struct rtas_fadump_section rgn[MAX_SECTIONS];
> };
>
> /*
More information about the Linuxppc-dev
mailing list