Xilinx ZCU102

From ERIKA WIKI
Revision as of 15:28, 7 March 2018 by Ida (talk | contribs)
Jump to: navigation, search

Introduction

The ERIKA3 RTOS can be run as a guest OS of the Jailhouse hypervisor on the Xilinx ZCU102.

Zynq UltraScale+™ MPSoC device has a quad-core ARM® Cortex-A53, dual-core Cortex-R5 real-time processors, and a Mali-400 MP2 graphics processing unit based on Xilinx's 16nm FinFET+ programmable logic fabric. The ZCU102 supports all major peripherals and interfaces enabling development for a wide range of applications.

Figure: Xilinx ZCU102 evaluation board.

Here are the steps to run ERIKA3 as Jailhouse cell:

  • Build and install Linux kernel v4.7+ on the Xilinx ZCU102
  • Build and install Jailhouse
  • Create an ERIKA3 Jailhouse inmate
  • Load and run the ERIKA3 Jailhouse inmate

Linux kernel v4.7+ on Xilinx ZCU102

Xilinx provides the tools in order to customize, build and deploy embedded Linux solutions on Xilinx processing systems. Such tools consists a set of pre-configured binary bootable images, fully customizable Linux for the Xilinx devices, and PetaLinux/Xilinx Vivado SDK. The Xilinx Vivado (with SDK) is used to define the hardware design of the related board, whereas the PetaLinux SDK includes tools and utilities to automate complex tasks across configuration, build, and deployment.

According to the Jailhouse documentation a linux kernel version 4.7+ is needed for ARM64. Starting from release 2017.1, the Xilinx kernel in PetaLinux has been upgraded from version 4.6 to version v.9 and thus the referred PetaLinux/Vivado SDKtool release has to be 2017.1 and further. In the following part of the section, we refer, without loss of generality, to PetaLinux tools 2017.2 release.

The compilation environment: PetaLinux tool

The PetaLinux Tools aim to configure, build and deploy a booting image for the Xilinx board on the basis of the hardware design file (.hdf). PetaLinux installation is very straight-forward. Without any options, PetaLinux tools will be installed into a subdirectory of the current working directory. Alternatively, an installation path may be specified.

Example of PetaLinux Tools 2017.2 installation in the /opt/pkg directory:

$ mkdir /opt/pkg
$ ./petalinux-v2017.2-final-installer.run /opt/pkg

In order to setup the PetaLinux working environment, it is required to source the appropriate settings script (e.g., from a bash shell):

$ source /opt/pkg/2017.2/settings.sh

A detailed instruction of the PetaLinux tools is in the reference user guide (link to manual). In the following part of the section, we give an overview on how to create a new PetaLinux project and build the boot image for the referred board.

Create a New PetaLinux Project

In order to create a new PetaLinux project for the referred board, run the following command from the command console (e.g. bash):

$ petalinux-create -t project -n <name> --template zynqMP

where name is used the project name.

After creating the project, the hardware configuration should be imported in order to build a Linux system for a customized hardware platform. Example of hardware design file can be found in the PetaLinux installation path (e.g.,/opt/pkg/2017.2/tools/hsm/data/embeddedsw/lib/hwplatform_templates/ZCU102_hw_platform/system.hdf) or in the Xilinx repository (zcu102 hdf example), whereas customized hardware design file can be created by means of Xilinx Vivado SDK. Run the following command to import the hardware description:

$ petalinux-config --get-hw-description=<path to directory which contains hardware description file>

Such command will import the hardware description of the .hdf file given as input. Then, it will launch the top system configuration menu when it runs first time for the PetaLinux project or the tool detects there is a change in the system primary hardware candidates.

In order to change the configuration of the system by launching the top system configuration menu, run the following command:

$ petalinux-config

This command is used to define the sets of components (e.g., u-boot, arm-trusted-firmware, kernel and rootfs). For each component, it defines the configuration settings and whether the configuration files will be auto updated (i.e., Auto Config Settings). Furthermore, the command allows to configure the hardware settings (e.g., system processor, memory, Serial port, Ethernet and so forth). o configur Furthermore , the petalinux-config command allows to configure a single component (e.g., u-boot, kernel or rootfs) as follows:

Kernel configuration:

$ petalinux-config -c kernel

U-boot configuration:

$ petalinux-config -c u-boot

Build the boot image

In order to build and create the boot image, the PetaLinux 2017.2 tool provides the following commands:

$ petalinux-build

The petalinux-build command is used to build the system image. As for the petalinux-config command, it is possible to rebuild a single component instead of the entire system with the -c <component> option.

Finally, the petalinux-package command is used to build various image format, firmware, prebuilt and bsps.

$ petalinux-package --boot|--bsp|--firmware|--image|--prebuilt [options]

The boot image for the ZynqMP contains a first stage bootloader image, FPGA bitstream and u-boot. It will be contained in a file referred to as BOOT.BIN, whereas the Linux kernel image will contained in a separated file, referred to as uImage.ub.

For creating the boot image , the command line is the following:

$ petalinux-package --boot --u-boot <path of the u-boot elf file> --fpga <path of the bitstream file>

Note that the images BOOT.BIN and uImage.ub, including the u-boot elf file and the bitstream file, are stored in <petalinux-project-root>/images/linux where <petalinux-project-root> is the path of the referred PetaLinux project.

For creating only the Linux kernel image, the command line is the following:

$ petalinux-package --image -c kernel --format uImage

Install the boot image

The boot image can be put into Flash or SD card. This section refers to the steps for booting from SD card and the the board configuration has to be switch for SD boot as shown in the following picture (for more details please refer to the section "ZCU102 board setup " of the Xilinx manual):

Figure: Configuration for SD boot.

The SD card has to contain two partitions:

  • the first partition, referred to as BOOT, contains the bootloader, u-boot, device-tree and kernel image. More in detail, the boot images created in PetaLinux project (i.e., BOOT.BIN and image.ub) will be installed in the root directory of the BOOT partition.
  • the second partition, referred to as rootfs, stores the system root filesystem.

The SD card partitions can be built by flashing prebuilded SD images or from scratch.

Prebuilded SD images can be found in the Xilinx repository and the SD card setup can be performed as follows:

  1. Mount the SD card on your host machine.
  2. Flash the downloaded image into the SD card:
    $ dd if=<file image> of=/dev/sdX bs=8M && sync

In case of the SD card partitions built from scratch, the SD card setup can be performed as follows:

  1. Mount the SD card on your host machine.
  2. Format the SD card in two partitions using gparted or fdisk:
    • The BOOT partition should be at least 40MB in size and formatted as a FAT32 filesystem. Ensure that there is 4MB of free space preceding the partition.
    • The rootfs partition should be formatted as an ext4 file-system and can take up the remaining space on the SD card.
  3. Copy BOOT.BIN and image.ub from <petalinux-project-root>/pre-built/linux/images/ into the root directory of the BOOT partition.
  4. Extract the file-system archive into the rootfs partition.

Build and install kernel modules

In order to build and install the kernel modules, run the following command:

$ make -C <path to compiled kernel> ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=<destination path>  modules_install 

where <path to compiled kernel> is the path of folder containing the compiled kernel in the petalinux project and <destination path> is typically the filesystem root.

Jailhouse for Xilinx ZCU102

The hypervisor requires a contiguous piece of RAM for itself and each additional cell. This currently has to be pre-allocated during boot-up. On ARM platforms this is usually achieved by reducing the amount of memory seen by the Linux kernel. You therefore need to modify the kernel boot arguments by resizing the kernel memory.

Jailhouse setup

As for jailhouse installation on Xilinx ZCU102, we refer to Jailhouse v0.7 on the GitHub repository. The commands to checkout at such version are the following:

$ git clone https://github.com/siemens/jailhouse 
$ cd jailhouse
$ git checkout v0.7 -b xilinx_jailhouse

Jailhouse directory contains the following subdirectories:

  • Documentation
  • ci - configuration files for different platforms.
  • configs - cell configuration files.
  • driver - jailhouse.ko kernel module code.
  • hypervisor - hypervisor code.
  • inmates - inmates demos. It also contains code for ti_app inmate example.
  • scripts
  • tools - jailhouse management utility.

Jailhouse build and installation

For building and installing Jailhouse, first setup the environment by simply setting the PetaLinux working environment:

$ source /opt/pkg/2017.2/settings.sh

Then a copy of the compiled Linux kernel with all object files is needed, to be able of building the kernel module. We refer to the path of folder containing the compiled kernel as <path to compiled kernel>.

Create the configuration file for the ZCU102 board (e.g., jailhouse-config-xilinx-zcu102.h):

#define CONFIG_TRACE_ERROR             1
#define CONFIG_ARM_GIC_V2              1
#define CONFIG_MACH_ZYNQMP_ZCU102      1

Copy the jailhouse-config-xilinx-zcu102.h file into <jailhouse directory>hypervisor/include/jailhouse directory and rename it to config.h

Build and install jailhouse as follows:

$ make clean
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- KDIR=<path to compiled kernel> DESTDIR=<destination directory> install

where <path to compiled kernel> is the path of folder containing the compiled kernel in the petalinux project and <destination path> is typically the filesystem root.

Copy also the zcu102 root cell (i.e., configs/zynqmp-zcu102.cell) on the SD card filesystem.

Build and install ERIKA3 as Jailhouse inmate

The main steps to create and build ERIKA v3 jailhouse inmate are the following:

  • download and install RT_DRUID that includes ERIKA v3 as Eclipse plugin.
  • create and build a new RT-Druid v3 Oil and C/C++ project containing the main application running on ERIKA v3 (i.e., source files and the oil file containing the configuration for the referred board)
  • install the generated binaries into the board

Downloading and installing ERIKA v3 and RT-Druid

RT-Druid can be downloaded using the download web page. Notice that to download RT-Druid, you have to accept the RT-Druid and the ERIKA v3 licenses. The ERIKA v3 license is a GPL v2, whereas the RT-Druid license is a proprietary license that allows you to use the provided version of RT-Druid at no cost.

RT-Druid requires Java Standard Edition version 8, or newer.

RT-Druid is provided as a compressed archive, which can be unpacked in your user directories. RT-Druid has ERIKA v3 source code as Eclipse plugin and the default path is RT_Druid folder/eclipse/plugins/com.eu.evidence.ee3_<version number>/ee_files/. However, it is possible to change the RT-Druid configuration in order to refer to another ERIKA 3 source code. For more details about RT-Druid configuration, see the RT-Druid configuration wiki page.

Starting RT-Druid

Before starting RT-Druid, setup the environment by setting the variables JAILHOUSE_DIR and JAILHOUSE_AARCH64_GCCPREFIX as follows:

$ export JAILHOUSE_DIR=<path of the jailhouse directory>
$ export JAILHOUSE_AARCH64_GCCPREFIX=aarch64-linux-gnu-

Furthermore since we refer to Jailhouse v0.7 for Xilinx ZCU102, set the environment variable JAILHOUSE_VERSION as follows:

$ export JAILHOUSE_VERSION=0.7

Finally, in order to cross-compile setup the PetaLinux working environment:

$ source /opt/pkg/2017.2/settings.sh

In order to start RT-Druid, launch eclipse application located into the eclipse folder extracted from the RT-Druid Package.

Creating a new RT-Druid project

Create a new project by clicking on File->New->RT-Druid v3 Oil and C/C++ Project menu entry. In the RT-Druid C/C++ Project Wizard type the name of the project in the Project name text-box (i.e, mytest for example). Then, select the Cross GCC toolchain and click on the Next button.

Figure: RT-Druid C/C++ Project Wizard.

Create a new file main.c file by clicking on File->New->Source file with the following content:

#include "ee.h"
#include <inmate.h>

static volatile u32 counter = 0;

DeclareTask(Task1);
DeclareTask(Task2);

/* First task */
TASK(Task1)
{
        GetResource(SharedUartResource);
        printk("Hello world from Task1! (%lu)\n", counter);
        counter++;
        ReleaseResource(SharedUartResource);
        TerminateTask();
}

/* Second task */
TASK(Task2)
{
        GetResource(SharedUartResource);
        printk("Hello world from Task2! (%lu)\n", counter);
        counter++;
        ReleaseResource(SharedUartResource);
        TerminateTask();
}

void idle_hook(void);
void idle_hook(void)
{
        /* endless loop*/
        while(1) {
                asm volatile("wfi": : : "memory");
        }
}

int main(void)
{
        printk("Starting OS...\n");
        StartOS(OSDEFAULTAPPMODE);
        return 0;
}

Modify the conf.oil file with the following content:

CPU mySystem {

  OS myOs {

    /* EE_OPT = "OS_EE_VERBOSE"; */
    EE_OPT = "OSEE_DEBUG";
    EE_OPT = "OS_EE_APPL_BUILD_DEBUG";
    EE_OPT = "OS_EE_BUILD_DEBUG";
    EE_OPT = "OSEE_ASSERT";

    CPU_DATA = AARCH64 {
      MULTI_STACK = TRUE;
      COMPILER = GCC;
      IDLEHOOK = TRUE {
        HOOKNAME = "idle_hook";
      };
    };

    SOC_DATA = XILINX_ZYNQ_ULTRASCALE_PLUS;

    KERNEL_TYPE = OSEK {
      CLASS = ECC1;
    };
  };

  COUNTER SystemTimer {
    MINCYCLE = 1;
    MAXALLOWEDVALUE = 2147483647;
    TICKSPERBASE = 1;
    TYPE = HARDWARE {
      SYSTEM_TIMER = TRUE;
      PRIORITY     = 1;
      DEVICE       = "GTIMER";
    };
    SECONDSPERTICK = 0.001;
  };

  ALARM AlarmTask1 {
    COUNTER = SystemTimer;
    ACTION = ACTIVATETASK {
      TASK = Task1;
    };
    AUTOSTART = TRUE {
      ALARMTIME = 500;
      CYCLETIME = 100;
    };
  };

  ALARM AlarmTask2 {
    COUNTER = SystemTimer;
    ACTION = ACTIVATETASK {
      TASK = Task2;
    };
    AUTOSTART = TRUE {
      ALARMTIME = 500;
      CYCLETIME = 100;
    };
  };

  TASK Task1 {
    PRIORITY = 1;
    STACK = PRIVATE {
      SIZE = 1024;
    };
    SCHEDULE = FULL;
    APP_SRC = "main.c";
    RESOURCE = SharedUartResource;
  };

  TASK Task2 {
    PRIORITY = 2;
    STACK = PRIVATE {
      SIZE = 1024;
    };
    SCHEDULE = FULL;
    RESOURCE = SharedUartResource;
  };

  RESOURCE SharedUartResource { RESOURCEPROPERTY = STANDARD; };
};

Building the RT-Druid project

To build an RT-Druid Project, right-click on your project, as example mytest, shown in the Eclipse Project Explorer panel, and then click on Build Project context-menu entry. The compilation process will generate the following directories:

  • erika - It stores all the files related to ERIKA v3
  • out - It stores all the files related to the application, included the final binaries

In particular, the out directory will contain the following files:

  • applSignature.oil - the application OIL signature, which is basically the OIL file re-exported by the tool
  • ee_applcfg. - the application configuration generated by RT-Druid
  • makefile - the main application makefile
  • erika_inmate.bin - the ERIKA v3 binary containing the application

Note that to completely clean the project by removing either generated and compiled files (i.e., erika and out folders), right-click on your project, as example mytest, shown in the Eclipse Project Explorer panel, and then click on Clean Erika context-menu entry.

Installing ERIKA v3 cell

In order to install ERIKA v3 cell on the ZCU102, copy the following file on the SD card file-system (i.e., on the root /):

  • zcu102 cell (i.e, configs/zynqmp-zcu102-gic-demo.cell) of the <jailhouse directory>.
  • ERIKA v3 binary stored in the <tt>out of the RT-Druid project.

Run ERIKA v3 on Jailhouse

In order to run ERIKA v3 as Jailhouse inmate, the SD card for the ZCU102 should contain the following files (see Jailhouse and ERIKA v3 cell installation):

  • Jailhouse kernel modules
  • zcu102 root cell (i.e., /zynqmp-zcu102.cell)
  • zcu102 cell (i.e., /zynqmp-gic-demo.cell)
  • Erika v3 binary (i.e., /erika_inmate.bin)

Board first boot

Since the hypervisor requires a contiguous piece of RAM for itself and each additional cell, the amount of memory seen by the Linux kernel has to be reduced.

In order to modify the kernel boot arguments by adding mem=<new value>, reboot the board and stop the execution at the u-boot prompt (typically by pressing any key at the boot). Change the bootargs as follows:

u-boot prompt> setenv bootargs '<previous values> mem=1536M'

Save the environment so that the kernel memory will be set to the desired value also for the next reboots and then restart the execution:

u-boot prompt> saveenv 
u-boot prompt> run bootcmd

At the kernel start, update the list of module dependencies:

 xlnx-linux prompt> sudo depmod -a

Jailhouse run

Once the boot arguments has been modified and the machine rebooted, insert jailhouse.ko kernel module:

 xlnx-linux prompt> sudo modprobe jailhouse

Enable jailhouse by specifing the zcu102 root cell path:

 xlnx-linux prompt> sudo jailhouse enable /zynqmp-zcu102.cell

Run ERIKA v3 on Jailhouse

Since ERIKA v3 will take the console for printing the application messages, send the following commands through the ssh connection. Create the jailhouse cell:

 xlnx-linux prompt> sudo jailhouse cell create /zynqmp-gic-demo.cell

Load the ERIKA v3 binary:

 xlnx-linux prompt> sudo jailhouse cell load gic-demo /erika-inmate.bin

Start ERIKA v3:

 xlnx-linux prompt> sudo jailhouse cell start gic-demo

The ERIKA v3 cell has to print the following output:

 Starting OS...
 Hello world from Task2! (0)
 Hello world from Task1! (1)
 Hello world from Task2! (2)
 Hello world from Task1! (3)
 Hello world from Task2! (4)
 ...