QEMU Options and Commands

This section contains commonly used options and commands when using QEMU with virtual Xilinx hardware.

A larger list of options can be found here.



Options

These options are passed by the command line when starting QEMU.

If using PetaLinux tools, these options can be passed in by using the --qemu-args "<options>" argument when booting your machine.
If using a multi-architecture system, such as Zynq UltraScale+ MPSoC or Versal Adaptive SoC, arguments can be passed into the MicroBlaze QEMU machine by using the --pmu-qemu-args "<options>" argument.

OptionDescriptionExample
-accel tcg,thread=<multi|single>

Forces multi-threaded tiny code generator (MTTCG) to run or not run on QEMU.  This means each VCPU runs on an individual host CPU thread.

This is enabled by default on systems where it is stable and does not need to be explicitly passed in.

Forcing MTTCG may cause incorrect emulation.

MTTCG can not be enabled with icount, since icount forces QEMU to run in a single thread

-accel tcg,thread=multi

Enables MTTCG

-accel tcg,thread=single

Disables MTTCG

-boot [order=<drives>][,once=<drives>][mode=<n>]

Specifies boot parameters when using U-Boot.

Boot pinsZynqMP Boot ModeVersal Boot Mode
1QSPI24QSPI24
2QSPI32QSPI32
3SD0SD0
4NAND (unsupported in QEMU)N/A
5SD1SD1
6eMMCeMMC
7USB (unsupported in QEMU)USB (unsupported in QEMU)
8N/AOSPI


-boot mode=5

Sets the value of boot mode pins to 5 (boot from SD1).

-chardev <backend>,id=<id>[,mux=on|off][,options]
-chardev help

Creates a character devices that allows communication between a QEMU front-end and back-end.

This can be thought of as a file descriptor that routes text from inside QEMU to outside QEMU.

-chardev socket,host=127.0.0.1,port=8887,id=pmu-console,server,nowait,mux=on

Creates a multiplexed chardev server socket on localhost, with port 8887 that has the name pmu-console.

-d <log item 1, ...> | help

Enables logging to stderr for all log items specified.

If help is specified, a list of available log items is printed.

See QEMU Module Debug Printing for more information on how to use -d.

-d guest_errors

Prints any guest errors that occur during emulation to stderr.

-d guest_errors,trace:m25p80_command_decoded

Prints any guest errors, and trace output for m25p80 decoded commands to stderr.

-D <log file>
Redirects stderr to log file.
-D out.log

Redirects stderr to out.log.

-device <driver>[,prop[=<value>][,...]]
-device help

Adds the device driver.
Properties and values depend on the driver being added.

Typically, when emulating Xilinx hardware with QEMU, this option is used to load software and bring CPUs out of reset by using the loader driver.  See: QEMU Loader Options for more information.

-device loader,file=/path/to/software/bl31.elf,cpu-num=0

Loads bl31.elf and runs it on CPU 0

-device loader,addr=0xFD1A0104,data=0x0000000E,data-len=4

Writes 0x0000000E to the register 0xFD1A0104, which brings A53 CPU 0 out of reset on ZymqMP.

When writing data to an address, the order must be addr=<addr>,data=<data>,data-len=<len>

-display <type>
The type of display to be used
-display none

Specifies there's no display.

-drive [file=<path>][,if=<interface>]\
[,format=<format>][index=<index>]
Defines a new drive.
See: Storage Media for more information.
-drive file=/path/to/img/qemu_boot.img,if=sd,format=raw,index=1

Creates an SD drive at index 1 with the image qemu_boot.img.

-dtb <dtb path>

The hardware description for the QEMU machine.  Anything that QEMU cannot emulate is discarded.

If a Linux kernel is present, the dtb is passed to it through a memory buffer. See: -dtb vs -hw-dtb for more detail.

-dtb /path/to/dtb/system.dtb

Speficies the QEMU hardware description to be system.dtb and passes it to the Linux Kernel (if present).

-gdb <host>:<port>
Opens a GDB server on host:port.
-gdb tcp:127.0.0.1:9001

Creates a GDB server on 127.0.0.1:9001

-global <property>=<val>
Sets driver properties for devices created by the machine model.
-global xlnx,zynqmp-boot.cpu-num=0

Releases A53 CPU 0 from reset.

-hw-dtb <dtb path>
The hardware description for the QEMU machine.
See: -dtb vs -hw-dtb for how this differs from the -dtb parameter.
-hw-dtb /path/to/dtb/zynqmp-qemu-multiarch-arm.dtb 

Specifies the QEMU hardware description to be zynqmp-qemu-multiarch-arm.dtb.

-kernel <kernel img>
Specifies an image, such as a kernel or bare-metal image.
-kernel /path/to/kernel/pmu_rom_qemu_sha3.elf

Specifies the image pmu_rom_qemu_sha3.elf.

-m <memory size>

Allocates memory size bytes of RAM for the virtual machine.

By default, QEMU allocates 128MB of RAM.

-m 4G

This machine will have 4GB of RAM allocated

-m 512M

This machine will have 512MB of RAM allocated

-M <machine>
Specifies the machine architecture.
-M arm-generic-fdt

Specifies that this is an ARM-generic-fdt machine.

-M microblaze-fdt

Specifies that this is a microblaze-fdt machine.

-machine-path <dir>

Specifies a directory where QEMU creates shared memory files and named UNIX sockets.

When emulating Xilinx hardware with QEMU, this is used to share data between architectures in multiarch environments, or for co-simulation.

It is recommended you clear the -machine-path directory between boots.  PetaLinux and Yocto tools do this for you.
See this section for more information.

-machine-path /tmp/qemu-shm

Specifies that /tmp/qemu-shm is where QEMU shared memory and UNIX sockets will be created.

-net nic[,netdev=<nd>][,macaddr=<mac>]
-net user|tap|bridge|socket|l2tpv3|vde[,...]

When nic is specified, this option configures or creates an on-board network interface card and connects it either to the emulated hub, or to the netdev nd.

When user is specified, this option configures a host network back-end and connects it to the emulated default hub.


-net nic

Creates an on-board NIC.

-net user,id=eth0,tftp=/host/path/for/tftp

Creates a network back-end with the ID eth0 that has TFTP access to the host path
/host/path/for/tftp.

-nographic

This machine will have no graphic output.

Also passes in the -serial stdio option.

-nographic

Specifies there's no graphics and passes in -serial stdio as well.

-S

Pauses the machine on the first instruction.

Typically this is used with the gdb option to debug the boot sequence of your machine.

-S

Pauses the machine on the first instruction.

-s
Shorthand for -gdb tcp::1234

-s

Creates a GDB server on 127.0.0.1:1234

-serial <dev>
Connects the serial device to dev.
-serial mon:stdio

Connect this serial device to the QEMU monitor and STDIO.

-serial null

Don't connect this serial device

-serial chardev:pmu-console

Connect this serial device to the chardev pmu-console.

-dtb vs -hw-dtb

Xilinx QEMU supports two device tree options:

  • -hw-dtb is used for the hardware device tree binary that QEMU uses to generate the model. Hardware device tree binaries will have the name of the device it represents. For example,  board-versal-ps-vc-p-a2197-00.dtb is for Versal and zcu102-arm.dtb for the ZCU102 board.
  • -dtb is generally a Linux device tree binary used for Linux kernel bootsWith the DTB passed in with -dtb option, QEMU removes the nodes that it cannot emulate and later copies them to RAM for the kernel. Xilinx Linux kernel device tree binaries are typically named system.dtb.

For booting Linux on multi-arch platforms, such as Zynq Ultrascale+ MPSoC and Versal Adaptive SoC, we use the -hw-dtb option, since guest device tree loading is skipped by QEMU.
If both -hw-dtb and -dtb are used in multi-arch environments, the DTB passed in with -dtb is ignored.

For standalone (single-arch) flows, these two arguments are fully interchangeable; specify only one or the other. 

This procedure is applicable only when -kernel is passed on QEMU command line.

For Zynq Ultrascale+ MPSoC and Versal Adaptive SoC in a multi-architecture environment, the QEMU DTB is different from the kernel system.dtb.

QEMU DTS are different for Zynq UltraScale+ MPSoC and Versal Adaptive SoC single and multi-architecture models. The following DTBs are available in PetaLinux project:

Zynq UltraScale+ MPSoC

  • Single-arch: zynqmp-qemu-arm.dtb
  • Multi-arch: zynqmp-qemu-multiarch-arm.dtb, zynqmp-qemu-multiarch-pmu.dtb

Versal Adaptive SoC

  • Single-arch: versal-qemu-ps.dtb
  • Multi-arch: versal-qemu-multiarch-ps.dtb, versal-qemu-multiarch-pmc.dtb

If building DTBs from source, the single-arch and multi-arch device trees will appear under path/to/dts-repo/LATEST/SINGLE_ARCH and path/to/dts-repo/LATEST/MULTI_ARCH respectively.

QEMU Loader Options

[-device loader,(file=<file_name>|data=<value>,data-len=4),[addr=<value>],[cpu-num=<value>],[force-raw=true]] ...

This (repeatable) argument configures the QEMU machine for boot.

The loader driver can perform the following tasks:

  • Load software or data into RAM sections
  • Set the CPU entry points
  • Release CPUs from reset
  • Write to registers

In Zynq Ultrascale+ MPSoC, by default, the six ARM CPUs (four ARM-A53 and two ARM-R5) are in reset by their respective reset controllers when no software is loaded.
You
can use a combination of -device loader arguments to load software and setup the CPUs.

There are two basic modes for the loader argument: file mode and single transaction mode. Specify only one mode for each -device argument.
The follo
wing subsections describe these modes.

File Mode

In file mode, the loader accepts a file as data to load. The file can be in any format and is passed using the file=<file_name> sub-option.

If the file is an ELF or a U-Boot image, the file is parsed and the sections loaded into memory as specified by the image; otherwise, the file is assumed as a raw image and loaded accordingly as an image into memory.

When loading raw images, the address is specified with the addr=<value> argument. The default address is 0. The address is ignored if the file is an ELF or U-Boot image.

Optionally, you can specify a CPU using the cpu-num=<value> sub-option.  Specifying cpu-num also sets the Program Counter (PC).

The CPU has a set entry point in the following situations:

  • For ELFs and U-Boot images, the entry point is set as specified by the image.
  • For raw images, the entry point is set to the start address.
  • If you do not specify a CPU, the bus for CPU0 loads images, but no program entry point is set.

There are cases where you might want to treat an ELF or a U-Boot image as a raw data image (particularly useful for testing bootloaders with ELF or U-Boot capability).
In this case, you can pass the force-raw=true sub-option to instruct the loader to treat the image as raw.
You must specify the addr, since the section information in the ELF and U-Boot images are ignored.

Single Transaction Mode

In single transaction mode, a single bus transaction occurs.

  • addr and data-len must be specified.
  • data-len must equal 4 (corresponding to a single 4-byte transaction).
  • addr must be 32-bit aligned.

Before the initial system reset for Zynq Ultrascale+ MPSoC or Versal Adaptive SoC, QEMU performs the specified bus transaction.

Optionally, you can specify a CPU using the cpu-num=<value> sub-option.
The list of CPU enumeration values for Zynq Ultrascale+ MPSoC and Versal Adaptive SoC are given below:

ValueZynq Ultrascale+ MPSoC CPU

0

A53-0
1A53-1
2A53-2
3A53-3
4R5-0
5R5-1
ValueVersal Adaptive SoC CPU
0A72-0
1A72-1
2R5-0
3R5-1


If you edit the /cpus node in the DTB, these enumerations change.

The single transaction occurs from the perspective of the specified CPU. If you do not specify a CPU, then the system assumes CPU0.

Storage Media

Several disk and storage media interfaces are modeled. You can pass each to a regular file(s) to use for stored data.
QEMU updates the files so the data can persist across multiple sessions.

Argument Format

-drive file=<image-path>, if=(mtd|sd|pflash),format=<fmt>,index=<value>[,readonly]

The argument allows specification of extra options such as marking the file as read-only.
The argument can also be used to specify the index of the device, allowing specifying files for devices in an order-independent way.

QSPI

QSPI is modeled with the Flash specified in DTS. The SPI flashes can connect in a single or dual-parallel arrangement.
The file size for each should match Flash model size.

If you are using only a single mode QSPI, then only one QSPI argument is needed.

For each drive, if an image is not provided, QEMU still models the flash, but initializes with NULL data and discards the data after QEMU exists.
Data can be written and read back within a single session in this case.

Creating a QSPI image and booting with QSPI is outlined here.

Flash Striper Utility

In parallel mode, the data that QSPI passes in for each flash is unique to that flash chip.
The QSPI controller also performs bit or byte striping in dual parallel mode, and because of this a special utility is needed to take a single QSPI data image and format it into two images.
The syntax is as follows:

flash_strip <input> <out1> <out0>
flash_strip_be <input> <out1> <out0>
flash_strip_bw <input> <out1> <out0>

Where:

  • flash_strip and flash_strip_be formats with bit striping.
  • flash_strip_be expects the flash data bits in big endian.
  • flash_strip_bw formats the output with byte wise striping.
  • <input> is a 128MB image for Zynq UltraScale+ or a 256MB image on Versal Adaptive SoC.
  • <out0> and <out1> are the two images with half the size of the input image (64MB or 128MB) passable to the -mtdblock arguments for QSPI.

The reverse is also possible, taking the two striped images and converting them back to a single 128MB or 256MB image as shown in the following command:

flash_unstrip <output> <in1> <in0>
flash_unstrip_be <output> <in1> <in0>
flash_unstrip_bw <output> <in1> <in0>

Building the Flash Striper utilities

The complete flash striper utility source code is available here.

Building the Bit Stripe Utilities

The bit stripe utilities are used for legacy QSPI (LQSPI) on Zynq7000.

Compile the flash striper utility for your host with the following commands:

gcc flash_stripe.c -o flash_strip
gcc flash_stripe.c -o flash_unstrip -DUNSTRIPE

If the flash data bits are in big-endian format use flash_strip_be when creating the flash images (and flash_unstrip_be for backwards conversion).

gcc flash_stripe.c -o flash_strip_be -DFLASH_STRIPE_BE
gcc flash_stripe.c -o flash_unstrip_be -DUNSTRIPE -DFLASH_STRIPE_BE
Building the Byte Stripe Utilities

The byte stripe utilities are used for generic QSPI (GQSPI) on Zynq UltraScale+ MPSoC and Versal Adaptive SoC.

Compile the flash striper utility for your host with the following commands:

gcc flash_stripe.c -o flash_strip_bw -DFLASH_STRIPE_BW
gcc flash_stripe.c -o flash_unstrip_bw -DUNSTRIPE -DFLASH_STRIPE_BW

flash_strip_bw is also available as part of the PetaLinux tools.

Supported QSPI Flash Models

VendorFlash Models
Atmelat25fs010, 25fs040, at25df041a, at25df321a, at25df641, at26f004, at26df081a, at26df161a, at26df321, at45db081d
EONen25f32, en25p32, en25q32b, en25p64, en25q64
GigaDevicegd25q32, gd25q64
Intel/Numonyx160s33b, 320s33b, 640s33b n25q064
Macronixmx25l2005a, mx25l4005a, mx25l8005, mx25l1606e, mx25l3205d, mx25l6405d, mx25l12805d, mx25l12855e, mx25l25635e, mx25l25655e
Micronn25q032a1, n25q032a13, n25q064a11, n25q064a13, n25q128a11, n25q128a13, n25q256a11, n25q256a13, n25q512a11, n25q512a1
Spansion – single (large) sector size only,
at least for the
chips listed here (without boot sectors)
s25sl032p, s25sl064p, s25fl256s0, s25fl256s1, s25fl512s, s70fl01gs, s25sl12800, s25sl12801, s25fl129p0,
s25fl129p1,
s25sl004a, s25sl008a, s25sl016as, 25sl032a, s25sl064a, s25fl016k, s25fl064k
Winbond – w25x “blocks” are 64k, “sectors” are 4KiBw25x10, w25x20, w25x40, w25x80, w25x16, w25x32, w25q32, w25q32dw, w25x64. w25q64, w25q80, w25q80b, w25q256
Numonyx25q128
SSTsst25vf040b, sst25vf080b, sst25vf016b, sst25vf032b, sst25wf512, sst25wf010, sst25wf020, sst25wf040, sst25wf080
ST Microelectronicsm25p05, m25p10, m25p20, m25p40, m25p80, m25p16, m25p32, m25p64, m25p128, n25q032,
m45pe10, m45pe80,
m45pe16, m25pe20, m25pe80, m25pe16, m25px32, m25px32-s0, m25px32-s1, m25px64

SPI

For each SPI Flash, if an image is not provided, QEMU still models the flash, but initializes with NULL data and discards the data after QEMU exits.
Data can
be written and read back within a single session in this case.

SD

QEMU models an SD card for -drive file=<file_path>,if=sd
The SD card model in QEMU is generic and does not attempt to model a specific physical part.
The size of the input file initializes the size of the emulated SD card.
Only 512MB SD images are officially supported, although powers of two around that order of magnitude will work.

SDXC (>32GB) sizes do not work.


If an SD argument is not specified, no SD card is modeled, the corresponding SD slot is ejected.
This is different from SPI, where the flash is still modeled even if an image is not provided.

Information for booting with SD can be found here.

eMMC

QEMU will model an eMMC card for -drive file=<file_path>,if=sd.  This requires changes in the system-level control register (SLCR) registers to enable eMMC. The table below shows the registers that need to be modified:

PlatformRegisterFields
Zynq UltraScale+ MPSoCIOU_SLCR

CTRL_REG_SD

Versal Adaptive SoCPMC_IOU_SLCR

SD0_CTRL_REG SD1_CTRL_REG

For Zynq Ultrascale+ MPSoC and Versal index=2 works as an EMMC card connected to sdhci0.

The size of the input file initializes the size of the emulated eMMC card.
Only 512MB images
are supported, although powers of two, around that order of magnitude will work.

EEPROM

QEMU models EEPROMs connected via I2C. A back-end file can be passed as follows:

-drive file=<file_path>,if=mtd,index=<id>.

Users can find the information on the connected EEPROMs in the board's DTS file.

Boot Examples

This section contains boot examples for Zynq Ultrascale+ MPSoC and Versal Adaptive SoC and what each parameter means.
Your boot parameters may vary slightly, depending on your project.

 Zynq UltraScale+ MPSoC Boot
$ qemu-system-microblazeel \
-M microblaze-fdt \
-serial mon:stdio \
-serial /dev/null \
-display none \
-kernel /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/pmu_rom_qemu_sha3.elf \
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/pmufw.elf \
-hw-dtb /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/zynqmp-qemu-multiarch-pmu.dtb \
-machine-path /tmp/tmp.MOj3amuPFs \
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 \
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4 \
&
$ qemu-system-aarch64 \
-M arm-generic-fdt \
-serial mon:stdio \
-serial /dev/null \
-display none \
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/bl31.elf,cpu-num=0 \
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/Image,addr=0x00080000 \
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/system.dtb,addr=0x15e80000 \
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/build/misc/linux-boot/linux-boot.elf \
-gdb tcp::9000 \
-dtb /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/system.dtb  \
-net nic -net nic -net nic -net nic,netdev=eth0 \
-netdev user,id=eth0,tftp=/scratch/petalinux-images/xilinx-zcu102-2020.1/images/linux \
-hw-dtb /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/zynqmp-qemu-multiarch-arm.dtb \
-machine-path /tmp/tmp.MOj3amuPFs \
-global xlnx,zynqmp-boot.cpu-num=0 \
-global xlnx,zynqmp-boot.use-pmufw=true \
-m 4G


Microblaze QEMU ParameterMeaning
-M microblaze-fdt
Set the machine to be a Microblaze machine
-serial mon:stdio
Set a serial device to STDIO and the QEMU monitor.
-serial /dev/null
Set a serial device to /dev/null
-display none
Don't use a display
-kernel /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/pmu_rom_qemu_sha3.elf
Make pmu_rom_qemu_sha3.elf the kernel image
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/pmufw.elf
Load pmufw.elf
-hw-dtb /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/zynqmp-qemu-multiarch-pmu.dtb
Use zynqmp-qemu-multiarch-pmu.dtb as the DTB for the machine
-machine-path /tmp/tmp.MOj3amuPFs
Use /tmp/tmp.MOj3amuPFs as the QEMU shared memory directory
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4
Write 0x01011003 to address 0xFD1A0074.
In this case, 0xFD1A0074 is the DP_AUDIO_REF_CTRL register
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4

Write 0x01010f03 to address 0xFD1A007C.
In this case, 0xFD1A007C is the DP_STC_REF_CTRL register

Aarch64 QEMU ParameterMeaning
-M arm-generic-fdt
Set the machine to be an ARM machine
-serial mon:stdio
Set a serial device to STDIO and the QEMU monitor.
-serial /dev/null
Set a serial device to /dev/null
-display none
Don't use a display
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/bl31.elf,cpu-num=0
Load bl31.elf and run it on CPU 0
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/Image,addr=0x00080000
Load Image and put it at address 0x80000
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/system.dtb,addr=0x15e80000
Load system.dtb and put it at address 0x15E80000
-device loader,file=/scratch/petalinux-images/xilinx-zcu102-2020.1/build/misc/linux-boot/linux-boot.elf
Load linux-boot.elf
-gdb tcp::9000
Make the QEMU GDB server listen on localhost:9000
-dtb /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/system.dtb
Use system.dtb as the hardware description for the machine.
This DTB is passed to the Linux Kernel
-net nic -net nic -net nic -net nic,netdev=eth0

Create 4 NICs, the last of which is connected to the network interface eth0

-netdev user,id=eth0,tftp=/scratch/petalinux-images/xilinx-zcu102-2020.1/images/linux

Create a network back-end on eth0, and change the default TFTP path to
/scratch/petalinux-images/xilinx-zcu102-2020.1/images/linux

-hw-dtb /scratch/petalinux-images/xilinx-zcu102-2020.1/pre-built/linux/images/zynqmp-qemu-multiarch-arm.dtb
Use zynqmp-qemu-multiarch-arm.dtb as the hardware description for the machine
-machine-path /tmp/tmp.MOj3amuPFs
Use /tmp/tmp.MOj3amuPFs as the QEMU shared memory directory
-global xlnx,zynqmp-boot.cpu-num=0
Set cpu-num to 0 in the zynqmp-boot driver
-global xlnx,zynqmp-boot.use-pmufw=true
Set pmufw to true in the zynqmp-boot driver
-m 4G
Allocate 4GB of RAM for the machine


 Versal ACAP Boot
$ qemu-system-microblazeel 
-M microblaze-fdt \ 
-serial mon:stdio \
-display none \
-device loader,addr=0xf0000000,data=0xba020004,data-len=4 \
-device loader,addr=0xf0000004,data=0xb800fffc,data-len=4 \
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/pmc_cdo.bin,addr=0xf2000000 \
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/BOOT_bh.bin,addr=0xf201e000,force-raw \
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/plm.elf \
-hw-dtb /scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/versal-qemu-multiarch-pmc.dtb \
-machine-path /tmp/tmp.qp3oHny0iJ \
-device loader,addr=0xF1110624,data=0x0,data-len=4 \
-device loader,addr=0xF1110620,data=0x1,data-len=4 \
&
$ qemu-system-aarch64 \
-M arm-generic-fdt \
-serial null -serial null -serial mon:stdio \
-display none \
-boot mode=5 \
-drive file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/qemu_boot.img,if=sd,format=raw,index=1 \
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/Image,addr=0x00080000 \
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/system.dtb,addr=0x15e80000 \
-gdb tcp::9000 -dtb /scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/system.dtb \
-net nic -net nic,netdev=eth0 \
-netdev user,id=eth0,tftp=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/ \  
-hw-dtb /scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/versal-qemu-multiarch-ps.dtb \
-machine-path /tmp/tmp.qp3oHny0iJ \
-m 4G


Microblaze QEMU ParameterMeaning
-M microblaze-fdt
Set the machine to be a Microblaze machine
-serial mon:stdio
Set a serial device to STDIO and the QEMU monitor
-display none
Don't use a display
-device loader,addr=0xf0000000,data=0xba020004,data-len=4 
Write 0xBA020004 to address 0xF0000000
-device loader,addr=0xf0000004,data=0xb800fffc,data-len=4 
Write 0xB800FFFC to address 0xF0000004
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/pmc_cdo.bin,addr=0xf2000000 
Load pmc_cdo.bin into address 0xF2000000
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/BOOT_bh.bin,addr=0xf201e000,force-raw 
Load BOOT_bh.bin into address 0xF201E0000
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/plm.elf 
Load plm.elf
-hw-dtb /scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/versal-qemu-multiarch-pmc.dtb 
Use zynqmp-qemu-multiarch-pmu.dtb as the DTB for the machine
-machine-path /tmp/tmp.MOj3amuPFs
Use /tmp/tmp.MOj3amuPFs as the QEMU shared memory directory
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4
Write 0x01011003 to address 0xFD1A0074.
In this case, 0xFD1A0074 is the DP_AUDIO_REF_CTRL register
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4

Write 0x01010f03 to address 0xFD1A007C.
In this case, 0xFD1A007C is the DP_STC_REF_CTRL register

Aarch64 QEMU ParameterMeaning
-M arm-generic-fdt
Set the machine to be an ARM machine
-serial null -serial null -serial mon:stdio
Set a serial device to STDIO and the QEMU monitor
-display none
Don't use a display
-boot mode=5
Set the boot pins to 5, which sets up the board to boot via SD
-drive file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/qemu_boot.img,if=sd,format=raw,index=1Create a new drive, which is an SD image that contains qemu_boot.img
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/Image,addr=0x00080000
Load Image and put it at address 0x80000
-device loader,file=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/system.dtb,addr=0x15e80000
Load system.dtb and put it at address 0x15E80000
microblazeel \
-M microblaze-fdt \
-serial mon:stdio \
-serial /dev/nul
-gdb tcp::9000
Make the QEMU GDB server listen on localhost:9000
-dtb /scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/system.dtb
Use system.dtb as the hardware description for the machine.
This DTB is passed to the Linux Kernel
-net nic -net nic,netdev=eth0

Create 2 NICs, the last of which is connected to the network interface eth0

-netdev user,id=eth0,tftp=/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/

Create a network back-end on eth0, and change the default TFTP path to
/scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/

-hw-dtb /scratch/petalinux-images/xilinx-vc-e-a2197-00-2019.2/pre-built/linux/images/versal-qemu-multiarch-ps.dtb
Use zynqmp-qemu-multiarch-arm.dtb as the hardware description for the machine
-machine-path /tmp/tmp.MOj3amuPFs
Use /tmp/tmp.MOj3amuPFs as the QEMU shared memory directory
-m 4G
Allocate 4GB of RAM for the machine

As an side note, these boot commands were created by going into a PetaLinux project and booting with the following command:

$ petalinux-boot --qemu --prebuilt 3

Booting with an Application

The following examples use the FSBL as the application being booted, however the command-line formats used in these examples are applicable to other standalone applications as well.
The FSBL is bundled with PetaLinux or Yocto BSPs.

QEMU does not model the DDRMC, for performance reasons.  Because of this, using the FSBL can cause hangs in QEMU.
See the known issues page for what to do if this problem occurs.

A53 Application (Zynq UltraScale+ MPSoC)

A53-0 FSBL in JTAG Mode

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=./images/linux/zynqmp_a53_fsbl.elf,cpu-num=0 \
-device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4

A53-0 FSBL in QSPI Boot Mode (Single)

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=./images/linux/zynqmp_a53_fsbl.elf,cpu-num=0 \
-device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 \
-drive file=qemu_qspi.bin,if=mtd,format=raw,index=0\
-boot mode=1

A53-0 FSBL in QSPI Boot Mode (Dual Parallel)

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=./images/linux/zynqmp_a53_fsbl.elf,cpu-num=0 \
-device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 \
-drive file=qemu_qspi_low.bin,if=mtd,format=raw,index=0 \
-drive file=qemu_qspi_high.bin,if=mtd,format=raw,index=1 \
-boot mode=1


Default ZCU102 Petalinux design has QSPI in a dual parallel Configuration.


A53-0 FSBL in SD0 Boot Mode

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=./images/linux/zynqmp_a53_fsbl.elf,cpu-num=0 \
-device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 \
-drive file=qemu_sd.img,if=sd,format=raw,index=0 \
-boot mode=3


Default ZCU102 board supports SD1. Index should be set to 1 for SD drive argument.


A72 Application (Versal Adaptive SoC)

A72-0 FSBL in JTAG Mode

qemu-system-aarch64 
-M arm-generic-fdt \
-m 8G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-device loader,addr=0xFD1A0300,data=0x8000000e,data-len=4 \
-hw-dtb /path/to/dtb/versal-qemu-ps.dtb \
-kernel /path/to/image/image.elf

Zynq UltraScale+ MPSoC R5 Application

R5-0 FSBL in JTAG Mode

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=zynqmp_r5_fsbl.elf,cpu-num=4 \
-device loader,addr=0xff5e023c,data=0x80008fde,data-len=4 \
-device loader,addr=0xff9a0000,data=0x80000218,data-len=4

R5-0 FSBL in QSPI Boot Mode (Single)

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=zynqmp_r5_fsbl.elf,cpu-num=4 \
-device loader,addr=0xff5e023c,data=0x80008fde,data-len=4 \
-device loader,addr=0xff9a0000,data=0x80000218,data-len=4 \
-drive file=qemu_qspi.bin,if=mtd,format=raw,index=0 \
-boot mode=1

R5-0 FSBL in QSPI Boot Mode (Dual Parallel)

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=zynqmp_r5_fsbl.elf,cpu-num=4 \
-device loader,addr=0xff5e023c,data=0x80008fde,data-len=4 \
-device loader,addr=0xff9a0000,data=0x80000218,data-len=4 \
-drive file=qemu_qspi_low.bin,if=mtd,format=raw,index=0 \
-drive file=qemu_qspi_high.bin,if=mtd,format=raw,index=1 \
-boot mode=1

R5-0 FSBL in SD0 Boot Mode

qemu-system-aarch64 \
-M arm-generic-fdt \
-m 4G \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=zynqmp_r5_fsbl.elf,cpu-num=4 \
-device loader,addr=0xff5e023c,data=0x80008fde,data-len=4 \
-device loader,addr=0xff9a0000,data=0x80000218,data-len=4 \
-drive file= qemu_sd.img,if=sd,format=raw,index=0 \
-boot mode=3

R5 Lockstep FSBL

Only one example is provided for lock step, although all boot modes are valid. See the previous example command line arguments for storage media and boot mode that could be applied to this command line.
This specific example is JTAG boot mode.

qemu-system-aarch64 \
-M arm-generic-fdt \
-nographic \
-serial null \
-serial null \
-serial mon:stdio \
-hw-dtb ./images/linux/zynqmp-qemu-arm.dtb \
-device loader,file=zynqmp_r5_fsbl.elf,cpu=4 \
-device loader,addr=0xff5e023c,data=0x80008fde,data-len=4

Versal Adaptive SoC R5 Application

R5-0 Application in JTAG Mode

/scratch/proj/qemu/build/aarch64-softmmu/qemu-system-aarch64 \
-M arm-generic-fdt \
-device loader,file=/path/to/image.elf,cpu-num=2 \
-device loader,addr=0xff5e0300,data=0x16,data-len=4 \
-device loader,addr=0xff9a0100,data=0x1,data-len=4 \
-device loader,addr=0xff9a0000,data=0x8,data-len=4 \
-serial null \
-serial null \
-serial stdio \
-display none \
-hw-dtb /path/to/dtb/board-versal-ps-virt.dtb

R5 Lockstep

/scratch/proj/qemu/build/aarch64-softmmu/qemu-system-aarch64 \
-M arm-generic-fdt \
-device loader,file=/path/to/image/image.elf,cpu-num=2 \
-device loader,addr=0xff5e0300,data=0x14,data-len=4 \
-device loader,addr=0xff9a0000,data=0x50,data-len=4 \
-device loader,addr=0xff9a0100,data=0x1,data-len=4 \
-serial null \
-serial null \
-serial stdio \
-display none \
-hw-dtb /path/to/dtb/board-versal-ps-virt.dtb


Terminal Commands

These are some of the terminal commands that can be used when QEMU is started with the -nographic option.

CommandDescription
CTRL+A C
Switch between the QEMU monitor and console.
CTRL+A X
Exit QEMU.
CTRL+A H
Prints the terminal command help message.

QEMU Monitor Commands

This is a short list of useful QEMU monitor commands, for a full list, use the help and help info commands in the QEMU Monitor.
To get to the QEMU monitor, do CTRL+A C while in QEMU.  To exit the QEMU monitor, do CTRL+A C while inside the QEMU monitor.

CommandDescription
help
Prints a list of monitor commands and a description of each one.
help info
Prints a list of info monitor commands and a description of each one.
info qtree
Prints the device tree.
info mtree

Prints the memory tree.

info cpus
Shows information for each CPU.
info registers [-a]

Shows the CPU registers.
Passing in -a shows register info for all CPUs.

memsave <addr> <len> <file>

Reads len bytes at memory address addr and saves it to file file as raw binary data.
See also: Linux Kernel Logbuf Extraction

system_reset
Resets the system.
x /fmt <addr>
Prints the memory at the virtual address addr, with format dictated by fmt
xp /fmt <addr>
Prints the memory at the physical address addr, with format dictated by fmt.
stopStops emulation
cResumes emulation
qQuits QEMU.

Hot Loading

You can use the loader at runtime to load new software into an already running system. This is accessible from the QEMU monitor.

From the monitor, you can stop the emulation using the stop command:

(qemu) stop

You can then use the loader to add new software or release CPUs from reset. The syntax is:

(qemu) device_add loader,(file=<file>|data=<value>,data len=4),[addr=<value>],[cpu-num=<value>],[force-raw=true]

The options are the same as the ones described in QEMU Loader Options.
The emulation can then be resumed (with the new memory and CPU state from the loading operations) using the c command:

(qemu) c

Linux Kernel Logbuf Extraction

Using the QEMU monitor command memsave, it is possible to extract the Linux kernel logbuf and read it.

Get the logbuf address and size

Use readelf to get the address and size of the logbuf.

$ readelf -a image.elf | grep __log_buf
     1: c1324c44 0x20000 OBJECT  LOCAL  DEFAULT   21 __log_buf

image.elf is the image you pass into QEMU that contains the Linux kernel whose logbuf you want to extract.

The numbers we care about in this case are c1324c44 and 0x20000, which are the virtual address and the size of the logbuf respectively.

Dump the logbuf from QEMU

In the QEMU monitor window, type:

(qemu) memsave 0xc1324c44 0x20000 dumpmem.logbuf

Read the contents

Parts of the logbuf will have binary data in it, which can be fixed by using a logbuf reader program, found here.

Compile the reader.

$ gcc logbuf-reader.c -o logbuf-reader

Then pipe the logbuf through the reader and cat it.

$ cat dumpmem.logbuf | logbuf-reader
Ramdisk addr 0x00000000, 
FDT at 0x813ae998
Linux version 4.19.0-xilinx-v2019.2 (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 Thu Oct 3 22:42:39 UTC 2019
setup_memory: max_mapnr: 0x7ffff
setup_memory: min_low_pfn: 0x80000
setup_memory: max_low_pfn: 0xb0000
setup_memory: max_pfn: 0xfffff
Zone ranges:
  DMA      [mem 0x0000000080000000-0x00000000afffffff]
  Normal   empty
  HighMem  [mem 0x00000000b0000000-0x00000000ffffefff]
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000080000000-0x00000000ffffefff]
Initmem setup node 0 [mem 0x0000000080000000-0x00000000ffffefff]
On node 0 totalpages: 524287
  DMA zone: 1536 pages used for memmap
  DMA zone: 0 pages reserved
  DMA zone: 196608 pages, LIFO batch:63
  HighMem zone: 327679 pages, LIFO batch:63
earlycon: uartlite_a0 at MMIO 0x40600000 (options '115200n8')
bootconsole [uartlite_a0] enabled
setup_cpuinfo: initialising
setup_cpuinfo: No PVR support. Using static CPU info from FDT
wt_msr
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0 
Built 1 zonelists, mobility grouping on.  Total pages: 522751
Kernel command line: console=ttyUL0,115200 earlycon
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 2059012K/2097148K available (4843K kernel code, 152K rwdata, 1380K rodata, 13129K init, 562K bss, 38136K reserved, 0K cma-reserved, 1310716K highmem)
Kernel virtual memory layout:
  * 0xfffea000..0xfffff000  : fixmap
  * 0xff800000..0xffc00000  : highmem PTEs
  * 0xff7ff000..0xff800000  : early ioremap
  * 0xf0000000..0xff7ff000  : vmalloc & ioremap
# ...




© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy