FT2000+ qemu kvm 触发内核锁死 假死 软锁 watchdog: BUG: soft lockup CPU#0 stuck for 23s;rcu_sched detected 示例程序
输入gg,快速下翻到页尾,可以看到内核打印了watchdog: BUG: soft lockup - CPU#0 stuck for 23s![softlockup_thre:1079],pc(Program Counter:程序计数器)指向地址为。其中:ARM64汇编指令 b 为跳转指令,即执行到ac地址处,跳转到ac地址处,对应while(1){}循环体。实际上,虚拟机已经处于假死状态,bas
watchdog: BUG: soft lockup - CPU#0 stuck for 23s!
虚拟机
创建目录
soft_lock_up
源程序
soft_lock_up_module.c
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
struct task_struct *task0;
static spinlock_t spinlock;
int val;
int task(void *arg) {
printk(KERN_INFO "%s:%d\n", __func__, __LINE__);
/* To generate panic uncomment following */
/* panic("softlockup: hung tasks"); */
while (!kthread_should_stop()) {
printk(KERN_INFO "%s:%d\n", __func__, __LINE__);
spin_lock(&spinlock);
printk(KERN_INFO "%s:%d\n", __func__, __LINE__);
/* busy loop in critical section */
while (1) {
}
spin_unlock(&spinlock);
}
return val;
}
static int softlockup_init(void) {
printk(KERN_INFO "%s:%d\n", __func__, __LINE__);
val = 1;
spin_lock_init(&spinlock);
task0 = kthread_run(&task, (void *)val, "softlockup_thread");
set_cpus_allowed_ptr(task0, cpumask_of(0));
return 0;
}
static void softlockup_exit(void) {
printk(KERN_INFO "%s:%d\n", __func__, __LINE__);
kthread_stop(task0);
}
module_init(softlockup_init);
module_exit(softlockup_exit);
MODULE_LICENSE("GPL v2"); // 表示模块代码接受的软件许可协议
MODULE_AUTHOR("www"); // 描述模块的作者信息
MODULE_DESCRIPTION("soft lock up module"); // 对模块的简单介绍
MODULE_ALIAS("soft_lock_up_module"); // 给模块设置一个别名
Makefile
# 指向编译出来的 linux 内核具体路径
KERNEL_DIR = /usr/lib/modules/4.19.113-300.axs7.14.aarch64/build
# 定义变量,并且导出变量给子 Makefile 使用
#ARCH = arm
#CROSS_COMPILE = arm-linux-gnueabihf-
#export ARCH CROSS_COMPILE
# obj-m := <模块名>.o: 定义要生成的模块
# soft_lock_up_module.o 自动搜索soft_lock_up_module.c进行编译,即:该模块C文件必须是soft_lock_up_module.c
obj-m := soft_lock_up_module.o
# 选项 "-C":让 make 工具跳转到 linux 内核目录下读取顶层 Makefile
# "M=" 表示内核模块源码目录
# $(CURDIR): Makefile 默认变量,值为当前目录所在路径
# make modules: 执行 Linux 顶层 Makefile 的伪目标,它实现内核模块的源码读取并编译为.ko文件
all:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
.PHONY:clean copy
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean
copy:
cp *.ko /tmp/
进入该目录,执行make,得到
安装内核模块
insmod soft_lock_up_module.ko
此时,bash被瞬间卡主。
宿主机
虚拟机卡主后,过几分钟,在宿主机上dump虚拟机内核
virsh dump --memory-only redflag1 qemu-virtual-machine/redflag1-memonly.dump
重启虚拟机
virsh destroy redflag1
virsh start redflag1
虚拟机
nfs挂载目录后,crash调试
此时状态为:TASK_RUNNING
实际上,虚拟机已经处于假死状态,bash交互界面已无法操作
输入指令:log
输入gg,快速下翻到页尾,可以看到内核打印了watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [softlockup_thre:1079],pc(Program Counter:程序计数器)指向地址为task+0xac/0xb8 [soft_lock_up_module]
dis反汇编
反汇编.ko
objdump -d soft_lock_up_module.ko > soft_lock_up_module.s
内容一致
其中:ARM64汇编指令 b 为跳转指令,即执行到ac地址处,跳转到ac地址处,对应while(1){}循环体。
objddump -S获取更多信息
addr2line查找源码行(不确定方法是否正确)
addr2line 定位到的位置在进入死循的环前一行。
bt查看调用栈
rcu: INFO: rcu_sched detected stalls on CPUs/tasks(hard lock up?)
源程序
hard_lock_up_module.c
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/spinlock.h>
MODULE_LICENSE("GPL");
static int hog_thread(void *data) {
static DEFINE_SPINLOCK(lock);
unsigned long flags;
printk(KERN_INFO "Hogging a CPU now\n");
spin_lock_irqsave(&lock, flags);
while (1)
;
/* unreached */
return 0;
}
static int __init hog_init(void) {
kthread_run(&hog_thread, NULL, "hog");
return 0;
}
module_init(hog_init);
MODULE_LICENSE("GPL v2"); // 表示模块代码接受的软件许可协议
MODULE_AUTHOR("www"); // 描述模块的作者信息
MODULE_DESCRIPTION("soft lock up module"); // 对模块的简单介绍
MODULE_ALIAS("soft_lock_up_module"); // 给模块设置一个别名
Makefile
# 指向编译出来的 linux 内核具体路径
KERNEL_DIR = /usr/lib/modules/4.19.113-300.axs7.14.aarch64/build
# 定义变量,并且导出变量给子 Makefile 使用
#ARCH = arm
#CROSS_COMPILE = arm-linux-gnueabihf-
#export ARCH CROSS_COMPILE
# obj-m := <模块名>.o: 定义要生成的模块
# hard_lock_up_module.o 自动搜索hard_lock_up_module.c进行编译,即:该模块C文件必须是hard_lock_up_module.c
obj-m := hard_lock_up_module.o
# 选项 "-C":让 make 工具跳转到 linux 内核目录下读取顶层 Makefile
# "M=" 表示内核模块源码目录
# $(CURDIR): Makefile 默认变量,值为当前目录所在路径
# make modules: 执行 Linux 顶层 Makefile 的伪目标,它实现内核模块的源码读取并编译为.ko文件
all:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
.PHONY:clean copy
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean
copy:
cp *.ko /tmp/
编译,安装模块
make
insmod hard_lock_up.ko
参考软锁,dump内核,crash调试
总结
触发软锁关键代码
spin_lock(&spinlock);
触发rcu_sched detected stalls关键代码:
spin_lock_irqsave(&lock, flags);
差别:spin_lock_irqsave关闭当前CPU上的中断
参考:
NMI watchdog: BUG: soft lockup - CPU#2 stuck for 23s!_rtoax的博客-CSDN博客
INFO: rcu_sched detected stalls on CPU/tasks_MIPSA的博客-CSDN博客
更多推荐
所有评论(0)