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);