From ae5fdf78a4d820c9fa6d24f7b9b381b3c4a5d40b Mon Sep 17 00:00:00 2001 From: YanLien Date: Sun, 31 Aug 2025 13:59:25 +0800 Subject: [PATCH 1/4] feat: update crate info --- Cargo.toml | 14 ++++++++------ README.md | 2 +- rust-toolchain.toml | 2 +- src/detect.rs | 27 ++++++++++++++++++--------- src/guest_mem.rs | 6 +++--- src/percpu.rs | 4 +++- src/regs.rs | 7 ++++--- src/vcpu.rs | 17 +++++++++-------- 8 files changed, 47 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 083f8b8..b58002f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "周睿 " ] description = "ArceOS-Hypervisor riscv vcpu module" -license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPubL-2.0 OR MulanPSL2" +license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPSL-2.0" # MulanPubL2 is not included in SPDX repository = "https://github.com/arceos-hypervisor/riscv_vcpu" categories = ["embedded", "no-std"] keywords = ["hypervisor", "riscv", "vcpu"] @@ -21,8 +21,10 @@ bitflags = "2.2" bit_field = "0.10" crate_interface = "0.1" -riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } -riscv-decode = { git = "https://github.com/KuangjuX/riscv-decode.git" } +riscv = { version = "0.14.0" } +riscv-h = "0.1" + +riscv-decode = "0.2.3" rustsbi = { version = "0.4.0", features = ["forward"] } sbi-rt = { version = "0.0.3", features = ["integer-impls"] } sbi-spec = { version = "0.0.7", features = ["legacy"] } @@ -33,6 +35,6 @@ axerrno = "0.1.0" page_table_entry = "0.5" memory_addr = "0.4" -axaddrspace = { git = "https://github.com/arceos-hypervisor/axaddrspace.git" } -axvcpu = { git = "https://github.com/arceos-hypervisor/axvcpu.git" } -axvisor_api = { git = "https://github.com/arceos-hypervisor/axvisor_api.git"} \ No newline at end of file +axaddrspace = "0.1" +axvcpu = "0.1" +axvisor_api = "0.1" diff --git a/README.md b/README.md index e3c11fd..393754f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ riscv_vcpu = "0.1" ## Basic Usage -```rust +```rust,ignore use riscv_vcpu::{RISCVVCpu, RISCVVCpuCreateConfig, has_hardware_support}; // Check if hardware virtualization is supported diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 6289821..06e0e5b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -4,4 +4,4 @@ components = ["rust-src", "llvm-tools", "rustfmt", "clippy"] profile = "minimal" targets = [ "riscv64gc-unknown-none-elf", -] \ No newline at end of file +] diff --git a/src/detect.rs b/src/detect.rs index 8474622..d04d90f 100644 --- a/src/detect.rs +++ b/src/detect.rs @@ -6,10 +6,13 @@ //! ref: use core::arch::{asm, naked_asm}; -use riscv::register::{ - scause::{Exception, Scause, Trap}, - sstatus, - stvec::{self, Stvec, TrapMode}, +use riscv::{ + interrupt::{Exception, Interrupt, Trap}, + register::{ + scause::Scause, + sstatus, + stvec::{self, Stvec, TrapMode}, + }, }; /// Detect if hypervisor extension exists on current hart environment @@ -44,8 +47,8 @@ extern "C" fn rust_detect_trap(trap_frame: &mut TrapFrame) { // specially: illegal instruction => 2 trap_frame.tp = trap_frame.scause.bits(); // if illegal instruction, skip current instruction - match trap_frame.scause.cause() { - Trap::Exception(Exception::IllegalInstruction) => { + match trap_frame.scause.cause().try_into::() { + Ok(Trap::Exception(Exception::IllegalInstruction)) => { let mut insn_bits = riscv_illegal_insn_bits((trap_frame.stval & 0xFFFF) as u16); if insn_bits == 0 { let insn_half = unsafe { *(trap_frame.sepc as *const u16) }; @@ -54,8 +57,9 @@ extern "C" fn rust_detect_trap(trap_frame: &mut TrapFrame) { // skip current instruction trap_frame.sepc = trap_frame.sepc.wrapping_add(insn_bits); } - Trap::Exception(_) => unreachable!(), // FIXME: unexpected instruction errors - Trap::Interrupt(_) => unreachable!(), // filtered out for sie == false + Ok(Trap::Exception(_)) => unreachable!(), // FIXME: unexpected instruction errors + Ok(Trap::Interrupt(_)) => unreachable!(), // filtered out for sie == false + Err(_) => unreachable!(), } } @@ -91,8 +95,13 @@ unsafe fn init_detect_trap(param: usize) -> (bool, Stvec, usize) { trap_addr += 0b1; } let stored_tp: usize; + + let mut stvec = Stvec::from_bits(0); + stvec.try_set_address(trap_addr).unwrap(); + stvec.set_trap_mode(TrapMode::Direct); + unsafe { - stvec::write(trap_addr, TrapMode::Direct); + stvec::write(stvec); // store tp register. tp will be used to load parameter and store return value asm!("mv {}, tp", "mv tp, {}", out(reg) stored_tp, in(reg) param, options(nomem, nostack)); } diff --git a/src/guest_mem.rs b/src/guest_mem.rs index cb54df8..3229ea1 100644 --- a/src/guest_mem.rs +++ b/src/guest_mem.rs @@ -1,6 +1,6 @@ use axaddrspace::{GuestPhysAddr, GuestVirtAddr}; use core::arch::riscv64::hfence_vvma_all; -use riscv::register::vsatp::Vsatp; +use riscv_h::register::vsatp::Vsatp; // Notes about this file: // @@ -38,7 +38,7 @@ pub(crate) fn copy_to_guest_va(src: &[u8], gva: GuestVirtAddr) -> usize { /// Copies data from guest physical address to host memory. #[inline(always)] pub(crate) fn copy_from_guest(dst: &mut [u8], gpa: GuestPhysAddr) -> usize { - let old_vsatp = riscv::register::vsatp::read().bits(); + let old_vsatp = riscv_h::register::vsatp::read().bits(); unsafe { // Set vsatp to 0 to disable guest virtual address translation. Vsatp::from_bits(0).write(); @@ -55,7 +55,7 @@ pub(crate) fn copy_from_guest(dst: &mut [u8], gpa: GuestPhysAddr) -> usize { /// Copies data from host memory to guest physical address. #[inline(always)] pub(crate) fn copy_to_guest(src: &[u8], gpa: GuestPhysAddr) -> usize { - let old_vsatp = riscv::register::vsatp::read().bits(); + let old_vsatp = riscv_h::register::vsatp::read().bits(); unsafe { // Set vsatp to 0 to disable guest virtual address translation. Vsatp::from_bits(0).write(); diff --git a/src/percpu.rs b/src/percpu.rs index 488d4f1..e6a0f31 100644 --- a/src/percpu.rs +++ b/src/percpu.rs @@ -2,7 +2,9 @@ use core::marker::PhantomData; use axerrno::{AxError, AxResult}; use axvcpu::{AxArchPerCpu, AxVCpuHal}; -use riscv::register::{hedeleg, hideleg, hvip, sie}; + +use riscv::register::sie; +use riscv_h::register::{hedeleg, hideleg, hvip}; use crate::consts::traps; use crate::has_hardware_support; diff --git a/src/regs.rs b/src/regs.rs index 284f394..5d36821 100644 --- a/src/regs.rs +++ b/src/regs.rs @@ -158,7 +158,7 @@ pub struct GuestVsCsrs { impl GuestVsCsrs { // Load the VS-level CSRs from hardware into this structure. pub fn load_from_hw(&mut self) { - use riscv::register::{ + use riscv_h::register::{ htimedelta, vsatp, vscause, vsepc, vsie, vsscratch, vsstatus, vstval, vstvec, }; @@ -188,7 +188,7 @@ pub struct GuestVirtualHsCsrs { impl GuestVirtualHsCsrs { /// Load the virtualized HS-level CSRs from hardware into this structure. pub fn load_from_hw(&mut self) { - use riscv::register::{hgatp, hgeie, hie}; + use riscv_h::register::{hgatp, hgeie, hie}; self.hie = hie::read().bits(); self.hgeie = hgeie::read(); @@ -210,7 +210,8 @@ pub struct VmCpuTrapState { impl VmCpuTrapState { /// Reads the trap-related CSRs from hardware and stores them in this structure. pub fn load_from_hw(&mut self) { - use riscv::register::{htinst, htval, scause, stval}; + use riscv::register::{scause, stval}; + use riscv_h::register::{htinst, htval}; self.scause = scause::read().bits(); self.stval = stval::read(); diff --git a/src/vcpu.rs b/src/vcpu.rs index 58d6dd9..07a6244 100644 --- a/src/vcpu.rs +++ b/src/vcpu.rs @@ -1,9 +1,9 @@ use crate::sbi_console::*; use axaddrspace::device::AccessWidth; -use riscv::register::hstatus; -use riscv::register::{hvip, scause, sie, sstatus}; +use riscv::register::{scause, sie, sstatus}; use riscv_decode::Instruction; use riscv_decode::types::{IType, SType}; +use riscv_h::register::{hstatus, hvip}; use rustsbi::{Forward, RustSBI}; use sbi_spec::{hsm, legacy}; @@ -179,7 +179,8 @@ impl RISCVVCpu { self.regs.trap_csrs.load_from_hw(); let scause = scause::read(); - use scause::{Exception, Interrupt, Trap}; + // use scause::{Exception, Interrupt, Trap}; + use riscv::interrupt::{Exception, Interrupt, Trap}; trace!( "vmexit_handler: {:?}, sepc: {:#x}, stval: {:#x}", @@ -188,8 +189,8 @@ impl RISCVVCpu { self.regs.trap_csrs.stval ); - match scause.cause() { - Trap::Exception(Exception::VirtualSupervisorEnvCall) => { + match scause.cause().try_into().unwrap() { + Trap::Exception(Exception::SupervisorEnvCall) => { let a = self.regs.guest_regs.gprs.a_regs(); let param = [a[0], a[1], a[2], a[3], a[4], a[5]]; let extension_id = a[7]; @@ -377,9 +378,9 @@ impl RISCVVCpu { // `as usize` will give use a wrong value. Ok(AxVCpuExitReason::ExternalInterrupt { vector: 9 }) } - Trap::Exception( - gpf @ (Exception::LoadGuestPageFault | Exception::StoreGuestPageFault), - ) => self.handle_guest_page_fault(gpf == Exception::StoreGuestPageFault), + Trap::Exception(gpf @ (Exception::LoadPageFault | Exception::StorePageFault)) => { + self.handle_guest_page_fault(gpf == Exception::StorePageFault) + } _ => { panic!( "Unhandled trap: {:?}, sepc: {:#x}, stval: {:#x}", From 1cf1b256be389f9e0292785a83948972a3afbe4c Mon Sep 17 00:00:00 2001 From: YanLien Date: Thu, 4 Sep 2025 09:56:06 +0800 Subject: [PATCH 2/4] Refactor code structure based on review feedback --- src/detect.rs | 19 +++++++++++++------ src/vcpu.rs | 26 ++++++++++++++++---------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/detect.rs b/src/detect.rs index d04d90f..decf6ed 100644 --- a/src/detect.rs +++ b/src/detect.rs @@ -46,9 +46,17 @@ extern "C" fn rust_detect_trap(trap_frame: &mut TrapFrame) { // store returned exception id value into tp register // specially: illegal instruction => 2 trap_frame.tp = trap_frame.scause.bits(); + + let trap: Trap = match trap_frame.scause.cause().try_into() { + Err(_) => { + return; + } + Ok(trap) => trap, + }; + // if illegal instruction, skip current instruction - match trap_frame.scause.cause().try_into::() { - Ok(Trap::Exception(Exception::IllegalInstruction)) => { + match trap { + Trap::Exception(Exception::IllegalInstruction) => { let mut insn_bits = riscv_illegal_insn_bits((trap_frame.stval & 0xFFFF) as u16); if insn_bits == 0 { let insn_half = unsafe { *(trap_frame.sepc as *const u16) }; @@ -57,9 +65,8 @@ extern "C" fn rust_detect_trap(trap_frame: &mut TrapFrame) { // skip current instruction trap_frame.sepc = trap_frame.sepc.wrapping_add(insn_bits); } - Ok(Trap::Exception(_)) => unreachable!(), // FIXME: unexpected instruction errors - Ok(Trap::Interrupt(_)) => unreachable!(), // filtered out for sie == false - Err(_) => unreachable!(), + Trap::Exception(_) => unreachable!(), // FIXME: unexpected instruction errors + Trap::Interrupt(_) => unreachable!(), // filtered out for sie == false } } @@ -97,7 +104,7 @@ unsafe fn init_detect_trap(param: usize) -> (bool, Stvec, usize) { let stored_tp: usize; let mut stvec = Stvec::from_bits(0); - stvec.try_set_address(trap_addr).unwrap(); + stvec.set_address(trap_addr); stvec.set_trap_mode(TrapMode::Direct); unsafe { diff --git a/src/vcpu.rs b/src/vcpu.rs index 07a6244..ac25ba1 100644 --- a/src/vcpu.rs +++ b/src/vcpu.rs @@ -1,16 +1,16 @@ -use crate::sbi_console::*; -use axaddrspace::device::AccessWidth; use riscv::register::{scause, sie, sstatus}; -use riscv_decode::Instruction; -use riscv_decode::types::{IType, SType}; +use riscv_decode::{ + Instruction, + types::{IType, SType}, +}; use riscv_h::register::{hstatus, hvip}; use rustsbi::{Forward, RustSBI}; use sbi_spec::{hsm, legacy}; -use crate::regs::*; -use crate::{EID_HVC, RISCVVCpuCreateConfig, guest_mem}; -use axaddrspace::{GuestPhysAddr, GuestVirtAddr, HostPhysAddr, MappingFlags}; -use axerrno::AxResult; +use crate::{EID_HVC, RISCVVCpuCreateConfig, guest_mem, regs::*, sbi_console::*}; + +use axaddrspace::{GuestPhysAddr, GuestVirtAddr, HostPhysAddr, MappingFlags, device::AccessWidth}; +use axerrno::{AxError::InvalidData, AxResult}; use axvcpu::{AxVCpuExitReason, AxVCpuHal}; unsafe extern "C" { @@ -179,7 +179,6 @@ impl RISCVVCpu { self.regs.trap_csrs.load_from_hw(); let scause = scause::read(); - // use scause::{Exception, Interrupt, Trap}; use riscv::interrupt::{Exception, Interrupt, Trap}; trace!( @@ -189,7 +188,14 @@ impl RISCVVCpu { self.regs.trap_csrs.stval ); - match scause.cause().try_into().unwrap() { + let trap = match scause.cause().try_into() { + Err(_) => { + return Err(InvalidData); + } + Ok(trap) => trap, + }; + + match trap { Trap::Exception(Exception::SupervisorEnvCall) => { let a = self.regs.guest_regs.gprs.a_regs(); let param = [a[0], a[1], a[2], a[3], a[4], a[5]]; From 53d2ebe817223496ba85748c7eeeb372faf9ff2e Mon Sep 17 00:00:00 2001 From: YanLien Date: Thu, 4 Sep 2025 15:02:09 +0800 Subject: [PATCH 3/4] feat: enhance trap error handling and logging --- Cargo.toml | 2 +- src/detect.rs | 8 +++++++- src/vcpu.rs | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b58002f..97a9ebf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ bitflags = "2.2" bit_field = "0.10" crate_interface = "0.1" -riscv = { version = "0.14.0" } +riscv = "0.14.0" riscv-h = "0.1" riscv-decode = "0.2.3" diff --git a/src/detect.rs b/src/detect.rs index decf6ed..a617755 100644 --- a/src/detect.rs +++ b/src/detect.rs @@ -49,7 +49,13 @@ extern "C" fn rust_detect_trap(trap_frame: &mut TrapFrame) { let trap: Trap = match trap_frame.scause.cause().try_into() { Err(_) => { - return; + // This instruction detection handler expects only known trap types. + // Unknown trap causes indicate either hardware issues or unsupported + // RISC-V extensions that this specialized handler cannot process. + panic!( + "Unknown trap cause in instruction detector: scause={:#x}", + trap_frame.scause.bits() + ); } Ok(trap) => trap, }; diff --git a/src/vcpu.rs b/src/vcpu.rs index ac25ba1..68d7791 100644 --- a/src/vcpu.rs +++ b/src/vcpu.rs @@ -190,6 +190,8 @@ impl RISCVVCpu { let trap = match scause.cause().try_into() { Err(_) => { + // Unknown trap cause, cannot handle it. + error!("Unknown trap cause: scause={:#x}", scause.bits()); return Err(InvalidData); } Ok(trap) => trap, From 7fd5fdcf36bfa0b7620f517b781ade4705ff426c Mon Sep 17 00:00:00 2001 From: YanLien Date: Thu, 4 Sep 2025 16:26:38 +0800 Subject: [PATCH 4/4] feat: improve error handling in trap handlers again --- src/vcpu.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/vcpu.rs b/src/vcpu.rs index 68d7791..8c0a689 100644 --- a/src/vcpu.rs +++ b/src/vcpu.rs @@ -188,14 +188,11 @@ impl RISCVVCpu { self.regs.trap_csrs.stval ); - let trap = match scause.cause().try_into() { - Err(_) => { - // Unknown trap cause, cannot handle it. - error!("Unknown trap cause: scause={:#x}", scause.bits()); - return Err(InvalidData); - } - Ok(trap) => trap, - }; + // Try to convert the raw trap cause to a standard RISC-V trap cause. + let trap = scause.cause().try_into().map_err(|_| { + error!("Unknown trap cause: scause={:#x}", scause.bits()); + InvalidData + })?; match trap { Trap::Exception(Exception::SupervisorEnvCall) => {