背景
自从arm64@linux kernel引入irq stack之后,running task的stacktrace有时会得不到正确的.只能看到__switch_to这一层,再往上就看不到了.本文利用实例介绍利用irq trace event
来获取完整stacktrace(而不用重新修改code)的一种方法:
问题
如下是一个for test的ko,它会创建一个busy loop的thread,所以这个thread会一直处于running state.
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>
static int test_routine(void *arg)
{
pr_info("%s start...\n",__func__);
while(1)
{
udelay(1);
}
return 0;
}
static int __init rtask_module_init(void)
{
struct task_struct *test_thread;
pr_info("%s\n",__func__);
test_thread = kthread_run(test_routine, NULL, "rtask");
if (IS_ERR(test_thread)) {
pr_warn("Failed to create the rtask thread\n");
}
return 0;
}
static void __exit rtask_module_exit(void)
{
pr_info("%s\n");
}
module_init(rtask_module_init);
module_exit(rtask_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hichi");
MODULE_DESCRIPTION("CHECK RUNING TASK's stacktrace");
在insmod这个ko之后,可以去通过/proc/PID/stack查看其stacktrace,但经常看到的是如下结果:
# ps | grep rtask
1283 root [rtask]
1316 root grep rtask
# cat /proc/1283/stack
[<ffffff8008085db0>] __switch_to+0x98/0xb0
[<ffffffc01d34cb00>] 0xffffffc01d34cb00
[<ffffffffffffffff>] 0xffffffffffffffff
只能看到__switch_to这一层,那么要怎么看到完整的stacktrace呢?
分析
因为task处于running state,虽然会被抢占,但总有抢到CPU的时候,如果这个时候发生中断,那么就可以利用ISR来打印stacktrace.可以利用irq trace event来实现这个功能
实践
mount -t debugfs nodev /sys/kernel/debug/
cd /sys/kernel/debug/tracing/events/irq/irq_handler_entry/
echo 0 >/sys/kernel/debug/tracing/tracing_on
echo common_pid==1283 >filter
echo stacktrace if common_pid==1283 >trigger
echo 1 >enable
echo 1 >/sys/kernel/debug/tracing/tracing_on
echo 0 >/sys/kernel/debug/tracing/tracing_on
echo 1 >/sys/kernel/debug/tracing/options/sym-offset
cat trace
结果会有很多组,选取其中一组看看,就可以得到rtask thread的stacktrace了.
rtask-1283 [002] d.h1 237.170260: <stack trace>
=> __handle_domain_irq+0x68/0xc0
=> gic_handle_irq+0x60/0xb0
=> el1_irq+0xb4/0x12c
=> __delay+0x50/0x120
=> __const_udelay+0x2c/0x38
=> test_routine+0x20/0x38 [rtask_stacktrace]
=> kthread+0x138/0x140
=> ret_from_fork+0x10/0x1c