Physical Frame Management
Relevant source files
Purpose and Scope
The Physical Frame Management system provides RAII-based allocation and management of 4KB-aligned physical memory pages for VMX operations. This system abstracts physical memory allocation through the AxVCpuHal
trait and ensures automatic cleanup through Rust's ownership model. The PhysFrame<H>
type serves as the fundamental building block for VMX data structures including VMCS regions, I/O bitmaps, and MSR bitmaps.
For information about how these physical frames are used in Extended Page Tables, see Extended Page Tables and Guest Memory. For details on the broader VMX data structures that consume these frames, see VMX Data Structures.
Core Architecture
PhysFrame RAII Wrapper
The PhysFrame<H: AxVCpuHal>
struct provides a type-safe wrapper around 4KB physical memory pages with automatic resource management:
flowchart TD subgraph subGraph2["Trait Implementations"] Drop["Drop::drop()"] Debug["Debug"] end subgraph subGraph1["Core Methods"] Alloc["alloc()"] AllocZero["alloc_zero()"] Uninit["unsafe uninit()"] StartPaddrMethod["start_paddr()"] AsMutPtr["as_mut_ptr()"] Fill["fill(byte: u8)"] end subgraph subGraph0["PhysFrame Structure"] PhysFrameStruct["PhysFrame<H>"] StartPaddr["start_paddr: Option<HostPhysAddr>"] Marker["_marker: PhantomData<H>"] end PhysFrameStruct --> Alloc PhysFrameStruct --> AllocZero PhysFrameStruct --> AsMutPtr PhysFrameStruct --> Debug PhysFrameStruct --> Drop PhysFrameStruct --> Fill PhysFrameStruct --> Marker PhysFrameStruct --> StartPaddr PhysFrameStruct --> StartPaddrMethod PhysFrameStruct --> Uninit
Sources: src/frame.rs(L12 - L16) src/frame.rs(L18 - L53)
Hardware Abstraction Layer
The AxVCpuHal
trait defines the interface between the frame allocator and the underlying platform:
flowchart TD subgraph subGraph1["PhysFrame Operations"] PhysFrameAlloc["PhysFrame::alloc()"] PhysFrameDrop["PhysFrame::drop()"] PhysFrameAccess["PhysFrame::as_mut_ptr()"] end subgraph subGraph0["AxVCpuHal Trait Interface"] AxVCpuHal["AxVCpuHal"] AllocFrame["alloc_frame() -> Option<HostPhysAddr>"] DeallocFrame["dealloc_frame(paddr: HostPhysAddr)"] PhysToVirt["phys_to_virt(paddr: HostPhysAddr) -> VirtAddr"] end AxVCpuHal --> AllocFrame AxVCpuHal --> DeallocFrame AxVCpuHal --> PhysToVirt PhysFrameAccess --> PhysToVirt PhysFrameAlloc --> AllocFrame PhysFrameDrop --> DeallocFrame
Sources: src/frame.rs(L6) src/frame.rs(L20 - L21) src/frame.rs(L47) src/frame.rs(L58)
Memory Allocation Lifecycle
Allocation Methods
The system provides three allocation strategies:
Method | Purpose | Zero-filled | Safety |
---|---|---|---|
alloc() | Standard allocation | No | Safe |
alloc_zero() | Zero-initialized allocation | Yes | Safe |
uninit() | Uninitialized frame | N/A | Unsafe |
Sources: src/frame.rs(L19 - L27) src/frame.rs(L29 - L33) src/frame.rs(L35 - L40)
Automatic Deallocation
The Drop
implementation ensures memory is automatically returned to the system:
flowchart TD subgraph subGraph1["Drop Implementation Details"] CheckPaddr["Check start_paddr.is_some()"] CallDealloc["H::dealloc_frame(start_paddr)"] LogDealloc["debug! log deallocation"] end subgraph subGraph0["RAII Lifecycle"] Creation["PhysFrame::alloc()"] Usage["Memory Usage Phase"] Destruction["PhysFrame goes out of scope"] DropCall["Drop::drop() called"] Deallocation["HAL::dealloc_frame()"] end CallDealloc --> LogDealloc CheckPaddr --> CallDealloc Creation --> Usage Destruction --> DropCall DropCall --> CheckPaddr DropCall --> Deallocation Usage --> Destruction
Sources: src/frame.rs(L55 - L62)
Memory Access Patterns
Address Translation and Access
The frame system provides both physical and virtual access to allocated memory:
flowchart TD subgraph subGraph2["HAL Translation"] PhysToVirt["phys_to_virt()"] end subgraph subGraph1["PhysFrame Access Methods"] StartPaddr["start_paddr()"] AsMutPtr["as_mut_ptr()"] Fill["fill(byte)"] end subgraph subGraph0["Address Types"] HostPhysAddr["HostPhysAddr"] VirtAddr["VirtAddr"] MutPtr["*mut u8"] end AsMutPtr --> PhysToVirt Fill --> AsMutPtr PhysToVirt --> VirtAddr StartPaddr --> HostPhysAddr VirtAddr --> MutPtr
Sources: src/frame.rs(L42 - L44) src/frame.rs(L46 - L48) src/frame.rs(L50 - L52)
Memory Operations
The system supports direct memory manipulation through safe abstractions:
Operation | Method | Safety | Purpose |
---|---|---|---|
Get physical address | start_paddr() | Safe | VMX structure setup |
Get virtual pointer | as_mut_ptr() | Safe | Direct memory access |
Fill with pattern | fill(byte) | Safe | Zero-initialization |
Integration with VMX Components
VMX Data Structure Usage
Physical frames serve as the foundation for critical VMX data structures:
flowchart TD subgraph PhysFrame<H>["PhysFrame<H>"] CoreFrame["PhysFrame<H>4KB alignedRAII managed"] end subgraph subGraph1["Frame Requirements"] VmxReq["1x 4KB frameVMXON/VMCS region"] IOReq["2x 4KB framesPort 0-0xFFFF bitmap"] MsrReq["1x 4KB frameMSR access bitmap"] EPTReq["Multiple 4KB framesPage table hierarchy"] end subgraph subGraph0["PhysFrame Consumers"] VmxRegion["VmxRegion"] IOBitmap["IOBitmap"] MsrBitmap["MsrBitmap"] EPTStructures["EPT Page Tables"] end EPTReq --> CoreFrame EPTStructures --> EPTReq IOBitmap --> IOReq IOReq --> CoreFrame MsrBitmap --> MsrReq MsrReq --> CoreFrame VmxRegion --> VmxReq VmxReq --> CoreFrame
Sources: src/frame.rs(L8) (PAGE_SIZE_4K constant)
Error Handling
The allocation system uses AxResult<T>
for error propagation:
flowchart TD subgraph subGraph0["Error Flow"] AllocCall["PhysFrame::alloc()"] HALCall["H::alloc_frame()"] HALResult["Option<HostPhysAddr>"] ErrorCheck["Check for None"] ErrorResult["Err(NoMemory)"] SuccessResult["Ok(PhysFrame)"] end AllocCall --> HALCall ErrorCheck --> ErrorResult ErrorCheck --> SuccessResult HALCall --> HALResult HALResult --> ErrorCheck
Sources: src/frame.rs(L19 - L27) src/frame.rs(L4) (AxResult import)
Constants and Configuration
The system uses standardized page sizing:
Constant | Value | Source | Purpose |
---|---|---|---|
PAGE_SIZE | PAGE_SIZE_4K | memory_addrcrate | Standard frame size |
Frame alignment | 4KB | Hardware requirement | VMX compatibility |
Sources: src/frame.rs(L8)