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:
GeneralRegisters
stores 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)