![]()
![]()
前言:
對于嵌入式產(chǎn)品的開發(fā)使用,盡管會經(jīng)歷大量的測試和驗證,但在大批量生產(chǎn)中,硬件物料的適配一致性,應(yīng)用軟件的異常消息隊列等因素,使得現(xiàn)場使用中存在極小概率發(fā)生意外狀況,出現(xiàn)如 kernel opps、panic等死機現(xiàn)象。這時系統(tǒng)日志無法及時寫入 flash,重啟后沒有存到任何關(guān)鍵信息,工程師也崩潰了。下文則基于眺望電子T113-i核心板產(chǎn)品為例,介紹如何在Linux系統(tǒng)上搭建并驗證ramoops, 以便在系統(tǒng)崩潰或異常時進行故障排查。
一、ramoops 簡介
ramoops 是一個 oops/panic 日志記錄器,它在系統(tǒng)崩潰之前將其日志寫入 RAM。它的工作原理是將 oops 和 panic 記錄在循環(huán)緩沖區(qū)中。ramoops 需要具有持久 RAM 的系統(tǒng),以便該區(qū)域的內(nèi)容在重啟后仍然存在。
二、ramoops 搭建
?2.1 ?環(huán)境說明
- 平臺: T113-I Tina
- SDK : talowe-T113-I-Tina-sdk_2025_03_10.tar.gz
- Kernel 版本: 5.4.61
- DRAM 類型: DDR3
查看系統(tǒng)內(nèi)存
[root@T113-I:/]# cat /proc/iomem
可以看到SRAM地址為0x40000000~0x5FFFFFFF,共512M,可以選擇kernel code和kernel data以外的地址用作ramoops空間。
??
?2.2 ?內(nèi)核配置修改
ramoops在內(nèi)核里面叫pstore ram,源碼路徑為:?
kernel/linux-5.4/fs/pstore/ram_core.c
kernel/linux-5.4/fs/pstore/ram.c
CONFIG_PSTORE_RAM=y # 下面的根據(jù)自己需求
CONFIG_PSTORE_CONSOLE=y # 保存控制臺日志(上一次的)
CONFIG_PSTORE_PMSG=y # 用戶信息存儲,可以往/dev/pmsg0節(jié)點寫入
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
ramoops@5f000000 {
compatible = "ramoops";
reg = <0 0x5f000000 0 0x100000>; // 1M內(nèi)存
record-size = <0x40000>; // oops/panic信息存儲
console-size = <0x4000>; // 內(nèi)核信息存儲
pmsg-size = <0x4000>; // 用戶信息存儲
no-map;
};
};
使用參數(shù)解析:
-
reg = <0 0x5f000000 0 0x100000>; 從0x5f000000開始,劃分0x100000內(nèi)存(也就是1M),用于ramoops
-
record-size = <0x40000>; 分配使用256K來存儲oops/panic信息,文件名稱為dmesg-ramoops-0
-
console-size = <0x4000>; 分配使用16K來存儲上一次的內(nèi)核信息,文件名稱為console-ramoops-0
-
pmsg-size = <0x4000>; 分配使用16K來存儲用戶上一次向/dev/pmsg0節(jié)點寫入的信息,文件名稱為pmsg-ramoops-0
-
no-map; 必須添加,亦或者修改kernel的內(nèi)存初始化,將這部分空間預(yù)留出來
其他參數(shù):
- lecc-size = <value>;
使用ecc糾錯機制,糾錯字節(jié)數(shù)為value,value為1時,使用16字節(jié)來糾錯,其他值會直接使用
使用ecc會消耗更多內(nèi)存消耗的內(nèi)存,消耗的內(nèi)存與cnt有關(guān),如下面注2,cnt為3,則會消耗3*ecc_value。
注1:size為2的冪向下取整?
注2:如果內(nèi)存劃分不規(guī)范,可能record的實際大小由(mem_size - console_size - pmsg_size) / record_size決定,如上面例子(0x100000 - 0x4000 - 0x4000)/0x40000,結(jié)果向下取整為3,所以record的大小為(0x100000 - 0x4000 - 0x4000)/ 3 ,結(jié)果向下取整為330k
?2.3 ?系統(tǒng)加載確認
2.3.1 驅(qū)動加載查看
將如上修改后的固件鏡像燒寫到T113-i核心板,進入系統(tǒng)后,使用以下指令查看ramoops內(nèi)存分配是否成功,如下圖顯示:成功從0x5f000000開始分配了0x100000(既1M),未啟用ECC糾錯碼(設(shè)備樹添加ecc-size屬性可以開啟)
[root@T113-I:/]# dmesg | grep ramoops
[root@T113-I:/]# cat /proc/iomem
- 5f000000~5f052aa9:330K,用作存儲上一次oops/panic信息
- 5f052aaa~5f0a5553:330K,用作存儲上一次oops/panic信息
- 5f0a5554~5f0f7ffd:330K,用作存儲上一次oops/panic信息
- 5f0f7ffe~5f0fbffd:16K,用作存儲上一次系統(tǒng)的內(nèi)核信息
- 5f0fbffe~5f0ffffd:16K,用于存儲上一次用戶自定義信息(向/dev/pmsg0寫入的信息)
注3:建議record按照實際大小分配一份即可,因為ramoops使用一個計數(shù)器來記錄多個轉(zhuǎn)儲,但計數(shù)器在重啟時重置(即,重啟后的新轉(zhuǎn)儲將覆蓋舊轉(zhuǎn)儲),所以每次都會將dmesg-ramoops-0覆蓋。
2.3.2?查看ramoops起始地址(mem_address)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/mem_address
[root@T113-I:/]# printf "0x%xn" $(cat /sys/module/ramoops/parameters/mem_address)
2.3.3?查看ramoops分配大小(mem_size)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/mem_size
[root@T113-I:/]# printf "0x%xn" $(cat /sys/module/ramoops/parameters/mem_size)
2.3.4?查看設(shè)備樹record-size設(shè)置(record_size)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/record_size
[root@T113-I:/]# printf "0x%xn" $(cat /sys/module/ramoops/parameters/record_size)
既256K
2.3.5 查看設(shè)備樹console-size設(shè)置(console_size)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/console_size
[root@T113-I:/]# printf "0x%xn" $(cat /sys/module/ramoops/parameters/console_size)
既16K
2.3.6 查看設(shè)備樹pmsg-size設(shè)置(pmsg_size)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/pmsg_size
[root@T113-I:/]# printf "0x%xn" $(cat /sys/module/ramoops/parameters/pmsg_size)
既16K
2.3.7 查看是否開啟ecc糾錯(ecc)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/ecc
- 0:未開啟
- 非0:開啟,使用該值的字節(jié)進行糾錯
2.3.8 查看存儲哪些的內(nèi)核信息類型(dump_oops)
[root@T113-I:/]# cat /sys/module/ramoops/parameters/dump_oops
- 1:存儲panic和oops
- 2:跳過oops存儲,只存儲panic
- 其他:請查看kernel/linux-5.4/include/linux/kmsg_dump.h和ramoops的ramoops_pstore_write函數(shù)
三、ramoops?機制驗證
?3.1 ?觸發(fā)panic測試
[root@T113-I:/]# echo 5 > /proc/sys/kernel/panic # 設(shè)置觸發(fā)panic時,5秒后重啟
[root@T113-I:/]# echo c > /proc/sysrq-trigger # 觸發(fā)panic
重啟后,掛載pstore系統(tǒng)查看日志
[root@T113-I:/]# mount -t pstore pstore /sys/fs/pstore/
[root@T113-I:/]# ls /sys/fs/pstore/
[root@T113-I:/]# tail -n 20 /sys/fs/pstore/dmesg-ramoops-0 #防止信息太多,只看之后20行
如下圖,可以看到前面的系統(tǒng)時間與內(nèi)容和崩潰時打印的一模一樣,同時前面多了日志等級標記
同時,console-ramoops-0也會有以上信息,這里只看最后10行方便對比
[root@T113-I:/]# tail -n 10 /sys/fs/pstore/dmesg-ramoops-0
[root@T113-I:/]# tail -n 10 /sys/fs/pstore/console-ramoops-0
?
?3.2 ?ramoops文件對比
由上一小節(jié)panic的測試可以看到console-ramoops-0的日志內(nèi)容和dmesg-ramoops-0的日志內(nèi)容一模一樣,兩者的區(qū)別是console-ramoops-0為reboot前的內(nèi)核所有信息,dmesg-ramoops-0為上一次觸發(fā)panic/oops時內(nèi)核的所有信息
在上小節(jié)測試完成后,執(zhí)行reboot,系統(tǒng)重新啟動后可以看到信息不一致,console為上一次內(nèi)核信息
[root@T113-I:/]# mount -t pstore pstore /sys/fs/pstore/
[root@T113-I:/]# tail -n 10 /sys/fs/pstore/dmesg-ramoops-0
[root@T113-I:/]# tail -n 10 /sys/fs/pstore/console-ramoops-0
?3.3 ?用戶自定義pmsg-ramoops
寫入信息
[root@T113-I:/]# echo 123 > /dev/pmsg0
[root@T113-I:/]# echo 456 > /dev/pmsg0
[root@T113-I:/]# reboot
[root@T113-I:/]# mount -t pstore pstore /sys/fs/pstore/
[root@T113-I:/]# cat /sys/fs/pstore/pmsg-ramoops-0
四、小結(jié)
以上則是基于ramoops在全志T113-i平臺上的簡單使用技巧,若您也有linux系統(tǒng)方面的問題或想了解更多相關(guān)技術(shù)知識或產(chǎn)品信息,請關(guān)注眺望電子公眾號并聯(lián)系我們,我們將竭誠為您服務(wù)!