← Back to Blog
RISC-V Development

OpenSBI Adds SpacemiT K3 Platform Support: 8 × X100 and 8 × A100 Harts with Mixed VLEN

RISC-V OpenSBI SpacemiT K3 X100 A100 HSM H-extension Linux-7.3

Published: 2026-09-16 · Category: RISC-V Development · Reading time: ~5 min · Status: DRAFT

A heterogeneous hart map

A patch series posted to the OpenSBI mailing list on 10 September 2026 adds basic platform initialisation and start-only HSM support for the SpacemiT K3. The cover letter states the topology plainly: the K3 has eight X100 harts and eight A100 harts across four clusters, and the two hart types are not ISA-identical.

That combination is the whole engineering problem. Most RISC-V firmware quietly assumes a homogeneous hart population: probe extensions once, pick a handler, apply it everywhere. On the K3, the vector length alone means a context-switch path sized for one hart type is wrong for the other, and the hypervisor extension is not even present on half of them. The series touches 21 files, 638 insertions and 153 deletions; the authors are Troy Mitchell (2 patches), Xianbin Zhu (3) and Valentin Haudiquet (1).

The per-hart expected-trap handler fix

The first generic change is the interesting one for anyone writing RISC-V firmware. OpenSBI selects an expected-trap handler — used when probing CSRs that may not exist — based on the cold-boot hart. If that hart implements H and another does not, the shared handler is wrong for one of them.

The fix moves the handler into per-hart scratch space and loads it directly, which also avoids an accessor call and its stack-protector instrumentation inside CSR probe paths. The scratch allocation alignment is preserved and the field is initialised before platform hooks run.

This is a small change with a large implication: per-hart state, not per-platform state, is the correct granularity for heterogeneous RISC-V parts. Expect more of this as vendors ship mixed core complexes.

Power: only hart 0 at reset

On the K3, only hart 0 is powered at reset. Secondary harts are started directly through the SoC PMU, and the HSM backend clears the requested hart's core and cluster power-down votes before waking it on demand.

An earlier revision of the series woke all harts during cold boot using WFI tables and a timeout. Version 3 removed that: secondary harts now start on demand from the K3 HSM callback. If you are debugging a K3 that appears to hang during boot, which revision of this series you are running changes the expected behaviour.

One boundary is drawn explicitly: RPMI support for the vendor kernel is out of scope, and the upstream Linux boot path does not depend on ESOS. Upstream Linux is not waiting on vendor firmware services here.

Boot ordering: PMA, cache and H-extension before warm entry

The K3 path performs PMA, cache and X100 H-extension setup before the common warm-boot entry, using the OpenSBI VMA and guest-translation fence helpers. Cold boot additionally programs the cluster reset vectors and enables CCI-550 snoop and DVM requests before any secondary hart starts.

The shared code between K1 and K3 is deliberately thin — common register definitions and the CCI-550 helper only. K1 keeps its own topology, boot flow and HSM behaviour. That is a reasonable split given how different the two parts are.

What was actually tested — and what was not

The author tested on a K3 COM260 with Linux v7.3-rc1, with only a v5 CPU PLL rate table patch applied, using the unmodified upstream k3-com260-ifx.dtb and a minimal initramfs. The board booted from SPI NOR using the public SDK's FSBL and U-Boot, with OpenSBI installed as a separate FIT.

Result: OpenSBI used the SDK's 16-hart device tree and booted on hart 0. Linux brought up the eight X100 harts described by its DT and reached a shell.

Two honest caveats in the same paragraph. The A100 harts were not brought up by Linux in this test — eight of sixteen harts, not sixteen. And the author did not reproduce a hang that Valentin Haudiquet had reported with Linux 7.2 and an eight-CPU kernel device tree. Build coverage is RV64 generic with CONFIG_STACK_PROTECTOR_ALL, plus RV32 generic with the SpacemiT objects excluded.

Reproducing it: the UART compatible trap

The cover letter documents a failure mode worth quoting, because it will cost someone an afternoon. OpenSBI relies on UART0's compatible ordering in k3.dtsi:

compatible = "spacemit,k1-uart", "intel,xscale-uart", "ns16550";

That order makes OpenSBI select UART_CAP_UUE and preserve UART_IER_UUE (bit 6). Match on "ns16550" alone and OpenSBI writes 0x00 to UART_IER — and serial output stops. If your K3 board boots silently, check this first.

The series also pins a full SDK v1.0.7 manifest set (manifests, scripts, U-Boot, ESOS and esos-lite) with specific commit hashes, and documents both fastboot entry paths.

Engineering takeaway

This is what upstream RISC-V enablement looks like when it is done properly: a stated topology, a named test board, a named kernel version, an unmodified device tree, and an explicit list of what did not work. If you are evaluating the K3 for a Linux product, the useful next question is not whether it boots — it is when the A100 harts and their 1024-bit vector units become usable from an upstream kernel, because that is where the part's AI capability lives.


Sources

Verification notes