# Kendryte K230 virt reference platform (`k230`)

The `k230` machine is compatible with the Kendryte K230 SDK.

The K230 is a chip from the AIoT SoC series made by Kendryte ® — a part of Canaan Inc. It uses a brand-new multi-heterogeneous unit accelerated computing structure.

This chip has 2 RISC-V computing cores and a new-generation KPU (Knowledge Process Unit) smart computing unit.

For more information, see <https://www.kendryte.com/en/proDetail/230>

## Supported devices

The `k230` machine supports the following devices:

- 1 c908 cores (little core)

- Core Local Interruptor (CLINT)

- Platform-Level Interrupt Controller (PLIC)

- 2 K230 Watchdog Timer

- 5 UART

## Boot options

The `k230` machine supports K230 SDK boot through M-mode U-Boot, which then starts OpenSBI/Linux with `bootm`. It also supports direct Linux boot.

K230 SDK Linux kernels use T-HEAD C9xx private MAEE page table attributes. QEMU does not implement MAEE in the generic RISC-V MMU, so such kernels need to be built with standard RISC-V PTE bits before they can boot under QEMU.

## Running

### Direct Linux boot

This flow lets QEMU load OpenSBI, Linux, initrd, and DTB directly, without running SDK U-Boot. The Linux Image must be rebuilt with standard RISC-V PTE bits before running under QEMU.

    $ SDK=k230_sdk/output/k230_canmv_defconfig
    $ qemu-system-riscv64 -machine k230 \
       -kernel "$SDK/images/little-core/Image" \
       -dtb "/tmp/user-k230-qemu.dtb" \
       -initrd "$SDK/images/little-core/rootfs.cpio.gz" \
       -append "console=ttyS0,115200 earlycon=sbi cma=0" \
       -nographic

Direct boot uses the SDK little-core RAM layout for OpenSBI at `0x08000000`, Linux at `0x08200000`, and the DTB at `0x0a000000`. The initrd is placed by QEMU’s generic RISC-V boot helper, and QEMU writes the initrd range and kernel command line into `/chosen`. The DTB passed with `-dtb` should be derived from `$SDK/images/little-core/k230.dtb` and must describe that initrd location as usable memory and disable any devices that are not emulated by this machine.

### U-Boot boot

This flow starts SDK U-Boot in M-mode with `-bios`. Until the SDK storage path is modeled, place OpenSBI, Linux, initrd, and DTB in RAM with loader devices and run `bootm` manually. The Linux Image must be rebuilt with standard RISC-V PTE bits before running under QEMU.

    $ SDK=k230_sdk/output/k230_canmv_defconfig
    $ IMAGE=$SDK/images/little-core/Image
    $ INITRD=$SDK/images/little-core/rootfs.cpio.gz
    $ DTB=$SDK/images/little-core/k230.dtb
    $ FWJUMP_UIMAGE=/tmp/k230-fw-jump.uImage
    $ INITRD_END=$(printf "0x%x" $((0x0a100000 + $(stat -c %s "$INITRD"))))
    $ "$SDK/little/buildroot-ext/host/bin/mkimage" \
       -A riscv -O linux -T kernel -C none \
       -a 0x8000000 -e 0x8000000 -n opensbi \
       -d "$SDK/images/little-core/fw_jump.bin" "$FWJUMP_UIMAGE"
    $ qemu-system-riscv64 -machine k230 \
       -bios "$SDK/little/uboot/u-boot" \
       -device loader,file="$FWJUMP_UIMAGE",addr=0xc100000,force-raw=on \
       -device loader,file="$IMAGE",addr=0x8200000,force-raw=on \
       -device loader,file="$INITRD",addr=0xa100000,force-raw=on \
       -device loader,file="$DTB",addr=0xa000000,force-raw=on \
       -nographic

The loader addresses mirror the SDK `k230_canmv_defconfig` output. Read the U-Boot addresses from the generated environment, and read the Linux RAM base from the generated `hw/k230.dts.txt`. This replaces the SDK storage and decompression steps.

Press Enter to stop autoboot. At the U-Boot prompt, run these commands:

    K230# setenv bootargs console=ttyS0,115200 earlycon=sbi cma=0
    K230# fdt addr 0xa000000
    K230# fdt resize 8192
    K230# fdt set /chosen linux,initrd-start <0x0 0xa100000>
    K230# fdt set /chosen linux,initrd-end <0x0 ${INITRD_END}>
    K230# fdt set /soc/sdhci0@91580000 status disabled
    K230# fdt set /soc/sdhci1@91581000 status disabled
    K230# bootm 0xc100000 - 0xa000000

Use `setenv` so `bootm` writes the kernel command line into `/chosen/bootargs`. The `fdt` commands select the loaded DTB, add space for edits, describe the initrd range in `/chosen`, and disable SDHCI nodes because this machine does not emulate those controllers yet. Replace `${INITRD_END}` with the host-calculated value above when typing the command. `cma=0` avoids the SDK kernel reserving too much of the little-core memory window for initramfs boot.