Re: [PATCH v4 18/25] powernv/fadump: process architected register state data provided by firmware
On 14/08/19 10:45 PM, Mahesh J Salgaonkar wrote: > On 2019-07-16 17:04:08 Tue, Hari Bathini wrote: >> From: Hari Bathini >> >> Firmware provides architected register state data at the time of crash. >> Process this data and build CPU notes to append to ELF core. >> >> Signed-off-by: Hari Bathini >> Signed-off-by: Vasant Hegde >> --- >> arch/powerpc/kernel/fadump-common.h |4 + >> arch/powerpc/platforms/powernv/opal-fadump.c | 197 >> -- >> arch/powerpc/platforms/powernv/opal-fadump.h | 39 + >> 3 files changed, 228 insertions(+), 12 deletions(-) >> > [...] >> @@ -430,6 +577,32 @@ int __init opal_fadump_dt_scan(struct fw_dump >> *fadump_conf, ulong node) >> return 1; >> } >> >> +ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, ); >> +if ((ret != OPAL_SUCCESS) || !addr) { >> +pr_err("Failed to get CPU metadata (%lld)\n", ret); >> +return 1; >> +} >> + >> +addr = be64_to_cpu(addr); >> +pr_debug("CPU metadata addr: %llx\n", addr); >> + >> +opal_cpu_metadata = __va(addr); >> +r_opal_cpu_metadata = (void *)addr; >> +fadump_conf->cpu_state_data_version = >> +be32_to_cpu(r_opal_cpu_metadata->cpu_data_version); >> +if (fadump_conf->cpu_state_data_version != >> +HDAT_FADUMP_CPU_DATA_VERSION) { >> +pr_err("CPU data format version (%lu) mismatch!\n", >> + fadump_conf->cpu_state_data_version); >> +return 1; >> +} I think cpu data version mismatch check should still be done early on? >> +fadump_conf->cpu_state_entry_size = >> +be32_to_cpu(r_opal_cpu_metadata->cpu_data_size); >> +fadump_conf->cpu_state_destination_addr = >> +be64_to_cpu(r_opal_cpu_metadata->region[0].dest); >> +fadump_conf->cpu_state_data_size = >> +be64_to_cpu(r_opal_cpu_metadata->region[0].size); >> + > > opal_fadump_dt_scan isn't the right place to do this. Can you please move > above > cpu related data processing to opal_fadump_build_cpu_notes() ? I will move the above cpu related data processing to opal_fadump_build_cpu_notes(). Thanks Hari
Re: [PATCH v4 18/25] powernv/fadump: process architected register state data provided by firmware
On 2019-07-16 17:04:08 Tue, Hari Bathini wrote: > From: Hari Bathini > > Firmware provides architected register state data at the time of crash. > Process this data and build CPU notes to append to ELF core. > > Signed-off-by: Hari Bathini > Signed-off-by: Vasant Hegde > --- > arch/powerpc/kernel/fadump-common.h |4 + > arch/powerpc/platforms/powernv/opal-fadump.c | 197 > -- > arch/powerpc/platforms/powernv/opal-fadump.h | 39 + > 3 files changed, 228 insertions(+), 12 deletions(-) > [...] > @@ -430,6 +577,32 @@ int __init opal_fadump_dt_scan(struct fw_dump > *fadump_conf, ulong node) > return 1; > } > > + ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, ); > + if ((ret != OPAL_SUCCESS) || !addr) { > + pr_err("Failed to get CPU metadata (%lld)\n", ret); > + return 1; > + } > + > + addr = be64_to_cpu(addr); > + pr_debug("CPU metadata addr: %llx\n", addr); > + > + opal_cpu_metadata = __va(addr); > + r_opal_cpu_metadata = (void *)addr; > + fadump_conf->cpu_state_data_version = > + be32_to_cpu(r_opal_cpu_metadata->cpu_data_version); > + if (fadump_conf->cpu_state_data_version != > + HDAT_FADUMP_CPU_DATA_VERSION) { > + pr_err("CPU data format version (%lu) mismatch!\n", > +fadump_conf->cpu_state_data_version); > + return 1; > + } > + fadump_conf->cpu_state_entry_size = > + be32_to_cpu(r_opal_cpu_metadata->cpu_data_size); > + fadump_conf->cpu_state_destination_addr = > + be64_to_cpu(r_opal_cpu_metadata->region[0].dest); > + fadump_conf->cpu_state_data_size = > + be64_to_cpu(r_opal_cpu_metadata->region[0].size); > + opal_fadump_dt_scan isn't the right place to do this. Can you please move above cpu related data processing to opal_fadump_build_cpu_notes() ? Thanks, -Mahesh. > pr_info("Firmware-assisted dump is active.\n"); > fadump_conf->dump_active = 1; > opal_fadump_get_config(fadump_conf, r_opal_fdm_active);
[PATCH v4 18/25] powernv/fadump: process architected register state data provided by firmware
From: Hari Bathini Firmware provides architected register state data at the time of crash. Process this data and build CPU notes to append to ELF core. Signed-off-by: Hari Bathini Signed-off-by: Vasant Hegde --- arch/powerpc/kernel/fadump-common.h |4 + arch/powerpc/platforms/powernv/opal-fadump.c | 197 -- arch/powerpc/platforms/powernv/opal-fadump.h | 39 + 3 files changed, 228 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/fadump-common.h b/arch/powerpc/kernel/fadump-common.h index 968745a..2dd0d9d 100644 --- a/arch/powerpc/kernel/fadump-common.h +++ b/arch/powerpc/kernel/fadump-common.h @@ -121,7 +121,11 @@ struct fw_dump { */ unsigned long preserv_area_start; + unsigned long cpu_state_destination_addr; + unsigned long cpu_state_data_version; + unsigned long cpu_state_entry_size; unsigned long cpu_state_data_size; + unsigned long hpte_region_size; unsigned long boot_memory_size; diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c index dffc0e7..479967c 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.c +++ b/arch/powerpc/platforms/powernv/opal-fadump.c @@ -27,6 +27,7 @@ #include "opal-fadump.h" static const struct opal_fadump_mem_struct *opal_fdm_active; +static const struct opal_mpipl_fadump *opal_cpu_metadata; static struct opal_fadump_mem_struct *opal_fdm; static void opal_fadump_update_config(struct fw_dump *fadump_conf, @@ -233,15 +234,115 @@ static int opal_fadump_invalidate_fadump(struct fw_dump *fadump_conf) return 0; } +static inline void opal_fadump_set_regval_regnum(struct pt_regs *regs, +u32 reg_type, u32 reg_num, +u64 reg_val) +{ + if (reg_type == HDAT_FADUMP_REG_TYPE_GPR) { + if (reg_num < 32) + regs->gpr[reg_num] = reg_val; + return; + } + + switch (reg_num) { + case SPRN_CTR: + regs->ctr = reg_val; + break; + case SPRN_LR: + regs->link = reg_val; + break; + case SPRN_XER: + regs->xer = reg_val; + break; + case SPRN_DAR: + regs->dar = reg_val; + break; + case SPRN_DSISR: + regs->dsisr = reg_val; + break; + case HDAT_FADUMP_REG_ID_NIP: + regs->nip = reg_val; + break; + case HDAT_FADUMP_REG_ID_MSR: + regs->msr = reg_val; + break; + case HDAT_FADUMP_REG_ID_CCR: + regs->ccr = reg_val; + break; + } +} + +static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt, +unsigned int reg_entry_size, +struct pt_regs *regs) +{ + int i; + struct hdat_fadump_reg_entry *reg_entry; + + memset(regs, 0, sizeof(struct pt_regs)); + + for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) { + reg_entry = (struct hdat_fadump_reg_entry *)bufp; + opal_fadump_set_regval_regnum(regs, + be32_to_cpu(reg_entry->reg_type), + be32_to_cpu(reg_entry->reg_num), + be64_to_cpu(reg_entry->reg_val)); + } +} + +static inline bool __init is_thread_core_inactive(u8 core_state) +{ + bool is_inactive = false; + + if (core_state == HDAT_FADUMP_CORE_INACTIVE) + is_inactive = true; + + return is_inactive; +} + /* * Convert CPU state data saved at the time of crash into ELF notes. + * + * Each register entry is of 16 bytes, A numerical identifier along with + * a GPR/SPR flag in the first 8 bytes and the register value in the next + * 8 bytes. For more details refer to F/W documentation. */ static int __init opal_fadump_build_cpu_notes(struct fw_dump *fadump_conf) { u32 num_cpus, *note_buf; struct fadump_crash_info_header *fdh = NULL; + struct hdat_fadump_thread_hdr *thdr; + unsigned long addr; + u32 thread_pir; + char *bufp; + struct pt_regs regs; + unsigned int size_of_each_thread; + unsigned int regs_offset, regs_cnt, reg_esize; + int i; + + if ((fadump_conf->cpu_state_destination_addr == 0) || + (fadump_conf->cpu_state_entry_size == 0)) { + pr_err("CPU state data not available for processing!\n"); + return -ENODEV; + } + + size_of_each_thread = fadump_conf->cpu_state_entry_size; + num_cpus = (fadump_conf->cpu_state_data_size / size_of_each_thread); + + addr = fadump_conf->cpu_state_destination_addr; + bufp = __va(addr);