General QEMU Information

See the QEMU Wiki Page for more information on using QEMU.

Supported Zynq UltraScale+ Devices

Below is a list of Zynq UltraScale+ models that Xilinx's QEMU supports:
  • Ethernet
  • SDHCI/SD
  • QSPI Controller
  • UART
  • SPI
  • I2C
  • DDR (No ECC)
  • OCM
  • APUs
    • 4 x A53s
      • AArch64 Support for: EL0, EL1, EL2 and EL3
      • AArch32 Support for: EL0, EL1
    • ARM GIC v2
  • RPUs
    • 2 x R5s
    • Limited run time configuration
      • No lock step fault capability
    • Globally accessible TCM
    • Interrupt Controller
  • XMPU
  • ARM SMMU
  • Limited PMU specific interprocessor interrupt functionality
  • PMU (Not supported in PetaLinux-Boot flow)
    • MicroBlaze
    • PMU Interrupt Controller
  • IPI

Running a Zynq UltraScale+ Linux Kernel Image On Xilinx's ARM QEMU

Below is an example of booting a Linux image on a ARM only Zynq UltraScale+ machine (ZCU102). This use case relies on the linux-boot.elf binary which is created by PetaLinux. To avoid requiring this binary use the u-boot boot flow shown below. The kernel should start booting and a shell prompt should be displayed. Control a-x will exit QEMU.
NOTE: This does not start the PMU and will not work with kernels that require the PMU FW (PetaLinux kernels after 2017.1).
$ ./aarch64-softmmu/qemu-system-aarch64 -M arm-generic-fdt -serial mon:stdio -serial /dev/null -display none \
  -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 \ # Un-reset the A53
  -device loader,file=./pre-built/linux/images/bl31.elf,cpu-num=0 \ # ARM Trusted Firmware
  -device loader,file=./pre-built/linux/images/Image,addr=0x00080000 \ # Linux kernel
  -device loader,file=./images/linux/system.dtb,addr=0x1407f00# \ # Linux Device Tree
  -device loader,file=./build/linux/misc/linux-boot/linux-boot.elf \ # A light boot loader, compiled by PetaLinux
  -hw-dtb ./pre-built/linux/images/zynqmp-qemu-arm.dtb # HW Device Tree that QEMU uses to generate the model
This will boot an example with the 4 A53s and the 2 R5s. If you would like to run the PMU as well (not always required, but it can be useful) see below:
Example images for the ZCU102 board (a Zynq UltraScale+ board) can be found in the Zynq release tarball available at: http://www.wiki.xilinx.com/Zynq+Releases

Running a Zynq UltraScale+ U-boot Image On Xilinx's ARM QEMU

Below is an example of booting a u-boot elf image on a ARM only Zynq UltraScale+ machine (ZCU102).
NOTE: This does not start the PMU and will not work with kernels that require the PMU FW (PetaLinux kernels after 2017.1).
$ ./aarch64-softmmu/qemu-system-aarch64 -M arm-generic-fdt -serial mon:stdio -serial /dev/null -display none \
  -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 \ # Un-reset the A53
  -device loader,file=./pre-built/linux/images/bl31.elf,cpu-num=0 \ # ARM Trusted Firmware
  -device loader,file=./pre-built/linux/images/u-boot.elf\ # The u-boot exectuable
  -hw-dtb ./pre-built/linux/images/zynqmp-qemu-arm.dtb # HW Device Tree that QEMU uses to generate the model

Running a Zynq UltraScale+ Linux Kernel Image On Xilinx's ARM/PMU QEMU

This example allows you to start two instances of QEMU, one with the ARM cores and one with the MicroBlaze PMU core. NOTE that the QEMU hardware device trees are only supplied with PetaLinux 2016.1 and later BSPs.
If you are having issues starting QEMU, you can run petalinux-boot --qemu to see an example command line.
In the first terminal, start the ARM cores
$ ./aarch64-softmmu/qemu-system-aarch64 -M arm-generic-fdt -serial mon:stdio -serial /dev/null -display none \
  # -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 \ # Un-reset the A53, only do this if not using the line below (if you are unsure, don't use this)
  -global xlnx,zynqmp-boot.cpu-num=0 -global xlnx,zynqmp-boot.use-pmufw=true \ # Setup multi-boot, if doing this you don't need to in-reset the APU
  -device loader,file=./pre-built/linux/images/bl31.elf,cpu-num=0 \ # ARM Trusted Firmware
  -device loader,file=./pre-built/linux/images/Image,addr=0x00080000 \ # Linux kernel
  -device loader,file=./images/linux/system.dtb,addr=0x1407f00# \ # Linux Device Tree
  -device loader,file=./build/linux/misc/linux-boot/linux-boot.elf \ # A light boot loader, compiled by PetaLinux
  -hw-dtb ./pre-built/linux/images/zynqmp-qemu-multiarch-arm.dtb \ # HW Device Tree that QEMU uses to generate the model
  -machine-path ./qemu-tmp # A shared directory the two instances can communicate. This must be the same directory for each instance
In a second terminal start the PMU instance. You will need to have an image prepared
$ ./microblazeel-softmmu/qemu-system-microblazeel -M microblaze-fdt -nographic \
  -hw-dtb ./pre-built/linux/images/zynqmp-qemu-multiarch-pmu.dtb \
  -kernel ./images/zynqmp/petalinux-v2017.1/pmu_rom_qemu_sha3.elf \ # PMU ROM
  -device loader,file=/images/zynqmp/petalinux-v2017.1/pmufw.elf \ # PMU FW
  -machine-path ./qemu-tmp \ # A shared directory the two instances can communicate. This must be the same directory for each instance
  -device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 -device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4 # Write some important data into memory
 

Debugging the A53s and the R5s from GDB

To debug the A53s and the R5s from GDB you will need to use a multiarch version of GDB. This can either be compilled from source or is included in some Linux distros. You will have to make sure the ARMv7 and ARMv8 support are both included in GDB.
For Ubuntu you can use the gdb-multiarch package.

Once you have started the multiarch GDB you can use these commands to connect and see the A53s and R5s.
        target extended-remote :1234
        add-inferior
        inferior 2
        attach 2
        info threads
Where 1234 is the port that was opened by QEMU.
You can open the QEMU port when starting QEMU using this argument:
-gdb tcp::1234
where 1234 is the port to open. You can also use the -S option which is short hand for the command shown above.
If QEMU is already running you can use the gdbserver command from the QEMU prompt to open the GDB server port.

To simplify this connection you can add a function to GDB. To do this edit your .gdbinit file (located in your home directory) and add something like this:
define rdo_arm
target extended-remote :1234
add-inferior
inferior 2
attach 2
info threads
end

QEMU Board Specific Device Trees

The QEMU board specific device trees are only used by QEMU and should not be used by other software. They are the device trees specified by the '-hw-dtb' argument.
The device trees can be built by cloning the Git repo here: https://github.com/Xilinx/qemu-devicetrees and then running the following command in the same directory as the files.
$ make
You will need to have DTC, make and GCC installed to be able to build the DTB files. DTC can be installed on Ubuntu using the following command:
$ sudo apt install device-tree-compiler gcc make

For versions of QEMU older then 2016.3 you can still download the prepared device trees below, although the qemu-devicetree repo should work on older versions of QEMU

ZCU102 - Single Architecture ARM instance - Released with PetaLinux 2016.1

ZCU102 - Multi Architecture ARM instance - Released with PetaLinux 2016.1

ZCU102 - Multi Architecture PMU instance - Released with PetaLinux 2016.1

ZCU102 - Single Architecture ARM instance - Released with PetaLinux 2015.4