remoteproc: qcom: pas: Rename subsystem minidump elf name

Currently, the name of ELF remain same whether it is subsystem's
minidump or full dump and it was difficult for parsing tool to
identify the elf's between them.

As previous patch adds the support of creation of ramdump device
with a given name, now we would be creating separate dummy
minidump device for a subsystem with a name appended by _md.
which will help us in creating different name for subsystem's
minidump e.g remoteproc-adsp-md_2022-05-08_18-19-32.elf .

Change-Id: I6b49532b425b480e7351b7d1c86bb0ce29b09e1a
Signed-off-by: Mukesh Ojha <quic_mojha@quicinc.com>
This commit is contained in:
Mukesh Ojha
2022-05-13 16:12:09 +05:30
parent 7b92fc2502
commit 9cdb3f5818
3 changed files with 132 additions and 5 deletions

View File

@@ -5,6 +5,7 @@
* Copyright (C) 2016 Linaro Ltd
* Copyright (C) 2015 Sony Mobile Communications Inc
* Copyright (c) 2012-2013, 2020-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/firmware.h>
@@ -17,9 +18,11 @@
#include <linux/slab.h>
#include <linux/soc/qcom/mdt_loader.h>
#include <linux/soc/qcom/smem.h>
#include <linux/devcoredump.h>
#include <trace/hooks/remoteproc.h>
#include <trace/events/rproc_qcom.h>
#include "remoteproc_elf_helpers.h"
#include "remoteproc_internal.h"
#include "qcom_common.h"
@@ -171,7 +174,114 @@ static int qcom_add_minidump_segments(struct rproc *rproc, struct minidump_subsy
return 0;
}
void qcom_minidump(struct rproc *rproc, unsigned int minidump_id, rproc_dumpfn_t dumpfn)
static void qcom_rproc_minidump(struct rproc *rproc, struct device *md_dev)
{
struct rproc_dump_segment *segment;
void *shdr;
void *ehdr;
size_t data_size;
size_t strtbl_size = 0;
size_t strtbl_index = 1;
size_t offset;
void *data;
u8 class = rproc->elf_class;
int shnum;
unsigned int dump_conf = rproc->dump_conf;
char *str_tbl = "STR_TBL";
if (list_empty(&rproc->dump_segments) ||
dump_conf == RPROC_COREDUMP_DISABLED)
return;
if (class == ELFCLASSNONE) {
dev_err(&rproc->dev, "Elf class is not set\n");
return;
}
/*
* We allocate two extra section headers. The first one is null.
* Second section header is for the string table. Also space is
* allocated for string table.
*/
data_size = elf_size_of_hdr(class) + 2 * elf_size_of_shdr(class);
shnum = 2;
/* the extra byte is for the null character at index 0 */
strtbl_size += strlen(str_tbl) + 2;
list_for_each_entry(segment, &rproc->dump_segments, node) {
data_size += elf_size_of_shdr(class);
strtbl_size += strlen(segment->priv) + 1;
data_size += segment->size;
shnum++;
}
data_size += strtbl_size;
data = vmalloc(data_size);
if (!data)
return;
ehdr = data;
memset(ehdr, 0, elf_size_of_hdr(class));
/* e_ident field is common for both elf32 and elf64 */
elf_hdr_init_ident(ehdr, class);
elf_hdr_set_e_type(class, ehdr, ET_CORE);
elf_hdr_set_e_machine(class, ehdr, rproc->elf_machine);
elf_hdr_set_e_version(class, ehdr, EV_CURRENT);
elf_hdr_set_e_entry(class, ehdr, rproc->bootaddr);
elf_hdr_set_e_shoff(class, ehdr, elf_size_of_hdr(class));
elf_hdr_set_e_ehsize(class, ehdr, elf_size_of_hdr(class));
elf_hdr_set_e_shentsize(class, ehdr, elf_size_of_shdr(class));
elf_hdr_set_e_shnum(class, ehdr, shnum);
elf_hdr_set_e_shstrndx(class, ehdr, 1);
/*
* The zeroth index of the section header is reserved and is rarely used.
* Set the section header as null (SHN_UNDEF) and move to the next one.
*/
shdr = data + elf_hdr_get_e_shoff(class, ehdr);
memset(shdr, 0, elf_size_of_shdr(class));
shdr += elf_size_of_shdr(class);
/* Initialize the string table. */
offset = elf_hdr_get_e_shoff(class, ehdr) +
elf_size_of_shdr(class) * elf_hdr_get_e_shnum(class, ehdr);
memset(data + offset, 0, strtbl_size);
/* Fill in the string table section header. */
memset(shdr, 0, elf_size_of_shdr(class));
elf_shdr_set_sh_type(class, shdr, SHT_STRTAB);
elf_shdr_set_sh_offset(class, shdr, offset);
elf_shdr_set_sh_size(class, shdr, strtbl_size);
elf_shdr_set_sh_entsize(class, shdr, 0);
elf_shdr_set_sh_flags(class, shdr, 0);
elf_shdr_set_sh_name(class, shdr, elf_strtbl_add(str_tbl, ehdr, class, &strtbl_index));
offset += elf_shdr_get_sh_size(class, shdr);
shdr += elf_size_of_shdr(class);
list_for_each_entry(segment, &rproc->dump_segments, node) {
memset(shdr, 0, elf_size_of_shdr(class));
elf_shdr_set_sh_type(class, shdr, SHT_PROGBITS);
elf_shdr_set_sh_offset(class, shdr, offset);
elf_shdr_set_sh_addr(class, shdr, segment->da);
elf_shdr_set_sh_size(class, shdr, segment->size);
elf_shdr_set_sh_entsize(class, shdr, 0);
elf_shdr_set_sh_flags(class, shdr, SHF_WRITE);
elf_shdr_set_sh_name(class, shdr,
elf_strtbl_add(segment->priv, ehdr, class, &strtbl_index));
/* No need to copy segments for inline dumps */
segment->dump(rproc, segment, data + offset, 0, segment->size);
offset += elf_shdr_get_sh_size(class, shdr);
shdr += elf_size_of_shdr(class);
}
dev_coredumpv(md_dev, data, data_size, GFP_KERNEL);
}
void qcom_minidump(struct rproc *rproc, struct device *md_dev,
unsigned int minidump_id, rproc_dumpfn_t dumpfn)
{
int ret;
struct minidump_subsystem *subsystem;
@@ -213,9 +323,10 @@ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id, rproc_dumpfn_t
}
if (rproc->elf_class == ELFCLASS64)
rproc_coredump_using_sections(rproc);
qcom_rproc_minidump(rproc, md_dev);
else
rproc_coredump(rproc);
clean_minidump:
qcom_minidump_cleanup(rproc);
}

View File

@@ -58,7 +58,8 @@ extern bool qcom_device_shutdown_in_progress;
typedef void (*rproc_dumpfn_t)(struct rproc *rproc, struct rproc_dump_segment *segment,
void *dest, size_t offset, size_t size);
void qcom_minidump(struct rproc *rproc, unsigned int minidump_id, rproc_dumpfn_t dumpfn);
void qcom_minidump(struct rproc *rproc, struct device *md_dev,
unsigned int minidump_id, rproc_dumpfn_t dumpfn);
void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink,
const char *ssr_name);

View File

@@ -5,6 +5,7 @@
* Copyright (C) 2016 Linaro Ltd
* Copyright (C) 2014 Sony Mobile Communications AB
* Copyright (c) 2012-2013, 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk.h>
@@ -28,6 +29,7 @@
#include <linux/soc/qcom/smem_state.h>
#include <linux/soc/qcom/qcom_aoss.h>
#include <trace/events/rproc_qcom.h>
#include <soc/qcom/qcom_ramdump.h>
#include "qcom_common.h"
#include "qcom_pil_info.h"
@@ -66,6 +68,7 @@ struct adsp_data {
struct qcom_adsp {
struct device *dev;
struct device *minidump_dev;
struct rproc *rproc;
struct qcom_q6v5 q6v5;
@@ -144,7 +147,7 @@ static void adsp_minidump(struct rproc *rproc)
if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
goto exit;
qcom_minidump(rproc, adsp->minidump_id, adsp_segment_dump);
qcom_minidump(rproc, adsp->minidump_dev, adsp->minidump_id, adsp_segment_dump);
exit:
trace_rproc_qcom_event(dev_name(adsp->dev), "adsp_minidump", "exit");
@@ -719,6 +722,7 @@ static int adsp_probe(struct platform_device *pdev)
struct rproc *rproc;
const char *fw_name;
const struct rproc_ops *ops = &adsp_ops;
char md_dev_name[32];
int ret;
desc = of_device_get_match_data(&pdev->dev);
@@ -828,11 +832,21 @@ static int adsp_probe(struct platform_device *pdev)
if (ret)
goto remove_subdevs;
snprintf(md_dev_name, ARRAY_SIZE(md_dev_name), "%s-md", pdev->dev.of_node->name);
adsp->minidump_dev = qcom_create_ramdump_device(md_dev_name, NULL);
if (!adsp->minidump_dev) {
dev_err(&pdev->dev, "Unable to create %s minidump device.\n", md_dev_name);
ret = -ENOMEM;
goto remove_attr_txn_id;
}
ret = rproc_add(rproc);
if (ret)
goto remove_attr_txn_id;
goto destroy_minidump_dev;
return 0;
destroy_minidump_dev:
qcom_destroy_ramdump_device(adsp->minidump_dev);
remove_attr_txn_id:
device_remove_file(adsp->dev, &dev_attr_txn_id);
remove_subdevs:
@@ -854,6 +868,7 @@ static int adsp_remove(struct platform_device *pdev)
struct qcom_adsp *adsp = platform_get_drvdata(pdev);
rproc_del(adsp->rproc);
qcom_destroy_ramdump_device(adsp->minidump_dev);
device_remove_file(adsp->dev, &dev_attr_txn_id);
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
qcom_remove_sysmon_subdev(adsp->sysmon);