Per-CPU Management
Relevant source files
Purpose and Scope
This document describes the per-CPU state management system in the RISC-V VCPU hypervisor, focusing on how each CPU core is initialized and configured for virtualization. The per-CPU management system handles Control and Status Register (CSR) initialization, hardware feature enablement, and interrupt/exception delegation setup required for RISC-V hypervisor extensions.
For information about overall VCPU lifecycle management, see VCPU Lifecycle and Management. For details about hardware feature detection, see Hardware Detection. For CSR register definitions and bitfield details, see CSR Definitions and Hardware Registers.
Per-CPU Architecture Overview
The per-CPU management system provides a hardware abstraction layer that initializes each CPU core for hypervisor operation. It bridges the gap between the ArceOS framework's generic per-CPU interface and RISC-V-specific hypervisor initialization requirements.
flowchart TD
subgraph subGraph2["Hardware Layer"]
hedeleg["HEDELEG CSR"]
hideleg["HIDELEG CSR"]
hvip["HVIP CSR"]
hcounteren["HCOUNTEREN CSR"]
sie["SIE CSR"]
end
subgraph subGraph1["RISC-V Per-CPU Implementation"]
RISCVPerCpu["RISCVPerCpu<H>"]
setup_csrs["setup_csrs()"]
hardware_enable["hardware_enable()"]
has_hardware_support["has_hardware_support()"]
end
subgraph subGraph0["ArceOS Framework"]
AxArchPerCpu["AxArchPerCpu Trait"]
AxVCpuHal["AxVCpuHal Interface"]
end
AxArchPerCpu --> RISCVPerCpu
AxVCpuHal --> RISCVPerCpu
RISCVPerCpu --> hardware_enable
RISCVPerCpu --> setup_csrs
hardware_enable --> has_hardware_support
setup_csrs --> hcounteren
setup_csrs --> hedeleg
setup_csrs --> hideleg
setup_csrs --> hvip
setup_csrs --> sie
Sources: src/percpu.rs(L1 - L82)
RISCVPerCpu Structure and Lifecycle
The RISCVPerCpu struct serves as the primary per-CPU state container, implementing the AxArchPerCpu trait to integrate with the ArceOS hypervisor framework.
Structure Definition
The structure uses a PhantomData marker to maintain the generic AxVCpuHal type parameter while storing no actual data, as the per-CPU state is maintained entirely in hardware CSRs.
Sources: src/percpu.rs(L10 - L13) src/percpu.rs(L15 - L41)
Initialization Flow
The per-CPU initialization follows a specific sequence that prepares each CPU core for hypervisor operation:
flowchart TD
subgraph subGraph0["setup_csrs() Details"]
exception_delegate["Configure Exception Delegation (HEDELEG)"]
interrupt_delegate["Configure Interrupt Delegation (HIDELEG)"]
clear_interrupts["Clear Virtual Interrupts (HVIP)"]
inst_misalign["INST_ADDR_MISALIGN"]
breakpoint["BREAKPOINT"]
ecall["ENV_CALL_FROM_U_OR_VU"]
page_faults["Page Fault Exceptions"]
vs_timer["VIRTUAL_SUPERVISOR_TIMER"]
vs_external["VIRTUAL_SUPERVISOR_EXTERNAL"]
vs_soft["VIRTUAL_SUPERVISOR_SOFT"]
clear_vssip["hvip::clear_vssip()"]
clear_vstip["hvip::clear_vstip()"]
clear_vseip["hvip::clear_vseip()"]
end
Start["RISCVPerCpu::new(cpu_id)"]
setup_csrs_call["Call setup_csrs()"]
setup_counters["Setup Counter Access (HCOUNTEREN)"]
enable_interrupts["Enable Supervisor Interrupts (SIE)"]
create_struct["Create RISCVPerCpu Instance"]
End["Return AxResult"]
Start --> setup_csrs_call
clear_interrupts --> clear_vseip
clear_interrupts --> clear_vssip
clear_interrupts --> clear_vstip
clear_interrupts --> setup_counters
create_struct --> End
enable_interrupts --> create_struct
exception_delegate --> breakpoint
exception_delegate --> ecall
exception_delegate --> inst_misalign
exception_delegate --> interrupt_delegate
exception_delegate --> page_faults
interrupt_delegate --> clear_interrupts
interrupt_delegate --> vs_external
interrupt_delegate --> vs_soft
interrupt_delegate --> vs_timer
setup_counters --> enable_interrupts
setup_csrs_call --> exception_delegate
Sources: src/percpu.rs(L16 - L24) src/percpu.rs(L44 - L81)
CSR Initialization Process
The setup_csrs() function performs critical hypervisor-level Control and Status Register initialization. This unsafe function configures the hardware delegation and interrupt management necessary for virtualization.
Exception Delegation Configuration
The hypervisor exception delegation register (HEDELEG) is configured to automatically forward specific exceptions from guest execution to the guest's supervisor mode rather than trapping to the hypervisor:
| Exception Type | Constant | Purpose |
|---|---|---|
| Instruction Address Misaligned | INST_ADDR_MISALIGN | Memory alignment errors |
| Breakpoint | BREAKPOINT | Debug breakpoint traps |
| Environment Call | ENV_CALL_FROM_U_OR_VU | System calls from user/virtual-user mode |
| Instruction Page Fault | INST_PAGE_FAULT | Instruction fetch page faults |
| Load Page Fault | LOAD_PAGE_FAULT | Load operation page faults |
| Store Page Fault | STORE_PAGE_FAULT | Store operation page faults |
| Illegal Instruction | ILLEGAL_INST | Invalid instruction execution |
Sources: src/percpu.rs(L47 - L56) src/consts.rs
Interrupt Delegation Setup
The hypervisor interrupt delegation register (HIDELEG) forwards virtual supervisor-level interrupts directly to the guest:
flowchart TD
subgraph subGraph2["Guest Handling"]
GuestISR["Guest Interrupt Handlers"]
end
subgraph subGraph1["HIDELEG Configuration"]
VSTIMER_BIT["VIRTUAL_SUPERVISOR_TIMER"]
VSEXT_BIT["VIRTUAL_SUPERVISOR_EXTERNAL"]
VSSOFT_BIT["VIRTUAL_SUPERVISOR_SOFT"]
end
subgraph subGraph0["Interrupt Sources"]
VSTimer["Virtual Supervisor Timer"]
VSExternal["Virtual Supervisor External"]
VSSoft["Virtual Supervisor Software"]
end
VSEXT_BIT --> GuestISR
VSExternal --> VSEXT_BIT
VSSOFT_BIT --> GuestISR
VSSoft --> VSSOFT_BIT
VSTIMER_BIT --> GuestISR
VSTimer --> VSTIMER_BIT
Sources: src/percpu.rs(L59 - L64) src/consts.rs
Counter and Interrupt Enablement
The initialization process also configures:
- Counter Access (
HCOUNTEREN): Enables guest access to performance counters by setting all bits to 1 - Virtual Interrupt Clearing (
HVIP): Clears all pending virtual supervisor interrupts - Supervisor Interrupt Enable (
SIE): Enables external, software, and timer interrupts at supervisor level
Sources: src/percpu.rs(L67 - L79)
Hardware Enablement Interface
The per-CPU system provides hardware enablement control through the AxArchPerCpu trait implementation:
stateDiagram-v2 [*] --> Uninitialized Uninitialized --> Initialized : new(cpu_id) Initialized --> HardwareEnabled : hardware_enable() HardwareEnabled --> HardwareDisabled : hardware_disable() HardwareDisabled --> HardwareEnabled : hardware_enable() note left of HardwareEnabled : ['has_hardware_support() == true'] note left of HardwareDisabled : ['Hardware virtualization disabled'] note left of Uninitialized : ['Per-CPU state not created']
Hardware Support Validation
The hardware_enable() method validates that the underlying hardware supports RISC-V hypervisor extensions before enabling virtualization features:
- Success Path: Returns
Ok(())whenhas_hardware_support()returnstrue - Failure Path: Returns
AxError::Unsupportedwhen hardware lacks H-extension support
Sources: src/percpu.rs(L30 - L36)
Unimplemented Features
The current implementation includes placeholder methods for future functionality:
is_enabled(): Returns whether hardware virtualization is currently active (unimplemented)hardware_disable(): Disables hardware virtualization features (unimplemented)
Sources: src/percpu.rs(L26 - L28) src/percpu.rs(L38 - L40)
Integration with System Architecture
The per-CPU management system integrates with the broader RISC-V hypervisor architecture through several key interfaces:
flowchart TD
subgraph subGraph3["VCPU Management"]
VCPUCreation["VCPU Creation"]
VCPUExecution["VCPU Execution"]
end
subgraph subGraph2["Hardware Detection"]
has_hardware_support_func["has_hardware_support()"]
detect_h_extension["detect_h_extension()"]
end
subgraph subGraph1["Per-CPU Layer"]
RISCVPerCpu_new["RISCVPerCpu::new()"]
setup_csrs_func["setup_csrs()"]
hardware_enable_func["hardware_enable()"]
end
subgraph subGraph0["System Initialization"]
SystemBoot["System Boot"]
CPUEnumeration["CPU Enumeration"]
PerCPUCreation["Per-CPU Creation"]
end
CPUEnumeration --> PerCPUCreation
PerCPUCreation --> RISCVPerCpu_new
RISCVPerCpu_new --> hardware_enable_func
RISCVPerCpu_new --> setup_csrs_func
SystemBoot --> CPUEnumeration
VCPUCreation --> VCPUExecution
hardware_enable_func --> has_hardware_support_func
has_hardware_support_func --> detect_h_extension
setup_csrs_func --> VCPUCreation
This per-CPU initialization must complete successfully before any VCPU instances can be created or executed on the respective CPU core, ensuring that the hardware virtualization environment is properly configured.
Sources: src/percpu.rs(L1 - L82) src/detect.rs