Hardware Detection

Relevant source files

This page documents the trap-based hardware feature detection system used to identify RISC-V H-extension support at runtime. The detection mechanism safely probes for hypervisor extension availability by attempting to access hypervisor-specific Control Status Registers (CSRs) and catching any resulting illegal instruction exceptions.

For information about per-CPU management and CSR initialization, see Per-CPU Management. For details about trap handling in the main VCPU system, see VM Exit Processing.

Purpose and Scope

The hardware detection system provides runtime identification of RISC-V hypervisor extension support through a controlled trap-and-return procedure. The system disables interrupts, attempts to access hypervisor CSRs, and uses exception handling to determine whether the hardware supports the required extensions.

Sources: src/detect.rs(L1 - L6) 

Detection Process Overview

The hardware detection system uses a trap-based approach to safely probe for hardware features. The process attempts to read the hgatp (Hypervisor Guest Address Translation and Protection) register, which is only available when the H-extension is present.

Detection Flow Diagram

flowchart TD
Start["detect_h_extension()"]
Setup["with_detect_trap()"]
DisableInt["Disable S-level interrupts"]
SetTrap["Set custom trap handler"]
AttemptCSR["Attempt to read hgatp CSR (0x680)"]
Success["CSR read successful"]
IllegalInst["Illegal instruction exception"]
RestoreOrig["Restore original state"]
TrapHandler["on_detect_trap assembly handler"]
RustHandler["rust_detect_trap()"]
SkipInst["Skip illegal instruction"]
RestoreAfterTrap["Restore original state"]
ReturnTrue["Return true (H-extension present)"]
ReturnFalse["Return false (H-extension absent)"]
End["Hardware support confirmed"]

AttemptCSR --> IllegalInst
AttemptCSR --> Success
DisableInt --> SetTrap
IllegalInst --> TrapHandler
RestoreAfterTrap --> ReturnFalse
RestoreOrig --> ReturnTrue
ReturnFalse --> End
ReturnTrue --> End
RustHandler --> SkipInst
SetTrap --> AttemptCSR
Setup --> DisableInt
SkipInst --> RestoreAfterTrap
Start --> Setup
Success --> RestoreOrig
TrapHandler --> RustHandler

Sources: src/detect.rs(L18 - L25)  src/detect.rs(L32 - L39) 

Implementation Architecture

The detection system consists of several interconnected components that work together to safely probe hardware features and handle any resulting exceptions.

Component Relationships

flowchart TD
subgraph subGraph3["Hardware Interface"]
    CSRAccess["CSR Access (hgatp)"]
    InsnDecoding["riscv_illegal_insn_bits()"]
end
subgraph subGraph2["Trap Handling System"]
    AsmHandler["on_detect_trap() (naked asm)"]
    RustHandler["rust_detect_trap()"]
    TrapFrameStruct["TrapFrame struct"]
end
subgraph subGraph1["Core Detection Logic"]
    WithTrap["with_detect_trap()"]
    InitTrap["init_detect_trap()"]
    RestoreTrap["restore_detect_trap()"]
end
subgraph subGraph0["Public Interface"]
    DetectFunc["detect_h_extension()"]
    PublicAPI["has_hardware_support (lib.rs)"]
end

AsmHandler --> RustHandler
CSRAccess --> AsmHandler
DetectFunc --> WithTrap
InitTrap --> AsmHandler
PublicAPI --> DetectFunc
RestoreTrap --> WithTrap
RustHandler --> InsnDecoding
RustHandler --> TrapFrameStruct
WithTrap --> CSRAccess
WithTrap --> InitTrap
WithTrap --> RestoreTrap

Sources: src/lib.rs(L20)  src/detect.rs(L18 - L25)  src/detect.rs(L32 - L39)  src/detect.rs(L155 - L217) 

Detection Process Implementation

The detect_h_extension() function serves as the primary entry point for hardware detection. It uses a controlled environment to attempt accessing hypervisor-specific CSRs.

Core Detection Function

The detection process attempts to read the hgatp CSR (register 0x680) within a controlled trap environment:

// From detect.rs lines 18-25
pub fn detect_h_extension() -> bool {
    let ans = with_detect_trap(0, || unsafe {
        asm!("csrr  {}, 0x680", out(reg) _, options(nomem, nostack)); // 0x680 => hgatp
    });
    ans != 2  // 0 => success, 2 => failed (illegal instruction)
}

The function returns true if the CSR access succeeds (indicating H-extension presence) or false if an illegal instruction exception occurs (indicating absence).

Sources: src/detect.rs(L18 - L25) 

Trap Environment Setup

The with_detect_trap() function creates a controlled environment for safe hardware probing:

PhaseFunctionPurpose
Setupinit_detect_trap()Disable interrupts, set custom trap handler
ExecutionClosure parameterExecute the probing instruction
Cleanuprestore_detect_trap()Restore original state, return result

The setup process preserves the original system state while creating a minimal trap handling environment.

Sources: src/detect.rs(L32 - L39)  src/detect.rs(L81 - L101)  src/detect.rs(L105 - L118) 

Trap Handling Mechanism

When an illegal instruction exception occurs during hardware probing, the system uses a specialized trap handling mechanism to safely recover and continue execution.

Trap Handler Flow

sequenceDiagram
    participant CPUCore as "CPU Core"
    participant on_detect_trapasm as "on_detect_trap() (asm)"
    participant rust_detect_trap as "rust_detect_trap()"
    participant TrapFrame as "TrapFrame"

    CPUCore ->> on_detect_trapasm: "Illegal instruction exception"
    on_detect_trapasm ->> TrapFrame: "Save all registers to TrapFrame"
    on_detect_trapasm ->> rust_detect_trap: "Call with TrapFrame pointer"
    rust_detect_trap ->> TrapFrame: "Read scause, stval, sepc"
    rust_detect_trap ->> rust_detect_trap: "Decode instruction length"
    rust_detect_trap ->> TrapFrame: "Update sepc to skip instruction"
    rust_detect_trap ->> TrapFrame: "Set tp register with exception code"
    rust_detect_trap ->> on_detect_trapasm: "Return to assembly handler"
    on_detect_trapasm ->> TrapFrame: "Restore all registers"
    on_detect_trapasm ->> CPUCore: "sret (return from trap)"

Sources: src/detect.rs(L155 - L217)  src/detect.rs(L42 - L60) 

TrapFrame Structure

The trap handler uses a specialized TrapFrame structure to preserve processor state during exception handling:

// Key fields from TrapFrame (lines 122-144)
struct TrapFrame {
    ra: usize,     // Return address
    tp: usize,     // Thread pointer (used for return value)
    a0-a7: usize,  // Argument registers
    t0-t6: usize,  // Temporary registers
    sstatus: usize, // Supervisor status
    sepc: usize,   // Exception program counter
    scause: Scause,// Exception cause
    stval: usize,  // Trap value
}

The tp register serves dual purposes: passing parameters into the detection routine and returning the exception code.

Sources: src/detect.rs(L121 - L144) 

Exception Processing and Recovery

The trap handler analyzes exceptions and implements appropriate recovery mechanisms based on the exception type.

Exception Analysis Process

flowchart TD
TrapEntry["rust_detect_trap() entry"]
ReadCause["Read scause register"]
CheckType["Exception type?"]
ProcessIllegal["Process illegal instruction"]
Unreachable1["unreachable!()"]
Unreachable2["unreachable!() (filtered)"]
ReadStval["Read stval for instruction bits"]
CheckStval["stval[0..16] == 0?"]
ReadMemory["Read instruction from sepc"]
DecodeStval["Decode from stval"]
DecodeLength["riscv_illegal_insn_bits()"]
UpdateSepc["sepc += instruction_length"]
SetReturnCode["tp = scause.bits()"]
Return["Return to assembly handler"]

CheckStval --> DecodeStval
CheckStval --> ReadMemory
CheckType --> ProcessIllegal
CheckType --> Unreachable1
CheckType --> Unreachable2
DecodeLength --> UpdateSepc
DecodeStval --> DecodeLength
ProcessIllegal --> ReadStval
ReadCause --> CheckType
ReadMemory --> DecodeLength
ReadStval --> CheckStval
SetReturnCode --> Return
TrapEntry --> ReadCause
UpdateSepc --> SetReturnCode

Sources: src/detect.rs(L42 - L60)  src/detect.rs(L64 - L77) 

Instruction Length Decoding

The system includes logic to determine RISC-V instruction lengths for proper exception recovery:

Instruction PatternLengthEncoding
xxxxxxxxxxxxxxxx11(bits [1:0] != 11)16-bitCompressed
xxxxxxxxxxxxxxxnnn11(bits [4:2] != 111)32-bitStandard
xxxxxxxxxxxxxxx11111(bits [4:2] == 111)≥48-bitExtended

The riscv_illegal_insn_bits() function implements this decoding logic to ensure the exception handler skips the correct number of bytes.

Sources: src/detect.rs(L64 - L77) 

Integration with System Architecture

The hardware detection system integrates with the broader RISC-V VCPU architecture through the public API and initialization processes.

Public Interface Integration

The detection functionality is exposed through the main library interface:

// From lib.rs line 20
pub use detect::detect_h_extension as has_hardware_support;

This allows other system components to query hardware capabilities before attempting to use hypervisor features.

Sources: src/lib.rs(L20) 

Error Handling Strategy

The detection system uses a fail-safe approach where:

  • Successful CSR access indicates H-extension support
  • Any exception (particularly illegal instruction) indicates lack of support
  • The system gracefully recovers from all exception scenarios
  • No system state is permanently modified during detection

This approach ensures that hardware detection can safely run on any RISC-V system, regardless of hypervisor extension availability.

Sources: src/detect.rs(L18 - L25)  src/detect.rs(L42 - L60)