mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
Merge "Minidump: Add update region support for minidump regions"
This commit is contained in:
commit
7b3ceccc73
8 changed files with 137 additions and 21 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ struct md_table {
|
|||
struct md_ss_toc *md_ss_toc;
|
||||
struct md_global_toc *md_gbl_toc;
|
||||
struct md_ss_region *md_regions;
|
||||
struct md_region entry[MAX_NUM_ENTRIES];
|
||||
struct md_region entry[MAX_NUM_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ int qcom_wdt_register(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)
|
||||
dev_err(wdog_dd->dev, "Failed to add Wdt data in Minidump\n");
|
||||
return 0;
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -25,14 +25,23 @@ struct md_region {
|
|||
u64 size;
|
||||
};
|
||||
|
||||
/* Register an entry in Minidump table
|
||||
/*
|
||||
* Register an entry in Minidump table
|
||||
* Returns:
|
||||
* Zero: on successful addition
|
||||
* Negetive error number on failures
|
||||
* region number: entry position in minidump table.
|
||||
* Negative error number on failures.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_QCOM_MINIDUMP)
|
||||
extern int msm_minidump_add_region(const struct md_region *entry);
|
||||
extern int msm_minidump_remove_region(const struct md_region *entry);
|
||||
/*
|
||||
* Update registered region address in Minidump table.
|
||||
* It does not hold any locks, so strictly serialize the region updates.
|
||||
* Returns:
|
||||
* Zero: on successfully update
|
||||
* Negetive error number on failures.
|
||||
*/
|
||||
extern int msm_minidump_update_region(int regno, const struct md_region *entry);
|
||||
extern bool msm_minidump_enabled(void);
|
||||
extern void dump_stack_minidump(u64 sp);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ static int msm_rtb_probe(struct platform_device *pdev)
|
|||
md_entry.virt_addr = (uintptr_t)msm_rtb.rtb;
|
||||
md_entry.phys_addr = msm_rtb.phys;
|
||||
md_entry.size = msm_rtb.size;
|
||||
if (msm_minidump_add_region(&md_entry))
|
||||
if (msm_minidump_add_region(&md_entry) < 0)
|
||||
pr_info("Failed to add RTB in Minidump\n");
|
||||
|
||||
#if defined(CONFIG_QCOM_RTB_SEPARATE_CPUS)
|
||||
|
|
|
|||
Loading…
Reference in a new issue