Core VCPU Implementation

Relevant source files

Purpose and Scope

This document covers the core virtual CPU implementation centered around the RISCVVCpu struct and its fundamental operations. The RISCVVCpu serves as the primary abstraction for executing RISC-V guest virtual machines within the ArceOS hypervisor framework, handling register state management, guest execution control, and hypervisor interactions.

For detailed information about VCPU creation and lifecycle management, see VCPU Lifecycle and Management. For SBI call processing and hypercall handling, see SBI Interface and Hypercalls. For VM exit event processing, see VM Exit Processing.

Core Data Structures

The VCPU implementation is built around several key data structures that manage virtual CPU state and execution context:

RISCVVCpu Structure

The main RISCVVCpu<H: AxVCpuHal> struct src/vcpu.rs(L23 - L27)  encapsulates all virtual CPU state:

FieldTypePurpose
regsVmCpuRegistersComplete guest register state including GPRs, CSRs, and trap context
sbiRISCVVCpuSbiSBI interface implementation for handling supervisor binary interface calls
_markerPhantomDataType marker for hardware abstraction layer integration

SBI Integration Structure

The RISCVVCpuSbi struct src/vcpu.rs(L29 - L33)  implements the RustSBI interface using the #[derive(RustSBI)] macro, providing automatic forwarding for standard SBI extensions including console, PMU, fence, reset, info, and HSM operations.

Configuration Structures

The system defines two configuration types:

Architecture Overview

The following diagram illustrates the core VCPU architecture and its relationship to key code entities:

flowchart TD
subgraph subGraph3["External Assembly Interface"]
    RunGuest["_run_guest()Assembly Entry Point"]
    TrapHandler["Trap Handlingtrap.S"]
end
subgraph subGraph2["Internal Implementation Methods"]
    VmexitHandler["vmexit_handler()VM Exit Processing"]
    AdvancePc["advance_pc()PC Manipulation"]
    GetGpr["get_gpr()Register Access"]
    SetGpr["set_gpr_from_gpr_index()Register Modification"]
end
subgraph subGraph1["AxArchVCpu Trait Implementation"]
    NewMethod["new()VCPU Creation"]
    SetupMethod["setup()CSR Configuration"]
    RunMethod["run()Guest Execution"]
    BindMethod["bind()Memory Binding"]
    SetEntryMethod["set_entry()Entry Point Setup"]
    SetEptRootMethod["set_ept_root()Page Table Root"]
end
subgraph subGraph0["RISCVVCpu Core Structure"]
    RISCVVCpu["RISCVVCpu<H>Main VCPU Implementation"]
    VmCpuRegisters["VmCpuRegistersComplete Register State"]
    RISCVVCpuSbi["RISCVVCpuSbiSBI Interface Handler"]
end

RISCVVCpu --> BindMethod
RISCVVCpu --> NewMethod
RISCVVCpu --> RISCVVCpuSbi
RISCVVCpu --> RunMethod
RISCVVCpu --> SetEntryMethod
RISCVVCpu --> SetEptRootMethod
RISCVVCpu --> SetupMethod
RISCVVCpu --> VmCpuRegisters
RunGuest --> TrapHandler
RunMethod --> RunGuest
RunMethod --> VmexitHandler
TrapHandler --> VmexitHandler
VmexitHandler --> AdvancePc
VmexitHandler --> GetGpr
VmexitHandler --> SetGpr

Sources: src/vcpu.rs(L23 - L164) 

VCPU State Management

The VCPU maintains comprehensive state through the VmCpuRegisters structure, which includes guest general-purpose registers, control and status registers, and trap context information.

Register Access Interface

The VCPU provides controlled access to guest registers through dedicated methods:

flowchart TD
subgraph subGraph1["Internal Storage"]
    GuestRegs["guest_regs.gprsGeneralPurposeRegisters"]
    VirtualCSRs["virtual_hs_csrsHypervisor CSRs"]
    TrapCSRs["trap_csrsTrap Context"]
end
subgraph subGraph0["Register Access Methods"]
    GetGpr["get_gpr(GprIndex)Read Guest Register"]
    SetGprIndex["set_gpr_from_gpr_index()Write by GprIndex"]
    SetGprOffset["set_gpr(usize, usize)Write by Offset"]
end

GetGpr --> GuestRegs
GuestRegs --> TrapCSRs
GuestRegs --> VirtualCSRs
SetGprIndex --> GuestRegs
SetGprOffset --> GuestRegs

Sources: src/vcpu.rs(L129 - L153) 

Execution Control Flow

The VCPU execution follows a structured pattern that integrates with the hypervisor's execution model:

Core Execution Cycle

sequenceDiagram
    participant HostHypervisor as "Host/Hypervisor"
    participant RISCVVCpurun as "RISCVVCpu::run()"
    participant _run_guest as "_run_guest()"
    participant vmexit_handler as "vmexit_handler()"

    HostHypervisor ->> RISCVVCpurun: Call run()
    RISCVVCpurun ->> RISCVVCpurun: Setup interrupts (sie)
    RISCVVCpurun ->> _run_guest: _run_guest(&mut regs)
    _run_guest ->> _run_guest: Execute guest code
    _run_guest ->> vmexit_handler: VM Exit occurs
    vmexit_handler ->> vmexit_handler: Read trap CSRs
    vmexit_handler ->> vmexit_handler: Process exit reason
    vmexit_handler ->> RISCVVCpurun: Return AxVCpuExitReason
    RISCVVCpurun ->> RISCVVCpurun: Cleanup interrupts
    RISCVVCpurun ->> HostHypervisor: Return exit reason

Sources: src/vcpu.rs(L92 - L111)  src/vcpu.rs(L167 - L308) 

Integration with ArceOS Framework

The VCPU implements the AxArchVCpu trait src/vcpu.rs(L42 - L142)  providing standardized interfaces for:

MethodPurposeKey Operations
new()VCPU creationInitialize registers, set hart ID and DTB address
setup()ConfigurationConfiguresstatusandhstatusCSRs
set_entry()Entry pointSet guest program counter (sepc)
set_ept_root()Memory setupConfigure hypervisor guest address translation (hgatp)
bind()Memory bindingActivate guest page tables and invalidate TLB
run()ExecutionExecute guest code and handle VM exits

Hardware Abstraction Layer Integration

The VCPU uses a generic type parameter H: AxVCpuHal src/vcpu.rs(L23)  to integrate with hardware abstraction layers, enabling platform-specific optimizations while maintaining a consistent interface.

Sources: src/vcpu.rs(L42 - L142)  src/lib.rs(L18 - L20) 

Memory Management Integration

The VCPU integrates with the ArceOS address space management through several key mechanisms:

Extended Page Table Support

The set_ept_root() method src/vcpu.rs(L87 - L90)  configures the hgatp CSR with an Sv48 page table format (mode 8) and the physical page number of the root page table, enabling two-stage address translation for guest memory access.

Memory Binding Operations

The bind() and unbind() methods src/vcpu.rs(L113 - L126)  manage the activation and deactivation of guest address spaces, including TLB invalidation through hfence_gvma_all() to ensure memory consistency.

Sources: src/vcpu.rs(L87 - L90)  src/vcpu.rs(L113 - L126)