Core VCPU Management
Relevant source files
This document covers the central AxVCpu
abstraction that provides the primary interface for virtual CPU management in the axvcpu crate. The AxVCpu
struct serves as an architecture-independent wrapper that delegates platform-specific operations to architecture implementations while maintaining consistent state management and lifecycle control.
For detailed information about VCPU state transitions and lifecycle stages, see VCPU State Machine and Lifecycle. For architecture-specific implementation details, see Architecture Abstraction Layer. For information about handling VCPU exits and events, see Exit Handling System.
AxVCpu Structure and Components
The AxVCpu
struct is designed as a generic wrapper that provides architecture-independent VCPU management by delegating specific operations to types implementing the AxArchVCpu
trait.
Core Data Structure
classDiagram class AxVCpu { -AxVCpuInnerConst inner_const -RefCell~AxVCpuInnerMut~ inner_mut -UnsafeCell~A~ arch_vcpu +new(id, favor_phys_cpu, phys_cpu_set, arch_config) AxResult~Self~ +setup(entry, ept_root, arch_config) AxResult +run() AxResult~AxVCpuExitReason~ +bind() AxResult +unbind() AxResult +state() VCpuState +id() usize +is_bsp() bool +set_gpr(reg, val) } class AxVCpuInnerConst { -usize id -usize favor_phys_cpu -Option~usize~ phys_cpu_set } class AxVCpuInnerMut { -VCpuState state } class VCpuState { <<enumeration>> Invalid Created Free Ready Running Blocked } AxVCpu *-- AxVCpuInnerConst AxVCpu *-- AxVCpuInnerMut AxVCpuInnerMut *-- VCpuState
The AxVCpu
structure separates concerns into three main components:
Component | Purpose | Mutability |
---|---|---|
AxVCpuInnerConst | Immutable VCPU configuration (ID, CPU affinity) | Constant |
AxVCpuInnerMut | Mutable state information managed throughRefCell | Interior mutable |
arch_vcpu | Architecture-specific implementation viaUnsafeCell | Unsafe interior mutable |
Sources: src/vcpu.rs(L8 - L63)
Architecture Independence Design
The AxVCpu
achieves architecture independence by using the AxArchVCpu
trait as a type parameter, allowing the same interface to work with different CPU architectures.
Trait Integration Pattern
The AxArchVCpu
trait defines the contract that architecture-specific implementations must fulfill:
Method | Purpose | State Requirement |
---|---|---|
new() | Create new architecture VCPU | - |
set_entry() | Set guest entry point | Before setup |
set_ept_root() | Set memory translation root | Before setup |
setup() | Complete VCPU initialization | After entry/EPT set |
run() | Execute guest code | Running state |
bind()/unbind() | CPU binding operations | Ready/Free transition |
Sources: src/arch_vcpu.rs(L6 - L44) src/vcpu.rs(L53 - L63)
VCPU Lifecycle Operations
The AxVCpu
provides key lifecycle operations that manage VCPU state transitions and delegate to architecture-specific implementations.
Creation and Initialization Flow
Runtime Operations
The main runtime operations follow a consistent pattern of state validation and architecture delegation:
flowchart TD subgraph subGraph1["Key Operations"] Bind["bind(): Free → Ready"] Run["run(): Ready → Running → Ready"] Unbind["unbind(): Ready → Free"] end subgraph subGraph0["VCPU Operation Pattern"] StateCheck["Check Current State"] ArchDelegate["Delegate to AxArchVCpu"] StateTransition["Update VCPU State"] Result["Return Result"] end ArchDelegate --> StateTransition Bind --> StateCheck Run --> StateCheck StateCheck --> ArchDelegate StateTransition --> Result Unbind --> StateCheck
Sources: src/vcpu.rs(L205 - L225) src/vcpu.rs(L86 - L99)
Current VCPU Management
The crate maintains per-CPU tracking of the currently executing VCPU using a percpu variable, enabling architecture implementations to access their containing AxVCpu
instance.
Per-CPU VCPU Tracking
flowchart TD subgraph subGraph2["Access Functions"] GetCurrent["get_current_vcpu<A>()"] SetCurrent["set_current_vcpu(vcpu)"] ClearCurrent["clear_current_vcpu<A>()"] end subgraph subGraph1["Physical CPU 1"] PCPU1["CURRENT_VCPU: Option<*mut u8>"] VCPU1["AxVCpu instance"] end subgraph subGraph0["Physical CPU 0"] PCPU0["CURRENT_VCPU: Option<*mut u8>"] VCPU0["AxVCpu instance"] end ClearCurrent --> PCPU0 ClearCurrent --> PCPU1 GetCurrent --> PCPU0 GetCurrent --> PCPU1 PCPU0 --> VCPU0 PCPU1 --> VCPU1 SetCurrent --> PCPU0 SetCurrent --> PCPU1
The current VCPU mechanism provides:
Function | Purpose | Safety |
---|---|---|
get_current_vcpu() | Get current VCPU reference | Safe |
get_current_vcpu_mut() | Get mutable current VCPU reference | Safe |
set_current_vcpu() | Set current VCPU pointer | Unsafe |
clear_current_vcpu() | Clear current VCPU pointer | Unsafe |
The with_current_cpu_set
method automatically manages current VCPU setup and cleanup:
sequenceDiagram participant Caller as Caller participant AxVCpu as AxVCpu participant CURRENT_VCPU as "CURRENT_VCPU" participant UserOperation as "User Operation" Caller ->> AxVCpu: "with_current_cpu_set(closure)" AxVCpu ->> CURRENT_VCPU: "check if already set" alt Already Set AxVCpu -->> AxVCpu: "panic!(nested operation)" else Not Set AxVCpu ->> CURRENT_VCPU: "set_current_vcpu(self)" AxVCpu ->> UserOperation: "execute closure" UserOperation -->> AxVCpu: "result" AxVCpu ->> CURRENT_VCPU: "clear_current_vcpu()" AxVCpu -->> Caller: "result" end
Sources: src/vcpu.rs(L238 - L290) src/vcpu.rs(L164 - L180)
Interior Mutability Pattern
The AxVCpu
uses a sophisticated interior mutability design to handle the different access patterns required for VCPU state and architecture-specific data.
Mutability Strategy
flowchart TD subgraph Methods["Methods"] GetId["id(), favor_phys_cpu()"] GetState["state(), with_state_transition()"] GetArch["get_arch_vcpu()"] end subgraph subGraph1["Access Patterns"] ConstAccess["ID, CPU affinity queries"] StateAccess["State transitions via RefCell"] ArchAccess["Direct architecture operations"] end subgraph subGraph0["AxVCpu Mutability Design"] InnerConst["AxVCpuInnerConst(Immutable)"] InnerMut["RefCell<AxVCpuInnerMut>(Safe Interior Mutability)"] ArchVCpu["UnsafeCell<A>(Unsafe Interior Mutability)"] end ArchAccess --> GetArch ArchVCpu --> ArchAccess ConstAccess --> GetId InnerConst --> ConstAccess InnerMut --> StateAccess StateAccess --> GetState
The design rationale for different mutability approaches:
Component | Mutability Type | Reason |
---|---|---|
inner_const | None | Immutable configuration data |
inner_mut | RefCell | Safe runtime borrowing for state |
arch_vcpu | UnsafeCell | Direct access needed during VCPU execution |
The manipulate_arch_vcpu
method combines state transition with architecture delegation:
flowchart TD Start["manipulate_arch_vcpu(from, to, closure)"] StateTransition["with_state_transition(from, to)"] CurrentSet["with_current_cpu_set()"] ArchAccess["get_arch_vcpu()"] Execute["Execute closure with &mut A"] Result["Return AxResult<T>"] ArchAccess --> Execute CurrentSet --> ArchAccess Execute --> Result Start --> StateTransition StateTransition --> CurrentSet
Sources: src/vcpu.rs(L53 - L63) src/vcpu.rs(L185 - L192) src/vcpu.rs(L199 - L203)