Skip to content

bao-project/bao-helloworld

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

"Hello world"? We prefer "Hello Bao!"

Welcome to the Bao Hypervisor! Get ready for an interactive journey as we explore the world of Bao together. Whether you're a experience Bao user or a newcomer, this tour is designed to give you a practical introduction to the Bao hypervisor.

If you're already familiar with Bao or want to dive into specific setups provided by our team, feel free to skip ahead to the Bao demos repository.

In this guide, we will take a tour of the different components required to build a setup using the Bao hypervisor and learn how the different components interact. For this purpose, the guide contains the following topics:

  • A getting started section that helps users to prepare the environment where we will build the target setups. We also provide extra detailed documentation notes regarding some implementation aspects of the hypervisor;
  • An initial setup section that explores the different components of the system and gets the first practical example of this guide;
  • An interactive tutorial on changing the guests running on top of Bao;
  • A practical example of changing the setup running;
  • An example of how different guests can coexist and interact with each other;

1. Getting Started

In this section, we'll guide you through preparing a development environment to build Bao. Don't worry; we'll provide you with helpful pointers to Bao's implementation details in case you want to explore any further.

1.1 Recommended Operating System: Linux (e.g., Ubuntu 22.04)

We recommend using a Linux-based operating system to make the most of this tutorial and the Bao hypervisor. While the instructions may work on other platforms, this guide is set up on top of a Linux-based machine, specifically Ubuntu 22.04. This will ensure compatibility and an optimal experience throughout the tour.

1.2 Installing Required Dependencies

Before we can dive into the world of Bao, we need to install several dependencies to enable a seamless setup process. Open your terminal and run the following command to install the necessary packages:

sudo apt install build-essential bison flex git libssl-dev ninja-build \
    u-boot-tools pandoc libslirp-dev pkg-config libglib2.0-dev libpixman-1-dev \
    gettext-base curl xterm cmake python3-pip

This command will install essential tools and libraries required for building and running Bao. Next, we need to install some Python packages. Execute the following command to do so:

pip3 install pykwalify packaging pyelftools

1.3 Download and setup the toolchain

1.3.1. Choosing the Right Toolchain

Before we delve deeper, let's ensure you have the right tools at your disposal. We'll guide you through obtaining and configuring the appropriate cross-compile toolchain for your target architecture.

Architecture Toolchain Name Download Link
Armv8 Aarch64 aarch64-none-elf- Arm Developer
Armv7/8 Aarch32 arm-none-eabi- Arm Developer
RISC-V riscv64-unknown-elf- SiFive Tools

1.3.2. Installing and Configuring the Toolchain

Download the pre-build binary packages of the appropriate toolchain for your target architecture. Then, set the CROSS_COMPILE environment variable with the reference toolchain prefix path:

export CROSS_COMPILE=/path/to/toolchain/install/dir/bin/your-toolchain-prefix-

1.4 Ensuring Enough Free Storage

Please note that having sufficient free storage is important for a smooth experience, particularly because of the Linux image that will be built for the Linux guest VM. To prevent any storage-related issues, we suggest having a minimum of 13 GiB of free storage available on your system. With your environment set up and all the dependencies installed, you are now prepared to explore the Bao hypervisor and create your first virtualized environmen

Component Required storage Percentage of storage Required
Bao 155.8 MiB 1.28%
Guest (Linux) 10.5 GiB 86.78%
Guest (freeRTOS) 24.8 MiB 0.20%
Guest (baremetal) 4.2 MiB 0.03%
Tools (QEMU) 1.3 GiB 10.74%
Tools (OpenSBI) 114 MiB 0.92%

2. Initial setup - Taking the First Steps!

Now that you're geared up, it's time to take the first steps on this tour. In the Initial Setup section, we'll explore the different components of the system and walk you through a practical example to give you a solid foundation.

We'll start by setting up a working environment. Begin by cloning the Bao hello world repository:

git clone https://github.com/bao-project/bao-helloworld.git
cd bao-helloworld

Next, proceed to configure the development environment and establish a directory tree to organize the various components required. Open your terminal and execute the following commands:

export ROOT_DIR=$(realpath .)
export PRE_BUILT_IMGS=$ROOT_DIR/bin
export SETUP_BUILD=$ROOT_DIR/build
export PATCHES_DIR=$ROOT_DIR/patches
export TOOLS_DIR=$ROOT_DIR/tools
export BUILD_GUESTS_DIR=$SETUP_BUILD/guests
export BUILD_BAO_DIR=$SETUP_BUILD/bao
export BUILD_FIRMWARE_DIR=$SETUP_BUILD/firmware

mkdir -p $BUILD_GUESTS_DIR
mkdir -p $BUILD_BAO_DIR
mkdir -p $BUILD_FIRMWARE_DIR
mkdir -p $TOOLS_DIR/bin

Upon completing these commands, your directory tree should look like this:

├── build
│   ├── bao
│   ├── firmware
│   └── guests
├── configs
│   ├──...
├── img
│  ├──...
└──README.md

2.1. Building Your First Bao Guest

Let's start the journey of building your first Bao guest. Here, you'll acquire hands-on experience in creating a Baremetal guest. Before we move on to the practical aspects, let's first understand the setup we're building. Our goal is to deploy a baremetal guest on top of the Bao hypervisor, as shown in the figure below:

Init Setup

ℹ️ For the sake of simplicity and accessibility, we'll use the QEMU emulator (don't worry, we'll guide you through its installation later in the tutorial). However, remember that you can apply these steps to various other platforms.

To start, let's define an environment variable for the baremetal app source code:

export BAREMETAL_SRCS=$ROOT_DIR/baremetal

Then, clone the Bao baremetal guest application we've prepared (you can skip this step if you already have your own baremetal source):

git clone https://github.com/bao-project/bao-baremetal-guest.git\
    --branch demo $BAREMETAL_SRCS

And now, let's compile it (for simplicity, our example includes a Makefile to compile the baremetal compilation):

git -C $BAREMETAL_SRCS apply $PATCHES_DIR/baremetal.patch
make -C $BAREMETAL_SRCS PLATFORM=qemu-riscv64-virt

Upon completing these steps, you'll find a binary file in the BAREMETAL_SRCS directory. If you followed our provided Makefile, the binary takes the name baremetal.bin. Now, move the binary file to your build directory (BUILD_GUESTS_DIR):

mkdir -p $BUILD_GUESTS_DIR/baremetal-setup
cp $BAREMETAL_SRCS/build/qemu-riscv64-virt/baremetal.bin \
    $BUILD_GUESTS_DIR/baremetal-setup/baremetal.bin

2.2. Build Bao Hypervisor - Laying the Foundation

Next up, we'll guide you through building the Bao Hypervisor itself. The first step involves configuring the hypervisor using Bao's configuration file. For this specific setup, we're providing you the configuration file to ease the process. If you're curious to explore different configuration options, our detailed Bao config documentation is here to help.

⚠️ If you are using a different directory structure of the one presented in the tutorial, please make sure to update the following code in the configuration file.

VM_IMAGE(baremetal_image, XSTR(BAO_WRKDIR_IMGS/baremetal-setup/baremetal.bin));

Now we must build Bao. There's no need for any complex setup; it's straightforward. Let's begin this stage-setting process:

2.2.1. Cloning the Bao Hypervisor

Your gateway to seamless virtualization begins with cloning the Bao Hypervisor repository. Execute the following commands in your terminal to initiate this crucial step:

export BAO_SRCS=$ROOT_DIR/bao
git clone https://github.com/bao-project/bao-hypervisor $BAO_SRCS\
    --branch demo

2.2.2. Compiling Bao Hypervisor

We are all set! It's time to bring the Bao Hypervisor to life. Now, we just need to compile it!

make -C $BAO_SRCS\
    PLATFORM=qemu-riscv64-virt\
    CONFIG_REPO=$ROOT_DIR/configs\
    CONFIG=baremetal\
    CPPFLAGS=-DBAO_WRKDIR_IMGS=$BUILD_GUESTS_DIR

Upon completing these steps, you'll find a binary file in the BAO_SRCS directory called bao.bin. Now, let's move the binary file to your build directory:

cp $BAO_SRCS/bin/qemu-riscv64-virt/baremetal/bao.bin $BUILD_BAO_DIR/bao.bin

3. Build Firmware - Powering Up Your Setup

Firmware is essential to power your virtual world. That's why we're here to assist you in obtaining the necessary firmware tailored to your target platform (you can find the instructions to build the firmware for other platforms here).

3.1 Getting Started with the QEMU Platform

QEMU provides a convenient alternative to a hardware platform. If you haven't installed it yet, don't worry. We're here to walk you through the process of building and installing it. In this guide, we'll target the riscv64 architecture.

If you already have qemu-system-riscv64, or if you'd prefer to install it directly using a package manager or another method, just make sure you're working with version 7.2.0 or higher. In that case, feel free to move on to the next step.

To install QEMU, simply run the following commands:

export QEMU_DIR=$ROOT_DIR/tools/qemu-riscv64
git clone https://github.com/qemu/qemu.git $QEMU_DIR --depth 1\
   --branch v7.2.0
cd $QEMU_DIR
./configure --target-list=riscv64-softmmu --enable-slirp
make -j$(nproc)
sudo make install

3.2 Clone OpenSBI

To get OpenSBI up and running, simply execute the following commands:

export OPENSBI_DIR=$ROOT_DIR/tools/OpenSBI
git clone https://github.com/bao-project/opensbi.git $OPENSBI_DIR\
    --depth 1 --branch bao/demo

4. Let's Try It Out! - Unleash the Power

Now that everything is set up, let's revise all the steps performed yet:

✅ Build guest (baremetal)

✅ Build bao hypervisor

✅ Build firmware (qemu)

Once everything is in place, we'll proceed with the QEMU launch. This is the command to run:

make -C $TOOLS_DIR/OpenSBI PLATFORM=generic \
    FW_PAYLOAD=y \
    FW_PAYLOAD_FDT_ADDR=0x80100000\
    FW_PAYLOAD_PATH=$BUILD_BAO_DIR/bao.bin

cp $TOOLS_DIR/OpenSBI/build/platform/generic/firmware/fw_payload.elf \
    $TOOLS_DIR/bin/opensbi.elf

qemu-system-riscv64 -nographic\
    -M virt -cpu rv64 -m 4G -smp 4\
    -bios $TOOLS_DIR/bin/opensbi.elf\
    -device virtio-net-device,netdev=net0 \
    -netdev user,id=net0,net=192.168.42.0/24,hostfwd=tcp:127.0.0.1:5555-:22\
    -device virtio-serial-device -chardev pty,id=serial3 -device virtconsole,chardev=serial3

Now, you should see OpenSBI initialization log. Now, let's set up connections and jump into Bao. Here's an example:

And you should have an output as follows (video here):

baremetal

To exit QEMU hold press Ctrl-A then X.

5. Adjusting Your Setup

As we progress, let's focus on fine-tuning your Bao setup. Having the ability to modify your virtual environment can be quite useful. In the upcoming sections, we'll provide you with detailed, step-by-step instructions to implement various changes to your guests. By the end of this segment, you'll have gained a deeper insight into how the different components interact, and you'll be skilful at making the necessary adjustments to meet your requirements.

5.1 Modify the baremetal VM

Let's begin by modifying the baremetal VM. We'll increase the number of vCPUs assigned to the baremetal, as presented in the following figure:

Init-mod Setup

5.1.1 Update the number of vCPUS assigned to the VM

Let's start by changing the number of vCPUs assigned to the VM (changes applied in the new configuration file):

-       .cpu_num = 1,                                       | line 17
+       .cpu_num = 4,                                       | line 17

5.1.2 Update the memory assigned to the VM

  1. Open the platform configuration file located at baremetal/src/platform/qemu-riscv64-virt/inc/plat.h.
  2. Modify the platform memory size from 64MiB (0x4000000) to 128 MiB (0x8000000):
 #define PLAT_MEM_BASE 0x80200000
-#define PLAT_MEM_SIZE 0x4000000
+#define PLAT_MEM_SIZE 0x8000000

After updating the baremetal, you need to modify the Bao configuration file. Update the configuration (configs/baremetal.c) with the new memory size:

            .regions =  (struct vm_mem_region[]) {      | line 20
                {                                       | line 21
                    .base = 0x80200000,                 | line 22
-                   .size = 0x4000000                   | line 23
+                   .size = 0x8000000                   | line 23
                }
            }

5.1.3 Recompile the baremetal

Run the following commands to rebuild the baremetal image:

make -C $BAREMETAL_SRCS PLATFORM=qemu-riscv64-virt
cp $BAREMETAL_SRCS/build/qemu-riscv64-virt/baremetal.bin \
    $BUILD_GUESTS_DIR/baremetal-setup/baremetal.bin

5.1.4 Recompile Bao

make -C $BAO_SRCS\
    PLATFORM=qemu-riscv64-virt\
    CONFIG_REPO=$ROOT_DIR/configs\
    CONFIG=baremetal_mod\
    CPPFLAGS=-DBAO_WRKDIR_IMGS=$BUILD_GUESTS_DIR

cp $BAO_SRCS/bin/qemu-riscv64-virt/baremetal_mod/bao.bin $BUILD_BAO_DIR/bao.bin

5.1.5 Run the setup

To run this setup just use the following command:

make -C $TOOLS_DIR/OpenSBI PLATFORM=generic \
    FW_PAYLOAD=y \
    FW_PAYLOAD_FDT_ADDR=0x80100000\
    FW_PAYLOAD_PATH=$BUILD_BAO_DIR/bao.bin

cp $TOOLS_DIR/OpenSBI/build/platform/generic/firmware/fw_payload.elf \
    $TOOLS_DIR/bin/opensbi.elf

qemu-system-riscv64 -nographic\
    -M virt -cpu rv64 -m 4G -smp 4\
    -bios $TOOLS_DIR/bin/opensbi.elf\
    -device virtio-net-device,netdev=net0 \
    -netdev user,id=net0,net=192.168.42.0/24,hostfwd=tcp:127.0.0.1:5555-:22\
    -device virtio-serial-device -chardev pty,id=serial3 -device virtconsole,chardev=serial3

Now, you should see OpenSBI initialization log. Now, let's set up connections and jump into Bao. Here's an example:

And you should have an output as follows (video here):

baremetal

5.2 Add a second guest - freeRTOS

In this section, we'll delve into various scenarios and demonstrate how to configure specific environments using Bao. Let's kick things off by incorporating a second VM running FreeRTOS.

Let's kick things off by incorporating a second VM running FreeRTOS.

Init Setup

First, we can use the baremetal compiled from the first setup:

mkdir -p $BUILD_GUESTS_DIR/baremetal-freeRTOS-setup
cp $BAREMETAL_SRCS/build/qemu-riscv64-virt/baremetal.bin \
    $BUILD_GUESTS_DIR/baremetal-freeRTOS-setup/baremetal.bin

5.2.1. Compile freeRTOS

Then, let's compile our new guest:

export FREERTOS_SRCS=$ROOT_DIR/freertos
export FREERTOS_PARAMS="STD_ADDR_SPACE=y"

git clone --recursive --shallow-submodules\
    https://github.com/bao-project/freertos-over-bao.git\
    $FREERTOS_SRCS --branch demo
git -C $FREERTOS_SRCS apply $PATCHES_DIR/freeRTOS.patch
make -C $FREERTOS_SRCS PLATFORM=qemu-riscv64-virt $FREERTOS_PARAMS

Upon completing these steps, you'll find a binary file in the FREERTOS_SRCS directory, called freertos.bin. Move the binary file to your build directory (BUILD_GUESTS_DIR):

cp $FREERTOS_SRCS/build/qemu-riscv64-virt/freertos.bin \
    $BUILD_GUESTS_DIR/baremetal-freeRTOS-setup/freertos.bin

5.2.2. Integrating the new guest

Now, we have both guests compiled and ready for our dual-guest setup. However, there are some steps required to fit the two VMs on our platform. Let's understand the differences between the configuration of the first setup and the configuration of the second setup.

First of all, we need to add the second VM image:

- VM_IMAGE(baremetal_image, XSTR(BAO_WRKDIR_IMGS/guests/baremetal-setup/baremetal.bin));
+ VM_IMAGE(baremetal_image, XSTR(BAO_WRKDIR_IMGS/guests/baremetal-freeRTOS-setup/baremetal.bin));
+ VM_IMAGE(freertos_image, XSTR(BAO_WRKDIR_IMGS/guests/baremetal-freeRTOS-setup/freertos.bin));

Also, since we now have 2 VMs, we need to change the vm_list_size in our configuration:

- .vmlist_size = 1,
+ .vmlist_size = 2,

Next, we need to think about resources. In the first setup, we assigned 4 vCPUs to the baremetal. But this time, we need to split the vCPUs between the two VMs. For the baremetal, we will use 3 CPUs:

- .cpu_num = 4,
+ .cpu_num = 3,

While for the freeRTOS VM, we will assign only one CPU:

+ .cpu_num = 1,

Additionally, we need to include all the configurations of the second VM. (Details are omitted for simplicity but you can check further details in the configuration file):

+        {
+            .image = {
+                .base_addr = 0x0,
+                .load_addr = VM_IMAGE_OFFSET(freertos_image),
+                .size = VM_IMAGE_SIZE(freertos_image)
+            },
+
+            ...        // omitted for simplicity
+        },

5.2.3. Let's rebuild Bao!

As we've seen, changing the guests includes changing the configuration file. Therefore, we need to repeat the process of building Bao. Please note that the flag CONFIG defines the configuration file to be used on the compilation of Bao. To compile it, use the following command:

make -C $BAO_SRCS\
    PLATFORM=qemu-riscv64-virt\
    CONFIG_REPO=$ROOT_DIR/configs\
    CONFIG=baremetal-freeRTOS\
    CPPFLAGS=-DBAO_WRKDIR_IMGS=$BUILD_GUESTS_DIR

Upon completing these steps, you'll find a binary file in the BAO_SRCS directory, called bao.bin. Move the binary file to your build directory (BUILD_BAO_DIR):

cp $BAO_SRCS/bin/qemu-riscv64-virt/baremetal-freeRTOS/bao.bin \
    $BUILD_BAO_DIR/bao.bin

5.2.4. Ready for launch!

Now, you have everything configured for testing your new setup! Just run the following command:

make -C $TOOLS_DIR/OpenSBI PLATFORM=generic \
    FW_PAYLOAD=y \
    FW_PAYLOAD_FDT_ADDR=0x80100000\
    FW_PAYLOAD_PATH=$BUILD_BAO_DIR/bao.bin

cp $TOOLS_DIR/OpenSBI/build/platform/generic/firmware/fw_payload.elf \
    $TOOLS_DIR/bin/opensbi.elf

qemu-system-riscv64 -nographic\
    -M virt -cpu rv64 -m 4G -smp 4\
    -bios $TOOLS_DIR/bin/opensbi.elf\
    -device virtio-net-device,netdev=net0 \
    -netdev user,id=net0,net=192.168.42.0/24,hostfwd=tcp:127.0.0.1:5555-:22\
    -device virtio-serial-device -chardev pty,id=serial3 -device virtconsole,chardev=serial3

Now, you should have an output as follows (video here):

baremetal-freeRTOS

5.3 Adding Linux to the Mix

Now, let's introduce a third VM running the Linux OS.

Init Setup

First, we can re-use our guests from the previous setup:

mkdir -p $BUILD_GUESTS_DIR/baremetal-linux-setup
cp $BAREMETAL_SRCS/build/qemu-riscv64-virt/baremetal.bin \
    $BUILD_GUESTS_DIR/baremetal-linux-setup/baremetal.bin

5.3.1 Build Linux Guest

Now let's start by building our linux guest. Setup linux environment variables:

export LINUX_DIR=$ROOT_DIR/linux
export LINUX_REPO=https://github.com/torvalds/linux.git
export LINUX_VERSION=v6.1

export LINUX_SRCS=$LINUX_DIR/linux-$LINUX_VERSION

mkdir -p $LINUX_DIR/linux-$LINUX_VERSION
mkdir -p $LINUX_DIR/linux-build

git clone $LINUX_REPO $LINUX_SRCS\
    --depth 1 --branch $LINUX_VERSION
cd $LINUX_SRCS
git apply $ROOT_DIR/srcs/patches/$LINUX_VERSION/*.patch

ℹ️ If you prefer to skip these steps and use a pre-built Linux image, execute the following commands and proceed to the next step.

mkdir -p $BUILD_GUESTS_DIR/baremetal-linux-setup
cp $PRE_BUILT_IMGS/guests/baremetal-linux-setup/linux.bin \
    $BUILD_GUESTS_DIR/baremetal-linux-setup/linux.bin

Setup an environment variable pointing to the target architecture and platform specific config to be used by buildroot:

export LINUX_CFG_FRAG=$(ls $ROOT_DIR/srcs/configs/base.config\
    $ROOT_DIR/srcs/configs/riscv64.config\
    $ROOT_DIR/srcs/configs/qemu-riscv64-virt.config 2> /dev/null)

Setup buildroot environment variables:

export BUILDROOT_SRCS=$LINUX_DIR/buildroot-riscv64-$LINUX_VERSION
export BUILDROOT_DEFCFG=$ROOT_DIR/srcs/buildroot/riscv64.config
export LINUX_OVERRIDE_SRCDIR=$LINUX_SRCS

Clone the latest buildroot at the latest stable version

git clone https://github.com/buildroot/buildroot.git $BUILDROOT_SRCS\
    --depth 1 --branch 2022.11
cd $BUILDROOT_SRCS

Use our provided buildroot defconfig, which points to the a Linux kernel defconfig and patches and build.

make defconfig BR2_DEFCONFIG=$BUILDROOT_DEFCFG
make linux-reconfigure all

mv $BUILDROOT_SRCS/output/images/Image\
    $BUILDROOT_SRCS/output/images/Image-qemu-riscv64-virt

The device tree for this setup is available in srcs/devicetrees/ qemu-riscv64-virt. For a device tree file named linux.dts define a environment variable and build:

export LINUX_VM=linux
dtc $ROOT_DIR/srcs/devicetrees/qemu-riscv64-virt/$LINUX_VM.dts >\
    $LINUX_DIR/linux-build/$LINUX_VM.dtb

Wrap the kernel image and device tree blob in a single binary:

make -j $(nproc) -C $ROOT_DIR/srcs/lloader\
    ARCH=riscv64\
    IMAGE=$BUILDROOT_SRCS/output/images/Image-qemu-riscv64-virt\
    DTB=$LINUX_DIR/linux-build/$LINUX_VM.dtb\
    TARGET=$LINUX_DIR/linux-build/$LINUX_VM

Finaly, copy the binary file to the (compiled) guests folder:

cp $LINUX_DIR/linux-build/$LINUX_VM.bin \
    $BUILD_GUESTS_DIR/baremetal-linux-setup/linux.bin

5.3.2 Welcome our new guest!

After building our new guest, it's time to integrate it into our setup.

First, we need to load our guests:

- VM_IMAGE(baremetal_image, XSTR(BAO_WRKDIR_IMGS/guests/baremetal-freeRTOS-setup/baremetal.bin));
+ VM_IMAGE(baremetal_image, XSTR(BAO_WRKDIR_IMGS/guests/baremetal-linux-setup/baremetal.bin));
+ VM_IMAGE(linux_image, XSTR(BAO_WRKDIR_IMGS/guests/baremetal-linux-setup/linux.bin));

Let's now update our VM list size to integrate our new guest:

-    .vmlist_size = 1,
+    .vmlist_size = 2,

Then, we need to rearrange the number of vCPUs:

    // baremetal configuration
    {
-       .cpu_num = 2,
+       .cpu_num = 1,
        ...
    },
    // linux configuration
    {
+       .cpu_num = 3,
    }

Additionally, you have the option to configure the Linux VM to integrate various devices and even memory regions. For specific details regarding this setup, refer to the the configuration file.

5.3.3. Let's rebuild Bao!

As we've seen, changing the guests includes changing the configuration file. Therefore, we need to repeat the process of building Bao using the following command:

make -C $BAO_SRCS\
    PLATFORM=qemu-riscv64-virt\
    CONFIG_REPO=$ROOT_DIR/configs\
    CONFIG=baremetal-linux\
    CPPFLAGS=-DBAO_WRKDIR_IMGS=$BUILD_GUESTS_DIR

Upon completing these steps, you'll find a binary file in the BAO_SRCS directory, called bao.bin. Move the binary file to your build directory (BUILD_BAO_DIR):

cp $BAO_SRCS/bin/qemu-riscv64-virt/baremetal-linux/bao.bin \
    $BUILD_BAO_DIR/bao.bin

5.3.4. Ready to Launch!

With all the necessary components in place, it's time to launch QEMU and see the results of your work. Let's proceed:

make -C $TOOLS_DIR/OpenSBI PLATFORM=generic \
    FW_PAYLOAD=y \
    FW_PAYLOAD_FDT_ADDR=0x80100000\
    FW_PAYLOAD_PATH=$BUILD_BAO_DIR/bao.bin

cp $TOOLS_DIR/OpenSBI/build/platform/generic/firmware/fw_payload.elf \
    $TOOLS_DIR/bin/opensbi.elf

qemu-system-riscv64 -nographic\
    -M virt -cpu rv64 -m 4G -smp 4\
    -bios $TOOLS_DIR/bin/opensbi.elf\
    -device virtio-net-device,netdev=net0 \
    -netdev user,id=net0,net=192.168.42.0/24,hostfwd=tcp:127.0.0.1:5555-:22\
    -device virtio-serial-device -chardev pty,id=serial3 -device virtconsole,chardev=serial3

To make the connection, open a fresh terminal window and establish a connection to the specified pseudoterminal. Here's how:

pyserial-miniterm --filter=direct /dev/pts/4

⚠️ Please be aware that the pts port may vary for each user. To find the correct pts port, kindly refer to the qemu output console.

After all, you should see an output as follows (video here):

baremetal-linux

5.4 Facilitating Guest Interaction

In specific scenarios, it's important for guests to establish a communication channel. To achieve this, we'll make use of a shared memory object and Inter-Process Communication (IPC) mechanisms, enabling the Linux VM to seamlessly interact with the system.

Init Setup

5.4.1. Add Shared Memory and IPC to our guest

Let's start by changin our baremetal to handle messages sent via IPC. We've prepared a patch that can be applied directly to the baremetal source code. To apply the changes, use the following command:

git -C $BAREMETAL_SRCS apply $PATCHES_DIR/baremetal_shmem.patch

Next, rebuild the baremetal:

make -C $BAREMETAL_SRCS PLATFORM=qemu-riscv64-virt

mkdir -p $BUILD_GUESTS_DIR/baremetal-linux-shmem-setup
cp $BAREMETAL_SRCS/build/qemu-riscv64-virt/baremetal.bin \
    $BUILD_GUESTS_DIR/baremetal-linux-shmem-setup/baremetal.bin

Now, let's integrate an IPC into Linux. For simplicity, the linux-shmem.dts file already includes the following changes.

+    bao-ipc@f0000000 {
+        compatible = "bao,ipcshmem";
+        reg = <0x0 0xf0000000 0x0 0x00010000>;
+		read-channel = <0x0 0x2000>;
+		write-channel = <0x2000 0x2000>;
+        interrupts = <0 52 1>;
+		id = <0>;
+    };

Now, let's generate the updated device tree:

export LINUX_VM=linux-shmem
dtc $ROOT_DIR/srcs/devicetrees/qemu-riscv64-virt/$LINUX_VM.dts >\
    $BUILD_GUESTS_DIR/baremetal-linux-shmem-setup/$LINUX_VM.dtb

⚠️ To correctly introduce these changes, you need to ensure that you applied the patch to Linux, as described before.

Bundle the kernel image and device tree blob into a single binary:

make -j $(nproc) -C $ROOT_DIR/srcs/lloader\
    ARCH=riscv64\
    IMAGE=$PRE_BUILT_IMGS/guests/baremetal-linux-shmem-setup/Image-qemu-riscv64-virt\
    DTB=$BUILD_GUESTS_DIR/baremetal-linux-shmem-setup/$LINUX_VM.dtb\
    TARGET=$BUILD_GUESTS_DIR/baremetal-linux-shmem-setup/$LINUX_VM

5.4.2. Rebuild Bao

Given that you've modified one of the guests, it's now essential to rebuild Bao. Thus, compile it using the following command:

make -C $BAO_SRCS\
    PLATFORM=qemu-riscv64-virt\
    CONFIG_REPO=$ROOT_DIR/configs\
    CONFIG=baremetal-linux-shmem\
    CPPFLAGS=-DBAO_WRKDIR_IMGS=$BUILD_GUESTS_DIR

Upon successful completion, you'll locate a binary file named bao.bin in the BAO_SRCS directory. Move it to your build directory (BUILD_BAO_DIR):

cp $BAO_SRCS/bin/qemu-riscv64-virt/baremetal-linux-shmem/bao.bin \
    $BUILD_BAO_DIR/bao.bin

5.4.3. Run Our Setup

Now, you're ready to execute the final setup:

make -C $TOOLS_DIR/OpenSBI PLATFORM=generic \
    FW_PAYLOAD=y \
    FW_PAYLOAD_FDT_ADDR=0x80100000\
    FW_PAYLOAD_PATH=$BUILD_BAO_DIR/bao.bin

cp $TOOLS_DIR/OpenSBI/build/platform/generic/firmware/fw_payload.elf \
    $TOOLS_DIR/bin/opensbi.elf

qemu-system-riscv64 -nographic\
    -M virt -cpu rv64 -m 4G -smp 4\
    -bios $TOOLS_DIR/bin/opensbi.elf\
    -device virtio-net-device,netdev=net0 \
    -netdev user,id=net0,net=192.168.42.0/24,hostfwd=tcp:127.0.0.1:5555-:22\
    -device virtio-serial-device -chardev pty,id=serial3 -device virtconsole,chardev=serial3

If all went according to plan, you should be able to spot the IPC on Linux by running the following command:

ls /dev

You'll see your IPC as follows (video here):

baremetal-linux-shmem

From here, you can employ the IPC on Linux to dispatch messages to the Baremetal by writing to /dev/baoipc0:

echo "Hello, Bao!" > /dev/baoipc0