104 lines
2.2 KiB
C
104 lines
2.2 KiB
C
|
/*
|
||
|
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
|
||
|
* http://www.samsung.com
|
||
|
*
|
||
|
* Samsung TN debugging code
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 as
|
||
|
* published by the Free Software Foundation.
|
||
|
*/
|
||
|
#include <linux/smp.h>
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/sec_debug.h>
|
||
|
#include <linux/stacktrace.h>
|
||
|
#include <linux/debug-snapshot.h>
|
||
|
#include <asm/stack_pointer.h>
|
||
|
#include <asm/stacktrace.h>
|
||
|
#include <linux/sched/debug.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/types.h>
|
||
|
#include "../../../kernel/sched/sched.h"
|
||
|
#include <linux/sched/signal.h>
|
||
|
|
||
|
static call_single_data_t csd;
|
||
|
static struct task_struct *suspect;
|
||
|
|
||
|
static inline char get_state(struct task_struct *p)
|
||
|
{
|
||
|
char state_array[] = {'R', 'S', 'D', 'T', 't', 'X', 'Z', 'P', 'x', 'K', 'W', 'I', 'N'};
|
||
|
unsigned char idx = 0;
|
||
|
unsigned long state;
|
||
|
|
||
|
if (!p)
|
||
|
return 0;
|
||
|
|
||
|
state = (p->state | p->exit_state) & (TASK_STATE_MAX - 1);
|
||
|
|
||
|
while (state) {
|
||
|
idx++;
|
||
|
state >>= 1;
|
||
|
}
|
||
|
|
||
|
return state_array[idx];
|
||
|
}
|
||
|
|
||
|
static void show_callstack(void *dummy)
|
||
|
{
|
||
|
#ifdef CONFIG_SEC_DEBUG_AUTO_COMMENT
|
||
|
show_stack_auto_comment(NULL, NULL);
|
||
|
#else
|
||
|
show_stack(NULL, NULL);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static struct task_struct *secdbg_softdog_find_key_suspect()
|
||
|
{
|
||
|
struct task_struct *c, *g;
|
||
|
|
||
|
for_each_process(g) {
|
||
|
if (g->pid == 1)
|
||
|
suspect = g;
|
||
|
else if (!strcmp(g->comm, "system_server")) {
|
||
|
suspect = g;
|
||
|
for_each_thread(g, c) {
|
||
|
if (!strcmp(c->comm, "watchdog")) {
|
||
|
suspect = c;
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
return suspect;
|
||
|
}
|
||
|
|
||
|
void secdbg_softdog_show_info(void)
|
||
|
{
|
||
|
struct task_struct *p = NULL;
|
||
|
|
||
|
p = secdbg_softdog_find_key_suspect();
|
||
|
|
||
|
if (p) {
|
||
|
pr_auto(ASL5, "[SOFTDOG] %s:%d %c(%d) exec:%lluns\n",
|
||
|
p->comm, p->pid, get_state(p), (int)p->state, p->se.exec_start);
|
||
|
|
||
|
if (task_running(task_rq(p), p)) {
|
||
|
csd.flags = 0;
|
||
|
csd.func = show_callstack;
|
||
|
csd.info = 0;
|
||
|
smp_call_function_single_async(task_cpu(p), &csd);
|
||
|
} else {
|
||
|
#ifdef CONFIG_SEC_DEBUG_AUTO_COMMENT
|
||
|
show_stack_auto_comment(p, NULL);
|
||
|
#else
|
||
|
show_stack(p, NULL);
|
||
|
#endif
|
||
|
}
|
||
|
} else {
|
||
|
pr_auto(ASL5, "[SOFTDOG] Init task not exist!\n");
|
||
|
}
|
||
|
}
|