Bringing Bao to RVA23 Silicon

Bringing Bao to RVA23 Silicon

Linux + FreeRTOS on the Banana Pi BPI-SM10

João Peixoto, Bao Maintainer, OSYX Technologies | 13 min read | September 22, 2026

A practical look at mixed-criticality partitioning on RISC-V, using the Hypervisor extension and AIA available on the RVA23-compliant SpacemiT K3.

The Banana Pi BPI-SM10 gives the Bao community something particularly interesting to work with: an RVA23-class RISC-V platform with the Hypervisor extension and Advanced Interrupt Architecture (AIA) available on real silicon.

In this post we bring up Bao on the BPI-SM10, built around the SpacemiT K3, and use it to run Linux and FreeRTOS side by side.

The result is a reproducible mixed-criticality setup in which Linux handles networking and general-purpose workloads while FreeRTOS runs independently on a dedicated hart with ownership of the serial console.

BPI-SM10 Overview

The BPI-SM10 (K3-CoM260) is a RISC-V Computer-on-Module and reference carrier board from Banana Pi built around the SpacemiT K3. Its general-purpose compute side includes:

  • 8x X100 64-bit RISC-V application cores at up to 2.4 GHz
  • 2 clusters of 4 X100 cores
  • 4 MB shared L2 cache per cluster
  • 64 KB instruction cache and 64 KB data cache per X100 core
  • RVA23 compliance
  • RISC-V Vector extension (RVV) 1.0 with VLEN=256
  • 8/16/32 GB LPDDR5 at 6400 MT/s

The SoC also includes 8x A100 AI compute cores, rated at 60 TOPS, with RVV 1.0 and VLEN=1024. These AI cores are separate from the X100 application cores used by Bao in the demo described here.

From a virtualization point of view, the X100 harts are the most relevant part of the platform. They implement the RISC-V Hypervisor (H) extension, the Advanced Interrupt Architecture (AIA), and the Sstc extension for timer support.

One of the first RVA23-compliant RISC-V platforms

The SpacemiT K3 is among the first wave of RISC-V silicon to provide RVA23 compliance, bringing the latest application-processor profile to commercially available hardware. This makes the BPI-SM10 an interesting platform for evaluating virtualization and mixed-criticality workloads directly on silicon.

The carrier board exposes:

  • 2x MIPI CSI-2 camera connectors
  • M.2 Key M with PCIe Gen3 x4/x1
  • M.2 Key E
  • 4x USB 3.0 Type-A
  • USB Type-C UFP
  • Gigabit Ethernet
  • DisplayPort 1.2
  • MIPI DSI
  • 40-pin header with UART, SPI, I2S, I2C, and GPIO

Its footprint is compatible with the NVIDIA Jetson Orin Nano form factor, which also makes the board interesting for developers evaluating RISC-V in systems that already use that carrier format.

A Quick Note on Bao

Bao is a lightweight, open-source static partitioning hypervisor designed for strong isolation and predictable execution.

Instead of scheduling virtual CPUs dynamically, Bao statically assigns CPUs, memory regions, devices, and interrupts to virtual machines at configuration time. In its core partitioning model, Bao deliberately avoids:

  • Runtime CPU scheduling
  • Runtime memory allocation
  • A full device-emulation layer
  • A privileged Linux management VM

Isolation is enforced using hardware virtualization mechanisms. On RISC-V systems with the H extension, this includes second-stage (G-stage in the RISC-V terminology) address translation together with hardware-assisted interrupt virtualization.

For mixed-criticality systems, this model gives each guest a fixed resource budget and removes scheduler interference between partitions.

Bao is developed by the community-driven Bao Project and released under the Apache 2.0 license.

OSYX is the industry-facing entity behind the Bao Project, providing commercial support, platform bring-up, system integration, and long-term maintenance for mixed-criticality designs.

What We Built

The BPI-SM10 demo runs two isolated guests:

  • Linux: SpacemiT’s vendor kernel, built through buildroot, providing networking and general-purpose functionality
  • FreeRTOS: running real-time tasks on a dedicated hart and owning the board’s serial console

The board exposes a single UART suitable for the console. Because a statically partitioned device belongs to one VM, UART0 is assigned to FreeRTOS. Linux therefore runs headless and is accessed through Ethernet using SSH.

Tested software configuration

  • Board: Banana Pi BPI-SM10 (K3-CoM260) module and reference carrier
  • Bao hypervisor: feat/plat-spacemit-k3
  • bao-demos: feat/k3-com260
  • Linux: SpacemiT vendor 6.18 kernel through buildroot
  • bao-drivers: linux-v6.18
  • U-Boot and OpenSBI: SpacemiT trees pinned to k3-br-v1.0.0

Technical demonstration

This is a technical demonstration rather than a production-ready integration. It covers platform bring-up, static partitioning, boot flow, device assignment, and inter-VM communication. Production deployments require additional hardening, validation, and, where applicable, certification work.

Resource partitioning

The demo uses four of the eight X100 application harts:

  • Hart 0: Linux
  • Hart 1: Linux
  • Hart 2: Linux
  • Hart 3: FreeRTOS
  • Harts 4 to 7: left unassigned and available for further partitions or experiments

Linux receives 1 GiB of RAM and the Ethernet-related device chain. FreeRTOS receives 128 MiB of RAM and UART0. A 64 KiB shared-memory region, together with a doorbell interrupt, provides a controlled IPC channel between the two VMs.

Linux owns three harts and the Ethernet device chain. FreeRTOS owns one hart and UART0. The only resource crossing the boundary is the configured shared-memory region.

Resource VM 1 (Linux) VM 2 (FreeRTOS)
Harts 0, 1, 2 (cpu_affinity = 0x7) 3 (cpu_affinity = 0x8)
RAM base 0x180000000 (place_phys) 0x0
RAM size 1 GiB 128 MiB
Devices gmac1, syscon_apbc, syscon_apmu, pinctrl, gpio UART0
Device interrupts 133, 277, 60, 58 42
Interrupt controller APLIC 0xe0804000, IMSIC 0xe0400000 APLIC 0xe0804000, IMSIC 0xe0400000
IPC shmem base 0xf0000000 0xf0000000
IPC shmem size 64 KiB 64 KiB
IPC interrupt 52 52
Network Ethernet with DHCP No
Console SSH UART0

The platform uses the RISC-V AIA for interrupt handling. On the K3 this includes an Advanced Platform-Level Interrupt Controller (APLIC) and an Incoming Message-Signaled Interrupt Controller (IMSIC).

Bao configures these resources once during initialization. After that, each guest executes on its assigned harts with its own memory and devices.

Ethernet Passthrough

Passing a device to a statically partitioned guest is often difficult than assigning one MMIO region and one interrupt. The K3 Ethernet controller is a good example.

Assigning gmac1 to Linux is not enough to produce a working network interface. The driver also depends on several other hardware blocks:

  • syscon_apbc: clock and reset related control
  • syscon_apmu: clock and reset related control
  • pinctrl: configuring the RGMII and MDIO pads
  • gpio: driving the Ethernet PHY reset line

In a conventional Linux system, the kernel can simply reach these provider devices through the normal device tree and driver framework. In a statically partitioned system, however, the Linux VM cannot access hardware that Bao has not explicitly assigned to it. That means the partition has to include the full dependency chain required by the device.

Linux VM
   |
   +-- GMAC1
   |
   +-- syscon_apbc  -> clocks / reset
   +-- syscon_apmu  -> clocks / reset
   +-- pinctrl      -> RGMII / MDIO muxing
   +-- GPIO         -> PHY reset

The lesson from the K3 bring-up

Device passthrough is not only about the endpoint device. It is about every hardware resource the guest driver needs in order to operate it. The same pattern applies when adding other peripherals to a partitioned system.

Two additional details are worth noting:

  1. The Linux memory region uses place_phys, meaning the guest sees the region at the same physical addresses used by the host.
  2. Only half of the X100 application cores are currently assigned, leaving four harts available for another VM.

From BootROM to Bao: the K3 Boot Chain

The K3 boot flow is more interesting than a conventional “U-Boot loads the hypervisor” sequence. The BootROM and secondary boot stages expect firmware components at fixed offsets on the SD card rather than discovering everything through a filesystem.

The Bao platform build therefore produces a complete sdcard.img containing:

  • A GPT
  • An ext4 bootfs partition
  • bao.itb
  • boot.scr
  • Firmware components written to the raw locations expected by the K3 boot process

boot-chain

Every stage before Bao is fixed by the K3 boot process. Bao configures harts, G-stage translation, devices, AIA routing, and the IPC channel, then hands control to both guests.

At that point:

  • FreeRTOS starts on hart 3, owns UART0, and begins executing tasks
  • Linux starts on harts 0 to 2, initializes Ethernet, and becomes reachable over SSH
  • Both systems continue executing independently without CPU scheduling interaction

K3 Platform Bring-up Notes

A few details of the port are specific enough to the platform that they are worth documenting for anyone adapting Bao to another K3 carrier board or BSP.

1. Pin the boot firmware

The boot firmware is generated from the SpacemiT U-Boot tree and includes u-boot.itb, the default environment, the FSBL, and the boot-info block. OpenSBI is built separately as fw_dynamic.itb.

The demo pins both to the k3-br-v1.0.0 tag instead of following the tip of the development branch. This avoids regressions such as exceeding the SPL size limit.

2. Use FIT images

U-Boot on this board does not accept legacy uImages for this flow. Bao and the boot script are therefore delivered as Flattened Image Tree (FIT) images.

The vendor bootcmd normally supports grub or a raw kernel boot. For the Bao flow, the environment is replaced using mkenvimage so that U-Boot sources boot.scr and enters Bao automatically.

3. Adjust the Linux vendor kernel

The Linux VM uses SpacemiT’s vendor 6.18 kernel built through the stock buildroot flow. The configuration adds the pieces needed for:

  • K3 SoC support
  • Clock control
  • pinctrl
  • GPIO
  • AIA
  • GMAC
  • 8250 UART support

One additional patch removes the vendor SBI dcache-flush calls. Under Bao, those ecalls are handled by the hypervisor rather than by the vendor firmware path, and the vendor configuration gating around them otherwise breaks the link.

These are exactly the kind of platform-specific details that are easy to miss when moving a hypervisor from an architectural model to real hardware.

Linux and FreeRTOS Communication

The two guests communicate only through a deliberately configured IPC channel:

  • 64 KiB shared memory
  • Mapped at 0xf0000000 in both guests
  • Doorbell interrupt: IRQ 52

On Linux, the bao-drivers IPC module exposes the channel as:

/dev/baoipc0

To send data from Linux to FreeRTOS:

echo "Hello from Linux" > /dev/baoipc0

FreeRTOS receives the message and prints it on the serial console alongside its normal task output. FreeRTOS can write data back into the same IPC channel, which Linux reads using:

cat /dev/baoipc0

This gives the two VMs a controlled communication path without sharing scheduling or devices. Because Linux is headless in this configuration, the IPC channel is also a natural way to expose FreeRTOS state to applications reachable through the network.

Build the Demo

The demo lives in bao-project/bao-demos:

  • Platform: k3-com260
  • Demo: linux+freertos
  • Branch: feat/k3-com260

Dependencies

The K3 platform requires three packages in addition to the standard bao-demos dependencies, because the build assembles the final SD-card image.

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 xilinx-bootgen file cpio \
    device-tree-compiler gdisk e2fsprogs

pip3 install pykwalify packaging pyelftools

Build

Set the RISC-V toolchains:

export CROSS_COMPILE=/path/to/riscv64-unknown-elf/bin/riscv64-unknown-elf-
export OPENSBI_CROSS_COMPILE=/path/to/toolchain/bin/riscv64-unknown-linux-gnu-

Clone the demos repository:

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

Select the platform and demo, then build:

export PLATFORM=k3-com260
export DEMO=linux+freertos

make -j$(nproc)

A single build invocation fetches and builds the complete software stack: OpenSBI, SpacemiT U-Boot, buildroot, the SpacemiT vendor Linux kernel, FreeRTOS, Bao, and the final sdcard.img. The buildroot stage dominates the first build.

Start with bare metal when bringing up a new board

If you are adapting the K3 support to another board or carrier, start with:

export DEMO=baremetal

The bare-metal configuration runs one guest across all eight X100 harts with 64 MiB of RAM at 0x102000000 and UART0 passed through directly. This gives you a simple way to validate the boot chain, Bao entry, hart initialization, memory configuration, and UART passthrough before introducing Linux, AIA device dependencies, or a second VM.

Deploy

Write the generated sdcard.img to a microSD card and boot the board. The platform makefile prints the target image path and the corresponding dd command after the build. The same process is documented in platforms/k3-com260/README.md.

Boot demonstration showing Linux and FreeRTOS starting under Bao on the BPI-SM10.

After boot:

  • FreeRTOS output is available over UART0
  • Linux obtains networking through DHCP
  • Linux is accessed over SSH
  • IPC is available through /dev/baoipc0

Things to Experiment With

The current demo intentionally leaves room for expansion.

Add another VM/partition

Only four of the eight X100 harts are currently used. Harts 4 to 7 can therefore be assigned to:

  • Another Linux guest
  • Another RTOS
  • A bare-metal workload
  • An isolated service partition

This makes the BPI-SM10 a useful platform for experimenting with more complex static-partitioning topologies.

Change the resource map

The Bao configuration can be modified in demos/linux+freertos/configs/k3-com260.c. Useful experiments include:

  • Moving harts between partitions
  • Changing RAM sizes
  • Assigning additional peripherals
  • Creating a third VM
  • Changing the IPC layout

Add more devices

The Ethernet bring-up is a useful template. For each new device, identify not only the MMIO regions and interrupts, but also all dependent resources needed by the guest driver: clocks, resets, pinctrl, GPIO, and IOMMU or DMA-related resources where applicable.

Evaluate interference

The current setup establishes the architectural isolation boundary. A natural next step is to characterize:

  • Interrupt latency
  • IPC latency
  • Execution-time jitter
  • Cache interference
  • Memory-system interference

Bao also supports techniques such as cache partitioning through cache coloring, which can be evaluated when tighter interference control is required. For a deeper analysis of static partitioning and mixed-criticality systems, see Shedding Light on Static Partitioning Hypervisors for Arm-based Mixed-Criticality Systems.

Where Next?

Linux and FreeRTOS are one pairing. The same partitioning model also hosts:

  • Multiple Linux guests, including Android-based guests
  • Zephyr, NuttX, and RT-Thread

When two guests need the same peripheral, Bao uses VirtIO: one VM owns the device and shares it with the others over shared memory.

For a minimal starting point, see bao-helloworld and our own walkthrough, Hello, Bao!.

Conclusion

The BPI-SM10 is a particularly interesting platform for Bao because it combines a modern RISC-V application processor, RVA23-class functionality, the Hypervisor extension, and AIA-based interrupt handling on real hardware.

The demo presented here shows the complete path from the K3 boot chain to two isolated guests: Linux for networking and general-purpose workloads, FreeRTOS for deterministic real-time execution, and Bao for static resource partitioning and hardware-enforced isolation.

More importantly, the bring-up exposes the details that matter when moving virtualization from an architectural specification to a real SoC: boot firmware constraints, interrupt-controller integration, device dependency chains, vendor-kernel assumptions, and explicit resource ownership.

For developers evaluating RISC-V for mixed-criticality systems, the BPI-SM10 provides a practical platform to explore those mechanisms directly on silicon.