Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Portability and continuous integration

The portable v1 promise is enforced by .github/workflows/ci.yml. This file is the source of truth for required checks; the table below explains why each job exists.

The minimum supported Rust version (MSRV) is 1.85.0. Rust 1.85 is the first release supporting the Rust 2024 edition selected by the workspace. Every package inherits the same rust-version.

CI matrix

JobToolchain and targetsContract enforced
style-and-apiCurrent stable on UbuntuFormatting, complete normative-requirement ledger, release-policy invariants, Clippy with warnings denied, and warning-free public docs
native-testCurrent stable on Ubuntu, macOS, and WindowsAll workspace unit, integration, target, feature, and documentation tests, runnable examples, and release-profile checking
openvino-host-testCurrent stable on Ubuntu with a pinned Intel OpenVINO runtimeThe real (probed) OpenVINO backend: lint, unit, integration, semantic-conformance, and example runs against the CPU plugin
vulkan-lavapipe-testCurrent stable on Ubuntu with the Mesa lavapipe ICD pinnedThe native Vulkan 1.3 backend: lint, unit, integration, semantic-conformance, the shared FP32 operator corpus, and example runs without allowing a placeholder skip
msrvRust 1.85.0 on UbuntuEvery workspace target and test continues to compile at the declared MSRV
portable-targetStable aarch64-unknown-none, riscv64gc-unknown-none-elf, and wasm32-unknown-unknowncleanroom, proto, transport, and core remain no_std; guest, split-queue, device, and facade layers require at most alloc; Wasm also checks the std reference crates
feature-sets-and-dependenciesStable on UbuntuEvery Cargo feature combination plus dependency and std/alloc leakage guards for the portable codecs, queue ports, and core
dependency-policyCargo-deny with Rust 1.85.0Advisories, yanked crates, duplicate versions, wildcard requirements, licenses, and dependency sources
fuzz-smokePinned nightly on UbuntuShared harness tests plus bounded smoke iterations over generated seed corpora and committed minimized regressions for every fuzz target
publish-dry-runStable on UbuntuEvery published crate packages in documented order into an isolated local registry, and each one builds, tests, and documents from its own extracted tarball rather than from the workspace

The native jobs intentionally use GitHub-hosted *-latest images so runner security and supported host versions advance without changing the project’s semantic target list. Release evidence records the concrete runner versions used for the release.

Crate portability tiers

Every crate below is published to crates.io, so its tier is a promise to downstream users rather than an internal convention: a crate may not move to a less-portable tier without the release-note entry and portability review required by release-policy.md. The std-reference tier is the ceiling for the reference and conformance crates, not a licence for host-OS or vendor-specific APIs — third parties depend on virtio-accel-conformance and virtio-accel-mock directly, and they must keep working on any platform the portable crates support.

TierCratesAllowed runtime surface
core-onlyvirtio-accel-cleanroom, virtio-accel-proto, virtio-accel-transport, virtio-accel-corecore; the clean-room codec and transport ports have no normal/build dependencies, while proc-macros used by other crates may execute with std on the build host
alloc-portablevirtio-accel-guest, virtio-accel-split-queue, virtio-accel-device, virtio-accel-tosa, virtio-accel-tosa-build, virtio-accelcore + alloc; no OS, filesystem, sockets, threads, or host synchronization
std-referencevirtio-accel-mock, virtio-accel-conformancePortable std; no host-OS or vendor-specific API
host-nativevirtio-accel-coreml, virtio-accel-openvino, virtio-accel-hexagon, virtio-accel-xdna, virtio-accel-vulkanCore ML/Foundation on macOS 14+, the OpenVINO C runtime (libopenvino_c 2026.x), the complete QAIRT/QNN C SDK on Windows ARM64, the amdxdna-native HRX runtime (libhrx), or a dynamically loaded Vulkan loader (via ash) on the build.rs-enumerated host targets; a compile-only unsupported-platform or unsupported-runtime placeholder elsewhere

No host-native crate is a dependency of the facade or any portable layer. The Core ML crate’s Objective-C bridge and TOSA-to-Core ML model compilation are built only when the Cargo target is macOS. The Linux, Windows, and Wasm workspace jobs compile the placeholder API and backend-local lowering utilities, while the macOS native job executes its real model and semantic-conformance tests. An accessible Apple Neural Engine is required to construct the real backend; macOS runners without one skip execution after checking that availability through Core ML.

The OpenVINO crate’s boundary is a build environment rather than a target operating system: its build script probes pkg-config for openvino and compiles the native FFI modules only on success. VIRTIO_ACCEL_OPENVINO=1 turns a missing runtime into a loud build failure, =0 forces the placeholder, and VIRTIO_ACCEL_OPENVINO_LIB_DIR links installations that ship no pkg-config metadata. The default native-test runners have no OpenVINO and compile the placeholder plus the portable TOSA-to-IR encoder; the dedicated openvino-host-test job installs a pinned runtime and exercises the real backend against the CPU plugin. NPU and GPU devices additionally require the Intel Level Zero NPU driver or the Intel OpenCL/Level Zero GPU runtime on the host; hosts without an inference device skip execution after enumeration.

The Hexagon crate exercises its SDK-free placeholder and strict FP16/BOOL/INT32 plus INT8 TOSA graph planner in portable CI. Its parity test compares the real Core ML/OpenVINO 42-operator surface and allowlists only ERF; portable fixtures lower every other shared operator without QAIRT. Its build script distinguishes a complete public QAIRT/QNN development installation from driver-only and AppBuilder/Genie bundles by requiring QnnInterface.h and the Windows ARM64 QnnHtp import library. VIRTIO_ACCEL_HEXAGON=0 forces the placeholder; VIRTIO_ACCEL_HEXAGON=1 makes missing requirements a build failure; VIRTIO_ACCEL_QNN_SDK_ROOT/QNN_SDK_ROOT and VIRTIO_ACCEL_QNN_LIB_DIR select the SDK. On the pinned Windows ARM64 hardware tier, backend-local tests execute numerical fixtures for all 41 advertised operators plus INT8 identity and zero-point-aware INT8 MATMUL through QNN HTP, followed by the reusable semantic suite. A public hardware CI lane remains unavailable, so the README publishes the exact manual replacement commands.

The AMD XDNA crate compiles its portable admission surface (lower, including the TOSA IDENTITY, MATMUL, MAX_POOL2D, explicit FP8-to-BF16 CAST, and exact INT8 IDENTITY/MATMUL/RESCALE admissions and its advertised Target constants), the portable precompiled-artifact codec, and a placeholder on every host; portable CI unit-tests admission. HRX exposes a plain C ABI, so its build script has no cc/CMake step; it enables the native modules (HRX FFI and the Accelerator implementation with its serialized dispatch worker) only when an amdxdna-native HRX prefix (VIRTIO_ACCEL_HRX_DIR/HRX_DIR) carries both HRX headers — the amdxdna header must declare hrx_amdxdna_executable_create, whose absence marks an older, incompatible libhrx generation — and lib/libhrx.so. VIRTIO_ACCEL_XDNA=0 forces the placeholder, VIRTIO_ACCEL_XDNA=1 makes a missing or incomplete runtime a build failure, and VIRTIO_ACCEL_HRX_LIB_DIR links a bare lib directory. No standard locations are scanned, keeping the runtime pin authoritative. On Unix, the bounded compiler-helper subprocess and compile_artifact remain available without HRX for offline catalog population; they require only the separately pinned VIRTIO_ACCEL_AMDXDNA_TOOLCHAIN. On the reference machine with that toolchain and an NPU, backend-local tests run a DMA passthrough, a compiled TOSA BF16 IDENTITY, a bit-exact BF16 → FP32 MATMUL, BF16 NHWC MAX_POOL2D against the shared bit-exact oracle, both FP8E4M3/E5M2 → BF16 CASTs against shared bit-exact oracles, and the shared exact INT8 identity, nonzero-zero-point MATMUL, and signed INT32-to-INT8 RESCALE oracles, plus the shared semantic conformance suite end to end; compilation invokes the aiecc helper as a bounded subprocess (never a Cargo dependency). The conformance run includes provider-resource accounting and direct-binding diagnostics; a feature-gated on-metal fault suite proves definite device loss, the 120-second tier-2 watchdog state machine with a shortened test deadline, rejected pending releases, stable terminal polling, and nonblocking poisoned-instance discard. MAX_POOL2D mirrors OpenVINO’s propagating-NaN and zero-padding semantics, but XDNA admission is deliberately narrower: batch 1, kernel and stride dimensions at most 8, and at most 8,192 input-plus-output elements so the full tensors fit in the AIE2P worker’s local memory. A public hardware CI lane remains unavailable. The INT8 capability preserves OpenVINO’s exact CONST/IDENTITY/MATMUL semantic baseline and adds RESCALE as a documented operator-surface expansion. The expansion uses released TOSA semantics and is needed to return an INT32 accumulator to signed INT8 without host arithmetic; XDNA admits only per-tensor scale32/SINGLE_ROUND forms proven against the shared exact oracle. An XDNA-specific one-core memory envelope still applies. AIE DMA’s four-byte transfer granularity is represented as explicit per-slot padding in the compiled artifact, never as hidden submission-time staging. Tile-compatible MATMUL shapes widen/subtract zero points on the NPU and use the native 4x4x8 INT16 matrix unit; smaller shapes and exact 64-bit RESCALE arithmetic use scalar on-NPU kernels. RESCALE clears the at-most-three-byte padded output tail on the NPU.

The Vulkan crate binds Vulkan 1.3 through the pinned ash crate and executes admitted TOSA graphs on crate-authored SPIR-V compute kernels specialized at load_program; the admitted tier is the FP32 operator set shared with Core ML and OpenVINO, executed graph-at-a-time (ADR 0007). Unlike the SDK-probing backends, there is nothing to detect at build time — ash loads the platform’s Vulkan loader dynamically at run time — so the va_vulkan cfg enumerates the host target operating systems (Linux, Android, Windows, macOS) and runtime loader or device absence surfaces as InitError. VIRTIO_ACCEL_VULKAN=0 forces the placeholder everywhere; VIRTIO_ACCEL_VULKAN=1 makes an unsupported target a loud build failure; unset is auto (ADR 0002 in docs/adr/). Buffers are dedicated allocations bound directly as storage buffers; Host and Shared domains are persistently mapped host-coherent memory, Device is device-local memory reached only through bounded staging inside the explicit transfer calls (ADR 0005). The dedicated vulkan-lavapipe-test job forces the native build, requires an enumerated device, and pins Mesa’s software ICD before running Clippy, all Vulkan tests, and the example. This keeps the run deterministic while ensuring loader discovery and the real Vulkan lifecycle execute in CI.

Concrete VMM, kernel, OS, and vendor adapters are outside the portable-v1 milestone and must not become default dependencies of a portable crate.

Cargo feature policy

CI runs cargo hack check --feature-powerset --no-dev-deps across the workspace. Features must be additive: disabling default features may remove convenience behavior but must not select a different protocol interpretation.

The portable dependency guard inspects normal and build target features for virtio-accel-cleanroom, virtio-accel-proto, virtio-accel-transport, and virtio-accel-core, virtio-accel-guest, virtio-accel-split-queue, and virtio-accel-tosa; test-only development dependencies are intentionally outside the target runtime graph. It additionally proves that the clean-room codec and transport ports have no normal or build dependencies at all. A dependency’s host-side derive macro may use std, but the target graph for these crates must not enable a dependency feature named std or alloc.

The official FlatBuffers runtime uses a pure-Rust build script with rustc_version and semver to detect the compiler. Those host-only dependencies use std; the guard checks the TOSA crate’s normal target graph separately and still forbids a std or alloc dependency feature there.

Dependency policy

deny.toml permits only crates.io dependencies and the workspace’s path dependencies. It rejects:

  • known advisories and yanked releases;
  • unmaintained direct workspace dependencies;
  • unsound dependencies;
  • multiple resolved versions of the same crate;
  • wildcard version requirements; and
  • licenses outside Apache-2.0, BSD-2-Clause, MIT, and Unicode-3.0.

GitHub Actions are pinned to immutable commit SHAs with their human-readable release versions kept in comments. Standalone CI tools are pinned too: cargo-hack 0.6.45, cargo-fuzz 0.13.2 on nightly-2026-07-13, and cargo-deny 0.20.2 (bundled by the pinned cargo-deny action).

Local verification

The host-independent checks can be reproduced with:

cargo fmt --all -- --check
python3 ci/check-normative-requirements.py --check
python3 ci/check-release-policy.py
cargo clippy --workspace --all-targets --all-features -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps
cargo test --workspace --all-targets --all-features
cargo test -p virtio-accel-device --test state_model
cargo test --workspace --doc --all-features
cargo run --example backend_conformance
cargo run --example reference_execution
cargo run -p virtio-accel-coreml --example tosa_coreml
cargo run -p virtio-accel-openvino --example tosa_openvino
cargo run -p virtio-accel-hexagon --example tosa_hexagon
cargo run -p virtio-accel-hexagon --example mock_classifier
cargo +1.85.0 check --workspace --all-targets --all-features
cargo hack check --workspace --feature-powerset --no-dev-deps
bash ci/check-portable-dependencies.sh
cargo deny --all-features check

The ordered publication dry run needs network access the first time, to vendor third-party dependencies into its local registry:

python3 ci/publish-dry-run.py

Add --keep to inspect the registry and the extracted per-crate sources afterwards.

Deeper deterministic state-model exploration can be run manually with:

VIRTIO_ACCEL_STATE_MODEL_SEED=9e3779b97f4a7c15 cargo test -p virtio-accel-device --test state_model deep_generated_object_graphs_match_the_reference_model -- --ignored

Fuzz smoke coverage can be reproduced with:

cargo test --manifest-path fuzz/Cargo.toml --lib --no-default-features
python3 ci/seed-fuzz-corpus.py
cargo fuzz run protocol_decode fuzz/corpus/protocol_decode fuzz/regressions/protocol_decode -- -runs=256 -max_total_time=20 -timeout=5 -rss_limit_mb=2048 -max_len=65536
cargo fuzz run descriptor_end_to_end fuzz/corpus/descriptor_end_to_end fuzz/regressions/descriptor_end_to_end -- -runs=256 -max_total_time=20 -timeout=5 -rss_limit_mb=2048 -max_len=65536
cargo fuzz run stateful_commands fuzz/corpus/stateful_commands fuzz/regressions/stateful_commands -- -runs=256 -max_total_time=20 -timeout=5 -rss_limit_mb=2048 -max_len=65536
cargo fuzz run guest_client fuzz/corpus/guest_client fuzz/regressions/guest_client -- -runs=256 -max_total_time=20 -timeout=5 -rss_limit_mb=2048 -max_len=65536
cargo fuzz run tosa_parse fuzz/corpus/tosa_parse fuzz/regressions/tosa_parse -- -runs=256 -max_total_time=20 -timeout=5 -rss_limit_mb=2048 -max_len=65536

Target checks require the corresponding Rust standard libraries:

rustup target add aarch64-unknown-none riscv64gc-unknown-none-elf wasm32-unknown-unknown
cargo check \
  -p virtio-accel-cleanroom \
  -p virtio-accel-proto \
  -p virtio-accel-transport \
  -p virtio-accel-core \
  -p virtio-accel-device \
  -p virtio-accel-guest \
  -p virtio-accel-split-queue \
  -p virtio-accel-tosa \
  -p virtio-accel \
  --target aarch64-unknown-none \
  --no-default-features