diff --git a/Cargo.toml b/Cargo.toml index 083f8b8..97a9ebf 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 = "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..a617755 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 @@ -43,8 +46,22 @@ 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(_) => { + // 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, + }; + // if illegal instruction, skip current instruction - match trap_frame.scause.cause() { + match trap { Trap::Exception(Exception::IllegalInstruction) => { let mut insn_bits = riscv_illegal_insn_bits((trap_frame.stval & 0xFFFF) as u16); if insn_bits == 0 { @@ -91,8 +108,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.set_address(trap_addr); + 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..8c0a689 100644 --- a/src/vcpu.rs +++ b/src/vcpu.rs @@ -1,16 +1,16 @@ -use crate::sbi_console::*; -use axaddrspace::device::AccessWidth; -use riscv::register::hstatus; -use riscv::register::{hvip, scause, sie, sstatus}; -use riscv_decode::Instruction; -use riscv_decode::types::{IType, SType}; +use riscv::register::{scause, sie, sstatus}; +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,7 @@ 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!( "vmexit_handler: {:?}, sepc: {:#x}, stval: {:#x}", @@ -188,8 +188,14 @@ impl RISCVVCpu { self.regs.trap_csrs.stval ); - match scause.cause() { - Trap::Exception(Exception::VirtualSupervisorEnvCall) => { + // 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) => { 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 +383,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}",