Compare commits

...

8 Commits

Author SHA1 Message Date
136a40cbe3 Merge branch 'Branch_Gaoyang3513' of https://gaoyang3513.synology.me:3000/gaoyang3513/MilkV-Duo into Branch_Gaoyang3513 2024-05-02 17:31:15 +08:00
b9741f3cc7 [Mod] Support the automatic mounting of pstore/ram. 2024-05-02 17:10:08 +08:00
e70f401895 [Mod] 简单实现Oops内容截取 2024-04-21 15:13:21 +08:00
40ff13d05f [Mod] ramoops修改为内核模块以动态加载,项目依据需要自行加载 2024-04-15 16:33:18 +08:00
dff961add1 [Mod] 完善测试用例test_ps,支持test_type:0,Oops测试;1 Oom测试; 2024-04-15 16:32:16 +08:00
f19003b239 [Mod] 新增忽略文件与目录:.cache/、compile_commmand.json 2024-04-15 16:29:51 +08:00
db0ee7322a [Mod] Pstore测试正常
[详细说明]
    1.使用dts方式,Pstore工作正常;模块加载方式未通过(dts中未声明reserver-memory);
    2.resever-memory定义:DRAM 末尾3MB位置开始,大小1MB(RTOS区域紧跟其后):{0x9fd0_0000, 0x9fdf_ffff};
2024-04-09 21:27:56 +08:00
b20adf0a85 [Add] 添加oops测试用ko模块 2024-04-09 21:27:02 +08:00
8 changed files with 249 additions and 1 deletions

4
.gitignore vendored
View File

@ -20,3 +20,7 @@ ncscope.*
__pycache__
.vscode
.cache/
compile_commands.json

View File

@ -530,3 +530,22 @@ CONFIG_BT_HCIUART_H4=y
# CONFIG_BT_HCIVHCI is not set
# CONFIG_BT_MRVL is not set
# CONFIG_BT_MTKSDIO is not set
# 死锁检测
CONFIG_LOCK_STAT=y
CONFIG_PROVE_LOCKING=y
# Ftracer
CONFIG_FUNCTION_TRACER=y
CONFIG_PSTORE_FTRACE=y
# Sysrq
CONFIG_MAGIC_SYSRQ=y
# Pstore
CONFIG_PSTORE=y
# Frontend
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_CONSOLE=y
# Backend
CONFIG_PSTORE_RAM=y

View File

@ -21,5 +21,12 @@
compatible = "ion-region";
size = <0x0 CVIMMAP_ION_SIZE>;
};
ramoops@9fd00000 {
compatible = "ramoops";
reg = <0 0x9fd00000 0 0x100000>;
record-size = <0x4000>;
console-size = <0x4000>;
};
};
};

View File

@ -7,3 +7,4 @@ tmpfs /tmp tmpfs mode=1777 0 0
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
sysfs /sys sysfs defaults 0 0
debug /sys/kernel/debug debugfs defaults 0 0
pstore /sys/fs/pstore pstore defaults 0 0

View File

@ -378,6 +378,42 @@ void pstore_record_init(struct pstore_record *record,
record->time = ns_to_timespec64(ktime_get_real_fast_ns());
}
static const char *key_words[] = {
// faults
"Unable to handle kernel",
"Unhandled fault",
"Unhandled prefetch abort",
// panic
"Kernel panic",
// oom
"invoked oom-killer",
NULL,
};
static size_t kmsg_data_strip(char *data, int len)
{
char *tmp, *first = NULL;
int i;
size_t ret = 0;
for (i=0; key_words[i]; i++) {
tmp = strnstr(data, key_words[i], len);
if (tmp) {
if (!first || (tmp < first)) {
ret = len - (first - data);
first = tmp;
}
}
}
if (first && ret > 0)
memmove(data, first, ret);
else
ret = len;
return ret;
}
/*
* callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the
* end of the buffer.
@ -407,7 +443,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
oopscount++;
while (total < kmsg_bytes) {
char *dst;
char *dst, *keyword;
size_t dst_size;
int header_size;
int zipped_len = -1;
@ -439,6 +475,14 @@ static void pstore_dump(struct kmsg_dumper *dumper,
dst_size, &dump_size))
break;
// dump_size = kmsg_data_strip(dst + header_size, dump_size);
keyword = strnstr(dst + header_size, "Unable to handle kernel", dump_size);
if (keyword) {
dump_size -= (keyword - (dst + header_size));
memmove(dst + header_size, keyword, dump_size);
}
if (big_oops_buf) {
zipped_len = pstore_compress(dst, psinfo->buf,
header_size + dump_size,

View File

@ -49,6 +49,9 @@ ifeq (, ${CONFIG_NO_TP})
OTHERS += cp_ext_tp
endif
KO_LIST += testing
OTHERS += cp_testing
$(info ** [ KO_LIST ] ** = $(KO_LIST))
export CROSS_COMPILE=$(patsubst "%",%,$(CONFIG_CROSS_COMPILE_KERNEL))
@ -69,12 +72,18 @@ wireless:
wiegand-gpio:
@$(call MAKE_EXT_KO, extdrv/${@})
testing:
@$(call MAKE_EXT_KO, extdrv/${@})
cp_ext_wireless:
@find extdrv/wireless -name '*.ko' -print -exec cp {} $(INSTALL_DIR)/3rd/ \;
cp_ext_tp:
@find extdrv/tp -name '*.ko' -print -exec cp {} $(INSTALL_DIR)/3rd/ \;
cp_testing:
@find extdrv/testing -name '*.ko' -print -exec cp {} $(INSTALL_DIR)/3rd/ \;
clean:
@for subdir in $(SUBDIRS); do cd $$subdir && $(MAKE) clean && cd $(CUR_DIR); done
@rm -f $(INSTALL_DIR)/*.ko

View File

@ -0,0 +1,24 @@
#
# Makefile for the Linux testings.
#
obj-m += test_ps.o
all:
$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL_DIR) M=$(shell pwd) modules
strip:
$(CROSS_COMPILE)strip $(MODULE_NAME).ko --strip-unneeded
clean:
find . -name *.d -delete
find . -name *.ko | xargs -i rm -rf {}
find . -name Module.symvers | xargs -i rm -rf {}
find . -name Module.markers | xargs -i rm -rf {}
find . -name modules.order | xargs -i rm -rf {}
find . -name *.mod.c | xargs -i rm -rf {}
find . -name *.mod | xargs -i rm -rf {}
find . -name *.o | xargs -i rm -rf {}
find . -name *.cmd | xargs -i rm -rf {}
find . -name *~ | xargs -i rm -rf {}
rm -fr .tmp_versions

View File

@ -0,0 +1,140 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
#include <linux/rcupdate.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
static unsigned int test_type;
module_param(test_type, uint, 0400);
MODULE_PARM_DESC(test_type, "set to 1 to try to OOM (default 0)");
static int trigger_oops(void)
{
int *ptr = (int *)0; // 强制类型转换0地址为指针并尝试读取
printk(KERN_ALERT "Dereferenced NULL pointer value: %d\n", *ptr);
return 0;
}
static int trigger_oom(void)
{
void *memory = NULL;
size_t memory_size = 0;
printk(KERN_INFO "oom_trigger: Initializing the oom_trigger LKM\n");
memory_size = 100*1024*1024;
while (1) { // 尝试分配大块内存
memory = vmalloc(memory_size);
if (!memory) {
printk(KERN_ALERT "oom_trigger: Memory allocation failed\n");
break;
}
// 仅为防止编译器优化,实际不访问分配的内存
memset(memory, 0, memory_size);
}
return 0;
}
static int test_data = 0;
static struct rcu_head test_rcu_head;
static void bad_rcu_callback(struct rcu_head *head)
{
// 违规操作在RCU回调函数中睡眠这可能导致RCU grace period过长
msleep(1000);
// 违规操作修改被RCU保护的数据结构
test_data++; // 不应在RCU回调中修改全局变量
pr_info("Bad RCU callback executed\n");
}
static void trigger_rcu(void)
{
pr_info("RCU error module loaded\n");
call_rcu(&test_rcu_head, bad_rcu_callback);
}
static int is_ready_thread1, is_ready_thread2;
static struct task_struct *thread1;
static struct task_struct *thread2;
static DEFINE_MUTEX(mutex_a);
static DEFINE_MUTEX(mutex_b);
static int thread_func(void *data)
{
char *name = (char *) data;
if (!strcmp(name, "Thread1")) {
printk(KERN_INFO "%s: Acquiring mutex A...\n", name);
mutex_lock(&mutex_a);
is_ready_thread1 = 1;
while (!is_ready_thread2);
printk(KERN_INFO "%s: Got mutex A. Now trying to acquire mutex B...\n", name);
mutex_lock(&mutex_b); // This will block, causing deadlock
printk(KERN_INFO "%s: Got mutex B.\n", name);
} else {
printk(KERN_INFO "%s: Acquiring mutex B...\n", name);
mutex_lock(&mutex_b);
is_ready_thread2 = 1;
while (!is_ready_thread1);
printk(KERN_INFO "%s: Got mutex B. Now trying to acquire mutex A...\n", name);
mutex_lock(&mutex_a); // This will block, causing deadlock
printk(KERN_INFO "%s: Got mutex A.\n", name);
}
return 0;
}
static int trigger_deadlock(void)
{
thread1 = kthread_run(thread_func, (void *) "Thread1", "thread1");
if (IS_ERR(thread1)) {
printk(KERN_ERR "Failed to create thread1\n");
return PTR_ERR(thread1);
}
thread2 = kthread_run(thread_func, (void *) "Thread2", "thread2");
if (IS_ERR(thread2)) {
printk(KERN_ERR "Failed to create thread2\n");
kthread_stop(thread1);
return PTR_ERR(thread2);
}
return 0;
}
static int trigger_init(void) {
if (test_type == 0)
trigger_oops();
else if (test_type == 1)
trigger_oom();
else if (test_type == 2)
trigger_rcu();
else if (test_type == 3)
trigger_deadlock();
return 0; // 加载模块不应该有返回值但这里返回0避免编译警告。
}
static void __exit trigger_exit(void) {
if (test_type == 3) {
kthread_stop(thread1);
kthread_stop(thread2);
printk(KERN_INFO "Deadlock trigger exit.\n");
}
}
module_init(trigger_init);
module_exit(trigger_exit);
MODULE_LICENSE("GPL");