Register Management
Relevant source files
Purpose and Scope
The register management system provides abstractions for handling x86-64 general-purpose registers within the hypervisor context. This module defines the GeneralRegisters structure for storing and manipulating register state, along with assembly macros for efficient stack-based register preservation. These components are essential for managing guest CPU state during VM exits and entries in the VMX virtualization engine.
For information about model-specific register (MSR) access, see MSR Access. For VMX-specific register handling during VM exits, see Virtual CPU Management.
GeneralRegisters Structure
The GeneralRegisters struct provides a C-compatible representation of the x86-64 general-purpose register set. This structure serves as the primary container for guest register state during hypervisor operations.
flowchart TD
subgraph subGraph1["Key Features"]
CRepr["#[repr(C)]C ABI Compatible"]
Debug["#[derive(Debug)]Debug output"]
Default["#[derive(Default)]Zero initialization"]
Clone["#[derive(Clone)]Copy semantics"]
end
subgraph subGraph0["GeneralRegisters Structure"]
RAX["rax: u64Return values"]
RCX["rcx: u64Loop counter"]
RDX["rdx: u64I/O operations"]
RBX["rbx: u64Base pointer"]
RSP["_unused_rsp: u64(Padding)"]
RBP["rbp: u64Frame pointer"]
RSI["rsi: u64Source index"]
RDI["rdi: u64Dest index"]
R8["r8: u64GP register"]
R9["r9: u64GP register"]
R10["r10: u64GP register"]
R11["r11: u64GP register"]
R12["r12: u64GP register"]
R13["r13: u64GP register"]
R14["r14: u64GP register"]
R15["r15: u64GP register"]
end
CRepr --> RAX
Clone --> RAX
Debug --> RAX
Default --> RAX
Register Layout and Characteristics:
| Register | Purpose | Index | Notes |
|---|---|---|---|
| rax | Return values, accumulator | 0 | Primary return register |
| rcx | Loop counter, 4th argument | 1 | Often used in loops |
| rdx | I/O operations, 3rd argument | 2 | Data register |
| rbx | Base pointer, callee-saved | 3 | Preserved across calls |
| _unused_rsp | Stack pointer (unused) | 4 | Excluded from direct access |
| rbp | Frame pointer, callee-saved | 5 | Stack frame base |
| rsi | Source index, 2nd argument | 6 | String operations source |
| rdi | Destination index, 1st argument | 7 | String operations destination |
| r8-r15 | Extended registers | 8-15 | Additional 64-bit registers |
Sources: src/regs.rs(L1 - L40)
Index-Based Register Access
The GeneralRegisters struct provides index-based access methods that map numerical indices to specific registers, following the x86-64 register encoding scheme used in instruction operands.
flowchart TD
subgraph subGraph1["Access Methods"]
GetReg["get_reg_of_index(index: u8) -> u64"]
SetReg["set_reg_of_index(index: u8, value: u64)"]
end
subgraph subGraph0["Register Index Mapping"]
I0["Index 0"]
RAX["rax"]
I1["Index 1"]
RCX["rcx"]
I2["Index 2"]
RDX["rdx"]
I3["Index 3"]
RBX["rbx"]
I4["Index 4"]
SKIP["(unused - rsp)"]
I5["Index 5"]
RBP["rbp"]
I6["Index 6"]
RSI["rsi"]
I7["Index 7"]
RDI["rdi"]
I8["Index 8"]
R8["r8"]
I9["Index 9"]
R9["r9"]
I10["Index 10"]
R10["r10"]
I11["Index 11"]
R11["r11"]
I12["Index 12"]
R12["r12"]
I13["Index 13"]
R13["r13"]
I14["Index 14"]
R14["r14"]
I15["Index 15"]
R15["r15"]
end
GetReg --> SetReg
I0 --> GetReg
I0 --> RAX
I1 --> RCX
I10 --> R10
I11 --> R11
I12 --> R12
I13 --> R13
I14 --> R14
I15 --> R15
I2 --> RDX
I3 --> RBX
I4 --> SKIP
I5 --> RBP
I6 --> RSI
I7 --> RDI
I8 --> R8
I9 --> R9
Key Implementation Details:
- Index Range: Valid indices are 0-15, excluding index 4 (RSP)
- Panic Behavior: Both methods panic on invalid indices or attempts to access RSP
- Performance: Direct match statements provide efficient O(1) access
- Safety: Index validation prevents undefined behavior
Usage Pattern:
// Reading a register by index
let rax_value = registers.get_reg_of_index(0); // Gets RAX
// Writing a register by index
registers.set_reg_of_index(8, 0x12345678); // Sets R8
Sources: src/regs.rs(L42 - L152)
Stack-Based Register Preservation
The module provides assembly macros for efficient bulk register save and restore operations, essential for hypervisor context switching and interrupt handling.
sequenceDiagram
participant HypervisorCode as "Hypervisor Code"
participant StackMemory as "Stack Memory"
participant CPURegisters as "CPU Registers"
Note over HypervisorCode: save_regs_to_stack!()
HypervisorCode ->> StackMemory: push r15
HypervisorCode ->> StackMemory: push r14
HypervisorCode ->> StackMemory: push r13
HypervisorCode ->> StackMemory: push r12
HypervisorCode ->> StackMemory: push r11
HypervisorCode ->> StackMemory: push r10
HypervisorCode ->> StackMemory: push r9
HypervisorCode ->> StackMemory: push r8
HypervisorCode ->> StackMemory: push rdi
HypervisorCode ->> StackMemory: push rsi
HypervisorCode ->> StackMemory: push rbp
HypervisorCode ->> StackMemory: sub rsp, 8 (skip rsp)
HypervisorCode ->> StackMemory: push rbx
HypervisorCode ->> StackMemory: push rdx
HypervisorCode ->> StackMemory: push rcx
HypervisorCode ->> StackMemory: push rax
Note over HypervisorCode: Critical section executes
Note over HypervisorCode: restore_regs_from_stack!()
StackMemory ->> CPURegisters: pop rax
StackMemory ->> CPURegisters: pop rcx
StackMemory ->> CPURegisters: pop rdx
StackMemory ->> CPURegisters: pop rbx
HypervisorCode ->> HypervisorCode: add rsp, 8 (skip rsp)
StackMemory ->> CPURegisters: pop rbp
StackMemory ->> CPURegisters: pop rsi
StackMemory ->> CPURegisters: pop rdi
StackMemory ->> CPURegisters: pop r8
StackMemory ->> CPURegisters: pop r9
StackMemory ->> CPURegisters: pop r10
StackMemory ->> CPURegisters: pop r11
StackMemory ->> CPURegisters: pop r12
StackMemory ->> CPURegisters: pop r13
StackMemory ->> CPURegisters: pop r14
StackMemory ->> CPURegisters: pop r15
Macro Implementation:
| Macro | Purpose | Stack Operations | RSP Handling |
|---|---|---|---|
| save_regs_to_stack! | Preserve all GP registers | 15 push operations + 1 subtract | sub rsp, 8to skip RSP slot |
| restore_regs_from_stack! | Restore all GP registers | 15 pop operations + 1 add | add rsp, 8to skip RSP slot |
Key Features:
- Order Preservation: Restore operations reverse the save order exactly
- RSP Handling: Stack pointer excluded from save/restore, space reserved with arithmetic
- Atomicity: Complete register set saved/restored as a unit
- Performance: Inline assembly provides minimal overhead
Sources: src/regs.rs(L154 - L196)
Integration with VMX System
The register management components integrate tightly with the VMX virtualization engine to support guest state management during VM transitions.
flowchart TD
subgraph subGraph2["VMX Components"]
VmxVcpu["VmxVcpu"]
VMCS["VMCS Fields"]
ExitHandler["Exit Handlers"]
end
subgraph subGraph1["Register Operations"]
SaveMacro["save_regs_to_stack!()"]
RestoreMacro["restore_regs_from_stack!()"]
GeneralRegs["GeneralRegisters"]
IndexAccess["Index-based Access"]
end
subgraph subGraph0["VMX Context Usage"]
VmExit["VM Exit Handler"]
VmEntry["VM Entry Preparation"]
GuestState["Guest Register State"]
HostState["Host Register State"]
end
ExitHandler --> IndexAccess
GeneralRegs --> IndexAccess
GuestState --> GeneralRegs
RestoreMacro --> HostState
SaveMacro --> GuestState
VMCS --> GuestState
VmEntry --> RestoreMacro
VmExit --> SaveMacro
VmxVcpu --> VmEntry
VmxVcpu --> VmExit
Integration Points:
- VM Exit Processing: Register state captured using stack macros during VM exits
- Guest State Management:
GeneralRegistersstores guest CPU state between VM operations - Instruction Emulation: Index-based access enables register modification for emulated instructions
- Context Switching: Stack preservation ensures host state integrity during guest execution
Performance Considerations:
- Zero-Copy: Direct register field access avoids unnecessary copying
- Cache Efficiency: C-compatible layout optimizes memory access patterns
- Assembly Integration: Macros provide efficient bulk operations for critical paths
Sources: src/regs.rs(L1 - L196)