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

Commit 7b3ceccc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "Minidump: Add update region support for minidump regions"

parents 5f046bd2 465231e6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2183,7 +2183,7 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv,
		    md_entry.name, va, &pa, size);

	ret = msm_minidump_add_region(&md_entry);
	if (ret)
	if (ret < 0)
		cnss_pr_err("Failed to add mini dump region, err = %d\n", ret);

	return ret;
+1 −1
Original line number Diff line number Diff line
@@ -1849,7 +1849,7 @@ static int dcc_probe(struct platform_device *pdev)
	md_entry.virt_addr = (uintptr_t)drvdata->ram_base;
	md_entry.phys_addr = res->start;
	md_entry.size = drvdata->ram_size;
	if (msm_minidump_add_region(&md_entry))
	if (msm_minidump_add_region(&md_entry) < 0)
		dev_err(drvdata->dev, "Failed to add DCC data in Minidump\n");

	return 0;
+2 −2
Original line number Diff line number Diff line
@@ -662,7 +662,7 @@ int msm_dump_data_register(enum msm_dump_table_ids id,

	ret = register_dump_table_entry(id, entry);
	if (!ret)
		if (msm_dump_data_add_minidump(entry))
		if (msm_dump_data_add_minidump(entry) < 0)
			pr_err("Failed to add entry in Minidump table\n");

	return ret;
@@ -856,7 +856,7 @@ static int mem_dump_alloc(struct platform_device *pdev)
		md_entry.size = size;
		md_entry.id = id;
		strlcpy(md_entry.name, child_node->name, sizeof(md_entry.name));
		if (msm_minidump_add_region(&md_entry))
		if (msm_minidump_add_region(&md_entry) < 0)
			dev_err(&pdev->dev, "Mini dump entry failed id = %d\n",
				id);

+44 −6
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/module.h>
@@ -11,6 +11,7 @@
#include <linux/thread_info.h>
#include <soc/qcom/minidump.h>
#include <asm/sections.h>
#include <asm/stacktrace.h>
#include <linux/mm.h>
#include <linux/sched/task.h>
#include <linux/vmalloc.h>
@@ -32,7 +33,7 @@ static void __init register_log_buf(void)
	md_entry.virt_addr = (uintptr_t) (*log_bufp);
	md_entry.phys_addr = virt_to_phys(*log_bufp);
	md_entry.size = *log_buf_lenp;
	if (msm_minidump_add_region(&md_entry))
	if (msm_minidump_add_region(&md_entry) < 0)
		pr_err("Failed to add logbuf in Minidump\n");
}

@@ -51,7 +52,7 @@ static void register_stack_entry(struct md_region *ksp_entry, u64 sp, u64 size,
		ksp_entry->phys_addr = virt_to_phys((uintptr_t *)sp);
	}

	if (msm_minidump_add_region(ksp_entry))
	if (msm_minidump_add_region(ksp_entry) < 0)
		pr_err("Failed to add stack of cpu %d in Minidump\n", cpu);
}

@@ -67,7 +68,7 @@ static void __init register_kernel_sections(void)
	ksec_entry.virt_addr = (uintptr_t)_sdata;
	ksec_entry.phys_addr = virt_to_phys(_sdata);
	ksec_entry.size = roundup((__bss_stop - _sdata), 4);
	if (msm_minidump_add_region(&ksec_entry))
	if (msm_minidump_add_region(&ksec_entry) < 0)
		pr_err("Failed to add data section in Minidump\n");

	/* Add percpu static sections */
@@ -80,7 +81,7 @@ static void __init register_kernel_sections(void)
		ksec_entry.virt_addr = (uintptr_t)start;
		ksec_entry.phys_addr = per_cpu_ptr_to_phys(start);
		ksec_entry.size = static_size;
		if (msm_minidump_add_region(&ksec_entry))
		if (msm_minidump_add_region(&ksec_entry) < 0)
			pr_err("Failed to add percpu sections in Minidump\n");
	}
}
@@ -152,13 +153,50 @@ void dump_stack_minidump(u64 sp)
	ktsk_entry.virt_addr = (u64)current;
	ktsk_entry.phys_addr = virt_to_phys((uintptr_t *)current);
	ktsk_entry.size = sizeof(struct task_struct);
	if (msm_minidump_add_region(&ktsk_entry))
	if (msm_minidump_add_region(&ktsk_entry) < 0)
		pr_err("Failed to add current task %d in Minidump\n", cpu);
}

#ifdef CONFIG_ARM64
static void register_irq_stack(void)
{
	int cpu;
	unsigned int i;
	int irq_stack_pages_count;
	u64 irq_stack_base;
	struct md_region irq_sp_entry;
	u64 sp;

	for_each_possible_cpu(cpu) {
		irq_stack_base = (u64)per_cpu(irq_stack_ptr, cpu);
		if (IS_ENABLED(CONFIG_VMAP_STACK)) {
			irq_stack_pages_count = IRQ_STACK_SIZE / PAGE_SIZE;
			sp = irq_stack_base & ~(PAGE_SIZE - 1);
			for (i = 0; i < irq_stack_pages_count; i++) {
				scnprintf(irq_sp_entry.name,
					  sizeof(irq_sp_entry.name),
					  "KISTACK%d_%d", cpu, i);
				register_stack_entry(&irq_sp_entry, sp,
						     PAGE_SIZE, cpu);
				sp += PAGE_SIZE;
			}
		} else {
			sp = irq_stack_base;
			scnprintf(irq_sp_entry.name, sizeof(irq_sp_entry.name),
				  "KISTACK%d", cpu);
			register_stack_entry(&irq_sp_entry, sp, IRQ_STACK_SIZE,
					     cpu);
		}
	}
}
#else
static inline void register_irq_stack(void) {}
#endif

static int __init msm_minidump_log_init(void)
{
	register_kernel_sections();
	register_irq_stack();
	register_log_buf();
	return 0;
}
+75 −6
Original line number Diff line number Diff line
@@ -55,8 +55,11 @@ struct md_elfhdr {

/* Protect elfheader and smem table from deferred calls contention */
static DEFINE_SPINLOCK(mdt_lock);
static DEFINE_RWLOCK(mdt_remove_lock);
static struct md_table		minidump_table;
static struct md_elfhdr		minidump_elfheader;
static int first_removed_entry = INT_MAX;
static bool md_init_done;

/* Number of pending entries to be added in ToC regions */
static unsigned int pendings;
@@ -166,11 +169,8 @@ bool msm_minidump_enabled(void)
}
EXPORT_SYMBOL(msm_minidump_enabled);

int msm_minidump_add_region(const struct md_region *entry)
static inline int validate_region(const struct md_region *entry)
{
	u32 entries;
	struct md_region *mdr;

	if (!entry)
		return -EINVAL;

@@ -180,6 +180,68 @@ int msm_minidump_add_region(const struct md_region *entry)
		return -EINVAL;
	}

	return 0;
}

int msm_minidump_update_region(int regno, const struct md_region *entry)
{
	int ret = 0;
	struct md_region *mdr;
	struct md_ss_region *mdssr;
	struct elfhdr *hdr = minidump_elfheader.ehdr;
	struct elf_shdr *shdr;
	struct elf_phdr *phdr;

	/* Ensure that init completes before we update regions */
	if (!smp_load_acquire(&md_init_done))
		return -EINVAL;

	if (validate_region(entry) || (regno >= MAX_NUM_ENTRIES))
		return -EINVAL;

	read_lock(&mdt_remove_lock);

	if (regno >= first_removed_entry) {
		pr_err("Region:[%s] was moved\n", entry->name);
		ret = -EINVAL;
		goto err_unlock;
	}

	if (md_entry_num(entry) < 0) {
		pr_err("Region:[%s] does not exist to update.\n", entry->name);
		ret = -ENOMEM;
		goto err_unlock;
	}

	mdr = &minidump_table.entry[regno];
	mdr->virt_addr = entry->virt_addr;
	mdr->phys_addr = entry->phys_addr;

	mdssr = &minidump_table.md_regions[regno + 1];
	mdssr->region_base_address = entry->phys_addr;

	shdr = elf_section(hdr, regno + 4);
	phdr = elf_program(hdr, regno + 1);

	shdr->sh_addr = (elf_addr_t)entry->virt_addr;
	phdr->p_vaddr = entry->virt_addr;
	phdr->p_paddr = entry->phys_addr;

err_unlock:
	read_unlock(&mdt_remove_lock);

	return ret;
}
EXPORT_SYMBOL(msm_minidump_update_region);

int msm_minidump_add_region(const struct md_region *entry)
{
	u32 entries;
	struct md_region *mdr;

	if (validate_region(entry))
		return -EINVAL;

	spin_lock(&mdt_lock);
	if (md_entry_num(entry) >= 0) {
		pr_err("Entry name already exist.\n");
@@ -212,7 +274,7 @@ int msm_minidump_add_region(const struct md_region *entry)

	spin_unlock(&mdt_lock);

	return 0;
	return entries;
}
EXPORT_SYMBOL(msm_minidump_add_region);

@@ -301,6 +363,7 @@ int msm_minidump_remove_region(const struct md_region *entry)
		return -EINVAL;

	spin_lock(&mdt_lock);
	write_lock(&mdt_remove_lock);
	ecount = minidump_table.num_regions;
	rcount = minidump_table.md_ss_toc->ss_region_count;
	rgno = md_entry_num(entry);
@@ -309,6 +372,8 @@ int msm_minidump_remove_region(const struct md_region *entry)
		goto out;
	}

	if (first_removed_entry > rgno)
		first_removed_entry = rgno;
	minidump_table.md_ss_toc->md_ss_toc_init = 0;

	/* Remove entry from: entry list, ss region list and elf header */
@@ -338,9 +403,11 @@ int msm_minidump_remove_region(const struct md_region *entry)
	minidump_table.md_ss_toc->md_ss_toc_init = 1;

	minidump_table.num_regions--;
	write_unlock(&mdt_remove_lock);
	spin_unlock(&mdt_lock);
	return 0;
out:
	write_unlock(&mdt_remove_lock);
	spin_unlock(&mdt_lock);
	pr_err("Minidump is broken..disable Minidump collection\n");
	return -EINVAL;
@@ -507,6 +574,8 @@ static int __init msm_minidump_init(void)
	pr_info("Enabled with max number of regions %d\n",
		CONFIG_MINIDUMP_MAX_ENTRIES);

	/* All updates above should be visible, before init completes */
	smp_store_release(&md_init_done, true);
	return 0;
}
subsys_initcall(msm_minidump_init)
Loading