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:

RegisterPurposeIndexNotes
raxReturn values, accumulator0Primary return register
rcxLoop counter, 4th argument1Often used in loops
rdxI/O operations, 3rd argument2Data register
rbxBase pointer, callee-saved3Preserved across calls
_unused_rspStack pointer (unused)4Excluded from direct access
rbpFrame pointer, callee-saved5Stack frame base
rsiSource index, 2nd argument6String operations source
rdiDestination index, 1st argument7String operations destination
r8-r15Extended registers8-15Additional 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:

MacroPurposeStack OperationsRSP Handling
save_regs_to_stack!Preserve all GP registers15 push operations + 1 subtractsub rsp, 8to skip RSP slot
restore_regs_from_stack!Restore all GP registers15 pop operations + 1 addadd 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)