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

Commit facd0a72 authored by Lingutla Chandrasekhar's avatar Lingutla Chandrasekhar Committed by Neeraj Upadhyay
Browse files

Minidump: Add update region support for minidump regions



Add support to update client's entry physical/virtual addresses,
which is useful for DLKM, dynamic address changing clients.

Currently, msm_minidump_add_region() returns 0 on success, instead
of that, return 'region number' of the entry in the minidump table.

So clients who wants to update their address in future, needs to
book keep their entry in minidump table.

Change-Id: I03abbbd87bf6d2e11cf637525412d352772821cf
Signed-off-by: default avatarLingutla Chandrasekhar <clingutla@codeaurora.org>
[neeraju@codeaurora: Add mdt_remove_lock to serialize with removal]
Signed-off-by: default avatarNeeraj Upadhyay <neeraju@codeaurora.org>
parent c77acc02
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1842,7 +1842,7 @@ static int lpm_probe(struct platform_device *pdev)
	md_entry.phys_addr = lpm_debug_phys;
	md_entry.size = size;
	md_entry.id = MINIDUMP_DEFAULT_ID;
	if (msm_minidump_add_region(&md_entry))
	if (msm_minidump_add_region(&md_entry) < 0)
		pr_info("Failed to add lpm_debug in Minidump\n");

	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -1897,7 +1897,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;
+2 −2
Original line number Diff line number Diff line
@@ -679,7 +679,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;
@@ -876,7 +876,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);

+5 −5
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ static void __init register_log_buf(void)
	md_entry.phys_addr = virt_to_phys(*log_bufp);
	md_entry.size = *log_buf_lenp;
	md_entry.id = MINIDUMP_DEFAULT_ID;
	if (msm_minidump_add_region(&md_entry))
	if (msm_minidump_add_region(&md_entry) < 0)
		pr_err("Failed to add logbuf in Minidump\n");
}

@@ -54,7 +54,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);
}

@@ -71,7 +71,7 @@ static void __init register_kernel_sections(void)
	ksec_entry.phys_addr = virt_to_phys(_sdata);
	ksec_entry.size = roundup((__bss_stop - _sdata), 4);
	ksec_entry.id = MINIDUMP_DEFAULT_ID;
	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 */
@@ -85,7 +85,7 @@ static void __init register_kernel_sections(void)
		ksec_entry.phys_addr = per_cpu_ptr_to_phys(start);
		ksec_entry.size = static_size;
		ksec_entry.id = MINIDUMP_DEFAULT_ID;
		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");
	}
}
@@ -158,7 +158,7 @@ void dump_stack_minidump(u64 sp)
	ktsk_entry.phys_addr = virt_to_phys((uintptr_t *)current);
	ktsk_entry.size = sizeof(struct task_struct);
	ktsk_entry.id = MINIDUMP_DEFAULT_ID;
	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);
}

+68 −6
Original line number Diff line number Diff line
@@ -55,8 +55,10 @@ 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;

/* Number of pending entries to be added in ToC regions */
static unsigned int pendings;
@@ -166,11 +168,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 +179,64 @@ 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;

	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 +269,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 +358,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 +367,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 +398,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;
Loading