関連記事
概要
x86_64の開発PCでARM64用にLinuxカーネルをビルド、busyboxで簡易initramfsを用意する。
また、QEMU (virtボード)でこれらのバイナリを動かした。
はじめに
Linuxカーネルは様々なアーキテクチャに対応している。
その中でもARMアーキテクチャでは、スマートフォンやゲーム機器などモバイル機器に広くから採用されている。
しかし、アーキテクチャ毎に命令セットが異なるため、ARM用にビルドされたバイナリを別のアーキテクチャで実行することはできない。
そこで、プロセッサエミュレータでもあるQEMUを用いてARM環境を構築し、ARM用にビルドされたLinuxカーネルを動かす方法を解説する。
また本記事では、以下の動作をする環境を目指す。
環境構成
本記事は、下記の環境とソフトウェアバージョンに基づいて説明する。
環境 | パラメータ |
---|---|
ホスト環境 | x86_64 |
ホストOS | Ubuntu 20.04 |
QEMU | QEMU emulator version 4.2.1 |
ターゲットボード | virt |
linux | 5.4.83 |
Busybox | 1_32_stable |
Docker | version 19.03.13 |
Docker image | ubuntu:20.04 |
クロスコンパイル環境の構築
Docker imageからコンテナを作成する
leava@ubuntu-bionic:~$ docker run --rm --name=kbuild -h "kbuild" -v /srv:/work -it ubuntu:20.04 /bin/bash
-
root@kbuild:/# apt update root@kbuild:/# apt install gcc-aarch64-linux-gnu
コンテナ内部でLinuxカーネルをビルドするために必要なパッケージをインストールする
root@kbuild:/# apt install build-essential bc bison flex libncurses-dev libelf-dev libssl-dev git wget
-
root@kbuild:/# wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.83.tar.xz root@kbuild:/# tar xf linux-5.4.83.tar.xz -C /work/ root@kbuild:/# cd work/linux-5.4.83 root@kbuild:/work/linux-5.4.83# export ARCH="arm64" root@kbuild:/work/linux-5.4.83# export CROSS_COMPILE="aarch64-linux-gnu-"
カーネルをビルドする。
root@kbuild:/work/linux-5.4.83# make defconfig root@kbuild:/work/linux-5.4.83# make -j `getconf _NPROCESSORS_ONLN` Image dtbs modules
上記のコマンドによって、/srv
ディレクトリに Kernel ImageとDevice Tree Bolb(DTB)、Loadable Moduleが生成される。
QEMUでカーネルを起動させる
ARM64用QEMUをインストールする
leava@ubuntu-bionic:~$ sudo apt install qemu-system-aarch64
-
leava@ubuntu-bionic:~$ qemu-system-aarch64 \ -M virt \ -cpu cortex-a53 \ -kernel /srv/linux-5.4.83/arch/arm64/boot/Image \ -nographic \ -append "console=ttyAMA0"
利用したオプションは下記の通り。
また、デバイスツリーを指定していないにも関わらず起動できているのは、QEMUのvirtがデバイスツリーを自動生成しているからである。
オプション | 概要 |
---|---|
-M | 利用するターゲットボードを指定する。今回は汎用ボードのvirt を使用する。 |
-cpu | CPUプロセッサを指定する。今回はARM64系のcortex-a53 を使用する |
-kernel | カーネルイメージを指定する。先ほどビルドしたイメージを使用する。 |
-nographic | GUIを立ち上げない |
-append | カーネルパラメータ。 ARMアーキテクチャのシリアルポートデバイスのttyAMA0 を使用する。 |
上記のコマンドを実行すると、kernel Panicしてしまう。
[ 0.440663] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
[ 0.440874] Please append a correct "root=" boot option; here are the available partitions:
[ 0.441240] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[ 0.441534] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.4.83 #1
[ 0.441648] Hardware name: linux,dummy-virt (DT)
[ 0.441849] Call trace:
[ 0.441927] dump_backtrace+0x0/0x140
[ 0.442063] show_stack+0x14/0x20
[ 0.442143] dump_stack+0xb4/0x114
[ 0.442212] panic+0x158/0x324
[ 0.442275] mount_block_root+0x1d0/0x284
[ 0.442349] mount_root+0x124/0x158
[ 0.442421] prepare_namespace+0x12c/0x18c
[ 0.442489] kernel_init_freeable+0x210/0x23c
[ 0.442553] kernel_init+0x10/0x100
[ 0.442619] ret_from_fork+0x10/0x1c
[ 0.442977] Kernel Offset: disabled
[ 0.443166] CPU features: 0x0002,24002004
[ 0.443266] Memory Limit: none
[ 0.443628] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
initramfsを用意する
上記のメッセージを確認すると、「rootファイルシステムがない」からPanicしたことがわかるので、C-a x
でQEMUを終了する。
そこで、BusyBoxを利用して最低限起動できるrootファイルシステムを作成する。
BusyBoxは、UNIX系ユーティリティツール単一の実行ファイルにまとめたパッケージで、組込みLinuxでも利用されている。
BusyBoxを取得する。
root@kbuild:/# cd work root@kbuild:/work# git clone git://git.busybox.net/busybox root@kbuild:/work# cd busybox root@kbuild:/work/busybox# git checkout remotes/origin/1_32_stable
ビルド用の設定を修正する。最低限の動作を目指しているので、デフォルトから
CONFIG_STATIC
を有効にするのみでよい。(CONFIG_STATIC
はSetting->Build static binary (no shared libs)
を有効にすることで設定される)root@kbuild:/work/busybox# make defconfig root@kbuild:/work/busybox# make menuconfig
BusyBoxをビルドし、イメージを
_install
に生成する。root@kbuild:/work/busybox# make root@kbuild:/work/busybox# make install
initramfsとして最低限必要なファイルやディレクトリを作成する。
root@kbuild:/work/busybox# cd _install root@kbuild:/work/busybox/_install# mkdir proc root@kbuild:/work/busybox/_install# mkdir sys root@kbuild:/work/busybox/_install# mkdir dev root@kbuild:/work/busybox/_install# sudo mknod dev/null c 1 3 root@kbuild:/work/busybox/_install# cat <<EOF > init #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys /sbin/mdev -s exec /bin/sh EOF root@kbuild:/work/busybox/_install# chmod +x init
initramfsを生成する。
root@kbuild:/work/busybox/_install# find . | cpio -o --format=newc > ../rootfs.img
作成したイメージを利用して、再度QEMUを実行する。
leava@ubuntu-bionic:~$ qemu-system-aarch64 \ -M virt \ -cpu cortex-a53 \ -kernel /srv/linux-5.4.83/arch/arm64/boot/Image \ -initrd /srv/busybox/rootfs.img \ -nographic \ -append "console=ttyAMA0"
オプション | 概要 |
---|---|
-initrd | 初期 RAM ディスク。BusyBoxで作成したイメージを使用する。 |
上記のコマンドを実行すると、シェルが立ち上がる。
[ 0.425197] sdhci: Copyright(c) Pierre Ossman
[ 0.425800] Synopsys Designware Multimedia Card Interface Driver
[ 0.427183] sdhci-pltfm: SDHCI platform and OF driver helper
[ 0.429410] ledtrig-cpu: registered to indicate activity on CPUs
[ 0.431969] usbcore: registered new interface driver usbhid
[ 0.432146] usbhid: USB HID core driver
[ 0.440648] NET: Registered protocol family 17
[ 0.441712] 9pnet: Installing 9P2000 support
[ 0.442051] Key type dns_resolver registered
[ 0.443071] registered taskstats version 1
[ 0.443167] Loading compiled-in X.509 certificates
[ 0.449869] input: gpio-keys as /devices/platform/gpio-keys/input/input0
[ 0.451992] rtc-pl031 9010000.pl031: setting system clock to 2020-12-13T15:31:16 UTC (1607873476)
[ 0.455420] ALSA device list:
[ 0.455514] No soundcards found.
[ 0.457913] uart-pl011 9000000.pl011: no DMA platform data
[ 0.648255] Freeing unused kernel memory: 4992K
[ 0.648750] Run /init as init process
/bin/sh: can't access tty; job control turned off
/ #
おわりに
実際にARMアーキテクチャを所持していなくても、QEMUでARM用Linuxカーネルを起動させることができた。今回の記事では紹介できなかったが、gdbデバッグが容易にできたりとデバッグ時にも大変有効であるので積極的に利用していきたい。
今回はBusyBoxのデフォルト設定でrootファイルシステムも生成したが、こちらは今後の課題となってくる。
変更履歴
- 2020/01/26: 記事公開
- 2020/12/11: ブログタイトルを "ARM64用" に訂正
- 2020/12/14: 実行環境をUbuntu18.04からUbuntu20.04に更新
- 2022/06/07: デザイン修正
参考
- Busybox for ARM on QEMU | Freedom Embedded
- Linuxカーネルのテスト実行とデバッグ (1) :QEMU編 - Fixstars Tech Blog /proc/cpuinfo
- RootFS and Network of Qemu
- LinuxカーネルをARM向けにビルドしてQEMUで起動する - hiroki.kanaの日常
- ビルドしたLinuxカーネルをブートできる最低限の環境を用意する(with Busybox & qemu) - 豆腐の豆腐和え
- QEMU: 仮想ボード ARM Cortex-A9 マルチコアで Linux を動かす - Cacher Snippet
- [QEMU][Linux] virt model の構成を見てみる | archmemo