K230 second-core feasibility
This source and boot-record audit includes a bounded physical CPU0 identity measurement recorded below. It does not claim that the second core can be enabled safely. The diagnostic firmware was restored; the normal kernel, device tree, OpenSBI, and stage 1 are unchanged.
Silicon and vendor architecture
Canaan’s primary documents describe two heterogeneous Xuantie C908 CPUs:
- K230 product datasheet, CPU subsystem: CPU0 is a 64-bit RISC-V core up to 800 MHz with 32 KiB L1 caches and 128 KiB L2; CPU1 is a 64-bit RISC-V core up to 1.6 GHz with RVV 1.0, 32 KiB L1 caches, and 256 KiB L2. The datasheet also documents separate CPU timers and a mailbox capable of CPU0/CPU1 interrupts.
- K230 power-management guide: the SDK’s documented split assigns CPU0 to Linux and CPU1 to RT-Smart; the large core also owns display, multimedia, and AI power domains.
- K230 SDK user manual: the SDK is organized as a Linux little-core side and an RT-Smart big-core side.
- K230 RVV description: confirms the C908 dual-core design and identifies RVV 1.0 as the large-core feature.
These documents establish hardware capability and the vendor SDK’s AMP design. They do not establish which physical core the current Xuantie Linux image uses, or that Linux can safely take the other core.
What the pinned image exposes
The pinned Linux source is nix/kernel-src.nix, from
ruyisdk/linux-xuantie-kernel revision
7d4e1f444f461dbe3833bd99a4640e7b6c2cd529. The evaluated source path was
/nix/store/hn11x8zd5linl193d8q0k9k99b46zqbm-linux-xuantie-k230-src.
arch/riscv/boot/dts/canaan/k230.dtsi:28-69 declares only cpu@0, with
reg = <0>, thead,c908, Sv39, and one cache description. There is no
cpu@1. Its PLIC at :210-218 references only cpu0_intc, and its CLINT at
:255-259 references only CPU0 software/timer interrupt lines.
The project image is the K230 Linux SDK/Xuantie Linux path, not a complete
Linux-plus-RT-Smart image. nix/stage1.nix:140-142 carries OpenSBI, its U-Boot
header, and the kernel-side boot files; it does not carry an RT-Smart payload.
nix/kernel.nix uses the vendor k230 kernel defconfig and sets SMP support,
but the DT presents one hart.
The boot-path comparison and
hardware userspace evidence record
nproc = 1 and only processor 0. Fresh physical evidence in
docs/evidence/cpu-readiness.txt records CONFIG_SMP=y, NR_CPUS=64,
RISCV_SBI=y, only CPU0 present/possible, live DT only cpu@0, and a Linux
hart reporting thead,c908, vector support, and a 256 KiB L2. That is
consistent with the datasheet’s big-core description, so it is unsafe to
label logical hart 0 as physical CPU0 or CPU1 without a register/firmware
observation.
The current boot transcript says:
Platform HART Count : 1
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 27000000Hz
Platform HSM Device : ---
Domain0 HARTs : 0*
[ 0.015...] smp: Brought up 1 node, 1 CPU
See docs/evidence/boot-from-source-cold.txt:104-125,230-231. The source
and logs establish one enumerated HART, not the physical-core identity and not
that RT-Smart is running on the other core in this image.
OpenSBI and SMP barriers
The official OpenSBI README
and official SBI HSM specification
describe HSM hart start/stop/status calls required for normal Linux multi-hart
boot. In the pinned OpenSBI source
/nix/store/k6kih6q1vh5nashsgaz96ch012742s8z-source,
lib/sbi/sbi_ecall_hsm.c:19-67 implements the HSM SBI calls and
lib/sbi/sbi_init.c:98-100 prints Platform HSM Device. That line reports a
platform-specific HSM device pointer; --- is not proof that the SBI HSM
extension is absent. The current log proves only that one HART was enumerated
and assigned to the root domain.
Adding a cpu@1 node alone is therefore insufficient:
- Physical mapping and ownership are unknown. The current carried image has no RT-Smart payload. The SDK’s CPU0/Linux, CPU1/RT-Smart mapping is a reference architecture, not proof for this image. The live hart’s RVV and L2 size make big-core execution plausible, but no source or current log maps logical hart 0 to a physical core. Display, multimedia, KPU, mailbox, and power-domain ownership must be established separately.
- HART discovery and start: OpenSBI must enumerate a second unique hart,
assign it to Linux, and provide a valid hart-start path. The current
/chosen/opensbi-domainsnode (k230.dtsi:21-26) does not describe a second-HART domain or ownership contract. - Interrupts and timers: the K230 DTS PLIC and CLINT target CPU0 only. CPU1 needs verified local interrupt, software/timer interrupt, and K230 timer/IPI wiring. The datasheet mailbox proves an inter-core mechanism, but not a Linux SBI IPI implementation.
- ISA and MMU: CPU1 has RVV 1.0 and a different cache topology. Linux needs an accurate CPU1 ISA/MMU/cache description and a common ISA baseline for SMP code.
- Coherency and shared memory: the repository has no proof of the cache coherency contract needed for Linux shared page tables and SMP atomics. This must be established from the K230 programming/reference material or a controlled firmware experiment before any Linux shared-memory test.
Options
The lowest-risk option is to leave this single-hart Linux image unchanged. The vendor SDK’s AMP split is a separate reference architecture; this image contains no RT-Smart payload, and its physical-core mapping and peripheral ownership remain unknown.
A Linux SMP option needs a coordinated patch family, not one DTS edit:
- DT CPU1 with verified hart ID, ISA, MMU, cache, local interrupt, and timer data;
- PLIC/CLINT or K230 interrupt-controller support for both harts;
- OpenSBI domain and hart-start support with generic HSM calls verified;
- kernel SMP bring-up with common-ISA handling; and
- an ownership decision for display, multimedia, KPU, mailbox, and power domains after removing the current single-hart/SDK assumptions.
An AMP Linux-plus-RT-Smart option would require adding and validating the RT-Smart payload and its ownership contract. It is not evidence about this image, and no ready Linux-side API for it is present here.
Minimal recoverable experiment
Do not experiment on the only working card. Preserve the current image and use a second card or reversible UMS image. Before attempting Linux SMP or shared memory:
- Establish the physical-to-hart map and ownership from the K230 reference manual and a controlled firmware/register observation. Confirm unique hart IDs, reset release, interrupt/timer routes, cache hierarchy, and the coherency/atomic-sharing contract.
- Only then prepare an experimental DT with CPU1 and those verified descriptions; do not infer routes from the CPU count.
- Generic SBI HSM is already compiled and detected in this image
(
docs/evidence/boot-from-source-cold.txt:173). Investigate whether the verified second hart can use OpenSBI’s existing raw-IPI start path or needs a platform HSM start device, then build a variant that enumerates it. Retain the Canaan MAEE quirk and a rollback image. TreatPlatform HSM Device: ---as informational, not as the acceptance test. - Boot with early serial logging and require HART count 2, Linux
smp: Brought up 1 node, 2 CPUs, and successful CPU status checks. Stop on any hang, missing HART, or interrupt/timer failure. Only after that test shared-memory/cache behavior and peripheral ownership. - Restore the known-good stage-1/kernel image over the proven UMS path after any failed experiment.
This would prove only that Linux can start a uniquely identified second hart after the coherency and ownership prerequisites are established. It would not prove RT-Smart AMP operation, display ownership, or the full vendor SDK. No board experiment was run for this audit.
2026-09 evidence update and decision
The primary K230 Technical Reference Manual v0.3.1 (TRM) resolves part of the physical mapping which the earlier audit deliberately left open. Section 1.3.2 identifies CPU0 as the 800 MHz/128 KiB-L2 small core and CPU1 as the 1.6 GHz/256 KiB-L2 RVV big core. Section 1.4.1 says BootROM starts CPU0 after reset deassertion and CPU0 controls CPU1 reset deassertion. That establishes reset ownership, but it does not assign Linux hart IDs or describe a Linux secondary-hart release protocol.
The current Linux hart reports RVV and a 256 KiB L2 while the TRM assigns both
features to CPU1. This makes CPU1 execution a strong inference for the
current Linux handoff. It remains an inference, not a basis to add a guessed
cpu@1: the physical-core-to-hart mapping is not in the captured handoff.
What the vendor register map proves—and does not
The TRM provides real CPU1 controls:
- RMU is at
0x91101000;CPU1_RST_CTLis offset0x0c. Its reset value is0x00002001; bit 0 iscpu1_reset_req(one means reset). Bit 4 requests an L2 flush and bits 12—13 are write-one-to-clear reset-done flags (TRM section 2.1.4). - PWR is at
0x91103000; CPU1 control/status are offsets0x18/0x1c(TRM section 2.3.4). The CPU power-flow text requires a completed NOC low-power handshake before a power transition (section 2.3.3). - The interrupt table lists distinct mailbox sources in both CPU0-to-CPU1 and CPU1-to-CPU0 directions (TRM section 2.4).
Those facts rule out a speculative register poke: a write would be an actual reset or power transition, and reads of the W1C-containing reset register must not be turned into read-modify-write operations. The TRM does not publish a CPU1 reset vector, physical hart ID, PLIC context mapping, ACLINT wiring, or an SBI HSM implementation for this device.
It also does not establish the condition Linux SMP actually needs: coherent
shared memory for page tables, spinlocks, and secondary-start data. The
existing DT’s dma-noncoherent property concerns DMA; it neither proves nor
disproves CPU-to-CPU cache coherence. The TRM describes per-C908 cache control
and an instruction-cache/data-cache snoop control, but contains no CPU0/CPU1
coherency or shared-atomic contract. This is a blocking absence of evidence,
not a demonstrated hardware impossibility.
Linux SMP is a different project from AMP
The pinned Linux code makes the integration requirements concrete. Its
cpu_ops_sbi.c
starts a secondary with SBI_EXT_HSM_HART_START; its
cpu.c
requires a valid ISA description for each DT CPU; and the K230 DTS supplies
only one CPU interrupt controller to its PLIC and CLINT. Therefore Linux SMP
needs a verified second hart, HSM start path, timer/IPI routes, CPU ISA/MMU and
cache description, and coherency contract before a DT change is even useful.
AMP has a different boundary: separate firmware images, mailbox notifications, explicitly managed shared buffers, and exclusive peripheral ownership. Canaan documents separate Linux little-core and RT-Smart big-core SDK images, which is evidence for an AMP model, not for Linux SMP. This image has neither the RT-Smart payload nor a Linux-side video-offload protocol, so AMP cannot yet improve the running video workload. A second core can help video only after a measured offload design exists; two cores alone do not improve a single-thread renderer or prove shared-memory safety.
Proposed safe next step: passive handoff audit
No boot configuration, device tree, CPU online state, or MMIO register is changed by this proposal. The integration operator should collect the following from a known-good board when it is free; this investigation does not take the serial device.
- Preserve a cold-boot console capture containing OpenSBI platform HART
count, domain HART list, HSM/IPI/timer device lines, and Linux’s
smp:result. This separates a firmware one-hart declaration from a Linux secondary-start failure. - Capture the live
cpusDT subtree, PLIC/CLINTinterrupts-extended,/sys/devices/system/cpu/{possible,present,online}, and per-CPU ISA/cache reports. These no-write facts identify the handoff Linux actually received. - Only with the operator’s established read-only MMIO capture method,
record values at
0x9110100c,0x91103018, and0x9110301c. Do not use a tool mode that writes, performs read-modify-write, clears W1C status, or probes adjacent registers. These values may show reset/power state; they cannot establish hart identity or coherency. - Obtain a Canaan statement or shipped stage-1 source proving the CPU1 release sequence and vector, physical hart IDs, PLIC/ACLINT contexts, and CPU-to-CPU coherency contract. An undocumented release sequence is a stop condition.
Only after step 4 should a separate rollback-card SMP proposal exist. It must
first make OpenSBI enumerate and HSM-start both verified harts, then add the
complete DT routes, then enable Linux SMP. Its acceptance criteria begin with
two OpenSBI harts, smp: Brought up 1 node, 2 CPUs, timer/IPI stress, and a
shared-memory atomic test. Video benchmarking comes after correctness, not
before it. No board experiment was performed for this update.
Vendor AMP source establishes a release contract, not SMP support
A further source review found the vendor’s concrete Linux-to-RT-Smart AMP path
in k230-amp.c
and its amp_test
client. This is primary vendor source, but it is not part of this NixOS image.
The client opens /dev/k230-amp, maps a device-tree-selected RT-Smart memory
region, loads a firmware image there, then invokes AMP_CMD_BOOT. The driver
writes that region back from the running Linux CPU’s cache, programs the CPU1
reset-vector register, and performs the CPU1 reset-control writes. Mapping the
region first holds the large core in reset. The companion README calls this
“small-core Linux controls big-core restart”. That is direct evidence that the
vendor AMP boundary requires an explicit firmware payload, memory reservation,
cache maintenance, reset vector, and reset protocol.
It does not establish Linux SMP. The driver hardcodes vendor addresses and does not create a Linux CPU, an OpenSBI domain, a PLIC/ACLINT route, or shared Linux page-table coherency. Its actual reset writes are why this project will not use it as a probe or copy it into the image.
The vendor’s generic OpenSBI platform independently counts harts by iterating
/cpus in platform/generic/platform.c.
The pinned handoff supplies only cpu@0, so the observed OpenSBI platform
count of one follows from the handoff description. OpenSBI’s generic HSM ecall
handler being linked only means it can dispatch HART_START for an assigned,
known hart; it does not manufacture CPU1 release support.
The publicly documented DRAM RAW/WAR coherency guarantees apply to the memory controller interfaces and are conditional on configuration for AXI. They are not a documented CPU0/CPU1 cache-coherency or atomic-sharing contract. This remains a blocker for Linux SMP, while the AMP source shows cache maintenance must be part of any separately designed shared-buffer protocol.
2026-09-26 pinned stage-1 audit: Linux runs on physical CPU1
The exact stage-1 source pinned by nix/k230-sdk-src.nix is Canaan’s
k230_linux_sdk revision 1104236db4d1e47873bd68924f912747b820228c.
nix/uboot-k230.nix copies its U-Boot overlay into the built source and uses
k230_canmv_v3_defconfig. In that overlay,
board/canaan/common/sdk_autoconf.h:16 defines
CONFIG_LINUX_RUN_CORE_ID 1; board/canaan/common/k230_img.c:53 includes
the header. Its k230_boot_uboot_uimage() branch at lines 276-284 calls
de_reset_big_core(image_get_load(pUh)) and parks the current core in wfi.
The release function at lines 149-170 writes CPU1’s reset-vector register
0x91102104, then performs the documented CPU1_RST_CTL sequence at
0x9110100c. board/canaan/common/k230_spl.c:164-166 selects the U-Boot
on-big-core path for the same configuration. This is shipped stage-1 source
for a physical CPU1 release, and the live hart’s RVV/256 KiB-L2 observation
corroborates it. The extra core we want is physical CPU0, the 800 MHz
non-RVV core.
This does not prove the physical CPU0 hart ID. The same U-Boot overlay’s
arch/riscv/dts/k230.dtsi:46-57 calls the single described, vector-capable
hart cpu@0, gives it reg = <0>, and lists 800 MHz. That contradicts the
physical CPU1 profile and shows the device-tree label/clock cannot be used as
a physical-core map. The physical mhartid values of both CPUs require a
direct, controlled firmware observation or a Canaan statement. U-Boot’s
arch/riscv/cpu/k230/cpu.c:125-160 also has a boot_baremetal path whose
CPU0 branch writes 0x91102100 and 0x91101004; it demonstrates a physical
CPU0 reset vector/release address but does not set up OpenSBI, interrupts,
timers, cache sharing, or Linux SMP.
There is stronger, adverse evidence about the hart map: in the Linux K230
DTS review, the patch
author reports that the physical big core’s CSR.MHARTID is 0, despite its
physical CPU1 name. A QEMU K230 board author reporting the physical
topology
states that both physical cores have mhartid 0. These are first-hand
developer reports, not a measurement on this board, but they directly
undermine the assumed unique-hart-ID prerequisite of conventional SBI HSM
and Linux SMP. They must be tested on a disposable board experiment before
any design assigns the extra core reg = <1>. If the collision is confirmed,
the existing SMP release option cannot proceed as written; AMP with a
separate CPU0 payload and explicit shared-memory protocol is the plausible
way to execute a workload on the extra physical core.
The pinned Linux tree at revision
7d4e1f444f461dbe3833bd99a4640e7b6c2cd529 has an internal SBI HSM
hart-status call in arch/riscv/kernel/cpu_ops_sbi.c:52-63, but its only
caller is the CPU hotplug cpu_is_stopped path at lines 107-119. The
read-only source search
rg -n 'sbi_hsm|hart_status|debugfs' <pinned-src>/arch/riscv found no
Linux userspace/debugfs passthrough that queries an unenumerated hart’s
HSM status without CPU up/down. That says the proposed Linux-side query is
unavailable in this pinned tree; it says nothing about whether firmware can
answer the ecall.
The pinned K230 Linux DTS still names only one PLIC/ACLINT target. Neither the pinned stage-1 overlay nor its OpenSBI generic-platform overlay defines a CPU0 PLIC context and ACLINT timer/IPI route for a joint Linux handoff. Thus task 3.1 is partly closed (physical CPU0 vector and release source) but remains blocked on the physical hart ID and interrupt topology. No reset, power, or vector write was performed in this audit.
2026-09-26 Linux SMP path audit (physical CPU0 is the target)
The requested outcome is one Linux kernel scheduling ordinary processes on
both physical cores. A separate CPU0 heartbeat or AMP payload cannot
satisfy it. the-small-core-runs-a-recoverable-heartbeat is suspended after
that scope correction. Pinned stage 1 (k230_img.c:276-285) already starts
physical CPU1 and leaves CPU0 in WFI; Linux is on CPU1. The remaining
physical core to bring into the same kernel is CPU0.
The pinned OpenSBI 1.4 generic platform is not ready for two physical cores
that report the same mhartid:
platform/generic/platform.c:95-132collects DT CPUreginto its hart-index-to-ID table.lib/utils/fdt/fdt_helper.c:263-284confirms thatregis the ID it reads.include/sbi/riscv_asm.h:166definescurrent_hartid()as a read ofCSR_MHARTID;lib/sbi/sbi_scratch.c:24-32resolves a hart ID to the first matching index.firmware/fw_base.S:441-462readsCSR_MHARTIDon warm entry and picks the first matching hart index before setting its M-mode scratch and stack. Thus duplicate IDs would reuse the boot hart’s stack/scratch, not merely produce an incorrect display name.lib/sbi/sbi_hsm.c:300-361indexes target scratch/HSM state by hart ID, then sends a raw IPI to that target index. A duplicate ID cannot identify CPU0 as a separate HSM target. Linux’sarch/riscv/kernel/smpboot.c:149-170also treats the boot hart’s ID as unique and skips a DT CPU with the samereg; itscpu_ops_sbi.c:66-80sendsSBI_EXT_HSM_HART_STARTusing the mapped ID.
The K230 QEMU author
reports that both physical cores read mhartid=0. The
Linux DTS author reports
that physical CPU1 reads 0 and says inter-core cache coherence is unknown.
These are firsthand reports, not measurements on this board. A fake
cpu@1 node would be unsafe even if a two-CPU DT compiled. A K230-specific
virtual ID would need an early physical-core discriminator and consistent
use in OpenSBI warm entry, scratch, domain, HSM, IPI, timer, and Linux
handoff. No such implementation exists in the pinned vendor overlay:
platform/generic/thead/thead-generic.c only applies C908 errata and PMU
setup. A grep for another physical core-ID CSR in the pinned U-Boot and
OpenSBI overlays found no defined candidate. This is an audited absence
within those overlays, not proof that the silicon has no such CSR.
The narrowest next physical identity measurement is source-reachable at an
already executing point. The optional, default-off patch
nix/patches/second-core/spl-cpu0-identity.patch reads mhartid and
misa in CPU0 SPL immediately before its existing CPU1 release, prints
them, and leaves the release/WFI behavior untouched. CPU1’s existing
OpenSBI boot banner reports its logical ID; an equivalent M-mode CPU1
readout would settle both physical CSR values. This diagnostic is not a
second program or a Linux feature. It still requires a separately reviewed
experimental stage-1 build and the board operator’s recovery/serial
session; it does not justify a reset write or SMP boot by itself.
The pinned Linux DT arch/riscv/boot/dts/canaan/k230.dtsi:210-218,255-259
supplies PLIC and CLINT routes only to its single CPU interrupt controller.
The vendor OpenSBI overlay has no CPU0-specific PLIC/ACLINT mapping for a
joint handoff. U-Boot’s CSR_SMPEN write in
arch/riscv/cpu/k230/cpu.c:39-49 is not a CPU0/CPU1 cache-coherence
contract: the pinned source does not define its semantics or show an
inter-core cache test. The vendor AMP driver cache-flushes shared data, so
initial Linux shared page tables and locks cannot safely be the first
coherence experiment. A controlled pre-Linux atomic/cache and timer/IPI
diagnostic or a Canaan contract must close those gates before any two-CPU
Linux boot. Once closed, the first Linux SMP image should use a scalar
common ISA across kernel and userspace; RVV can return only with a proven
per-hart scheduling and userspace capability design.
Canaan’s public small-core Linux
DT
at src/little/linux/arch/riscv/boot/dts/kendryte/k230.dtsi:18-63
separately describes physical CPU0 as its sole logical cpu@0, with PLIC
at 0xf00000000 and CLINT at 0xf04000000, each wired only to that one
local interrupt controller. This public main source was read during the
2026-09-26 audit but is not this project’s pinned SDK revision and is
not a combined two-core DT. The matching base addresses in the pinned
big-core DT do not establish whether the hardware maps separate PLIC/
CLINT instances into per-core address spaces or exposes usable second
contexts to one joint Linux image. It cannot justify inventing a second
interrupts-extended entry.
2026-09-27 physical CPU0 identity measurement
The default-off CPU0 SPL diagnostic was run on the board and its two raw
SPL slots were restored byte-for-byte afterward. The
physical trial
recorded CPU0_SPL_IDENTITY mhartid=0x0 misa=0x800000000094112f
before the existing CPU1 release, followed by
one-hart OpenSBI and one-CPU Linux. The restored image then booted normally.
This turns the pinned source’s physical CPU0 identity sampling point
into a first-hand mhartid=0 observation. Source tracing also resolves
what the CPU1-side Boot HART ID : 0 means. The pinned OpenSBI 1.4
include/sbi/riscv_asm.h:166 defines current_hartid() as
csr_read(CSR_MHARTID). Canaan’s pinned overlay
lib/sbi/sbi_init.c:534 assigns that value to hartid, :394 passes it
to sbi_boot_print_hart(), and :169 prints Boot HART ID from it.
The pinned stage-1 k230_img.c:276-285 releases CPU1 into this boot
path while CPU0 parks; the observed 256 KiB L2/RVV profile corroborates
that physical assignment. Therefore the board’s CPU1-side banner is
also a first-hand CSR read of zero, with its physical attribution grounded
in the stage-1 source. No new CPU1-specific marker was added.
Both physical cores reporting hardware mhartid=0 rules out a DT-only
second CPU node under this generic OpenSBI’s current scratch/HSM indexing.
A safe virtual-ID scheme or other supported two-hart mapping, CPU0
interrupt/timer routing, and the shared cached-memory/atomic contract
remain open before any Linux SMP attempt.
TRM mailbox register map (task 1.1, 2026-10-12)
Result: the TRM publishes a mailbox register map. It is in TRM section
2.9 “Mailbox”, not section 2.4. Section 2.4 is “Interrupt System”
(PDF page 104); earlier text here and in
openspec/changes/the-small-core-runs-as-a-coprocessor/ that attributed the
mailbox to “section 2.4” meant only the interrupt table, which names the
mailbox interrupt sources. The map below is read from the primary document;
nothing is inferred from th1520-mailbox.c.
Source: K230 Technical Reference Manual v0.3.1 (2024-11-18), the URL linked
above, downloaded 2026-10-12 (SHA-256
4a18fdbd1cd25c5a33ca4d54b78c95e0e338305bceb17397133370fa10c1e5f0) and
text-extracted with pdftotext -layout. The PDF is not stored in the repo or
the Nix store (the repo keeps no vendor documents); PDF page numbers below are
physical page indexes of that file. Section 2.9 starts at PDF page 172; the
register descriptions run through page 185.
-
Base:
0x9110_4000, 4 KiB, block namemailboxin the SoC address map (TRM section 1 address table). Lives inside SYSCTL; APB 3.0, 32-bit registers, clocked bymailbox_pclk(100 MHz). Clock gate:mailbox_pclk_enable, bit 4 of the CMU register at offset 0x50 (PDF page 55;docs/research/k230-clock-gates-vendor-vs-mainline.md:109lists the same0x50/4). Reset: bit 17mailbox_resetin the RMUSOC_CTL_RST_CTLregister (PDF page 18, reset value 0x1). Mainlinereset-k230.calready names this asRST_MAILBOX(offset 0x20, bit 17, software-done type); no mainline K230 mailbox driver or DT node exists (grep -i mailbox k230.dtsiin the mainline tree finds none). -
Function (2.9.1): hardware interlock (mutex) registers for CPU0/CPU1 hand-shake and shared-storage arbitration, mutual interrupts, and some submodule configuration/status registers.
-
Four interrupt-group register sets (groups 0-3), each ten 32-bit registers (five per direction); group 0 in full, groups 1-3 repeat it at the offsets below:
Offset Register Meaning 0x0000 CPU2DSP_INT_EN0 cpu0_sys to cpu1_sys enable. bits 31:16 intr_raw_en; bit 1intr_soft_rstclears all counts (both directions); bit 0intr_en0x0004 CPU2DSP_INT_SET0 write-only; writing N (0..15) adds 1 to interrupt count N 0x0008 CPU2DSP_INT_CLEAR0 write-only; writing N subtracts 1 from count N 0x000C CPU2DSP_INT_STATUS0 read-only; 2-bit count for each of 16 sources (bits 1:0 = source 0 … 31:30 = source 15) 0x0010 CPU2DSP_INT_ERR0 read-only; 31:16 overflow flags (count already 3), 15:0 underflow flags 0x0014 DSP2CPU_INT_EN0 cpu1_sys to cpu0_sys, same fields 0x0018 DSP2CPU_INT_SET0 same as above 0x001C DSP2CPU_INT_CLEAR0 same as above 0x0020 DSP2CPU_INT_STATUS0 same as above 0x0024 DSP2CPU_INT_ERR0 same as above 0x0028-0x009C *_INT_*1,*2,*3groups 1-3, same layout, each group is 0x28 bytes (CPU2DSP block at 0x28/0x50/0x78, DSP2CPU block at 0x3C/0x64/0x8C) 0x00A0-0x029C MAILBOX0..MAILBOX127 128 interlock registers; bit 0 Lock(1 locked, 0 not), RW, reset 00x02A0-0x02F8 UART_LP_REQ_, QOS_CTRL0-4, NOC_WR_BUFFERABLE_CTRL, DDR_, MIPI_TX_BISTON, SSI_SLEEP, PVDET_*, OTP_HS_MSC_SEL, DDRC_SELFREF_TYPE, CODEC_AD2DA_LOOP, TIMER_EN unrelated SYSCTL configuration registers that share the block; a mailbox driver must not touch them -
Interrupt sources (TRM section 2.4 table, PDF page 104 onward):
MB_CPU12CPU0_0= bit 93,MB_CPU12CPU0_1= bit 94,MB_CPU02CPU1_0= bit 95,MB_CPU02CPU1_1= bit 96. Only two interrupt lines exist per direction although four register groups are listed; which groups drive which line is not stated in the sections read.
What this does not establish (kept UNVERIFIED):
- Which register group maps to which of the two interrupt lines per
direction; whether the
intr_raw_enbits gate individual sources and howintr_encomposes with them (the TRM text is a machine-translation with several truncated cells). - Whether the lock registers are test-and-set on read or a plain RW bit; the TRM only says “1: locked, 0: not locked” (2.9.1 says hardware mutual exclusion but gives no read-to-acquire semantics). No driver may rely on a guess.
- That CPU0 firmware can take the interrupt: CPU0’s PLIC wiring and the mailbox line routing to it are not in this document. The cache/coherency situation of the interlock registers is moot (device registers), but the shared data buffers remain under the non-coherent contract in design.md Decision 3.
- Nothing here was exercised on the board. A mailbox driver or firmware that touches these registers needs its own task and board proof; the change keeps using a polled shared-memory slot until then.
Cross-check, naming only: drivers/mailbox/th1520-mailbox.c also has
per-direction status/set/clear groups, but the K230 counters (two bits per
source, 16 sources) and the 128 interlock registers are K230’s own and are
not borrowed from it.