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:
| Field | Type | Purpose |
|---|---|---|
| regs | VmCpuRegisters | Complete guest register state including GPRs, CSRs, and trap context |
| sbi | RISCVVCpuSbi | SBI interface implementation for handling supervisor binary interface calls |
| _marker | PhantomData | Type 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:
VCpuConfigsrc/vcpu.rs(L18 - L19) - Architecture-dependent configuration (currently empty)RISCVVCpuCreateConfigsrc/lib.rs(L29 - L36) - Creation-time configuration including hart ID and device tree address
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:
| Method | Purpose | Key Operations |
|---|---|---|
| new() | VCPU creation | Initialize registers, set hart ID and DTB address |
| setup() | Configuration | ConfiguresstatusandhstatusCSRs |
| set_entry() | Entry point | Set guest program counter (sepc) |
| set_ept_root() | Memory setup | Configure hypervisor guest address translation (hgatp) |
| bind() | Memory binding | Activate guest page tables and invalidate TLB |
| run() | Execution | Execute 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.