translatedcode

QEMU for and on ARM cores

Debian on QEMU’s Raspberry Pi 3 model

with 17 comments

For the QEMU 2.12 release we added support for a model of the Raspberry Pi 3 board (thanks to everybody involved in developing and upstreaming that code). The model is sufficient to boot a Debian image, so I wanted to write up how to do that.

Things to know before you start

Before I start, some warnings about the current state of the QEMU emulation of this board:

  • We don’t emulate the boot rom, so QEMU will not automatically boot from an SD card image. You need to manually extract the kernel, initrd and device tree blob from the SD image first. I’ll talk about how to do that below.
  • We don’t have an emulation of the BCM2835 USB controller. This means that there is no networking support, because on the raspi devices the ethernet hangs off the USB controller.
  • Our raspi3 model will only boot AArch64 (64-bit) kernels. If you want to boot a 32-bit kernel you should use the “raspi2” board model.
  • The QEMU model is missing models of some devices, and others are guesswork due to a lack of documentation of the hardware; so although the kernel I tested here will boot, it’s quite possible that other kernels may fail.

You’ll need the following things on your host system:

  • QEMU version 2.12 or better
  • libguestfs (on Debian and Ubuntu, install the libguestfs-tools package)

Getting the image

I’m using the unofficial preview images described on the Debian wiki.

$ wget https://people.debian.org/~stapelberg/raspberrypi3/2018-01-08/2018-01-08-raspberry-pi-3-buster-PREVIEW.img.xz
$ xz -d 2018-01-08-raspberry-pi-3-buster-PREVIEW.img.xz

Extracting the guest boot partition contents

I use libguestfs to extract files from the guest SD card image. There are other ways to do this but I think libguestfs is the easiest to use. First, check that libguestfs is working on your system:

$ virt-filesystems -a 2018-01-08-raspberry-pi-3-buster-PREVIEW.img
/dev/sda1
/dev/sda2

If this doesn’t work, then you should sort that out first. A couple of common reasons I’ve seen:

  • if you’re on Ubuntu then your kernels in /boot are installed not-world-readable; you can fix this with sudo chmod 644 /boot/vmlinuz*
  • if you’re running Virtualbox on the same host it will interfere with libguestfs’s attempt to run KVM; you can fix that by exiting Virtualbox

Now you can ask libguestfs to extract the contents of the boot partition:

$ mkdir bootpart
$ guestfish --ro -a 2018-01-08-raspberry-pi-3-buster-PREVIEW.img -m /dev/sda1

Then at the guestfish prompt type:

copy-out / bootpart/
quit

This should have copied various files into the bootpart/ subdirectory.

Run the guest image

You should now be able to run the guest image:

$ qemu-system-aarch64 \
  -kernel bootpart/vmlinuz-4.14.0-3-arm64 \
  -initrd bootpart/initrd.img-4.14.0-3-arm64 \
  -dtb bootpart/bcm2837-rpi-3-b.dtb \
  -M raspi3 -m 1024 \
  -serial stdio \
  -append "rw earlycon=pl011,0x3f201000 console=ttyAMA0 loglevel=8 root=/dev/mmcblk0p2 fsck.repair=yes net.ifnames=0 rootwait memtest=1" \
  -drive file=2018-01-08-raspberry-pi-3-buster-PREVIEW.img,format=raw,if=sd

and have it boot to a login prompt (the root password for this Debian image is “raspberry”).

There will be several WARNING logs and backtraces printed by the kernel as it starts; these will have a backtrace like this:

[  145.157957] [] uart_get_baud_rate+0xe4/0x188
[  145.158349] [] pl011_set_termios+0x60/0x348
[  145.158733] [] uart_change_speed.isra.3+0x50/0x130
[  145.159147] [] uart_set_termios+0x7c/0x180
[  145.159570] [] tty_set_termios+0x168/0x200
[  145.159976] [] set_termios+0x2b0/0x338
[  145.160647] [] tty_mode_ioctl+0x358/0x590
[  145.161127] [] n_tty_ioctl_helper+0x54/0x168
[  145.161521] [] n_tty_ioctl+0xd4/0x1a0
[  145.161883] [] tty_ioctl+0x150/0xac0
[  145.162255] [] do_vfs_ioctl+0xc4/0x768
[  145.162620] [] SyS_ioctl+0x8c/0xa8

These are ugly but harmless. (The underlying cause is that QEMU doesn’t implement the undocumented ‘cprman’ clock control hardware, and so Linux thinks that the UART is running at a zero baud rate and complains.)

Written by pm215

April 25, 2018 at 9:07 am

Posted in linaro, qemu

17 Responses

Subscribe to comments with RSS.

  1. Does it have graphics/VGA output? Or is it headless only?

    gilius

    April 27, 2018 at 8:06 pm

    • I’m not sure — I don’t personally have much use for graphics output so I haven’t tested. I think it ought to support basic 2d framebuffer graphics, though. There is definitely no GPU emulation.

      pm215

      April 30, 2018 at 9:19 am

  2. Instead of using libguestfs, you can also just mount the partition, and copy the files out:

    sudo mount -r -o loop,offset=1048576 2018-01-08-raspberry-pi-3-buster-PREVIEW.img somedir
    cp somedir/* bootpart
    sudo umount somedir

    1048576 is 2048*512, where 2048 is the startsector of the boot partition.

    Thorsten Otto

    May 5, 2018 at 10:25 am

    • Yes, indeed — as I say there are several ways to do this. I just like libguestfs because it doesn’t require you to mess around fishing out starting sectors from the partition table and doing arithmetic on them.

      pm215

      May 5, 2018 at 11:12 am

  3. Hi, I am trying to emulate the pi3, cortex-a53 with raspbian in an ubuntu 16.04 pc. I have qemu 2.12, and it has the machine raspi3 and the cpu cortex-a53. But I can not make it work with qemu-system-aarch64. I have downloaded the raspian stretch image and the kernel-qemu rpi. I do not knwo how to go on. Can you give me any hints? Unfortunately I didn’t find tutorials on this

    Rodrigo Santos

    June 2, 2018 at 12:45 am

    • The blog post you’re commenting on is all the help I have…the instructions in it work for me.

      pm215

      June 2, 2018 at 12:13 pm

  4. What are the compile or configure arguments, or required packages, to build QEMU with the raspi3 machine enabled? raspi3 wasn’t available in the version in the latest Ubuntu repo (as of 2018-06-11), and though I built 2.12 from source (with all targets), raspi3 still wasn’t a valid machine.

    calmor15014

    June 13, 2018 at 4:43 pm

    • The only configure option you need is to make sure you’re building qemu-system-aarch64 with at least QEMU 2.12.

      pm215

      June 14, 2018 at 11:29 am

      • Thanks for your comment. I have aarch64 and QEMU 2.12 direct from the QEMU site, but no raspi3.

        Now that we’re discussing it, perhaps I have a conflict with the version that I installed from the repository. I’ll check that next. Thanks!

        calmor15014

        June 14, 2018 at 3:43 pm

  5. hi i am currently trying to emulate a raspi2 environment however when it launches i get the 4 pi icons but nothing else.

    The variable i am using are

    qemu-system-arm -M raspi2
    -kernel ./images/kernel7.img
    -sd ./images/raspbian-stretch-lite.qcow
    -dtb ./images/bcm2709-rpi-2-b.dtb
    -serial stdio
    -append “rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2”

    I have a kernel output if that helps

    https://www.dropbox.com/s/6w656nrytklb0sf/kernel%20output.txt?dl=0

    Hope someone can help

    Thanks

    Richard Griffiths

    July 1, 2018 at 4:22 pm

    • Did it work for you? I am trying something similar and facing a tough time making it work

      Aditya Govardhan

      July 21, 2019 at 6:01 am

    • Actually I am getting stuck at Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(0,0) with command provided by you

      Aditya Govardhan

      July 21, 2019 at 6:02 am

  6. Hey,

    when im trying this out the kernel boot hangs endless in the Starting/Stopped network Time Synchronization Domain.
    Of course, there is no network support but how can I proceed with booting the kernel without network? maybe a missing qemu flag?

    Thanks!!

    Jan Bolke

    September 17, 2018 at 12:49 pm

    • All I can say is “this works for me”. Yes, the NTP daemon startup won’t work, but that will eventually time out.

      pm215

      September 24, 2018 at 12:58 pm

  7. Hey!

    Thanks a lot for the hard work, appreciate the contribution :)

    Currently I am able to boot correctly into the machine, however since there is no networking i cannot obtain the tools for compiling or monitoring execution.

    Was thinking about 9P protocol for file sharing but it seems not working either (followed https://superuser.com/questions/628169/how-to-share-a-directory-with-the-host-without-networking-in-qemu):
    No ‘PCI’ bus found for device ‘virtio-9p-pci’

    Sending binaries over serial looks inconvenient, so i was wondering if you have any suggestion on how to achieve file transfer / sharing at the current state.

    Thanks in advance.

    Adrián Herrera Arcila

    October 23, 2018 at 2:48 pm

    • Correct, there’s no PCI bus on a raspi. Usually the answer to this is “use networking”, but there’s no networking support in the QEMU model at the moment. I would suggest “shut down the guest; use guestfish to read or write files from the guest disk image; restart the guest”, which is pretty clunky but will work.

      pm215

      November 12, 2018 at 10:30 am

  8. Has anyone been able to get the display to work?

    Cary Lewis

    December 29, 2018 at 11:09 pm


Leave a reply to Aditya Govardhan Cancel reply