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

Commit 1e461678 authored by Lingutla Chandrasekhar's avatar Lingutla Chandrasekhar
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>
parent d070dfa3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1776,7 +1776,7 @@ static int lpm_probe(struct platform_device *pdev)
	md_entry.virt_addr = (uintptr_t)lpm_debug;
	md_entry.phys_addr = lpm_debug_phys;
	md_entry.size = size;
	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
@@ -140,7 +140,7 @@ int msm_dump_data_register(enum msm_dump_table_ids id,

	dmac_flush_range(table, (void *)table + sizeof(struct msm_dump_table));

	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 0;
+6 −6
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 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
@@ -37,7 +37,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");
}

@@ -53,7 +53,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 */
@@ -66,7 +66,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");
	}
}
@@ -87,14 +87,14 @@ void dump_stack_minidump(u64 sp)
	ksp_entry.virt_addr = sp;
	ksp_entry.phys_addr = virt_to_phys((uintptr_t *)sp);
	ksp_entry.size = THREAD_SIZE;
	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);

	scnprintf(ktsk_entry.name, sizeof(ktsk_entry.name), "KTASK%d", cpu);
	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);
}

+55 −13
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 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
@@ -169,17 +169,10 @@ 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;
	int ret = 0;

	if (!entry)
		return -EINVAL;

	if ((strlen(entry->name) > MAX_NAME_LENGTH) ||
		md_check_name(entry->name) || !entry->virt_addr) {
	if (!entry || (strlen(entry->name) > MAX_NAME_LENGTH) ||
		!entry->virt_addr) {
		pr_err("Invalid entry details\n");
		return -EINVAL;
	}
@@ -188,6 +181,55 @@ int msm_minidump_add_region(const struct md_region *entry)
		pr_err("size should be 4 byte aligned\n");
		return -EINVAL;
	}
	return 0;
}

int msm_minidump_update_region(int regno, const struct md_region *entry)
{
	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;

	if (!md_check_name(entry->name)) {
		pr_err("Region:[%s] does not exist to update.\n", entry->name);
		return -ENOMEM;
	}

	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;

	return 0;
}
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;

	if (md_check_name(entry->name)) {
		pr_err("Region name [%s] already registered\n", entry->name);
		return -EEXIST;
	}

	spin_lock(&mdt_lock);
	entries = minidump_table.num_regions;
@@ -215,7 +257,7 @@ int msm_minidump_add_region(const struct md_region *entry)

	spin_unlock(&mdt_lock);

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

+1 −1
Original line number Diff line number Diff line
@@ -885,7 +885,7 @@ static int msm_watchdog_probe(struct platform_device *pdev)
	md_entry.virt_addr = (uintptr_t)wdog_dd;
	md_entry.phys_addr = virt_to_phys(wdog_dd);
	md_entry.size = sizeof(*wdog_dd);
	if (msm_minidump_add_region(&md_entry))
	if (msm_minidump_add_region(&md_entry) < 0)
		pr_info("Failed to add Watchdog data in Minidump\n");

	return 0;
Loading