Step 1: Getting QEMU

The first step in running a QEMU ARM guest is to obtain the appropriate QEMU binary. You can either install QEMU directly through the package manager on your system, or you can download and compile the sources:

git clone git://git.qemu.org/qemu.git && cd qemu
sudo apt-get build-dep qemu
./configure
make -j <n>

If you see this error E: You must put some 'source' URIs in your sources.list when trying to install the build-dependencies, make sure you have the appropriate deb-src entries in your /etc/apt/sources.list (Google for the specifics).

Note, if you don't care about other QEMU targets than 32-bit ARM, you can run

./configure --target-list=arm-softmmu

This will place your QEMU binary in arm-softmmu/qemu-system-arm within the qemu directory.

Step 2: Configuring an Ubuntu guest rootfs

sudo mkdir arm-trusty-root
sudo qemu-debootstrap --arch=armhf trusty ./arm-trusty-root/

When it's done, you'll need to tweak some files in the chroot:

  • copy etc/init/tty1.conf to etc/init/ttyAMA0.conf and edit it to change 'tty1' to 'ttyAMA0' everywhere
  • sudo chroot arm-trusty-root and run passwd to set root's password

  • create an etc/apt/sources.list:

deb http://ports.ubuntu.com/ trusty main restricted universe
deb-src http://ports.ubuntu.com/ trusty main restricted universe

Note that since this is a qemu-debootstrap-created directory tree you can run "sudo chroot arm-trusty-root" to chroot into it using qemu's linux-user emulation. This is particularly useful for installing random extra packages. (If you try to do anything too exciting in the chroot you may run into issues with QEMU. Sorry...)

Step 3: Creating an image file

You are going to have to create an image file that QEMU can mount and that your guest can access. For this purpose we are going to create an ext4 image, which we can pass to QEMU as a virtio-block device.

To create a 2GB sized ext4 image:

dd if=/dev/zero of=arm-trusty.img bs=1M count=2048
mkfs.ext4 arm-trusty.img

We need to populate the image with the generated rootfs from above. To do that, we're going to loopback mount the image and populate it:

sudo mkdir /mnt/temp
sudo mount -o loop -t ext4 arm-trusty.img /mnt/temp
sudo cp -a arm-trusty-root/* /mnt/temp/.

Remember to unmount the file system:

sudo umount /mnt/temp

Step 4: Build your kernel

You need a cross-compiler on your system to build a Linux kernel to use with QEMU. You can download one of Linaro's recent compilers from here: http://www.linaro.org/downloads/

You may have to tweak the URL depending on the latest release, but you should be able to do:

wget http://releases.linaro.org/14.09/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz
mkdir ~/tools/armhf-toolchain
tar -C ~/tools/armhf-toolchain --strip-components=1 -xf gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz
export PATH=~/tools/armhf-toolchain/bin:$PATH

Note that you may be able to simply install a cross-compiler from your distro, but recent versions of the cross compiler do not work with the upstream kernel.

Now download the Linux kernel sources:

git clone https://github.com/torvalds/linux.git
cd linux
git checkout v3.7 # or some other version

You can now configure and build the kernel:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make vexpress_defconfig
./scripts/config -e CONFIG_LBDAF
./scripts/config -e CONFIG_VIRTIO_BLK
./scripts/config -e CONFIG_SCSI_VIRTIO
./scripts/config -e CONFIG_VIRTIO_NET
./scripts/config -e CONFIG_VIRTIO_CONSOLE
./scripts/config -e CONFIG_VIRTIO
./scripts/config -e CONFIG_VIRTIO_BALLOON
./scripts/config -e CONFIG_VIRTIO_MMIO
./scripts/config -e CONFIG_DEVTMPFS_MOUNT
yes '' | make oldconfig
make -j <n>

This should produce your kernel in arch/arm/boot/zImage.

Step 5: Run QEMU

You now have all the required components. The example command line assumes you will have all the following files in the current directory:

  • zImage
  • arm-trusty.img

./qemu-system-arm \
  -cpu cortex-a15 \
  -machine type=virt \
  -m 2048 \
  -kernel zImage \
  -append 'console=ttyAMA0 root=/dev/vda rw' \
  -serial mon:stdio \
  -display none \
  -drive index=0,id=rootfs,file=arm-trusty.img \
  -device virtio-blk-device,drive=rootfs \
  -netdev user,id=mynet \
  -device virtio-net-device,netdev=mynet

Core/Virtualization/HowTo/Arm32QemuGuest (last modified 2014-12-07 13:54:43)