XEN EL1 Baremetal DomU

The purpose of this page is to describe the build and execution of the Hello World EL1 Baremetal application as a DomU on Zynq UltraScale+ MPSoC ,using PetaLinux and Xilinx SDK Tools.


Table of Contents

Build EL1 Baremetal Application Using XSCT

Create Hello World standalone application using the command line interface XSCT.

source /path/to/Vitis/settings64.sh
xsct
set WORKSPACE <build directory>
setws -switch $WORKSPACE

app create -name standalone-hello-world -template {Hello World} -proc psu_cortexa53_0 -hw /path/to/vitis/data/embeddedsw/lib/fixed_hwplatforms/zcu102.xsa -os standalone
bsp config stdin psu_uart_1
bsp config stdout psu_uart_1
bsp config hypervisor_guest true
# edit src/lscript.ld, change psu_ddr_0_MEM_0 to 0x40000000

app build -name standalone-hello-world
aarch64-linux-gnu-objcopy -O binary --gap-fill 0 ./Debug/standalone-hello-world.elf ./Debug/standalone-hello-world.bin

The steps above select UART1 for the console output. Please refer to this article on how to assign UART1 to a Xen guest.

Build EL1 Baremetal Application Using Vitis

Create Hello World standalone application using Vitis. Open src/lscript.ld and change psu_ddr_0_MEM_0 to 0x40000000.

Open the Board Support Package Settings ("Board Support Package" → "Modify BSP Settings") and set hypervisor_guest to true.

After building the project, one additional step is required to generate the bootable .bin file from the .elf file:

source /path/to/Vitis/settings64.sh
aarch64-linux-gnu-objcopy -O binary --gap-fill 0 ./Debug/standalone-hello-world.elf ./Debug/standalone-hello-world.bin


Build EL1 Baremetal Application Using SDK

Create Hello World standalone application in SDK by selecting Hypervisor Guest as "yes", Refer image given below,


  • Once application is created, please confirm following changes in application/BSP
    • BSP settings: stdin/stout has to pointed at psu_uart_1
    • Application linker file:Application has to be built with starting address: 0x40000000
  • Build the application if settings mentioned above are configured correctly. Bin file will be created in the "<app_project>/Debug/" directory, after successful compilation of application.
  • If Bin file is not generated automatically, execute this command from the SDK application project Debug directory: aarch64-none-elf-objcopy -O binary --gap-fill 0 <elf file name> <bin file name>

Baremetal Console Output

The examples above configure the baremetal application to use UART0 or UART1 as console input/output.

PV Console

Baremetal guests can make use of PV console. When using PV console, it is not necessary to dedicate and assign UART1 (or UART0) to the Virtual Machine. PV console is available to all regular Xen guests, but it is not available to dom0less guests.

The following line configures the BSP to use PV console:

bsp config -append extra_compiler_flags "-DXEN_USE_PV_CONSOLE=1"

Then, at runtime in dom0 you can connect to the PV console of your domU with the following command :

xl console guest-name


Xen Console

It is also possible for the baremetal app to print directly to the Xen console, the principal console used by Xen itself and Dom0. See xen_printf below:

#define HYPERVISOR_console_io           18
#define CONSOLEIO_write 0

/* hypercalls */
static inline int64_t xen_hypercall(unsigned long arg0, unsigned long arg1,
                                    unsigned long arg2, unsigned long arg3,
                                    unsigned long hypercall)
{
    register uintptr_t a0 asm("x0") = arg0;
    register uintptr_t a1 asm("x1") = arg1;
    register uintptr_t a2 asm("x2") = arg2;
    register uintptr_t a3 asm("x3") = arg3;
    register uintptr_t nr asm("x16") = hypercall;
    asm volatile("hvc 0xea1\n"
                     : "=r" (a0), "=r"(a1), "=r" (a2), "=r" (a3), "=r" (nr)
                     : "0" (a0),
                       "r" (a1),
                       "r" (a2),
                       "r" (a3),
                       "r" (nr));
    return a0;
}

static inline void xen_console_write(const char *str)
{
    ssize_t len = strlen(str);

    xen_hypercall(CONSOLEIO_write, len, (unsigned long)str, 0,
                  HYPERVISOR_console_io);
}

static inline void xen_printf(const char *fmt, ...)
{
    char buf[128];
    va_list ap;
    char *str = &buf[0];
    memset(buf, 0x0, 128);

    va_start(ap, fmt);
    vsprintf(str, fmt, ap);
    va_end(ap);

    xen_console_write(buf);
}

This way, there is no need to dedicate a UART to the baremetal app; the output is printed directly to the primary console by Xen. This method works with both regular and dom0less guests.

For it to work, Xen needs to be build with DEBUG enabled, which can be done as follows:

petalinux-config -c xen
  select "Developer Checks"

Alternatively, it is also possible to do the same manually with the following steps after sourcing Petalinux tools/settings.sh:

git clone https://github.com/Xilinx/xen.git
cd xen/xen/
git checkout -b my-2021.2 xlnx_rebase_4.14_2021.2
export CROSS_COMPILE=aarch64-none-elf-
export XEN_TARGET_ARCH=arm64
make menuconfig
  select "Developer Checks"
make -j8
cp xen /path/to/xen


Changes Required in XEN DTS Using Petalinux

Before starting you need to create a PetaLinux project. It is assumed that a default PetaLinux reference design is used unchanged in these instructions.
  • The peripheral devices used as part of EL1 Baremetal application need to be passthrough in xen-overlay.dtsi (<petalinux_project>/project-spec/meta-user/recipes-bsp/device-tree/files/xen-overlay.dtsi)
  • For example , The "Hello world" standalone application uses uart1 to print messages, so passthrough the uart1 device in xen-overlay.dtsi, as shown below,
  • &uart1 {
       xen,passthrough = <0x1>;
    };
  • Build the images for XEN with above change using the petalinux. Please refer section "Configuring and building XEN from source using PetaLinux 2017.1" in XEN Hypervisor for steps.


Xen Config file

  • XEN needs xl configuration file, which describes the DomU guest.
  • Here is a content of hello_world.cfg, an configuration file used to run Hello World application as an domU guest
  •    #Guest name
         name = "hello_world"
       # Kernel image to boot
         kernel = "xapp_hello_world_el1.bin"
       # Kernel command line options - Allocate 8MB
         memory = 8
       # Number of VCPUS
         vcpus = 1
       # Pin to CPU 0
         cpus = [1]
         irqs = [ 54 ]
         iomem = [ "0xff010,1" ]
  • As shown in configuration file, bin file generated through SDK (i.e. xapp_hello_world_el1.bin generated through SDK in previous steps)
    has to be mentioned as kernel image in "kernel" field of xen guest configuration file. Also, "irqs" and "iomem" fields are updated
    with uart1 interrupt id and base address receptively. Similar way these fields in config needs to be updated for the other peripherals
    as well, if application is using any.
  • More information on config file can be found at
    https://xenbits.xen.org/docs/unstable/man/xl.cfg.5.html



How to Execute an EL1 DomU Baremetal Application

  • Copy the bin file xapp_hello_world_el1.bin generated in previous steps and hello_world.cfg to SD card or else use tftp to get them
    in dom0's files system after booting dom0.
  • Boot XEN dom0 with the images built in earlier steps. Refer section "TFTP Booting Xen and Dom0 2017.1" in XEN Hypervisor, for dom0 boot up steps.
  • Once XEN dom0 is up and running, copy the config file hello_world.cfg and bin file xapp_hello_world_el1.bin from SD card to dom0 file system/use tftp to get them in dom0 file system
  • Go to that path in dom0 file system and Execute below command
    • xl create hello_world.cfg
  • You'll see hello world baremetal application running as XEN domU , prints in bare metal application would be available on uart1 console
  • More detail on xl command can be found at https://xenbits.xen.org/docs/unstable/man/xl.1.html

Related Links

© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy