Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3906d34c authored by Lingutla Chandrasekhar's avatar Lingutla Chandrasekhar
Browse files

soc: qcom: Add Minidump support



Add Minidump support for clients to get minimum required data
at the time of system crash. The Minidump table resides in SMEM,
BOOT(SBL) will iterate the table entries and dumps out (to USB/Flash)
the data in address location.

Any client can register to this table with static or known addresses,
as currently Minidump doesn't support dumping of dynamic data structures.

To simplify post processing, we create an ELF header, where each entry in
the minidump table is a section in elf header.
If Memory dump table enabled, Dump all data entries registered with MDT.

Enable Minidump:
	echo mini > /sys/kernel/dload/dload_mode

Change-Id: I0fc8d21aef71ded34a498426ee3d7f86b063a639
Signed-off-by: default avatarLingutla Chandrasekhar <clingutla@codeaurora.org>
parent 7514c164
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
/* Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -2557,6 +2557,8 @@ static int etm4_set_reg_dump(struct etmv4_drvdata *drvdata)

	drvdata->reg_data.addr = virt_to_phys(baddr);
	drvdata->reg_data.len = size;
	scnprintf(drvdata->reg_data.name, sizeof(drvdata->reg_data.name),
		"KETM_REG%d", drvdata->cpu);

	dump_entry.id = MSM_DUMP_DATA_ETM_REG + drvdata->cpu;
	dump_entry.addr = virt_to_phys(&drvdata->reg_data);
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012, 2016 The Linux Foundation. All rights reserved.
/* Copyright (c) 2012, 2016-2017 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1726,6 +1726,9 @@ static int tmc_etf_set_buf_dump(struct tmc_drvdata *drvdata)

	drvdata->buf_data.addr = virt_to_phys(drvdata->buf);
	drvdata->buf_data.len = drvdata->size;
	scnprintf(drvdata->buf_data.name, sizeof(drvdata->buf_data.name),
		"KTMC_ETF%d", count);

	dump_entry.id = MSM_DUMP_DATA_TMC_ETF + count;
	dump_entry.addr = virt_to_phys(&drvdata->buf_data);

@@ -1817,6 +1820,8 @@ static int tmc_set_reg_dump(struct tmc_drvdata *drvdata)

	drvdata->reg_data.addr = virt_to_phys(drvdata->reg_buf);
	drvdata->reg_data.len = size;
	scnprintf(drvdata->reg_data.name, sizeof(drvdata->reg_data.name),
		"KTMC_REG%d", count);

	dump_entry.id = MSM_DUMP_DATA_TMC_REG + count;
	dump_entry.addr = virt_to_phys(&drvdata->reg_data);
+2 −0
Original line number Diff line number Diff line
@@ -864,6 +864,8 @@ static int msm_11ad_ssr_init(struct msm11ad_ctx *ctx)

	ctx->dump_data.addr = virt_to_phys(ctx->ramdump_addr);
	ctx->dump_data.len = WIGIG_RAMDUMP_SIZE;
	strlcpy(ctx->dump_data.name, "KWIGIG",
			 sizeof(ctx->dump_data.name));
	dump_entry.id = MSM_DUMP_DATA_WIGIG;
	dump_entry.addr = virt_to_phys(&ctx->dump_data);

+46 −4
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <soc/qcom/scm.h>
#include <soc/qcom/restart.h>
#include <soc/qcom/watchdog.h>
#include <soc/qcom/minidump.h>

#define EMERGENCY_DLOAD_MAGIC1    0x322A4F99
#define EMERGENCY_DLOAD_MAGIC2    0xC67E4350
@@ -42,9 +43,10 @@
#define SCM_IO_DISABLE_PMIC_ARBITER	1
#define SCM_IO_DEASSERT_PS_HOLD		2
#define SCM_WDOG_DEBUG_BOOT_PART	0x9
#define SCM_DLOAD_MODE			0X10
#define SCM_DLOAD_FULLDUMP		0X10
#define SCM_EDLOAD_MODE			0X01
#define SCM_DLOAD_CMD			0x10
#define SCM_DLOAD_MINIDUMP		0X20


static int restart_mode;
@@ -69,6 +71,7 @@ static void scm_disable_sdi(void);
#endif

static int in_panic;
static int dload_type = SCM_DLOAD_FULLDUMP;
static int download_mode = 1;
static struct kobject dload_kobj;
static void *dload_mode_addr, *dload_type_addr;
@@ -142,7 +145,7 @@ static void set_dload_mode(int on)
		mb();
	}

	ret = scm_set_dload_mode(on ? SCM_DLOAD_MODE : 0, 0);
	ret = scm_set_dload_mode(on ? dload_type : 0, 0);
	if (ret)
		pr_err("Failed to set secure DLOAD mode: %d\n", ret);

@@ -185,7 +188,6 @@ static int dload_set(const char *val, struct kernel_param *kp)
	int old_val = download_mode;

	ret = param_set_int(val, kp);

	if (ret)
		return ret;

@@ -454,7 +456,7 @@ static ssize_t show_emmc_dload(struct kobject *kobj, struct attribute *attr,
	else
		show_val = 0;

	return snprintf(buf, sizeof(show_val), "%u\n", show_val);
	return scnprintf(buf, sizeof(show_val), "%u\n", show_val);
}

static size_t store_emmc_dload(struct kobject *kobj, struct attribute *attr,
@@ -477,10 +479,50 @@ static size_t store_emmc_dload(struct kobject *kobj, struct attribute *attr,

	return count;
}

#ifdef CONFIG_QCOM_MINIDUMP

static DEFINE_MUTEX(tcsr_lock);

static ssize_t show_dload_mode(struct kobject *kobj, struct attribute *attr,
				char *buf)
{
	return scnprintf(buf, PAGE_SIZE, "DLOAD dump type: %s\n",
			(dload_type == SCM_DLOAD_MINIDUMP) ? "mini" : "full");
}

static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
				const char *buf, size_t count)
{
	if (sysfs_streq(buf, "full")) {
		dload_type = SCM_DLOAD_FULLDUMP;
	} else if (sysfs_streq(buf, "mini")) {
		if (!msm_minidump_enabled()) {
			pr_info("Minidump is not enabled\n");
			return -ENODEV;
		}
		dload_type = SCM_DLOAD_MINIDUMP;
	} else {
		pr_info("Invalid value. Use 'full' or 'mini'\n");
		return -EINVAL;
	}

	mutex_lock(&tcsr_lock);
	/*Overwrite TCSR reg*/
	set_dload_mode(dload_type);
	mutex_unlock(&tcsr_lock);
	return count;
}
RESET_ATTR(dload_mode, 0644, show_dload_mode, store_dload_mode);
#endif

RESET_ATTR(emmc_dload, 0644, show_emmc_dload, store_emmc_dload);

static struct attribute *reset_attrs[] = {
	&reset_attr_emmc_dload.attr,
#ifdef CONFIG_QCOM_MINIDUMP
	&reset_attr_dload_mode.attr,
#endif
	NULL
};

+17 −0
Original line number Diff line number Diff line
@@ -441,6 +441,23 @@ config QCOM_MEMORY_DUMP_V2
	  of deadlocks or cpu hangs these dump regions are captured to
	  give a snapshot of the system at the time of the crash.

config QCOM_MINIDUMP
	bool "QCOM Minidump Support"
	depends on MSM_SMEM && QCOM_DLOAD_MODE
	help
	  This enables minidump feature. It allows various clients to
	  register to dump their state at system bad state (panic/WDT,etc.,).
	  This uses SMEM to store all registered client information.
	  This will dump all registered entries, only when DLOAD mode is enabled.

config MINIDUMP_MAX_ENTRIES
	int "Minidump Maximum num of entries"
	default 200
	depends on QCOM_MINIDUMP
	help
	  This defines maximum number of entries to be allocated for application
	  subsytem in Minidump SMEM table.

config ICNSS
	tristate "Platform driver for Q6 integrated connectivity"
	---help---
Loading