一、pstore 简介
pstore 最初是用于系统发生 oops 或 panic 时,自动保存内核 log buffer 中的日志。不过在当前内核版本中,其已经支持了更多的功能,如保存 console 日志、ftrace 消息和用户空间日志。同时,它还支持将这些消息保存在不同的存储设备中,如内存、块设备或 mtd 设备。
为了提高灵活性和可扩展性,pstore 将以上功能分别抽象为前端和后端,其中像 dmesg、console 等为 pstore 提供数据的模块称为前端,而内存设备、块设备等用于存储数据的模块称为后端,pstore core 则分别为它们提供相关的注册接口。
二、预留内存用于存储崩溃日志
1. 确认当前系统内存范围
大小为256M
2. 修改代码
从系统内存中取出32M用于保持崩溃日志
有两种修改方式:
方式一:uboot 下修改 bootargs 参数
修改前
hisilicon # printenv bootargs
bootargs=console=ttyAMA0,115200 rdinit=/linuxrc mem=256M
修改后
hisilicon # setenv bootargs console=ttyAMA0,115200 rdinit=/linuxrc mem=224M
hisilicon # saveenv
方式二:内核代码中修改
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -596,7 +596,9 @@ static int __init early_mem(char *p)
if (*endp == '@')
start = memparse(endp + 1, NULL);
- arm_add_memory(start, size);
+ printk("%s[%d]:--1--reserve %#x bytes at addr=%#llx\n", __func__, __LINE__, size, start);
+
+ arm_add_memory(start, size-SZ_32M);
return 0;
}
3.选择任一种修改方式验证
修改完成后,重新烧录,系统内存范围更改了,减少了32M。
预留32M(0x4e000000 ~ 0x4fffffff)来存储崩溃日志
三、Pstore配置
参考文档:linux-3.10.0/Documentation/ramoops.txt
该模块代码主要位于/fs/pstore下
Kconfig Makefile ftrace.c inode.c internal.h platform.c ram.c ram_core.c
主要修改的代码在文件 ram.c 中。
配置步骤如下:
1.修改配置文件
+CONFIG_EFI_VARS_PSTORE=m
+# CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE is not set
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_FTRACE=y
+CONFIG_PSTORE_RAM=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_REED_SOLOMON_DEC16=y
2.修改代码
2.1 分配地址
#include <linux/slab.h>
#include <linux/compiler.h>
#include <linux/pstore_ram.h>
+#include <linux/memblock.h>
@@ -567,6 +568,17 @@ static void ramoops_register_dummy(void)
static int __init ramoops_init(void)
{
int ret=-1;
u64 oops_reserve_mem_start = 0x4e000000;
u32 oops_mem_size = SZ_32M;
+ printk("%s[%d]: ---oops-- reserve %#x bytes at addr=%#llx\n", __func__, __LINE__, oops_mem_size, oops_reserve_mem_start);
+ ret = memblock_reserve(oops_reserve_mem_start, oops_mem_size); //保留内存:addr=0x4e000000 office=32M
+ if(ret) {
+ printk("%s[%d]: --fail to reserve %#x bytes at addr=%#llx\n", __func__, __LINE__,oops_mem_size, oops_reserve_mem_start);
+ return;
+ }
ramoops_register_dummy();
return platform_driver_register(&ramoops_driver);
}
2.2 分配步骤一中的内存
@@ -34,9 +34,10 @@
#define RAMOOPS_KERNMSG_HDR "===="
-#define MIN_MEM_SIZE 4096UL
+#define MIN_MEM_SIZE 512000UL
// 修改存储日志的文件容量为500k
-static ulong mem_address;
+static ulong mem_address=0x4E000000; // 定义存储崩溃日志内存的起始地址
module_param(mem_address, ulong, 0400);
MODULE_PARM_DESC(mem_address,
"start of reserved RAM used to store oops/panic logs");
-static ulong mem_size;
+static ulong mem_size=SZ_32M; // 定义存储崩溃日志内存的大小
module_param(mem_size, ulong, 0400);
MODULE_PARM_DESC(mem_size,
"size of reserved RAM used to store oops/panic logs");
至此,pstore 功能就配置好了。
四、功能验证
1.编译升级系统,触发panic
echo c > /proc/sysrq-trigger
2. 重启设备后获取崩溃日志
挂载pstore文件系统,由于其挂载点为/sys/fs/pstore,因此相应的挂载操作如下:
mount -t pstore pstore /sys/fs/pstore
挂载完成后,若后端中已经保存了先前的pstore消息,则可在/sys/fs/pstore目录下查看到对应的文件。用户可对该文件执行读取,删除等操作
ls /sys/fs/pstore
可以看到,上次重启后的串口日志、dmesg信息都保留下来了。