1.記事一覧
記事は複数回に分けて投稿する予定です。AMD/XilinxのARM SoC(ZynqMP Kria K26 SOM)で動作する、AMD/Xilinx公式認定Ubuntuやベアメタル開発を勉強していく覚書きです。
ZynqMP(APU:Cortex-A53,Arm64) 組込みLinux入門編
- 【ZynqMP】1. 認定UbuntuでPLのGPIOを使う
- 【ZynqMP】2. 認定Ubuntuのカーネルビルド
- 【ZynqMP】3. 認定UbuntuのDeviceTree変更
- 【ZynqMP】4. 認定UbuntuでOpenAMPを試す【CR5Lockstep】
- 【ZynqMP】5. UARTでAMP【コア間通信】
- 【Linux】6. crash toolでカーネルメモリを見る←本記事
ZynqMP(RPU:Cortex-R5,Arm32) RPU入門編
2.解析ツールcrashで動作中のメモリを見てみる
2-1. きっかけ
私がよく拝見させていただいている、Youtubeチャネル”satlinuxtube”で面白そうな動画が上がっていました。
crashコマンドと呼ばれるGDBベースのツールは、Linuxカーネルのクラッシュダンプや、動作中のカーネルメモリを読み込んで解析できます。動画の内容は、動作中のカーネルメモリを少し覗いて見ようという内容です。
私はcrashツール自体初耳だったので、これを機に少し触ってみます。下準備が面倒なので、いざ使うときに困らないよう、一度チュートリアルとして慣れておく算段です。
動画ではx86のUbuntuマシンで行っていますが、今回はZynqMP(arm64)で動作する、Xilinx認定Ubuntu22.04でやっていきます。
開発ツール | VSCode(Remote-SSH) |
ターゲットOS | Xilinx認定Ubuntu22.04 Linux Kernel : 5.15.0-1031-xilinx-zynqmp |
ターゲットボード(インターネット接続必要) | Xilinx社製 Kria KR260 ロボティクススターターキット(SK-KR260-G) SOM : Xilinx社 Kria K26 SOM (Zynq UltraScale+ MPSoCベース) APU : Arm CA53x4 1333MHz arm64 RPU : Arm CR5x2 533MHz armv7-R SDRAM : DDR4 4GB |
2-2. 今回の流れ
動画の内容をそのままZynqMPでやっていこうと思います。それと追加でグローバル変数を見てみようと思います。
- 環境準備:リポジトリ有効化
- 環境準備:カーネルデバッグシンボルのインストール
- 環境準備:crashのインストール
- crash:log
- crash:runq
- crash:p
3.環境準備
3-1. リポジトリを有効化
デバッグシンボルをインストールするためにリポジトリを有効化します。
Ubuntu Server documentation-Debug symbol packages
上記URLの通りにやればOKです。2つ方法があります。
- Debuginfodというオンデマンドサービスを利用する
- リポジトリを有効化する←今回はこっち
前者はオンラインサービスでデバッグシンボルの手動インストールを不要に出来ます。Ubuntu22.04以降で使える最新のやり方のようです。ただし、crashを利用するマシン(今回はZynqMPボード)がインターネット接続されている必要があります。
後者は従来どおり、リポジトリを有効化して、デバッグシンボルをインストールする方法です。今回はこちらにします。crashを使用する際にオンラインでなければいけないのは組込みボードに限っては困ることが多いからです。
署名鍵のインポート
ZynqMP上で作業していきます。
$ sudo apt install ubuntu-dbgsym-keyring
ddebs.listの作成
/etc/apt/sources.list.d/ddebs.listを作成します。
$ echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list
最後にapt updateしておきます。
$ sudo apt update
3-2. デバッグシンボルのインストール
カーネルデバッグシンボルパッケージ名はカーネル名によって変わります。認定Ubuntuなので、公式でパッケージが用意されています。とても便利。
ちなみにインストールに15分程度かかりました。
$ sudo apt install linux-image-$(uname -r)-dbgsym
3-3. crashのインストール
$ sudo apt install crash
4.crashで動作中のカーネルメモリを見る
4-1. crashの起動
crashを起動してみましょう。カーネルデバッグシンボルのパスを与えて起動します。1分程度起動に時間がかかります。
$ sudo crash /usr/lib/debug/boot/vmlinux-5.15.0-1031-xilinx-zynqmp
crash 8.0.0
Copyright (C) 2002-2021 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011, 2020-2021 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Copyright (C) 2015, 2021 VMware, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
GNU gdb (GDB) 10.2
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "aarch64-unknown-linux-gnu".
Type "show configuration" for configuration details.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
KERNEL: /usr/lib/debug/boot/vmlinux-5.15.0-1031-xilinx-zynqmp [TAINTED]
DUMPFILE: /proc/kcore
CPUS: 4
DATE: Wed Aug 28 02:51:17 JST 2024
UPTIME: 01:59:53
LOAD AVERAGE: 1.06, 0.72, 0.79
TASKS: 449
NODENAME: kria
RELEASE: 5.15.0-1031-xilinx-zynqmp
VERSION: #35-Ubuntu SMP Fri Jun 14 02:59:36 UTC 2024
MACHINE: aarch64 (unknown Mhz)
MEMORY: 4 GB
PID: 12520
COMMAND: "crash"
TASK: ffff000802d65140 [THREAD_INFO: ffff000802d65140]
CPU: 3
STATE: TASK_RUNNING (ACTIVE)
crash>
crash起動時にカーネルクラッシュダンプファイルを指定しない場合、デフォルトでkcoreが読み込まれます(“DUMPFILE: /proc/kcore”)。kcoreは動作中の全物理メモリの情報が読めるそうです。
4-2. crash log でdmesgバッファ読出し
crashを起動すると”crash>”プロンプトが表示されてコマンドを打つことが出来るようになります。logコマンドはdmesgで表示される内容の元となるバッファを直に読むことが出来ます。
crash> log
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[ 0.000000] Linux version 5.15.0-1031-xilinx-zynqmp (buildd@bos03-arm64-030) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #35-Ubuntu SMP Fri Jun 14 02:59:36 UTC 2024 (Ubuntu 5.15.0-1031.35-xilinx-zynqmp 5.15.152)
[ 0.000000] Machine model: ZynqMP KR260 revB
[ 0.000000] efi: UEFI not found.
[ 0.000000] earlycon: cdns0 at MMIO 0x00000000ff010000 (options '115200n8')
[ 0.000000] printk: bootconsole [cdns0] enabled
[ 0.000000] NUMA: No NUMA configuration found
[ 0.000000] NUMA: Faking a node at [mem 0x0000000000000000-0x000000087fffffff]
[ 0.000000] NUMA: NODE_DATA [mem 0x87f7c5340-0x87f7c9fff]
[ 0.000000] Zone ranges:
[ 0.000000] DMA [mem 0x0000000000000000-0x00000000ffffffff]
[ 0.000000] DMA32 empty
[ 0.000000] Normal [mem 0x0000000100000000-0x000000087fffffff]
[ 0.000000] Device empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000000000-0x000000007fefffff]
[ 0.000000] node 0: [mem 0x000000007ff00000-0x000000007fffffff]
[ 0.000000] node 0: [mem 0x0000000800000000-0x000000087fffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x000000087fffffff]
(...)
shellコマンドも使えます。
crash> log |grep cma
[ 0.000000] cma: Reserved 1000 MiB at 0x0000000037400000
[ 0.000000] Kernel command line: root=LABEL=writable rootwait earlycon console=ttyPS1,115200 console=tty1 clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio xilinx_tsn_ep.st_pcp=4 cma=1000M
[ 0.000000] Memory: 2924836K/4194304K available (20992K kernel code, 3314K rwdata, 15584K rodata, 6848K init, 1340K bss, 245468K reserved, 1024000K cma-reserved)
4-3. crash runq でタスクレディキューを見る
runqコマンドは各コア(SMPの場合)のプロセススケジューラのタスクレディキューの状態を見れます。どの様なときに使えそうかと言われると正直私はわかりません。
動作中なので、読出し中に内容が書き換わっている可能性があり、完全なスナップショットではありません。
crash> runq
CPU 0 RUNQUEUE: ffff00087f747440
CURRENT: PID: 12520 TASK: ffff000802d65140 COMMAND: "crash"
RT PRIO_ARRAY: ffff00087f747700
[no tasks queued]
CFS RB_ROOT: ffff00087f747580
[no tasks queued]
CPU 1 RUNQUEUE: ffff00087f766440
CURRENT: PID: 0 TASK: ffff00080027b0c0 COMMAND: "swapper/1"
RT PRIO_ARRAY: ffff00087f766700
[no tasks queued]
CFS RB_ROOT: ffff00087f766580
[120] PID: 27057 TASK: ffff000800382080 COMMAND: "kworker/u8:3"
[120] PID: 2098 TASK: ffff000804d90000 COMMAND: "code-fee1edb8d6"
CPU 2 RUNQUEUE: ffff00087f785440
CURRENT: PID: 0 TASK: ffff00080027c100 COMMAND: "swapper/2"
RT PRIO_ARRAY: ffff00087f785700
[no tasks queued]
CFS RB_ROOT: ffff00087f785580
[no tasks queued]
CPU 3 RUNQUEUE: ffff00087f7a4440
CURRENT: PID: 0 TASK: ffff000800278000 COMMAND: "swapper/3"
RT PRIO_ARRAY: ffff00087f7a4700
[no tasks queued]
CFS RB_ROOT: ffff00087f7a4580
[no tasks queued]
4-4. crash p で グローバル変数表示
ここから先は例の動画では扱っていない内容です。まだまだcrashには多くの機能が用意されていますが、とても説明しきれないので便利そうなものを紹介します。
pコマンドはカーネル空間のグローバル変数を表示できます。
カーネルやカーネルモジュールのパラメータ値の確認などに使えそうです。
今回は時間変数jiffiesを読んでみます。これはカーネルのtickをカウントした回数です。
crash> p jiffies
jiffies = $2 = 4300814933
# HEX
crash> px jiffies
jiffies = $3 = 0x10084496e
以下のQiita記事でカーネルモジュールのパラメータを確認する方法の一つとして、crashを使用する方法が紹介されていました。Sysfsなどで参照不可なパラメータの値を読み出すことが出来ます。
Linuxでモジュールパラメータの値を確認する方法 (+ live kernel debugについて):Qiita @tmsn氏
5.最後に
今回は武内覚氏のYoutube動画の内容を実際にやってみました。crashツールの全ての機能は試してませんが、ここで挙げてない機能の方が、真価を発揮しそうなものがありそうでした。ただし、使い方が難しい部分があるので、続きはまた今度にしようと思います。
これまでにLinuxドライバまわりで躓いた際は、Linuxカーネルのソースコードを見に行くという方法をとっていました。しかし、いくつかこの方法には不便なところがあります。
- gitのリビジョンと実際に動作しているカーネルのリビジョンを一致出来ない場合(わからない)がある。
- 実際に動作しているカーネルでしか得られない情報がある。
- ソースコードではポインタを追うのが困難
crashにより、実際に動作しているカーネルの情報が引っこ抜けるのはかなり助けになるような気がします。今後、便利そうな使い方があれば、また紹介したいと思います。
次回は、crashコマンドを使用した、カーネルクラッシュダンプ解析のチュートリアルをやる予定です。