Merge "soc: qcom: minidump: Add md_get_region function"

This commit is contained in:
qctecmdr 2020-09-09 12:24:23 -07:00 • committed by Gerrit - the friendly Code Review server
commit 32eeccd006
6 changed files with 170 additions and 12 deletions

View file

@ -101,6 +101,16 @@ static int die_cpu = -1;
static struct seq_buf *md_cntxt_seq_buf;
#endif
/* Meminfo */
#define MD_MEMINFO_PAGES 1
struct seq_buf *md_meminfo_seq_buf;
/* Slabinfo */
#define MD_SLABINFO_PAGES 8
struct seq_buf *md_slabinfo_seq_buf;
/* Modules information */
#ifdef CONFIG_MODULES
#define NUM_MD_MODULES 200
@ -961,6 +971,12 @@ dump_rq:
#ifdef CONFIG_MODULES
md_dump_module_data();
#endif
if (md_meminfo_seq_buf)
md_dump_meminfo();
if (md_slabinfo_seq_buf)
md_dump_slabinfo();
md_in_oops_handler = false;
return NOTIFY_DONE;
}
@ -1031,6 +1047,10 @@ static void md_register_panic_data(void)
md_register_panic_entries(MD_CPU_CNTXT_PAGES, "KCNTXT",
&md_cntxt_seq_buf);
#endif
md_register_panic_entries(MD_MEMINFO_PAGES, "MEMINFO",
&md_meminfo_seq_buf);
md_register_panic_entries(MD_SLABINFO_PAGES, "SLABINFO",
&md_slabinfo_seq_buf);
}
#ifdef CONFIG_MODULES

View file

@ -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.
*/
#define pr_fmt(fmt) "Minidump: " fmt
@ -89,6 +89,19 @@ static inline unsigned int set_section_name(const char *name)
return ret;
}
struct md_region *md_get_region(char *name)
{
struct md_region *mdr;
int i, regno = minidump_table.num_regions;
for (i = 0; i < regno; i++) {
mdr = &minidump_table.entry[i];
if (!strcmp(mdr->name, name))
return mdr;
}
return NULL;
}
static inline int md_region_num(const char *name, int *seqno)
{
struct md_ss_region *mde = minidump_table.md_regions;

View file

@ -20,15 +20,39 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include "internal.h"
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
#include <soc/qcom/minidump.h>
#include <linux/seq_buf.h>
#endif
void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
{
}
static void show_val_kb2(struct seq_file *m, const char *s, unsigned long num)
{
if (m) {
seq_printf(m, s, num);
} else {
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
if (md_meminfo_seq_buf)
seq_buf_printf(md_meminfo_seq_buf, s, num);
#endif
}
}
static void show_val_kb(struct seq_file *m, const char *s, unsigned long num)
{
seq_put_decimal_ull_width(m, s, num << (PAGE_SHIFT - 10), 8);
seq_write(m, " kB\n", 4);
if (m) {
seq_put_decimal_ull_width(m, s, num << (PAGE_SHIFT - 10), 8);
seq_write(m, " kB\n", 4);
} else {
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
if (md_meminfo_seq_buf)
seq_buf_printf(md_meminfo_seq_buf, "%s : %lld KB\n", s,
num << (PAGE_SHIFT - 10));
#endif
}
}
static int meminfo_proc_show(struct seq_file *m, void *v)
@ -103,10 +127,10 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
show_val_kb(m, "Slab: ", sreclaimable + sunreclaim);
show_val_kb(m, "SReclaimable: ", sreclaimable);
show_val_kb(m, "SUnreclaim: ", sunreclaim);
seq_printf(m, "KernelStack: %8lu kB\n",
show_val_kb2(m, "KernelStack: %8lu kB\n",
global_zone_page_state(NR_KERNEL_STACK_KB));
#ifdef CONFIG_SHADOW_CALL_STACK
seq_printf(m, "ShadowCallStack:%8lu kB\n",
show_val_kb2(m, "ShadowCallStack:%8lu kB\n",
global_zone_page_state(NR_KERNEL_SCS_BYTES) / 1024);
#endif
show_val_kb(m, "PageTables: ",
@ -120,14 +144,14 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
global_node_page_state(NR_WRITEBACK_TEMP));
show_val_kb(m, "CommitLimit: ", vm_commit_limit());
show_val_kb(m, "Committed_AS: ", committed);
seq_printf(m, "VmallocTotal: %8lu kB\n",
show_val_kb2(m, "VmallocTotal: %8lu kB\n",
(unsigned long)VMALLOC_TOTAL >> 10);
show_val_kb(m, "VmallocUsed: ", vmalloc_nr_pages());
show_val_kb(m, "VmallocChunk: ", 0ul);
show_val_kb(m, "Percpu: ", pcpu_nr_pages());
#ifdef CONFIG_MEMORY_FAILURE
seq_printf(m, "HardwareCorrupted: %5lu kB\n",
show_val_kb2(m, "HardwareCorrupted: %5lu kB\n",
atomic_long_read(&num_poisoned_pages) << (PAGE_SHIFT - 10));
#endif
@ -150,13 +174,21 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
global_zone_page_state(NR_FREE_CMA_PAGES));
#endif
hugetlb_report_meminfo(m);
arch_report_meminfo(m);
if (m) {
hugetlb_report_meminfo(m);
arch_report_meminfo(m);
}
return 0;
}
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
void md_dump_meminfo(void)
{
meminfo_proc_show(NULL, NULL);
}
#endif
static int __init proc_meminfo_init(void)
{
proc_create_single("meminfo", 0, NULL, meminfo_proc_show);

View file

@ -32,6 +32,9 @@ struct md_region {
* Negative error number on failures.
*/
#if IS_ENABLED(CONFIG_QCOM_MINIDUMP)
extern struct seq_buf *md_meminfo_seq_buf;
extern struct seq_buf *md_slabinfo_seq_buf;
extern int msm_minidump_add_region(const struct md_region *entry);
extern int msm_minidump_remove_region(const struct md_region *entry);
/*
@ -43,7 +46,10 @@ extern int msm_minidump_remove_region(const struct md_region *entry);
*/
extern int msm_minidump_update_region(int regno, const struct md_region *entry);
extern bool msm_minidump_enabled(void);
extern struct md_region *md_get_region(char *name);
extern void dump_stack_minidump(u64 sp);
extern void md_dump_meminfo(void);
extern void md_dump_slabinfo(void);
#else
static inline int msm_minidump_add_region(const struct md_region *entry)
{
@ -55,8 +61,11 @@ static inline int msm_minidump_remove_region(const struct md_region *entry)
return 0;
}
static inline bool msm_minidump_enabled(void) { return false; }
static inline struct md_region *md_get_region(char *name) { return NULL; }
static inline void dump_stack_minidump(u64 sp) {}
static inline void add_trace_event(char *buf, size_t size) {}
static inline void md_dump_meminfo(void) {}
static inline void md_dump_slabinfo(void) {}
#endif
#ifdef CONFIG_QCOM_MINIDUMP_FTRACE
extern void minidump_add_trace_event(char *buf, size_t size);

View file

@ -129,6 +129,10 @@
#include "internal.h"
#include "slab.h"
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
#include <soc/qcom/minidump.h>
#include <linux/seq_buf.h>
#endif
/*
* DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
@ -4084,10 +4088,21 @@ void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
unsigned long node_frees = cachep->node_frees;
unsigned long overflows = cachep->node_overflow;
seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu %4lu",
if (m) {
seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu %4lu",
allocs, high, grown,
reaped, errors, max_freeable, node_allocs,
node_frees, overflows);
} else {
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
if (md_slabinfo_seq_buf)
seq_buf_printf(md_slabinfo_seq_buf,
" : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu %4lu",
allocs, high, grown,
reaped, errors, max_freeable,
node_allocs, node_frees, overflows);
#endif
}
}
/* cpu stats */
{
@ -4096,8 +4111,17 @@ void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
unsigned long freehit = atomic_read(&cachep->freehit);
unsigned long freemiss = atomic_read(&cachep->freemiss);
seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu",
if (m) {
seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu",
allochit, allocmiss, freehit, freemiss);
} else {
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
if (md_slabinfo_seq_buf)
seq_buf_printf(md_slabinfo_seq_buf,
" : cpustat %6lu %6lu %6lu %6lu",
allochit, allocmiss, freehit, freemiss);
#endif
}
}
#endif
}

View file

@ -27,6 +27,10 @@
#include <trace/events/kmem.h>
#include "slab.h"
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
#include <soc/qcom/minidump.h>
#include <linux/seq_buf.h>
#endif
enum slab_state slab_state;
LIST_HEAD(slab_caches);
@ -1501,6 +1505,62 @@ static int slab_show(struct seq_file *m, void *p)
return 0;
}
#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP
void md_dump_slabinfo(void)
{
struct kmem_cache *s;
struct slabinfo sinfo;
if (!md_slabinfo_seq_buf)
return;
/* print_slabinfo_header */
#ifdef CONFIG_DEBUG_SLAB
seq_buf_printf(md_slabinfo_seq_buf,
"slabinfo - version: 2.1 (statistics)\n");
#else
seq_buf_printf(md_slabinfo_seq_buf,
"slabinfo - version: 2.1\n");
#endif
seq_buf_printf(md_slabinfo_seq_buf,
"# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab>");
seq_buf_printf(md_slabinfo_seq_buf,
" : tunables <limit> <batchcount> <sharedfactor>");
seq_buf_printf(md_slabinfo_seq_buf,
" : slabdata <active_slabs> <num_slabs> <sharedavail>");
#ifdef CONFIG_DEBUG_SLAB
seq_buf_printf(md_slabinfo_seq_buf,
" : globalstat <listallocs> <maxobjs> <grown> <reaped> <error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
seq_buf_printf(md_slabinfo_seq_buf,
" : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
#endif
seq_buf_printf(md_slabinfo_seq_buf, "\n");
/* Loop through all slabs */
mutex_lock(&slab_mutex);
list_for_each_entry(s, &slab_root_caches, root_caches_node) {
memset(&sinfo, 0, sizeof(sinfo));
get_slabinfo(s, &sinfo);
memcg_accumulate_slabinfo(s, &sinfo);
seq_buf_printf(md_slabinfo_seq_buf,
"%-17s %6lu %6lu %6u %4u %4d",
cache_name(s), sinfo.active_objs, sinfo.num_objs, s->size,
sinfo.objects_per_slab, (1 << sinfo.cache_order));
seq_buf_printf(md_slabinfo_seq_buf, " : tunables %4u %4u %4u",
sinfo.limit, sinfo.batchcount, sinfo.shared);
seq_buf_printf(md_slabinfo_seq_buf,
" : slabdata %6lu %6lu %6lu",
sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail);
slabinfo_show_stats(NULL, s);
seq_buf_printf(md_slabinfo_seq_buf, "\n");
}
mutex_unlock(&slab_mutex);
}
#endif
void dump_unreclaimable_slab(void)
{
struct kmem_cache *s, *s2;