Core Architecture
Relevant source files
This document provides a detailed examination of axvm's fundamental architecture, focusing on the core components that enable virtual machine creation, management, and execution. It covers the main AxVM
struct, its internal organization, lifecycle management, and integration with hardware abstraction layers.
For information about specific vCPU architecture implementations, see Virtual CPU Architecture. For details about hardware abstraction interfaces, see Hardware Abstraction Layer. For VM configuration mechanisms, see Configuration System.
Architecture Overview
The axvm hypervisor is built around a central AxVM
struct that coordinates virtual machine execution through a clean separation of concerns. The architecture employs generic type parameters to abstract hardware and vCPU implementations while maintaining compile-time optimization.
flowchart TD subgraph subGraph4["Generic Type Parameters"] HAL["H: AxVMHal"] VCPUHAL["U: AxVCpuHal"] end subgraph subGraph3["VM Lifecycle Flags"] Running["running: AtomicBool"] ShuttingDown["shutting_down: AtomicBool"] end subgraph subGraph2["Mutable VM State"] AddrSpace["address_space: Mutex<AddrSpace<H::PagingHandler>>"] PhantomData["_marker: PhantomData<H>"] end subgraph subGraph1["Immutable VM State"] VMId["id: usize"] VMConfig["config: AxVMConfig"] VCpuList["vcpu_list: Box[AxVCpuRef<U>]"] VMDevices["devices: AxVmDevices"] end subgraph subGraph0["Core VM Structure"] AxVM["AxVM<H, U>"] AxVMInnerConst["AxVMInnerConst<U>"] AxVMInnerMut["AxVMInnerMut<H>"] end AxVM --> AxVMInnerConst AxVM --> AxVMInnerMut AxVM --> HAL AxVM --> Running AxVM --> ShuttingDown AxVM --> VCPUHAL AxVMInnerConst --> VCpuList AxVMInnerConst --> VMConfig AxVMInnerConst --> VMDevices AxVMInnerConst --> VMId AxVMInnerMut --> AddrSpace AxVMInnerMut --> PhantomData
Sources: src/vm.rs(L47 - L53) src/vm.rs(L31 - L39) src/vm.rs(L41 - L45)
Core VM Structure
The AxVM
struct is organized into distinct sections that separate immutable configuration data from mutable runtime state. This design ensures thread safety while minimizing lock contention during VM execution.
Data Organization
Component | Type | Purpose | Thread Safety |
---|---|---|---|
running | AtomicBool | VM execution state | Lock-free atomic operations |
shutting_down | AtomicBool | VM shutdown state | Lock-free atomic operations |
inner_const | AxVMInnerConst | Immutable VM configuration | Unsafe Send/Sync implementation |
inner_mut | AxVMInnerMut | Mutable runtime state | Mutex-protected access |
The immutable section (AxVMInnerConst
) contains the VM identifier, configuration, vCPU list, and device registry. The mutable section (AxVMInnerMut
) contains the address space with its associated page table handler.
Sources: src/vm.rs(L47 - L53) src/vm.rs(L31 - L39) src/vm.rs(L41 - L45)
VM Creation and Initialization
VM creation follows a multi-stage initialization process that sets up vCPUs, memory regions, and devices before the VM can be executed.
sequenceDiagram participant AxVMnew as "AxVM::new()" participant vCPUCreation as "vCPU Creation" participant MemorySetup as "Memory Setup" participant DeviceSetup as "Device Setup" participant AddrSpace as "AddrSpace" AxVMnew ->> vCPUCreation: "Create VCpus from config" Note over vCPUCreation: "Architecture-specific AxVCpuCreateConfig" vCPUCreation ->> vCPUCreation: "Arc::new(VCpu::new())" AxVMnew ->> MemorySetup: "Process memory_regions()" MemorySetup ->> AddrSpace: "AddrSpace::new_empty()" loop "For each memory region" MemorySetup ->> MemorySetup: "Validate MappingFlags" alt "VmMemMappingType::MapIentical" MemorySetup ->> AddrSpace: "map_linear()" else "VmMemMappingType::MapAlloc" MemorySetup ->> AddrSpace: "map_alloc()" end end loop "For each pass_through_device" MemorySetup ->> AddrSpace: "map_linear() with DEVICE flags" end AxVMnew ->> DeviceSetup: "AxVmDevices::new()" DeviceSetup ->> DeviceSetup: "Initialize from emu_configs" AxVMnew ->> AxVMnew: "Create AxVM struct" loop "For each vCPU" AxVMnew ->> vCPUCreation: "vcpu.setup(entry, ept_root, config)" end
Sources: src/vm.rs(L59 - L219) src/vm.rs(L95 - L163) src/vm.rs(L182 - L184) src/vm.rs(L204 - L217)
Memory Region Setup
The VM initialization process handles two distinct memory mapping types:
VmMemMappingType::MapIentical
: Creates identity mappings where guest physical addresses map directly to host physical addressesVmMemMappingType::MapAlloc
: Allocates new physical memory pages that may be non-contiguous in host physical memory
The address space spans from VM_ASPACE_BASE
(0x0) to VM_ASPACE_SIZE
(0x7fff_ffff_f000), providing a large virtual address space for guest execution.
Sources: src/vm.rs(L18 - L19) src/vm.rs(L122 - L162)
VM Lifecycle Management
The VM lifecycle is controlled through atomic boolean flags that coordinate state transitions across multiple threads without requiring locks.
State Validation
VM operations include state validation to prevent invalid transitions:
boot()
checks hardware virtualization support and prevents double-bootingshutdown()
prevents multiple shutdown attemptsrun_vcpu()
validates vCPU existence before execution
Sources: src/vm.rs(L277 - L288) src/vm.rs(L299 - L310) src/vm.rs(L328 - L376)
vCPU Execution Loop
The core VM execution occurs in the run_vcpu()
method, which implements a continuous loop that handles various exit reasons from hardware virtualization.
flowchart TD Start["run_vcpu(vcpu_id)"] ValidateVCpu["vcpu(vcpu_id)?"] BindVCpu["vcpu.bind()"] RunLoop["vcpu.run()"] ExitReason["Match exit_reason"] MmioRead["MmioRead"] MmioWrite["MmioWrite"] PageFault["NestedPageFault"] IoOps["IoRead/IoWrite"] Other["Other reasons"] DeviceRead["devices.handle_mmio_read()"] SetGPR["vcpu.set_gpr()"] Continue["Continue loop"] DeviceWrite["devices.handle_mmio_write()"] HandleFault["address_space.handle_page_fault()"] Unbind["vcpu.unbind()"] Return["Return exit_reason"] BindVCpu --> RunLoop Continue --> RunLoop DeviceRead --> SetGPR DeviceWrite --> Continue ExitReason --> IoOps ExitReason --> MmioRead ExitReason --> MmioWrite ExitReason --> Other ExitReason --> PageFault HandleFault --> Continue IoOps --> Continue MmioRead --> DeviceRead MmioWrite --> DeviceWrite Other --> Unbind PageFault --> HandleFault RunLoop --> ExitReason SetGPR --> Continue Start --> ValidateVCpu Unbind --> Return ValidateVCpu --> BindVCpu
The execution loop handles several categories of VM exits:
- MMIO Operations: Delegated to the device emulation layer via
AxVmDevices
- Page Faults: Handled by the address space's page fault handler
- I/O Operations: Currently handled as no-ops
- Unhandled Exits: Return control to the caller
Sources: src/vm.rs(L328 - L376) src/vm.rs(L335 - L372)
Component Integration
The AxVM
struct integrates with several key subsystems through well-defined interfaces:
Address Space Integration
flowchart TD AxVM["AxVM"] AddrSpaceMutex["Mutex<AddrSpace<H::PagingHandler>>"] AddrSpace["AddrSpace"] PageTableRoot["page_table_root()"] HandlePageFault["handle_page_fault()"] TranslateBuffer["translated_byte_buffer()"] EPTRoot["ept_root() for vCPU setup"] ImageLoad["get_image_load_region()"] AddrSpace --> HandlePageFault AddrSpace --> PageTableRoot AddrSpace --> TranslateBuffer AddrSpaceMutex --> AddrSpace AxVM --> AddrSpaceMutex PageTableRoot --> EPTRoot TranslateBuffer --> ImageLoad
Device Integration
flowchart TD AxVM["AxVM"] AxVmDevices["AxVmDevices"] MmioRead["handle_mmio_read()"] MmioWrite["handle_mmio_write()"] DeviceConfig["AxVmDeviceConfig"] EmuConfigs["emu_configs: Vec"] AxVM --> AxVmDevices AxVmDevices --> DeviceConfig AxVmDevices --> MmioRead AxVmDevices --> MmioWrite DeviceConfig --> EmuConfigs
vCPU Management
The VM maintains references to vCPUs through Arc<VCpu<AxArchVCpuImpl<U>>>
allowing shared ownership across threads while providing architecture-independent access through the AxArchVCpu
trait.
Sources: src/vm.rs(L21 - L26) src/vm.rs(L242 - L250) src/vm.rs(L260 - L270) src/vm.rs(L315 - L318)
Type System and Generics
The architecture leverages Rust's type system to provide compile-time guarantees about hardware compatibility and vCPU implementations:
H: AxVMHal
: Hardware abstraction layer interfaceU: AxVCpuHal
: vCPU hardware abstraction layer interface- Type Aliases:
AxVMRef<H, U>
andAxVCpuRef<U>
provide ergonomic reference types
This design enables architecture-specific optimizations while maintaining a unified API across different hardware platforms.