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:

ComponentPurposeMutability
AxVCpuInnerConstImmutable VCPU configuration (ID, CPU affinity)Constant
AxVCpuInnerMutMutable state information managed throughRefCellInterior mutable
arch_vcpuArchitecture-specific implementation viaUnsafeCellUnsafe 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:

MethodPurposeState Requirement
new()Create new architecture VCPU-
set_entry()Set guest entry pointBefore setup
set_ept_root()Set memory translation rootBefore setup
setup()Complete VCPU initializationAfter entry/EPT set
run()Execute guest codeRunning state
bind()/unbind()CPU binding operationsReady/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:

FunctionPurposeSafety
get_current_vcpu()Get current VCPU referenceSafe
get_current_vcpu_mut()Get mutable current VCPU referenceSafe
set_current_vcpu()Set current VCPU pointerUnsafe
clear_current_vcpu()Clear current VCPU pointerUnsafe

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:

ComponentMutability TypeReason
inner_constNoneImmutable configuration data
inner_mutRefCellSafe runtime borrowing for state
arch_vcpuUnsafeCellDirect 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)