Skip to content

Latest commit

 

History

History
121 lines (93 loc) · 4.39 KB

File metadata and controls

121 lines (93 loc) · 4.39 KB

Phase 1 — The minimal Linux 7.1 kernel

Goal: the smallest possible bootable Linux 7.1 kernel.

Result: a 945 KB bzImage (967 680 bytes) that boots to userspace in ~0.29 s under QEMU/KVM and runs a PID 1 init from an initramfs.

Metric Value
Kernel Linux 7.1.0
bzImage size 945 KB (967 680 bytes)
Enabled (=y) config symbols 522 (vs. ~1850 for the modern build)
Build time ~40 s on 12 cores
Time-to-userspace 0.294 s (KVM)
initramfs 308 KB (static init + /dev/console)

The idea: tinyconfig + the few options needed to boot

make tinyconfig produces the absolute minimum config the kernel will accept — on x86 that is a 32-bit, console-less kernel (367 =y symbols) that cannot reach userspace. To make it bootable we add only what is strictly required:

Option Why it's needed
CONFIG_64BIT build a 64-bit kernel (run a 64-bit init)
CONFIG_PRINTK emit kernel log messages at all
CONFIG_TTY + CONFIG_SERIAL_8250(_CONSOLE) a console on the QEMU serial port
CONFIG_BINFMT_ELF execute an ELF init binary
CONFIG_BLK_DEV_INITRD unpack and run an initramfs
CONFIG_EARLY_PRINTK see messages before the console is fully up

That is the whole philosophy of "minimal": start from nothing, add only the handful of symbols that take you from "won't boot" to "runs userspace". The result still has no networking, no block devices, no filesystems beyond the in-memory initramfs, no modules — by design.

Build steps (exactly what was run)

KSRC=~/os_experiments/linux_kernel/src
BMIN=~/os_experiments/linux_kernel/build-minimal

# 1. absolute-minimum baseline (out-of-tree build dir via O=)
make -C "$KSRC" O="$BMIN" tinyconfig

# 2. add only the options needed to boot + run an init
"$KSRC"/scripts/config --file "$BMIN/.config" \
    -e 64BIT -e PRINTK -e PRINTK_TIME -e TTY \
    -e SERIAL_8250 -e SERIAL_8250_CONSOLE \
    -e BINFMT_ELF -e BLK_DEV_INITRD -e EARLY_PRINTK
make -C "$KSRC" O="$BMIN" olddefconfig      # resolve dependencies

# 3. build (≈40 s)
make -C "$KSRC" O="$BMIN" -j"$(nproc)" bzImage
#   -> $BMIN/arch/x86/boot/bzImage  (945 KB)

The initramfs (so there is something to run)

A kernel with no root filesystem panics with "No init found". We give it the tiniest possible userspace: a single static init that prints a banner and powers off. Device nodes are added without root using the kernel's own gen_init_cpio tool (so /dev/console exists and the init's stdout reaches the serial port):

gcc -static -Os -s -o init init.c          # statically linked PID 1
gcc -O2 -o gen_init_cpio "$KSRC/usr/gen_init_cpio.c"

cat > initramfs.list <<EOF
dir   /dev          0755 0 0
nod   /dev/console  0600 0 0 c 5 1
file  /init  $PWD/init  0755 0 0
EOF

./gen_init_cpio initramfs.list | gzip -9 > initramfs.cpio.gz   # 308 KB

init.c is ~20 lines: write(1, banner), then reboot(RB_POWER_OFF).

Boot test (QEMU + KVM)

qemu-system-x86_64 -M pc -accel kvm -m 256M \
  -kernel  arch/x86/boot/bzImage \
  -initrd  initramfs.cpio.gz \
  -append "console=ttyS0" \
  -nographic -no-reboot

Captured output (artifacts/minimal/boot.log), trimmed:

[    0.261603] Unpacking initramfs...
[    0.294286] Run /init as init process

==================================================
  Hello from the MINIMAL Linux 7.1 kernel!
  I am PID 1 (init), launched from initramfs.
  The whole bzImage is < 1 MB.
==================================================

[    0.696909] reboot: Power off not available: System halted instead

The kernel reaches userspace in 0.29 s and our init runs. The "Power off not available" line is expected and is itself a sign of how minimal the kernel is — it has no ACPI, so it cannot power the machine off; it halts and QEMU is reaped by the wrapper's timeout. (Adding ACPI for a clean power-off would mean leaving "minimal" territory.)

WSL2 note: /dev/kvm exists but is group-restricted. We enabled acceleration with sudo usermod -aG kvm $USER + sudo chmod 0666 /dev/kvm. Without KVM, QEMU still boots this kernel under pure software emulation (TCG), just much slower — fine for a one-off, painful for iteration.

Reproduce

Everything is captured under artifacts/minimal/: bzImage, config, initramfs.cpio.gz, init.c, boot.log, and run-qemu.sh (one-command re-boot).