Commit 6f713d18 authored by Hari Bathini's avatar Hari Bathini Committed by Michael Ellerman

powerpc/opalcore: export /sys/firmware/opal/core for analysing opal crashes

Export /sys/firmware/opal/core file to analyze opal crashes. Since OPAL
core can be generated independent of CONFIG_FA_DUMP support in kernel,
add this support under a new kernel config option CONFIG_OPAL_CORE.
Also, avoid code duplication by moving common code used while exporting
/proc/vmcore and/or /sys/firmware/opal/core file(s).
Signed-off-by: default avatarHari Bathini <hbathini@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/156821378503.5656.3693769384945087756.stgit@hbathini.in.ibm.com
parent 58cf055d
......@@ -592,6 +592,15 @@ config PRESERVE_FA_DUMP
memory preserving kernel boot would process this crash data.
Petitboot kernel is the typical usecase for this option.
config OPAL_CORE
bool "Export OPAL memory as /sys/firmware/opal/core"
depends on PPC64 && PPC_POWERNV
help
This option uses the MPIPL support in firmware to provide an
ELF core of OPAL memory after a crash. The ELF core is exported
as /sys/firmware/opal/core file which is helpful in debugging
OPAL crashes using GDB.
config IRQ_ALL_CPUS
bool "Distribute interrupts on all CPUs by default"
depends on SMP
......
......@@ -9,6 +9,7 @@ obj-y += ultravisor.o
obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
obj-$(CONFIG_FA_DUMP) += opal-fadump.o
obj-$(CONFIG_PRESERVE_FA_DUMP) += opal-fadump.o
obj-$(CONFIG_OPAL_CORE) += opal-core.o
obj-$(CONFIG_PCI) += pci.o pci-ioda.o npu-dma.o pci-ioda-tce.o
obj-$(CONFIG_CXL_BASE) += pci-cxl.o
obj-$(CONFIG_EEH) += eeh-powernv.o
......
This diff is collapsed.
......@@ -85,6 +85,10 @@ 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;
#ifdef CONFIG_OPAL_CORE
extern bool kernel_initiated;
#endif
static int opal_fadump_unregister(struct fw_dump *fadump_conf);
static void opal_fadump_update_config(struct fw_dump *fadump_conf,
......@@ -349,62 +353,6 @@ static void opal_fadump_cleanup(struct fw_dump *fadump_conf)
pr_warn("Could not reset (%llu) kernel metadata tag!\n", ret);
}
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)
{
struct hdat_fadump_reg_entry *reg_entry;
int i;
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));
}
}
/*
* Verify if CPU state data is available. If available, do a bit of sanity
* checking before processing this data.
......@@ -529,7 +477,7 @@ opal_fadump_build_cpu_notes(struct fw_dump *fadump_conf,
continue;
opal_fadump_read_regs((bufp + regs_offset), regs_cnt,
reg_esize, &regs);
reg_esize, true, &regs);
note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
pr_debug("CPU PIR: 0x%x - R1 : 0x%lx, NIP : 0x%lx\n",
thread_pir, regs.gpr[1], regs.nip);
......@@ -573,6 +521,18 @@ static int __init opal_fadump_process(struct fw_dump *fadump_conf)
return rc;
}
#ifdef CONFIG_OPAL_CORE
/*
* If this is a kernel initiated crash, crashing_cpu would be set
* appropriately and register data of the crashing CPU saved by
* crashing kernel. Add this saved register data of crashing CPU
* to elf notes and populate the pt_regs for the remaining CPUs
* from register state data provided by firmware.
*/
if (fdh->crashing_cpu != FADUMP_CPU_UNKNOWN)
kernel_initiated = true;
#endif
rc = opal_fadump_build_cpu_notes(fadump_conf, fdh);
if (rc)
return rc;
......
......@@ -8,6 +8,8 @@
#ifndef _POWERNV_OPAL_FADUMP_H
#define _POWERNV_OPAL_FADUMP_H
#include <asm/reg.h>
/*
* OPAL FADump metadata structure format version
*
......@@ -77,4 +79,64 @@ struct hdat_fadump_reg_entry {
__be64 reg_val;
} __packed;
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,
bool cpu_endian,
struct pt_regs *regs)
{
struct hdat_fadump_reg_entry *reg_entry;
u64 val;
int i;
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;
val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) :
reg_entry->reg_val);
opal_fadump_set_regval_regnum(regs,
be32_to_cpu(reg_entry->reg_type),
be32_to_cpu(reg_entry->reg_num),
val);
}
}
#endif /* _POWERNV_OPAL_FADUMP_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment