From 089cfbda14685be866c1512696edeecf8781c1e1 Mon Sep 17 00:00:00 2001 From: Huang Yiwei Date: Tue, 22 Feb 2022 15:54:57 +0800 Subject: [PATCH] soc: qcom: minidump_log: Add task info collection Add task info collection to minidump, and MINIDUMP_ALL_TASK_INFO is used to config only runnable or all task info need to collect. Also change runqueue dump format to only print pid, since detailed task info is in task info collection. Change-Id: I14366db4f6e20767fed11e94ff6b1baf8892fb1b Signed-off-by: Huang Yiwei --- drivers/soc/qcom/Kconfig | 9 +++ drivers/soc/qcom/minidump_log.c | 109 ++++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 25 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 6cd658fb8312..b7b2436d1891 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -359,6 +359,15 @@ config QCOM_STATS various SoC level low power modes statistics and export to debugfs interface. +config MINIDUMP_ALL_TASK_INFO + bool "Minidump All task info" + depends on QCOM_MINIDUMP + help + Minidump runqueue dump only collect running task + info by default, this enables all task info + collection during panic. This can provide more + debug info. + config QCOM_LOGBUF_VENDOR_HOOKS tristate "QTI Logbuf Vendor Hooks Support" depends on ARCH_QCOM && ANDROID_VENDOR_HOOKS diff --git a/drivers/soc/qcom/minidump_log.c b/drivers/soc/qcom/minidump_log.c index 299f2c60d776..aa6897ffffcc 100644 --- a/drivers/soc/qcom/minidump_log.c +++ b/drivers/soc/qcom/minidump_log.c @@ -44,6 +44,7 @@ #include #include "../../../kernel/sched/sched.h" +#include #include #include @@ -106,7 +107,11 @@ static bool minidump_ftrace_dump = true; #ifdef CONFIG_QCOM_MINIDUMP_PANIC_DUMP /* Rnqueue information */ +#ifndef CONFIG_MINIDUMP_ALL_TASK_INFO #define MD_RUNQUEUE_PAGES 8 +#else +#define MD_RUNQUEUE_PAGES 150 +#endif static bool md_in_oops_handler; static atomic_t md_handle_done; @@ -709,31 +714,15 @@ static void md_dump_task_info(struct task_struct *task, char *status, se = &task->se; if (task == curr) { seq_buf_printf(md_runq_seq_buf, - "[status: curr] pid: %d comm: %s preempt: %#x\n", - task_pid_nr(task), task->comm, + "[status: curr] pid: %d preempt: %#x\n", + task_pid_nr(task), task->thread_info.preempt_count); return; } seq_buf_printf(md_runq_seq_buf, - "[status: %s] pid: %d tsk: %#lx comm: %s stack: %#lx", - status, task_pid_nr(task), - (unsigned long)task, - task->comm, - (unsigned long)task->stack); - seq_buf_printf(md_runq_seq_buf, - " prio: %d aff: %*pb", - task->prio, cpumask_pr_args(&task->cpus_mask)); -#ifdef CONFIG_SCHED_WALT - seq_buf_printf(md_runq_seq_buf, " enq: %lu wake: %lu sleep: %lu", - task->wts.last_enqueued_ts, task->wts.last_wake_ts, - task->wts.last_sleep_ts); -#endif - seq_buf_printf(md_runq_seq_buf, - " vrun: %lu arr: %lu sum_ex: %lu\n", - (unsigned long)se->vruntime, - (unsigned long)se->exec_start, - (unsigned long)se->sum_exec_runtime); + "[status: %s] pid: %d\n", + status, task_pid_nr(task)); } static void md_dump_cfs_rq(struct cfs_rq *cfs, struct task_struct *curr); @@ -829,12 +818,46 @@ static void md_dump_rt_rq(struct rt_rq *rt_rq, struct task_struct *curr) } } +static const char * const task_state_array[] = { + "R", /* 0x00 */ + "S", /* 0x01 */ + "D", /* 0x02 */ + "T", /* 0x04 */ + "t", /* 0x08 */ + "X", /* 0x10 */ + "Z", /* 0x20 */ + "P", /* 0x40 */ + "I", /* 0x80 */ +}; + +/* In line with task_state_index from fs/proc/array.c */ +static inline unsigned int md_task_state_index(struct task_struct *tsk) +{ + unsigned int tsk_state = READ_ONCE(tsk->__state); + unsigned int state = (tsk_state | tsk->exit_state) & TASK_REPORT; + + if (tsk_state == TASK_IDLE) + state = TASK_REPORT_IDLE; + + return fls(state); +} + +/* In line with get_task_state from fs/proc/array.c */ +static inline const char *md_get_task_state(struct task_struct *tsk) +{ + return task_state_array[md_task_state_index(tsk)]; +} + static void md_dump_runqueues(void) { int cpu; struct rq *rq; struct rt_rq *rt; struct cfs_rq *cfs; + struct task_struct *p, *t; +#if IS_ENABLED(CONFIG_SCHED_WALT) + struct walt_task_struct *wts; +#endif if (!md_runq_seq_buf) return; @@ -844,19 +867,55 @@ static void md_dump_runqueues(void) rt = &rq->rt; cfs = &rq->cfs; seq_buf_printf(md_runq_seq_buf, - "CPU%d %d process is running\n", - cpu, rq->nr_running); - md_dump_task_info(cpu_curr(cpu), "curr", NULL); + "CPU%d has %d process, current is pid %d\n", + cpu, rq->nr_running, cpu_curr(cpu)->pid); seq_buf_printf(md_runq_seq_buf, - "CFS %d process is pending\n", + "CFS has %d process\n", cfs->nr_running); md_dump_cfs_rq(cfs, cpu_curr(cpu)); seq_buf_printf(md_runq_seq_buf, - "RT %d process is pending\n", + "RT has %d process\n", rt->rt_nr_running); md_dump_rt_rq(rt, cpu_curr(cpu)); seq_buf_printf(md_runq_seq_buf, "\n"); } + + seq_buf_printf(md_runq_seq_buf, "%-15s", "Task name"); + seq_buf_printf(md_runq_seq_buf, "%*s", 6, "PID"); + seq_buf_printf(md_runq_seq_buf, "%*s", 16, "Exec_started_at"); + seq_buf_printf(md_runq_seq_buf, "%*s", 16, "Last_queued_at"); + seq_buf_printf(md_runq_seq_buf, "%*s", 16, "Total_wait_time"); + seq_buf_printf(md_runq_seq_buf, "%*s", 12, "Exec_times"); + seq_buf_printf(md_runq_seq_buf, "%*s", 4, "CPU"); + seq_buf_printf(md_runq_seq_buf, "%*s", 5, "Prio"); + seq_buf_printf(md_runq_seq_buf, "%*s", 6, "State"); +#if IS_ENABLED(CONFIG_SCHED_WALT) + seq_buf_printf(md_runq_seq_buf, "%*s", 17, "Last_enqueued_ts"); + seq_buf_printf(md_runq_seq_buf, "%*s", 16, "Last_sleep_ts"); +#endif + seq_buf_printf(md_runq_seq_buf, "\n"); + + for_each_process_thread(p, t) { +#ifndef CONFIG_MINIDUMP_ALL_TASK_INFO + if (READ_ONCE(t->__state)) + continue; +#endif + seq_buf_printf(md_runq_seq_buf, "%-15s", t->comm); + seq_buf_printf(md_runq_seq_buf, "%6d", t->pid); + seq_buf_printf(md_runq_seq_buf, "%16lld", t->sched_info.last_arrival); + seq_buf_printf(md_runq_seq_buf, "%16lld", t->sched_info.last_queued); + seq_buf_printf(md_runq_seq_buf, "%16lld", t->sched_info.run_delay); + seq_buf_printf(md_runq_seq_buf, "%12ld", t->sched_info.pcount); + seq_buf_printf(md_runq_seq_buf, "%4d", t->on_cpu); + seq_buf_printf(md_runq_seq_buf, "%5d", t->prio); + seq_buf_printf(md_runq_seq_buf, "%*s", 6, md_get_task_state(t)); +#if IS_ENABLED(CONFIG_SCHED_WALT) + wts = (struct walt_task_struct *) t->android_vendor_data1; + seq_buf_printf(md_runq_seq_buf, "%17ld", wts->last_enqueued_ts); + seq_buf_printf(md_runq_seq_buf, "%16ld", wts->last_sleep_ts); +#endif + seq_buf_printf(md_runq_seq_buf, "\n"); + } } #ifdef CONFIG_QCOM_MINIDUMP_PANIC_CPU_CONTEXT