From 2ae883be00b3477112cbea805df9b4945ee4849b Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Wed, 15 Jul 2020 18:15:04 +0530 Subject: [PATCH 1/3] soc: qcom: Enable meminfo support in minidump Register and dump meminfo on kernel panic to minidump table. Change-Id: I367d09ce8aabf4feda6d352411d9e10038a37ff9 Signed-off-by: Vijayanand Jitta --- drivers/soc/qcom/minidump_log.c | 9 ++++++ fs/proc/meminfo.c | 50 +++++++++++++++++++++++++++------ include/soc/qcom/minidump.h | 4 +++ 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/minidump_log.c b/drivers/soc/qcom/minidump_log.c index 5bdf3ac3f21d..dd0d90945594 100644 --- a/drivers/soc/qcom/minidump_log.c +++ b/drivers/soc/qcom/minidump_log.c @@ -101,6 +101,11 @@ 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; + /* Modules information */ #ifdef CONFIG_MODULES #define NUM_MD_MODULES 200 @@ -961,6 +966,8 @@ dump_rq: #ifdef CONFIG_MODULES md_dump_module_data(); #endif + if (md_meminfo_seq_buf) + md_dump_meminfo(); md_in_oops_handler = false; return NOTIFY_DONE; } @@ -1031,6 +1038,8 @@ 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); } #ifdef CONFIG_MODULES diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index a678d7ecc8ad..0b10af0be77f 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -20,15 +20,39 @@ #include #include #include "internal.h" +#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP +#include +#include +#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); diff --git a/include/soc/qcom/minidump.h b/include/soc/qcom/minidump.h index 66eaa0ae42ed..4496a32620aa 100644 --- a/include/soc/qcom/minidump.h +++ b/include/soc/qcom/minidump.h @@ -32,6 +32,8 @@ struct md_region { * Negative error number on failures. */ #if IS_ENABLED(CONFIG_QCOM_MINIDUMP) +extern struct seq_buf *md_meminfo_seq_buf; + extern int msm_minidump_add_region(const struct md_region *entry); extern int msm_minidump_remove_region(const struct md_region *entry); /* @@ -44,6 +46,7 @@ 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 void dump_stack_minidump(u64 sp); +extern void md_dump_meminfo(void); #else static inline int msm_minidump_add_region(const struct md_region *entry) { @@ -57,6 +60,7 @@ static inline int msm_minidump_remove_region(const struct md_region *entry) static inline bool msm_minidump_enabled(void) { return false; } 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) {} #endif #ifdef CONFIG_QCOM_MINIDUMP_FTRACE extern void minidump_add_trace_event(char *buf, size_t size); From 65caff83525c1836634b88702b597d11db2ba228 Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Thu, 16 Jul 2020 11:30:55 +0530 Subject: [PATCH 2/3] soc: qcom: Enable slabinfo support in minidump Register and dump slabinfo on kernel panic to minidump table. Change-Id: I8e2eabf63233bdb0039a7c7c962b980fba2e21ef Signed-off-by: Vijayanand Jitta --- drivers/soc/qcom/minidump_log.c | 11 ++++++ include/soc/qcom/minidump.h | 3 ++ mm/slab.c | 28 +++++++++++++-- mm/slab_common.c | 60 +++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/minidump_log.c b/drivers/soc/qcom/minidump_log.c index dd0d90945594..67948134835d 100644 --- a/drivers/soc/qcom/minidump_log.c +++ b/drivers/soc/qcom/minidump_log.c @@ -106,6 +106,11 @@ static struct seq_buf *md_cntxt_seq_buf; 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 @@ -968,6 +973,10 @@ dump_rq: #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; } @@ -1040,6 +1049,8 @@ static void md_register_panic_data(void) #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 diff --git a/include/soc/qcom/minidump.h b/include/soc/qcom/minidump.h index 4496a32620aa..5eb78a038608 100644 --- a/include/soc/qcom/minidump.h +++ b/include/soc/qcom/minidump.h @@ -33,6 +33,7 @@ struct md_region { */ #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); @@ -47,6 +48,7 @@ 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); 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) { @@ -61,6 +63,7 @@ static inline bool msm_minidump_enabled(void) { return false; } 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); diff --git a/mm/slab.c b/mm/slab.c index d1d7624cec4a..1a75a1204ff4 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -129,6 +129,10 @@ #include "internal.h" #include "slab.h" +#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP +#include +#include +#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 } diff --git a/mm/slab_common.c b/mm/slab_common.c index e36dd36c7076..65abe10384ec 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -27,6 +27,10 @@ #include #include "slab.h" +#ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP +#include +#include +#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 "); + seq_buf_printf(md_slabinfo_seq_buf, + " : tunables "); + seq_buf_printf(md_slabinfo_seq_buf, + " : slabdata "); + #ifdef CONFIG_DEBUG_SLAB + seq_buf_printf(md_slabinfo_seq_buf, + " : globalstat "); + seq_buf_printf(md_slabinfo_seq_buf, + " : cpustat "); + #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; From 0d1287fa01853d5aae1a6bfd22abaad617a5751e Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Tue, 28 Jul 2020 14:17:02 +0530 Subject: [PATCH 3/3] soc: qcom: minidump: Add md_get_region function Add a function md_get_region which returns md_region when we pass minidump entry name to it. Change-Id: Ibbd84737041c5b1c25cc46b9c740d415978de7e6 Signed-off-by: Vijayanand Jitta --- drivers/soc/qcom/msm_minidump.c | 15 ++++++++++++++- include/soc/qcom/minidump.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/msm_minidump.c b/drivers/soc/qcom/msm_minidump.c index 3ed713753f1c..7cf2fc95ce99 100644 --- a/drivers/soc/qcom/msm_minidump.c +++ b/drivers/soc/qcom/msm_minidump.c @@ -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; diff --git a/include/soc/qcom/minidump.h b/include/soc/qcom/minidump.h index 5eb78a038608..38676514047f 100644 --- a/include/soc/qcom/minidump.h +++ b/include/soc/qcom/minidump.h @@ -46,6 +46,7 @@ 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); @@ -60,6 +61,7 @@ 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) {}