Development and Tooling

Relevant source files

This document covers the development infrastructure, build configuration, testing framework, and tooling used to develop and maintain the RISC-V VCPU hypervisor system. It includes details on the CI/CD pipeline, dependency management, code generation tools, and documentation workflow.

For information about the core VCPU implementation, see Core VCPU Implementation. For details about system architecture components, see System Architecture.

Build System and Dependencies

The RISC-V VCPU system uses Cargo as its primary build system with a carefully curated set of dependencies that provide RISC-V architecture support, hypervisor functionality, and low-level register manipulation capabilities.

Package Configuration

The project is configured as a Rust library crate targeting the 2024 edition with the package name riscv_vcpu version 0.1.0. The build system is designed specifically for bare-metal RISC-V environments without standard library support.

Dependency Architecture

flowchart TD
subgraph subGraph4["riscv_vcpu Implementation"]
    vcpu_lib["riscv_vcpu Library"]
end
subgraph subGraph3["ArceOS Framework Dependencies"]
    axerrno["axerrno:0.1.0Error Handling"]
    page_table_entry["page_table_entry:0.5Page Table Management"]
    memory_addr["memory_addr:0.3.1Memory Addressing"]
    axaddrspace["axaddrspaceAddress Space Management"]
    axvcpu["axvcpuVCPU Abstractions"]
end
subgraph subGraph2["SBI and Hypervisor Support"]
    rustsbi["rustsbi:0.4.0SBI Implementation"]
    sbi_rt["sbi-rt:0.0.3SBI Runtime"]
    sbi_spec["sbi-spec:0.0.7SBI Specifications"]
end
subgraph subGraph1["RISC-V Architecture Support"]
    riscv_crate["riscvCore RISC-V Support"]
    riscv_decode["riscv-decodeInstruction Decoding"]
    tock_registers["tock-registers:0.8.1Register Abstractions"]
    memoffset["memoffsetMemory Layout"]
end
subgraph subGraph0["Core Dependencies"]
    log["log:0.4.19Logging Framework"]
    cfg_if["cfg-if:1.0Conditional Compilation"]
    bitflags["bitflags:2.2Flag Types"]
    bit_field["bit_field:0.10Bit Manipulation"]
    crate_interface["crate_interface:0.1Interface Definitions"]
end

axaddrspace --> vcpu_lib
axerrno --> vcpu_lib
axvcpu --> vcpu_lib
bit_field --> vcpu_lib
bitflags --> vcpu_lib
cfg_if --> vcpu_lib
crate_interface --> vcpu_lib
log --> vcpu_lib
memoffset --> vcpu_lib
memory_addr --> vcpu_lib
page_table_entry --> vcpu_lib
riscv_crate --> vcpu_lib
riscv_decode --> vcpu_lib
rustsbi --> vcpu_lib
sbi_rt --> vcpu_lib
sbi_spec --> vcpu_lib
tock_registers --> vcpu_lib

Sources: Cargo.toml(L6 - L26) 

Key Dependency Categories

CategoryCratesPurpose
RISC-V Coreriscv,riscv-decode,tock-registersProvide RISC-V instruction set support, instruction decoding, and register manipulation primitives
SBI Interfacerustsbi,sbi-rt,sbi-specImplement Supervisor Binary Interface for guest OS communication
ArceOS Integrationaxaddrspace,axvcpu,axerrnoInterface with the ArceOS hypervisor framework
Low-Level Utilitiesbitflags,bit_field,memoffsetProvide bit manipulation and memory layout tools

CI/CD Pipeline

The continuous integration pipeline ensures code quality, compatibility across Rust toolchains, and automated documentation deployment using GitHub Actions.

Pipeline Architecture

flowchart TD
subgraph subGraph3["Documentation Pipeline"]
    doc_build["cargo docDocumentation Generation"]
    doc_deploy["GitHub PagesDocumentation Deployment"]
end
subgraph subGraph2["Quality Checks"]
    fmt_check["cargo fmt --checkCode Formatting"]
    clippy_check["cargo clippyLinting Analysis"]
    build_check["cargo buildCompilation Test"]
    unit_test["cargo testUnit Testing"]
end
subgraph subGraph1["CI Job Matrix"]
    toolchain1["nightly-2024-12-25riscv64gc-unknown-none-elf"]
    toolchain2["nightlyriscv64gc-unknown-none-elf"]
end
subgraph subGraph0["Trigger Events"]
    push["Push Events"]
    pr["Pull Requests"]
end

doc_build --> doc_deploy
pr --> toolchain1
pr --> toolchain2
push --> toolchain1
push --> toolchain2
toolchain1 --> build_check
toolchain1 --> clippy_check
toolchain1 --> doc_build
toolchain1 --> fmt_check
toolchain1 --> unit_test
toolchain2 --> build_check
toolchain2 --> clippy_check
toolchain2 --> fmt_check
toolchain2 --> unit_test

Sources: .github/workflows/ci.yml(L1 - L65) 

CI Configuration Details

The pipeline runs two primary jobs: ci for code quality and testing, and doc for documentation generation and deployment.

Code Quality Matrix

The CI system tests against multiple Rust toolchain versions to ensure compatibility:

  • Primary Toolchain: nightly-2024-12-25 (stable reference)
  • Latest Toolchain: nightly (forward compatibility)
  • Target Architecture: riscv64gc-unknown-none-elf (bare-metal RISC-V 64-bit)

Quality Gates

StageCommandPurposeFailure Handling
Format Checkcargo fmt --all -- --checkEnforce consistent code formattingHard failure
Lintingcargo clippy --target riscv64gc-unknown-none-elf --all-featuresStatic analysis and best practicesContinue on error for nightly
Buildcargo build --target riscv64gc-unknown-none-elf --all-featuresCompilation verificationContinue on error for nightly
Unit Testscargo test --target x86_64-unknown-linux-gnuFunctional testingHard failure

Sources: .github/workflows/ci.yml(L20 - L32) 

Documentation Workflow

The documentation pipeline automatically generates and deploys API documentation to GitHub Pages for the default branch.

flowchart TD
subgraph subGraph1["Deployment Pipeline"]
    gh_pages["GitHub PagesBranch: gh-pages"]
    auto_deploy["JamesIves/github-pages-deploy-action"]
end
subgraph subGraph0["Documentation Generation"]
    source["Source Codewith Doc Comments"]
    cargo_doc["cargo doc--no-deps --all-features"]
    index_gen["Index Page Generation"]
end

auto_deploy --> gh_pages
cargo_doc --> index_gen
index_gen --> auto_deploy
source --> cargo_doc

Sources: .github/workflows/ci.yml(L34 - L64) 

The documentation build includes strict linting with RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs to ensure documentation completeness and link integrity.

Code Generation and Register Definitions

The system employs sophisticated code generation techniques to create type-safe register definitions for RISC-V Control and Status Registers (CSRs).

Register Definition Architecture

flowchart TD
subgraph subGraph2["Runtime Usage"]
    csr_access["CSR Read/WriteOperations"]
    type_safety["Compile-timeType Safety"]
    field_manipulation["BitfieldManipulation"]
end
subgraph subGraph1["Generated CSR Definitions"]
    csr_constants["CSR Address ConstantsCSR_HSTATUS: 0x600"]
    register_structs["Register Structshstatus::Register"]
    field_definitions["Field Definitionsspv, vsxl, vtvm"]
    field_values["Field Value EnumsUser, Supervisor"]
end
subgraph subGraph0["Register Definition Generator"]
    tock_registers["tock-registersMacro Framework"]
    register_bitfields["register_bitfields!Macro Invocation"]
end

csr_constants --> csr_access
field_definitions --> field_manipulation
field_values --> field_manipulation
register_bitfields --> csr_constants
register_bitfields --> field_definitions
register_bitfields --> field_values
register_bitfields --> register_structs
register_structs --> type_safety
tock_registers --> register_bitfields

Sources: def.rs(L1 - L1910) 

CSR Definition Structure

The register definitions follow a hierarchical pattern:

  1. CSR Address Constants: Hexadecimal addresses for each CSR register
  2. Register Modules: Type-safe wrappers for each register
  3. Field Definitions: Bit field specifications with masks and offsets
  4. Value Enumerations: Named constants for field values

Example Register Definition Pattern

The hstatus register demonstrates the complete pattern:

// CSR address constant
pub const CSR_HSTATUS: u16 = 0x600;

// Register module with fields
pub mod hstatus {
    pub struct Register;
    
    // Field definitions with bit positions
    pub const spv: Field<usize, Register> = Field::new(mask, offset);
    
    // Field value enumerations  
    pub mod spv {
        pub enum Value {
            User = 0,
            Supervisor = 1,
        }
    }
}

Sources: def.rs(L37 - L881) 

Generated Register Coverage

Register CategoryExamplesPurpose
Supervisor CSRsCSR_SSTATUS,CSR_SIE,CSR_SATPGuest supervisor mode state
Virtual Supervisor CSRsCSR_VSSTATUS,CSR_VSIE,CSR_VSATPVirtualized supervisor state
Hypervisor CSRsCSR_HSTATUS,CSR_HEDELEG,CSR_HIEHypervisor control and delegation

Testing Framework

The testing strategy combines unit testing for functional verification with CI-based integration testing across multiple toolchain versions.

Test Execution Environment

flowchart TD
subgraph subGraph1["Test Categories"]
    functional["Functional TestsCore Logic Verification"]
    compilation["Compilation TestsCross-platform Build"]
    linting["Static AnalysisClippy Checks"]
    formatting["Style Testsrustfmt Validation"]
end
subgraph subGraph0["Test Environments"]
    unit_tests["Unit Testsx86_64-unknown-linux-gnu"]
    integration_tests["Integration Testsriscv64gc-unknown-none-elf"]
end

integration_tests --> compilation
integration_tests --> formatting
integration_tests --> linting
unit_tests --> functional

Sources: .github/workflows/ci.yml(L30 - L32) 

Test Configuration

The test suite runs with specific configurations:

  • Unit Tests: Execute on x86_64-unknown-linux-gnu for host-based testing
  • Integration Tests: Build verification on riscv64gc-unknown-none-elf target
  • Test Output: Uses --nocapture flag for complete test output visibility

Development Workflow Integration

The development workflow integrates multiple tools and processes to ensure code quality and system reliability.

Development Tool Chain

flowchart TD
subgraph Deployment["Deployment"]
    crate_publish["Crate Publication"]
    gh_pages["GitHub PagesDocumentation"]
end
subgraph subGraph2["Automated Validation"]
    ci_pipeline["CI Pipeline"]
    quality_gates["Quality Gates"]
    doc_generation["Documentation"]
end
subgraph subGraph1["Version Control"]
    git_commit["Git Commit"]
    git_push["Git Push"]
    pull_request["Pull Request"]
end
subgraph subGraph0["Local Development"]
    rust_toolchain["Rust Nightly Toolchain"]
    cargo_fmt["cargo fmtCode Formatting"]
    cargo_clippy["cargo clippyLinting"]
    cargo_test["cargo testUnit Testing"]
end

cargo_clippy --> cargo_test
cargo_fmt --> cargo_clippy
cargo_test --> git_commit
ci_pipeline --> quality_gates
doc_generation --> gh_pages
git_commit --> git_push
git_push --> ci_pipeline
pull_request --> ci_pipeline
quality_gates --> crate_publish
quality_gates --> doc_generation
rust_toolchain --> cargo_fmt

Sources: .github/workflows/ci.yml(L1 - L65)  Cargo.toml(L1 - L26) 

Required Toolchain Components

The development environment requires specific Rust toolchain components:

  • Rust Source: rust-src for cross-compilation support
  • Clippy: Static analysis and linting tool
  • Rustfmt: Code formatting tool
  • Target Support: riscv64gc-unknown-none-elf compilation target

Sources: .github/workflows/ci.yml(L18 - L19)