VMCS Field Management
Relevant source files
This document covers the Virtual Machine Control Structure (VMCS) field management system within the VMX virtualization engine. The VMCS is Intel's hardware structure that controls virtual machine behavior, and this module provides type-safe access patterns, control field manipulation algorithms, and VM exit information gathering mechanisms.
For Virtual CPU lifecycle management and VM execution flow, see Virtual CPU Management. For the underlying VMX data structures that contain VMCS regions, see VMX Data Structures.
VMCS Field Organization
The VMCS contains hundreds of fields organized into distinct categories based on their purpose and access patterns. The hypervisor provides type-safe enums for each category, ensuring correct field access and preventing runtime errors.
flowchart TD
subgraph subGraph5["Access Implementations"]
ReadImpl["vmcs_read! macrogenerates .read() methods"]
WriteImpl["vmcs_write! macrogenerates .write() methods"]
ROFields["define_vmcs_fields_ro!read-only field traits"]
RWFields["define_vmcs_fields_rw!read-write field traits"]
end
subgraph subGraph4["VMCS Field Categories"]
subgraph subGraph3["Read-Only Data Fields"]
ReadOnly32["VmcsReadOnly32EXIT_REASON, VM_INSTRUCTION_ERROR"]
ReadOnly64["VmcsReadOnly64GUEST_PHYSICAL_ADDR"]
ReadOnlyNW["VmcsReadOnlyNWEXIT_QUALIFICATION, GUEST_LINEAR_ADDR"]
end
subgraph subGraph2["Host State Fields"]
Host16["VmcsHost16ES_SELECTOR, TR_SELECTOR"]
Host32["VmcsHost32IA32_SYSENTER_CS"]
Host64["VmcsHost64IA32_PAT, IA32_EFER"]
HostNW["VmcsHostNWCR0, RSP, RIP"]
end
subgraph subGraph1["Guest State Fields"]
Guest16["VmcsGuest16ES_SELECTOR, CS_SELECTOR"]
Guest32["VmcsGuest32ES_LIMIT, INTERRUPTIBILITY_STATE"]
Guest64["VmcsGuest64IA32_EFER, IA32_PAT"]
GuestNW["VmcsGuestNWCR0, RSP, RIP, RFLAGS"]
end
subgraph subGraph0["Control Fields"]
Control16["VmcsControl16VPID, EPTP_INDEX"]
Control32["VmcsControl32EXEC_CONTROLS, EXCEPTION_BITMAP"]
Control64["VmcsControl64IO_BITMAP_A_ADDR, MSR_BITMAPS_ADDR"]
ControlNW["VmcsControlNWCR0_GUEST_HOST_MASK, CR4_READ_SHADOW"]
end
end
Control16 --> RWFields
Control32 --> RWFields
Control64 --> RWFields
ControlNW --> RWFields
Guest16 --> RWFields
Guest32 --> RWFields
Guest64 --> RWFields
GuestNW --> RWFields
Host16 --> RWFields
Host32 --> RWFields
Host64 --> RWFields
HostNW --> RWFields
ROFields --> ReadImpl
RWFields --> ReadImpl
RWFields --> WriteImpl
ReadOnly32 --> ROFields
ReadOnly64 --> ROFields
ReadOnlyNW --> ROFields
Sources: src/vmx/vmcs.rs(L85 - L486)
Field Access Patterns
The system uses code generation macros to create consistent, type-safe access patterns for all VMCS fields. These macros handle the underlying vmread and vmwrite instructions while providing error handling and architecture-specific adaptations.
Read/Write Macro Implementation
flowchart TD
subgraph subGraph3["Architecture Handling"]
Arch64["64-bit: Direct access"]
Arch32["32-bit: Split high/low"]
end
subgraph subGraph2["Hardware Instructions"]
VmreadInstr["vmx::vmread()"]
VmwriteInstr["vmx::vmwrite()"]
end
subgraph subGraph1["Generated Methods"]
ReadMethod[".read() -> AxResult<T>"]
WriteMethod[".write(value: T) -> AxResult"]
end
subgraph subGraph0["Field Access Macros"]
VmcsRead["vmcs_read! macro"]
VmcsWrite["vmcs_write! macro"]
DefineRO["define_vmcs_fields_ro!"]
DefineRW["define_vmcs_fields_rw!"]
end
DefineRO --> ReadMethod
DefineRW --> ReadMethod
DefineRW --> WriteMethod
ReadMethod --> VmreadInstr
VmcsRead --> ReadMethod
VmcsWrite --> WriteMethod
VmreadInstr --> Arch32
VmreadInstr --> Arch64
VmwriteInstr --> Arch32
VmwriteInstr --> Arch64
WriteMethod --> VmwriteInstr
The vmcs_read! and vmcs_write! macros generate implementations that automatically handle 32-bit vs 64-bit architecture differences. On 32-bit systems, 64-bit fields require two separate hardware accesses to read the high and low portions.
Sources: src/vmx/vmcs.rs(L19 - L83)
VM Exit Information Gathering
When a VM exit occurs, the hypervisor must gather information about why the exit happened and the guest's state. The VMCS provides read-only fields containing this information, which the system abstracts into structured data types.
sequenceDiagram
participant GuestVM as "Guest VM"
participant VMXHardware as "VMX Hardware"
participant VMCSFields as "VMCS Fields"
participant exit_info as "exit_info()"
participant ExitHandler as "Exit Handler"
GuestVM ->> VMXHardware: "Instruction causes VM exit"
VMXHardware ->> VMCSFields: "Populate exit fields"
Note over VMCSFields: EXIT_REASON<br>EXIT_QUALIFICATION<br>VMEXIT_INSTRUCTION_LEN<br>Guest RIP
ExitHandler ->> exit_info: "Call exit_info()"
exit_info ->> VMCSFields: "VmcsReadOnly32::EXIT_REASON.read()"
exit_info ->> VMCSFields: "VmcsReadOnly32::VMEXIT_INSTRUCTION_LEN.read()"
exit_info ->> VMCSFields: "VmcsGuestNW::RIP.read()"
exit_info ->> ExitHandler: "VmxExitInfo struct"
ExitHandler ->> ExitHandler: "Process exit reason"
Exit Information Structures
The system defines several structured types for different categories of VM exit information:
| Structure | Purpose | Key Fields |
|---|---|---|
| VmxExitInfo | General exit information | exit_reason,entry_failure,guest_rip |
| VmxInterruptInfo | Interrupt/exception details | vector,int_type,err_code |
| VmxIoExitInfo | I/O instruction exits | port,access_size,is_in |
| CrAccessInfo | Control register access | cr_number,access_type,gpr |
Sources: src/vmx/vmcs.rs(L488 - L582) src/vmx/vmcs.rs(L645 - L774)
Control Field Management
Control fields determine VM behavior and require careful management to ensure compatibility with the underlying hardware. The set_control() function implements the Intel-specified algorithm for safely setting control bits while respecting hardware capabilities.
flowchart TD
subgraph subGraph1["Capability Check"]
MSRRead["capability_msr.read()"]
Allowed0["allowed0 = cap[31:0](must be 1)"]
Allowed1["allowed1 = cap[63:32](may be 1)"]
Flexible["flexible = !allowed0 & allowed1"]
end
subgraph subGraph0["Control Setting Algorithm"]
Input["set_control(control, msr, old, set, clear)"]
ReadMSR["Read capability MSR"]
ExtractBits["Extract allowed0/allowed1"]
ValidateConflict["Validate set & clear don't conflict"]
ValidateAllowed1["Validate set bits allowed in allowed1"]
ValidateAllowed0["Validate clear bits allowed in allowed0"]
CalculateValue["Calculate final value:fixed1 | default | set"]
WriteVMCS["Write to VMCS field"]
end
Allowed0 --> Flexible
Allowed1 --> Flexible
CalculateValue --> WriteVMCS
ExtractBits --> Allowed0
ExtractBits --> Allowed1
ExtractBits --> ValidateConflict
Flexible --> CalculateValue
Input --> ReadMSR
MSRRead --> ExtractBits
ReadMSR --> MSRRead
ValidateAllowed0 --> CalculateValue
ValidateAllowed1 --> ValidateAllowed0
ValidateConflict --> ValidateAllowed1
The algorithm follows Intel SDM Volume 3C, Section 31.5.1, Algorithm 3, ensuring that control bits are set correctly based on processor capabilities.
Sources: src/vmx/vmcs.rs(L589 - L631)
Event Injection
The hypervisor can inject interrupts and exceptions into the guest using VMCS entry control fields. The inject_event() function handles the complex logic of setting up proper event injection based on the event type.
Event Injection Flow
flowchart TD
subgraph subGraph1["VMCS Fields Updated"]
EntryErrCode["VMENTRY_EXCEPTION_ERR_CODE"]
EntryInstrLen["VMENTRY_INSTRUCTION_LEN"]
EntryIntInfo["VMENTRY_INTERRUPTION_INFO_FIELD"]
end
subgraph subGraph0["Event Injection Process"]
InjectCall["inject_event(vector, err_code)"]
DetermineType["Determine VmxInterruptionType from vector"]
HandleError["Handle error code:- Required by vector type?- Use provided or exit code"]
CreateInfo["Create VmxInterruptInfo"]
WriteErrorCode["Write VMENTRY_EXCEPTION_ERR_CODE"]
HandleSoft["For soft interrupts:Set VMENTRY_INSTRUCTION_LEN"]
WriteIntInfo["Write VMENTRY_INTERRUPTION_INFO_FIELD"]
end
CreateInfo --> WriteErrorCode
DetermineType --> HandleError
HandleError --> CreateInfo
HandleSoft --> EntryInstrLen
HandleSoft --> WriteIntInfo
InjectCall --> DetermineType
WriteErrorCode --> EntryErrCode
WriteErrorCode --> HandleSoft
WriteIntInfo --> EntryIntInfo
The VmxInterruptInfo structure encodes the interrupt information according to Intel specifications, with specific bit fields for vector, interruption type, error code validity, and overall validity.
Sources: src/vmx/vmcs.rs(L677 - L694) src/vmx/vmcs.rs(L515 - L534)
Specialized Information Extraction
The system provides specialized functions for extracting detailed information from different types of VM exits:
I/O Exit Information
- Function:
io_exit_info() - Purpose: Extract port number, access size, direction for I/O instruction exits
- Fields: Port number, access size (1-4 bytes), IN/OUT direction, string/repeat flags
EPT Violation Information
- Function:
ept_violation_info() - Purpose: Extract guest physical address and access type for memory violations
- Returns:
NestedPageFaultInfowith fault address and access flags
Control Register Access
- Function:
cr_access_info() - Purpose: Decode control register access attempts (MOV, CLTS, LMSW)
- Fields: CR number, access type, GPR involved, LMSW source data
EFER Management
- Function:
update_efer() - Purpose: Handle guest IA32_EFER updates, particularly long mode transitions
- Actions: Set LONG_MODE_ACTIVE bit, update VM-entry controls
Sources: src/vmx/vmcs.rs(L696 - L774)