Low-Level Implementation
Relevant source files
This page covers the assembly-level implementations, hardware register definitions, and low-level system constants that form the foundation of the RISC-V VCPU system. This includes the critical assembly trap handlers, Control and Status Register (CSR) bitfield definitions, and system-wide constants for interrupts and exceptions.
For higher-level VCPU management and lifecycle operations, see Core VCPU Implementation. For register state management data structures, see Register Management.
Assembly Trap Handler Implementation
The core of the hypervisor's guest-host transition mechanism is implemented in assembly language through the trap handler system. This provides the critical low-level routines for entering and exiting guest virtual machines.
Guest Entry and Exit Assembly Functions
The system implements two primary assembly functions that handle the critical guest-hypervisor transitions:
Guest Entry Flow (_run_guest
)
flowchart TD start["_run_guest"] save_hyp["Save Hypervisor GPRs"] swap_csr["Swap in Guest CSRs"] set_stvec["Set stvec to _guest_exit"] save_sscratch["Save sscratch, set to GuestInfo"] restore_guest["Restore Guest GPRs"] sret["sret - Enter Guest"] guest_exec["Guest Execution"] trap["VM Exit/Trap"] guest_exit["_guest_exit"] guest_exec --> trap restore_guest --> sret save_hyp --> swap_csr save_sscratch --> restore_guest set_stvec --> save_sscratch sret --> guest_exec start --> save_hyp swap_csr --> set_stvec trap --> guest_exit
Guest Exit Flow (_guest_exit
)
flowchart TD guest_exit["_guest_exit"] swap_a0["Swap GuestInfo from sscratch"] save_guest["Save Guest GPRs"] save_guest_a0["Save Guest a0 from sscratch"] restore_csr["Swap in Hypervisor CSRs"] save_sepc["Save Guest EPC"] restore_hyp["Restore Hypervisor GPRs"] ret_hyp["ret - Return to Hypervisor"] guest_exit --> swap_a0 restore_csr --> save_sepc restore_hyp --> ret_hyp save_guest --> save_guest_a0 save_guest_a0 --> restore_csr save_sepc --> restore_hyp swap_a0 --> save_guest
The assembly implementation uses precise register offset calculations to access the VmCpuRegisters
structure fields. The offsets are computed using compile-time constants generated by the hyp_gpr_offset
and guest_gpr_offset
functions in src/trap.rs(L8 - L19)
Sources: src/trap.S(L1 - L183) src/trap.rs(L1 - L103)
Register Context Switching Mechanism
The trap handler performs comprehensive context switching between hypervisor and guest register states:
flowchart TD subgraph subGraph1["Memory Layout"] VmCpuRegs["VmCpuRegisters"] HypState["HypervisorCpuStatehyp_regs"] GuestState["GuestCpuStateguest_regs"] end subgraph subGraph0["Register Categories"] GPRs["General Purpose Registersra, gp, tp, s0-s11, a1-a7, sp"] CSRs["Control Status Registerssstatus, hstatus, scounterenstvec, sscratch, sepc"] Special["Special Handlinga0 (via sscratch)t0-t6 (guest only)"] end CSRs --> GuestState CSRs --> HypState GPRs --> GuestState GPRs --> HypState VmCpuRegs --> GuestState VmCpuRegs --> HypState
The offset calculation macros hyp_csr_offset!
and guest_csr_offset!
at src/trap.rs(L22 - L33) enable the assembly code to access specific CSR fields within the register structure using compile-time computed offsets.
Sources: src/trap.rs(L35 - L102) src/trap.S(L32 - L156)
CSR Register Definitions and Hardware Interfaces
The system provides comprehensive definitions for RISC-V Control and Status Registers using the tock_registers
framework, enabling type-safe bitfield manipulation of hardware registers.
Hypervisor Extension CSR Definitions
Key hypervisor-specific CSRs are defined with detailed bitfield structures:
CSR Name | Address | Purpose |
---|---|---|
hstatus | 0x600 | Hypervisor status register |
hedeleg | 0x602 | Hypervisor exception delegation |
hideleg | 0x603 | Hypervisor interrupt delegation |
hie | 0x604 | Hypervisor interrupt enable |
hcounteren | 0x606 | Hypervisor counter enable |
hvip | 0x645 | Hypervisor virtual interrupt pending |
HSTATUS Register Bitfield Layout
The hstatus
register contains critical hypervisor state control bits:
flowchart TD subgraph subGraph0["hstatus Register Fields"] VSBE["vsbe[6]Virtual SupervisorBig Endian"] GVA["gva[6]Guest VirtualAddress"] SPV["spv[7]Supervisor PreviousVirtualization Mode"] SPVP["spvp[8]Supervisor PreviousVirtual Privilege"] HU["hu[9]Hypervisor inUser Mode"] VGEIN["vgein[17:12]Virtual GuestExternal Interrupt"] VTVM["vtvm[20]Virtual TLBManagement"] VTW["vtw[21]Virtual TimeoutWait"] VTSR["vtsr[22]Virtual TimeoutState Reporting"] VSXL["vsxl[33:32]Virtual SupervisorXLEN"] end
The SPV field uses enumerated values for privilege modes:
User = 0
- User mode virtualizationSupervisor = 1
- Supervisor mode virtualization
Sources: def.rs(L37 - L1284)
Exception and Interrupt Delegation Registers
The hedeleg
register controls which exceptions are delegated to VS-mode:
flowchart TD subgraph subGraph0["Exception Types (hedeleg)"] MISALIGN["instr_misaligned[0]Instruction Address Misaligned"] IFAULT["instr_fault[1]Instruction Access Fault"] ILLEGAL["illegal_instr[2]Illegal Instruction"] BREAK["breakpoint[3]Breakpoint"] LMISALIGN["load_misaligned[4]Load Address Misaligned"] LFAULT["load_fault[5]Load Access Fault"] SMISALIGN["store_misaligned[6]Store Address Misaligned"] SFAULT["store_fault[7]Store Access Fault"] UECALL["u_ecall[8]User Environment Call"] IPFAULT["instr_page_fault[12]Instruction Page Fault"] LPFAULT["load_page_fault[13]Load Page Fault"] SPFAULT["store_page_fault[15]Store Page Fault"] end
The hideleg
register controls interrupt delegation with fields for:
vssoft[2]
- VS-mode software interruptvstimer[6]
- VS-mode timer interruptvsext[10]
- VS-mode external interrupt
Sources: def.rs(L55 - L1420)
System Constants and Trap Definitions
The system defines comprehensive constants for interrupt handling, exception types, and trap processing organized into logical modules.
Interrupt Type Constants
The interrupt constants are organized by interrupt source and privilege level:
flowchart TD subgraph subGraph0["Interrupt Constants (consts::traps::interrupt)"] USER_SOFT["USER_SOFT = 1<<0"] SUPERVISOR_SOFT["SUPERVISOR_SOFT = 1<<1"] VIRTUAL_SUPERVISOR_SOFT["VIRTUAL_SUPERVISOR_SOFT = 1<<2"] MACHINE_SOFT["MACHINE_SOFT = 1<<3"] USER_TIMER["USER_TIMER = 1<<4"] SUPERVISOR_TIMER["SUPERVISOR_TIMER = 1<<5"] VIRTUAL_SUPERVISOR_TIMER["VIRTUAL_SUPERVISOR_TIMER = 1<<6"] MACHINE_TIMER["MACHINE_TIMER = 1<<7"] USER_EXTERNAL["USER_EXTERNAL = 1<<8"] SUPERVISOR_EXTERNAL["SUPERVISOR_EXTERNAL = 1<<9"] VIRTUAL_SUPERVISOR_EXTERNAL["VIRTUAL_SUPERVISOR_EXTERNAL = 1<<10"] MACHINEL_EXTERNAL["MACHINEL_EXTERNAL = 1<<11"] SUPERVISOR_GUEST_EXTERNEL["SUPERVISOR_GUEST_EXTERNEL = 1<<12"] end
Exception Type Constants
Exception constants define the various fault and trap conditions:
Exception Type | Constant Value | Description |
---|---|---|
INST_ADDR_MISALIGN | 1<<0 | Instruction address misaligned |
INST_ACCESSS_FAULT | 1<<1 | Instruction access fault |
ILLEGAL_INST | 1<<2 | Illegal instruction |
BREAKPOINT | 1<<3 | Breakpoint |
LOAD_ADDR_MISALIGNED | 1<<4 | Load address misaligned |
LOAD_ACCESS_FAULT | 1<<5 | Load access fault |
STORE_ADDR_MISALIGNED | 1<<6 | Store address misaligned |
STORE_ACCESS_FAULT | 1<<7 | Store access fault |
ENV_CALL_FROM_U_OR_VU | 1<<8 | Environment call from U-mode or VU-mode |
ENV_CALL_FROM_HS | 1<<9 | Environment call from HS-mode |
ENV_CALL_FROM_VS | 1<<10 | Environment call from VS-mode |
ENV_CALL_FROM_M | 1<<11 | Environment call from M-mode |
IRQ Processing Constants
The IRQ module provides constants for interrupt processing and cause register interpretation:
flowchart TD subgraph subGraph0["IRQ Constants (consts::traps::irq)"] INTC_BASE["INTC_IRQ_BASE1 << (usize::BITS - 1)Interrupt Bit Mask"] S_SOFT["S_SOFTINTC_IRQ_BASE + 1Supervisor Software IRQ"] S_TIMER["S_TIMERINTC_IRQ_BASE + 5Supervisor Timer IRQ"] S_EXT["S_EXTINTC_IRQ_BASE + 9Supervisor External IRQ"] MAX_IRQ["MAX_IRQ_COUNT = 1024Maximum IRQ Number"] TIMER_IRQ["TIMER_IRQ_NUM = S_TIMERTimer IRQ Identifier"] end
The INTC_IRQ_BASE
constant at src/consts.rs(L79) provides the base value for distinguishing interrupts from exceptions in the scause
register, with interrupts having the most significant bit set.
Sources: src/consts.rs(L1 - L92)