Xtensa on QEMU: Difference between revisions

From Linux/Xtensa
Jump to navigation Jump to search
(Add debugging with qemu section)
m (update core import script location)
 
(13 intermediate revisions by the same user not shown)
Line 3: Line 3:
[http://wiki.qemu.org QEMU] is a free processor/machine emulator and virtualizer.
[http://wiki.qemu.org QEMU] is a free processor/machine emulator and virtualizer.


Starting with version 1.0 QEMU offers Xtensa architecture emulation.
Starting with version 1.0 QEMU offers [http://wiki.qemu.org/Features/Xtensa Xtensa architecture emulation].
DC232B (LE) and fsf (BE) cores are supported on sim and LX60/LX200 platforms.
DC232B, DC233C (LE) and fsf (BE) cores are supported on sim and LX60/LX200/ML605/KC705 platforms.


== Getting and building QEMU ==
== Getting and building QEMU ==
Line 28: Line 28:
| -cpu dc232b
| -cpu dc232b
|-
|-
| -m megs
| -m <memory size>
| Set emulated RAM size to megs MB
| Set emulated RAM size. M and G suffixes for mega- and gigabytes.
| -m 128
| -m 128M
|-
|-
| -semihosting
| -semihosting
Line 36: Line 36:
| -semihosting
| -semihosting
|-
|-
| -kernel <elf-image>
| -kernel <elf-image/uImage>
| Load elf-image and start emulation from its entry point. Note that image is loaded to virtual addresses it is linked for. For LX60/LX200 this option also chooses 'boot from SRAM' mode, mapping SRAM to the System ROM region at physical address 0xFE000000.
| Load elf-image or uImage and start emulation from its entry point. Note that image is loaded to virtual addresses it is linked for. For XTFPGA this option also chooses 'boot from SRAM' mode, mapping SRAM to the System ROM region at physical address 0xFE000000.
| -kernel xtensa-2.6.29-smp/arch/xtensa/boot/Image.elf
| -kernel xtensa-2.6.29-smp/arch/xtensa/boot/Image.elf
|-
|-
Line 43: Line 43:
| (Not for sim) Wrap kernel arguments into the bootparameters block and pass pointer to it to the elf-image in a2.
| (Not for sim) Wrap kernel arguments into the bootparameters block and pass pointer to it to the elf-image in a2.
| -append 'console=ttyS0 ip=dhcp root=/dev/nfs rw'
| -append 'console=ttyS0 ip=dhcp root=/dev/nfs rw'
|-
| -initrd <initrd-image>
| (Not for sim) Load initial RAM disk image and pass its location to kernel in the bootparameters block.
| -initrd buildroot-build/images/rootfs.cpio
|-
| -dtb <Device-Tree-Blob>
| (Not for sim) Load DTB image and pass its location to kernel in the bootparameters block.
| -dtb xtensa-build/arch/xtensa/boot/dts/kc705.dtb
|-
|-
| -pflash <flash-image>
| -pflash <flash-image>
| (Not for sim) Mount flash-image as a system FLASH. Note that image size must match platform FLASH size (4MB for LX60, 16MB for LX200).
| (Not for sim) Mount flash-image as a system FLASH. Note that image size must match platform FLASH size (4MB for LX60, 16MB for LX200 and ML605, 128MB for KC705).
| -pflash u-boot.dc232b_xtav200.flash
| -pflash u-boot.dc232b_xtav200.flash
|-
|-
Line 61: Line 69:


The sim platform is modelled after Tensilica ISS. It may run ELF images built for ISS, see e.g. [[Buildroot_Build_Instructions#Build_and_Run_a_Linux_Kernel_on_the_Instruction_Set_Simulator_(ISS)|Build and Run a Linux Kernel on the Instruction Set Simulator (ISS)]].
The sim platform is modelled after Tensilica ISS. It may run ELF images built for ISS, see e.g. [[Buildroot_Build_Instructions#Build_and_Run_a_Linux_Kernel_on_the_Instruction_Set_Simulator_(ISS)|Build and Run a Linux Kernel on the Instruction Set Simulator (ISS)]].
There's only SIMCALL external interface available for the sim machine. To avoid console interference with QEMU monitor, monitor should be disabled with -monitor null or moved to network interface.
There's only SIMCALL external interface available for the sim machine. To avoid console interference with QEMU monitor, monitor should be disabled with -monitor null or moved to network interface with e.g. -monitor tcp::1236,telnet,server,nowait.
   '''$ qemu-system-xtensa -cpu dc232b -M sim -m 128M -semihosting -nographic -monitor null -kernel sim-2.6.29-smp/arch/xtensa/boot/Image.elf'''
 
   $ '''qemu-system-xtensa -cpu dc232b -M sim -m 128M -semihosting -nographic -monitor null \'''
    '''-kernel sim-2.6.29-smp/arch/xtensa/boot/Image.elf'''
 
Since the QEMU doesn't manage terminal settings in semihosting mode, ^C and other terminal control codes interrupt QEMU instead of its guest. '''stty -echo -icanon -isig''' may be used to set up terminal to not echo input characters and not terminate QEMU.


== LX60/LX200 platform ==
== XTFPGA (LX60/LX200/ML605/KC705/...) platforms ==


LX60/LX200 platform emulates system RAM, board-specific FPGA, UART, OpenCores 10/100 Mbit Ethernet MAC, National Semiconductors DP83848C 10/100 PHY and parallel FLASH.
XTFPGA platform emulates system RAM, board-specific FPGA, UART, OpenCores 10/100 Mbit Ethernet MAC, National Semiconductors DP83848C 10/100 PHY and parallel FLASH.
The platform may boot from either SRAM (when -kernel option is specified, SRAM is mapped to the System ROM region and ELF image is loaded) or from FLASH.
The platform may boot from either SRAM (when -kernel option is specified, SRAM is mapped to the System ROM region and ELF image is loaded) or from FLASH.


NFS root export record for user network (there's no way to specify root-path option for the QEMU builtin DHCP server. Unless kernel parameter 'rootpath' is given, you'll have to put the rootfs to /tftpboot/<hostname>):
NFS root export record for user network (there's no way to specify root-path option for the QEMU builtin DHCP server. Unless kernel parameter 'nfsroot' is given, you'll have to put the rootfs to /tftpboot/<hostname>):
   /tftpboot/      127.0.0.1(rw,no_root_squash,insecure)
   /tftpboot/      127.0.0.1(rw,no_root_squash,insecure)


Booting linux image from SRAM (FLASH not mapped):
Booting linux image from SRAM (FLASH not mapped):
   $ '''qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -kernel lx60-2.6.29-smp/arch/xtensa/boot/Image.elf'''
   $ '''qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic \'''
    '''-net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 \'''
    '''-kernel lx60-2.6.29-smp/arch/xtensa/boot/Image.elf'''


Booting u-boot image from SRAM (empty FLASH image is created and mapped):
Booting u-boot image from SRAM (empty FLASH image is created and mapped):
   $ '''head -c 16M /dev/zero > lx200.flash'''
   $ '''head -c 16M /dev/zero > lx200.flash'''
   $ '''qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -pflash lx200.flash -kernel u-boot-xtensa.git/u-boot.dc232b_xtav200'''
   $ '''qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic \'''
In this scenario binary u-boot image may be downloaded from TFTP and copied to the FLASH as described [[Setting_up_U-Boot|here]].
    '''-net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -pflash lx200.flash \'''
    '''-kernel u-boot-xtensa.git/u-boot.dc232b_xtav200'''
In this scenario binary u-boot image may be downloaded from TFTP and copied to the FLASH as described [[U-Boot|here]].


Alternatively FLASH image containing u-boot may be preformatted and QEMU may be booted from it:
Alternatively FLASH image containing u-boot may be preformatted and QEMU may be booted from it:
   $ '''cat u-boot-xtensa.git/u-boot.bin.dc232b_xtav200 /dev/zero | head -c 16M > lx200.flash'''
   $ '''cat u-boot-xtensa.git/u-boot.bin.dc232b_xtav200 /dev/zero | head -c 16M > lx200.flash'''
   $ '''qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -pflash lx200.flash'''
   $ '''qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic \'''
    '''-net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -pflash lx200.flash'''
 
(Note that KC705 expects bootloader to be at the offset 0x06000000 in the FLASH, unlike the older boards that boot at offset 0).


== Debugging with QEMU ==
== Debugging with QEMU ==
=== GDB ===
There's builtin GDB server in the QEMU. -s command line switch activates it on the address 0.0.0.0:1234 (-gdb tcp:<ip>:<port> may be used instead of -s to change address and port to listen), -S switch stops QEMU at the first guest instruction waiting for 'continue' command from gdb.


There's builtin GDB server in the QEMU. -s command line switch activates it on the address 0.0.0.0:1234, -S switch stops QEMU at the first guest instruction waiting for 'continue' command from gdb.
  $ '''qemu-system-xtensa -M lx200 -nographic -pflash lx200.flash \'''
    '''-net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 \'''
    '''-kernel u-boot-xtensa.git/u-boot.dc232b_xtav200 -s -S'''


  $ '''qemu-system-xtensa -M lx200 -nographic -pflash lx200.flash -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -kernel u-boot-xtensa.git/u-boot.dc232b_xtav200 -s -S'''
By default xtensa gdb may only access unprivileged core registers. To allow access to all available registers ./gdb/xtensa-config.c needs to be modified, marking privileged registers as non-privileged. If [https://github.com/jcmvbkbc/xtensa-toolchain-build these scripts] are used to build the toolchain, the fixup-gdb.sh step does that.
 
By default xtensa gdb may only access unprivileged core registers. To allow access to all available registers ./gdb/xtensa-config.c needs to be modified, marking privileged registers as non-privileged.


GDB breakpoints, watchpoints, single-stepping and other debugging features work as usual.
GDB breakpoints, watchpoints, single-stepping and other debugging features work as usual.
Line 138: Line 159:
     f8000000-f83fffff (prio 0): lx60.io.flash
     f8000000-f83fffff (prio 0): lx60.io.flash
     fe000000-fe01ffff (prio 0): lx60.sram
     fe000000-fe01ffff (prio 0): lx60.sram
=== Logging ===
QEMU can log guest CPU state/opcode translation during execution. Invalid, reserved and not implemented opcodes, invalid conditions for certain opcodes, reserved/not implemented SR access, page table lookups, interrupt requests are all logged with this method. Logging may be enabled with -d<logging types> command line option, or with monitor command 'log <logging types>'. By default logs go to the file /tmp/qemu.log. Verbose logging slows down execution significantly, it may be useful to control logging from GDB, enabling it via monitor command for the specific code blocks.
{| border="1"
|-
! Logging type !! Meaning
|-
| none
| disable logging
|-
| out_asm
| show generated host assembly code for each compiled TB
|-
| in_asm
| show target assembly code for each compiled TB (not implemented for Xtensa)
|-
| op
| show micro ops for each compiled TB
|-
| op_opt
| show micro ops after liveness analysis
|-
| int
| show interrupts/exceptions in short format
|-
| exec
| show trace before each executed TB
|-
| cpu
| show CPU state before block translation
|-
|}


== Extending QEMU ==
== Extending QEMU ==
Starting with QEMU-2.2 there's a script [https://github.com/OSLL/qemu-xtensa/blob/master/target/xtensa/import_core.sh qemu/target-xtensa/import_core.sh] that adds new core to QEMU from the xtensa configuration overlay.

Latest revision as of 17:55, 9 March 2018

Setting up and running Xtensa simulation on QEMU

QEMU is a free processor/machine emulator and virtualizer.

Starting with version 1.0 QEMU offers Xtensa architecture emulation. DC232B, DC233C (LE) and fsf (BE) cores are supported on sim and LX60/LX200/ML605/KC705 platforms.

Getting and building QEMU

QEMU is developed using git. The main tree is located at git://git.qemu.org/qemu.git. Release tarballs and guest systems images are available at http://wiki.qemu.org/Download.

This will make a copy of master QEMU repository, configure, build and install QEMU binaries for little-endian and big-endian targets:

 $ git clone git://git.qemu.org/qemu.git
 $ mkdir qemu-xtensa ; cd qemu-xtensa
 $ ../qemu/configure --prefix=`pwd`/root --target-list=xtensa-softmmu,xtensaeb-softmmu
 $ make install

QEMU options

Option Meaning Example
-M <machine-name> Emulate specific platform type. Use '?' to list all supported platform types. -M lx60
-cpu <core-name> Emulate specific core type. Use '?' to list all supported core types. -cpu dc232b
-m <memory size> Set emulated RAM size. M and G suffixes for mega- and gigabytes. -m 128M
-semihosting Enable SIMCALL instruction for the protection ring 0. -semihosting
-kernel <elf-image/uImage> Load elf-image or uImage and start emulation from its entry point. Note that image is loaded to virtual addresses it is linked for. For XTFPGA this option also chooses 'boot from SRAM' mode, mapping SRAM to the System ROM region at physical address 0xFE000000. -kernel xtensa-2.6.29-smp/arch/xtensa/boot/Image.elf
-append <kernel arguments> (Not for sim) Wrap kernel arguments into the bootparameters block and pass pointer to it to the elf-image in a2. -append 'console=ttyS0 ip=dhcp root=/dev/nfs rw'
-initrd <initrd-image> (Not for sim) Load initial RAM disk image and pass its location to kernel in the bootparameters block. -initrd buildroot-build/images/rootfs.cpio
-dtb <Device-Tree-Blob> (Not for sim) Load DTB image and pass its location to kernel in the bootparameters block. -dtb xtensa-build/arch/xtensa/boot/dts/kc705.dtb
-pflash <flash-image> (Not for sim) Mount flash-image as a system FLASH. Note that image size must match platform FLASH size (4MB for LX60, 16MB for LX200 and ML605, 128MB for KC705). -pflash u-boot.dc232b_xtav200.flash
-net nic,<nic-parameters> (Not for sim) Set network interface parameters. -net nic,vlan=0
-net user,<SLIRP parameters> (Not for sim) Use the user mode network stack. SLIRP parameters may be used to tune built-in DHCP and TFTP servers. -net user,vlan=0,tftp=.,hostname=dc232b-lx200

sim platform

The sim platform is modelled after Tensilica ISS. It may run ELF images built for ISS, see e.g. Build and Run a Linux Kernel on the Instruction Set Simulator (ISS). There's only SIMCALL external interface available for the sim machine. To avoid console interference with QEMU monitor, monitor should be disabled with -monitor null or moved to network interface with e.g. -monitor tcp::1236,telnet,server,nowait.

 $ qemu-system-xtensa -cpu dc232b -M sim -m 128M -semihosting -nographic -monitor null \
   -kernel sim-2.6.29-smp/arch/xtensa/boot/Image.elf

Since the QEMU doesn't manage terminal settings in semihosting mode, ^C and other terminal control codes interrupt QEMU instead of its guest. stty -echo -icanon -isig may be used to set up terminal to not echo input characters and not terminate QEMU.

XTFPGA (LX60/LX200/ML605/KC705/...) platforms

XTFPGA platform emulates system RAM, board-specific FPGA, UART, OpenCores 10/100 Mbit Ethernet MAC, National Semiconductors DP83848C 10/100 PHY and parallel FLASH. The platform may boot from either SRAM (when -kernel option is specified, SRAM is mapped to the System ROM region and ELF image is loaded) or from FLASH.

NFS root export record for user network (there's no way to specify root-path option for the QEMU builtin DHCP server. Unless kernel parameter 'nfsroot' is given, you'll have to put the rootfs to /tftpboot/<hostname>):

 /tftpboot/      127.0.0.1(rw,no_root_squash,insecure)

Booting linux image from SRAM (FLASH not mapped):

 $ qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic \
   -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 \
   -kernel lx60-2.6.29-smp/arch/xtensa/boot/Image.elf

Booting u-boot image from SRAM (empty FLASH image is created and mapped):

 $ head -c 16M /dev/zero > lx200.flash
 $ qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic \
   -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -pflash lx200.flash \
   -kernel u-boot-xtensa.git/u-boot.dc232b_xtav200

In this scenario binary u-boot image may be downloaded from TFTP and copied to the FLASH as described here.

Alternatively FLASH image containing u-boot may be preformatted and QEMU may be booted from it:

 $ cat u-boot-xtensa.git/u-boot.bin.dc232b_xtav200 /dev/zero | head -c 16M > lx200.flash
 $ qemu-system-xtensa -cpu dc232b -M lx200 -m 96M -nographic \
   -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 -pflash lx200.flash

(Note that KC705 expects bootloader to be at the offset 0x06000000 in the FLASH, unlike the older boards that boot at offset 0).

Debugging with QEMU

GDB

There's builtin GDB server in the QEMU. -s command line switch activates it on the address 0.0.0.0:1234 (-gdb tcp:<ip>:<port> may be used instead of -s to change address and port to listen), -S switch stops QEMU at the first guest instruction waiting for 'continue' command from gdb.

 $ qemu-system-xtensa -M lx200 -nographic -pflash lx200.flash \
   -net nic,vlan=0 -net user,vlan=0,tftp=.,hostname=dc232b-lx200 \
   -kernel u-boot-xtensa.git/u-boot.dc232b_xtav200 -s -S

By default xtensa gdb may only access unprivileged core registers. To allow access to all available registers ./gdb/xtensa-config.c needs to be modified, marking privileged registers as non-privileged. If these scripts are used to build the toolchain, the fixup-gdb.sh step does that.

GDB breakpoints, watchpoints, single-stepping and other debugging features work as usual.

 $ xtensa-dc232b-elf-gdb
 GNU gdb (GDB) 7.3.50.20110709-cvs
 Copyright (C) 2011 Free Software Foundation, Inc.
 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
 and "show warranty" for details.
 This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=xtensa-dc232b-elf".
 For bug reporting instructions, please see:
 <http://www.gnu.org/software/gdb/bugs/>.
 (gdb) target remote 127.0.0.1:1234
 Remote debugging using 127.0.0.1:1234
 0xfe000000 in ?? ()
 (gdb) symbol-file u-boot-xtensa.git/u-boot.dc232b_xtav200
 Reading symbols from u-boot-xtensa.git/u-boot.dc232b_xtav200...done.
 (gdb) x/10i $pc
 => 0xfe000000 <_ResetVector>:   j       0xfe00000c <_ResetVector+12>
    0xfe000003 <_ResetVector+3>: break   0, 0
    0xfe000006 <_ResetVector+6>: excw
    0xfe000009 <_ResetVector+9>: .byte 0xff
    0xfe00000a <_ResetVector+10>:        .byte 0xff
    0xfe00000b <_ResetVector+11>:        .byte 0xff
    0xfe00000c <_ResetVector+12>:        l32r    a2, 0xfe000004 <_ResetVector+4>
    0xfe00000f <_ResetVector+15>:        jx      a2
    0xfe000012 <_ResetVector+18>:        ill
    0xfe000015 <_ResetVector+21>:        subx2   a0, a0, a0
 (gdb) si
 69      1:      l32r    a2, 2b
 (gdb)

QEMU monitor commands may be invoked via gdb monitor command:

 (gdb) monitor info mtree
 memory
 00000000-fffffffe (prio 0): system
   00000000-07ffffff (prio 0): lx60.dram
   f0000000-fdffffff (prio 0): lx60.io
     fd020000-fd02ffff (prio 0): lx60.fpga
     fd030000-fd030053 (prio 0): open_eth.regs
     fd030400-fd0307ff (prio 0): open_eth.desc
     fd050020-fd05003f (prio 0): serial
     fd800000-fd803fff (prio 0): open_eth.ram
   f8000000-f83fffff (prio 0): lx60.io.flash
   fe000000-fe01ffff (prio 0): lx60.sram

Logging

QEMU can log guest CPU state/opcode translation during execution. Invalid, reserved and not implemented opcodes, invalid conditions for certain opcodes, reserved/not implemented SR access, page table lookups, interrupt requests are all logged with this method. Logging may be enabled with -d<logging types> command line option, or with monitor command 'log <logging types>'. By default logs go to the file /tmp/qemu.log. Verbose logging slows down execution significantly, it may be useful to control logging from GDB, enabling it via monitor command for the specific code blocks.

Logging type Meaning
none disable logging
out_asm show generated host assembly code for each compiled TB
in_asm show target assembly code for each compiled TB (not implemented for Xtensa)
op show micro ops for each compiled TB
op_opt show micro ops after liveness analysis
int show interrupts/exceptions in short format
exec show trace before each executed TB
cpu show CPU state before block translation

Extending QEMU

Starting with QEMU-2.2 there's a script qemu/target-xtensa/import_core.sh that adds new core to QEMU from the xtensa configuration overlay.