summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/powernv/opal-fadump.c
diff options
context:
space:
mode:
authorHari Bathini <hbathini@linux.ibm.com>2019-09-11 17:50:57 +0300
committerMichael Ellerman <mpe@ellerman.id.au>2019-09-13 17:04:43 +0300
commit742a265accd3e3afcc8e7b17f409c93c1de8be85 (patch)
tree134a9dce27087f15d67dd637a7cb0175709ca457 /arch/powerpc/platforms/powernv/opal-fadump.c
parent6abec12c65e8870d8cafe154a86240fe0bcdd4f7 (diff)
downloadlinux-742a265accd3e3afcc8e7b17f409c93c1de8be85.tar.xz
powerpc/fadump: register kernel metadata address with opal
OPAL allows registering address with it in the first kernel and retrieving it after MPIPL. Setup kernel metadata and register its address with OPAL to use it for processing the crash dump. Signed-off-by: Hari Bathini <hbathini@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/156821345011.5656.13567765019032928471.stgit@hbathini.in.ibm.com
Diffstat (limited to 'arch/powerpc/platforms/powernv/opal-fadump.c')
-rw-r--r--arch/powerpc/platforms/powernv/opal-fadump.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c
index bbc5356bdc77..21de832f2ba4 100644
--- a/arch/powerpc/platforms/powernv/opal-fadump.c
+++ b/arch/powerpc/platforms/powernv/opal-fadump.c
@@ -11,13 +11,83 @@
#include <linux/seq_file.h>
#include <linux/of_fdt.h>
#include <linux/libfdt.h>
+#include <linux/mm.h>
+#include <asm/page.h>
#include <asm/opal.h>
#include <asm/fadump-internal.h>
+#include "opal-fadump.h"
+
+static struct opal_fadump_mem_struct *opal_fdm;
+
+/* Initialize kernel metadata */
+static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm)
+{
+ fdm->version = OPAL_FADUMP_VERSION;
+ fdm->region_cnt = 0;
+ fdm->registered_regions = 0;
+ fdm->fadumphdr_addr = 0;
+}
+
static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf)
{
- return fadump_conf->reserve_dump_area_start;
+ u64 addr = fadump_conf->reserve_dump_area_start;
+
+ 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;
+
+ /*
+ * Kernel metadata is passed to f/w and retrieved in capture kerenl.
+ * So, use it to save fadump header address instead of calculating it.
+ */
+ opal_fdm->fadumphdr_addr = (opal_fdm->rgn[0].dest +
+ fadump_conf->boot_memory_size);
+
+ return addr;
+}
+
+static u64 opal_fadump_get_metadata_size(void)
+{
+ return PAGE_ALIGN(sizeof(struct opal_fadump_mem_struct));
+}
+
+static int opal_fadump_setup_metadata(struct fw_dump *fadump_conf)
+{
+ int err = 0;
+ s64 ret;
+
+ /*
+ * Use the last page(s) in FADump memory reservation for
+ * kernel metadata.
+ */
+ fadump_conf->kernel_metadata = (fadump_conf->reserve_dump_area_start +
+ fadump_conf->reserve_dump_area_size -
+ opal_fadump_get_metadata_size());
+ pr_info("Kernel metadata addr: %llx\n", fadump_conf->kernel_metadata);
+
+ /* Initialize kernel metadata before registering the address with f/w */
+ opal_fdm = __va(fadump_conf->kernel_metadata);
+ opal_fadump_init_metadata(opal_fdm);
+
+ /*
+ * Register metadata address with f/w. Can be retrieved in
+ * the capture kernel.
+ */
+ ret = opal_mpipl_register_tag(OPAL_MPIPL_TAG_KERNEL,
+ fadump_conf->kernel_metadata);
+ if (ret != OPAL_SUCCESS) {
+ pr_err("Failed to set kernel metadata tag!\n");
+ err = -EPERM;
+ }
+
+ return err;
}
static int opal_fadump_register(struct fw_dump *fadump_conf)
@@ -43,6 +113,16 @@ static int __init opal_fadump_process(struct fw_dump *fadump_conf)
static void opal_fadump_region_show(struct fw_dump *fadump_conf,
struct seq_file *m)
{
+ const struct opal_fadump_mem_struct *fdm_ptr = opal_fdm;
+ u64 dumped_bytes = 0;
+ int i;
+
+ for (i = 0; i < fdm_ptr->region_cnt; i++) {
+ seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
+ fdm_ptr->rgn[i].src, fdm_ptr->rgn[i].dest);
+ seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
+ fdm_ptr->rgn[i].size, dumped_bytes);
+ }
}
static void opal_fadump_trigger(struct fadump_crash_info_header *fdh,
@@ -60,6 +140,8 @@ static void opal_fadump_trigger(struct fadump_crash_info_header *fdh,
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,
+ .fadump_setup_metadata = opal_fadump_setup_metadata,
.fadump_register = opal_fadump_register,
.fadump_unregister = opal_fadump_unregister,
.fadump_invalidate = opal_fadump_invalidate,