🤖

QEMU + ARM64用の最小Linuxカーネルをビルドする

2024/05/11に公開

本記事は、Linux カーネルを QEMU + ARM64 環境向けに最小限の機能のみ(本当にシリアル出力とキーボード入力のみレベル)に限定してビルドする手順をまとめています。

ソースコード取得

git clone --depth=1 -b v6.8 https://github.com/torvalds/linux.git
cd linux

最小のコンフィグを用意する

LinuxをQEMUで動かす(Armv8-A中心)を参考にさせていただきました。

arch/arm64/configs/qemu-busybox-min.configを作成します。

CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y

CONFIG_GPIOLIB=y
CONFIG_GPIO_PL061=y

CONFIG_KEYBOARD_GPIO=y

CONFIG_CMDLINE="console=ttyAMA0 nokaslr rdinit=/sbin/init"

.configファイルの生成

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make allnoconfig
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make qemu-busybox-min.config

カーネルのビルド

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j$(nproc)

QEMUで動作確認

この先に進む(通常のLinuxのプロンプトを表示するなど)にはrootfsを別途用意する必要があります。

$ qemu-system-aarch64 -machine virt,virtualization=on,gic-version=2 -net none -cpu cortex-a53 -m 1G -kernel arch/arm64/boot/Image -nographic
Booting Linux on physical CPU 0x0000000000 [0x410fd034]
Linux version 6.8.0 (hidenori@vm-ubuntu22) (aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #3 SMP Sat May 11 09:41:01 JST 2024
random: crng init done
Machine model: linux,dummy-virt
Zone ranges:
  DMA      [mem 0x0000000040000000-0x000000007fffffff]
  DMA32    empty
  Normal   empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000040000000-0x000000007fffffff]
Initmem setup node 0 [mem 0x0000000040000000-0x000000007fffffff]
psci: probing for conduit method from DT.
psci: PSCIv1.1 detected in firmware.
psci: Using standard PSCI v0.2 function IDs
psci: Trusted OS migration not required
psci: SMC Calling Convention v1.0
percpu: Embedded 16 pages/cpu s33824 r0 d31712 u65536
Detected VIPT I-cache on CPU0
alternatives: applying boot alternatives
Kernel command line: console=ttyAMA0 nokaslr rdinit=/sbin/init
Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
Inode-cache hash table entries: 65536 (order: 7, 524288 bytes, linear)
Built 1 zonelists, mobility grouping on.  Total pages: 258048
mem auto-init: stack:off, heap alloc:off, heap free:off
software IO TLB: SWIOTLB bounce buffer size adjusted to 1MB
software IO TLB: area num 1.
software IO TLB: mapped [mem 0x000000007ed00000-0x000000007ee00000] (1MB)
Memory: 1023844K/1048576K available (2368K kernel code, 620K rwdata, 508K rodata, 640K init, 323K bss, 24732K reserved, 0K cma-reserved)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
rcu: Hierarchical RCU implementation.
rcu: 	RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=1.
rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
Root IRQ handler: gic_handle_irq
GIC: Using split EOI/Deactivate mode
rcu: srcu_init: Setting srcu_struct sizes based on contention.
arch_timer: cp15 timer(s) running at 62.50MHz (phys).
clocksource: arch_sys_counter: mask: 0x1ffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
sched_clock: 57 bits at 63MHz, resolution 16ns, wraps every 4398046511096ns
Console: colour dummy device 80x25
Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=250000)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 2048 (order: 2, 16384 bytes, linear)
Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes, linear)
cacheinfo: Unable to detect cache hierarchy for CPU 0
rcu: Hierarchical SRCU implementation.
rcu: 	Max phase no-delay instances is 1000.
smp: Bringing up secondary CPUs ...
smp: Brought up 1 node, 1 CPU
SMP: Total of 1 processors activated.
CPU: All CPU(s) started at EL2
CPU features: detected: 32-bit EL0 Support
CPU features: detected: CRC32 instructions
alternatives: applying system-wide alternatives
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
futex hash table entries: 256 (order: 2, 16384 bytes, linear)
DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
ASID allocator initialised with 65536 entries
Serial: AMBA PL011 UART driver
9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 14, base_baud = 0) is a PL011 rev1
printk: legacy console [ttyAMA0] enabled
clocksource: Switched to clocksource arch_sys_counter
workingset: timestamp_bits=62 max_order=18 bucket_order=0
pl061_gpio 9030000.pl061: PL061 GPIO chip registered
clk: Disabling unused clocks
List of all partitions:
No filesystem could mount root, tried: 

Kernel panic - not syncing: VFS: Unable to mount root fs on "" or unknown-block(0,0)
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.8.0 #3
Hardware name: linux,dummy-virt (DT)
Call trace:
 dump_backtrace+0x9c/0xd0
 show_stack+0x14/0x1c
 dump_stack_lvl+0x44/0x58
 dump_stack+0x14/0x1c
 panic+0x320/0x334
 mount_root_generic+0x2dc/0x2f4
 mount_root+0x18c/0x24c
 prepare_namespace+0x44/0x2a0
 kernel_init_freeable+0x1d8/0x230
 kernel_init+0x24/0x1d4
 ret_from_fork+0x10/0x20
Kernel Offset: disabled
CPU features: 0x0,00000000,00000000,0100400b
Memory Limit: none
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on "" or unknown-block(0,0) ]---

Discussion