Back to all posts
LinuxQEMUarmvirtualization

Linux on QEMU (Arm-based)

Linux on QEMU (Arm-based)

This guide provides a step-by-step approach to running a Linux distribution on QEMU for Arm-based architectures. QEMU is a powerful open-source emulator that allows you to run operating systems for different architectures on your host machine.

We will use QEMU source code to build and configure a virtual machine that runs an Arm-based Linux distribution. We will only need three things to get started:

  1. QEMU source code
  2. Linux kernel source code
  3. A root filesystem (rootfs) for Arm

Linux Kernel Source Code

You can download the Linux kernel source code from the official repository:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

After that, navigate to the Linux source directory and build the kernel for the Arm architecture:

make ARCH=arm64 LLVM=1 defconfig
make ARCH=arm64 LLVM=1 -j$(nproc)

We don't use cross-compilation here to avoid complexity, so ensure you have clang, lld, and llvm installed on your system.

After building, the kernel image will be located at arch/arm64/boot/Image.

QEMU Source Code

Next, clone the QEMU source code from its official repository:

git clone https://git.qemu.org/git/qemu.git

Navigate to the QEMU source directory and configure it for Arm architecture:

cd qemu
./configure enable-debug
make -j$(nproc)

This will build QEMU with support for Arm-based virtual machines. You can find the QEMU binary at build/qemu-system-aarch64.

Root Filesystem (rootfs)

You can create a simple root filesystem using BusyBox. But, we use Alpine Linux for this guide. Download the Alpine Linux rootfs for Arm64:

# Download Alpine Linux minirootfs for ARM64
wget https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/aarch64/alpine-minirootfs-3.19.0-aarch64.tar.gz

# Extract it
mkdir alpine-rootfs
cd alpine-rootfs
tar xzf ../alpine-minirootfs-3.19.0-aarch64.tar.gz

# Create init script
cat > init << 'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
echo "========================================"
echo "Booted Alpine Linux ARM64 successfully!"
echo "========================================"
exec /bin/sh
EOF
chmod +x init

# Package it
find . | cpio -o -H newc | gzip > ../alpine-arm64.cpio.gz

Running QEMU with the Linux Kernel and rootfs

Now that we have the kernel and root filesystem ready, we can run QEMU with the following command:

./build/qemu-system-aarch64 \
  -machine virt \  # Use the 'virt' machine type
  -cpu cortex-a57 \  # Specify the CPU type
  -m 1024 \  # Allocate 1GB of RAM
  -kernel ../linux/arch/arm64/boot/Image \  # Path to the kernel image
  -initrd ../alpine-arm64.cpio.gz \  # Path to the root filesystem
  -nographic \  # Disable graphical output
  -append "console=ttyAMA0 root=/dev/ram rw"  # Kernel command line arguments

If you need networking support, you can add the following options to the QEMU command:

-netdev user,id=net0 \
-device virtio-net-pci,netdev=net0

This will set up user-mode networking for the virtual machine.

Conclusion

You should now see the Alpine Linux booting up in the QEMU terminal. You can interact with the shell and explore the Arm-based Linux environment. This setup provides a great way to experiment with Linux on Arm architecture without needing physical hardware. Enjoy your virtualized Linux experience!