Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ authors = [
"周睿 <[email protected]>"
]
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"]
Expand All @@ -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"] }
Expand All @@ -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"}
axaddrspace = "0.1"
axvcpu = "0.1"
axvisor_api = "0.1"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ components = ["rust-src", "llvm-tools", "rustfmt", "clippy"]
profile = "minimal"
targets = [
"riscv64gc-unknown-none-elf",
]
]
34 changes: 28 additions & 6 deletions src/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
//! ref: <https://github.com/luojia65/zihai/blob/main/zihai/src/detect.rs>

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
Expand Down Expand Up @@ -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<Interrupt, Exception> = 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 {
Expand Down Expand Up @@ -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));
}
Expand Down
6 changes: 3 additions & 3 deletions src/guest_mem.rs
Original file line number Diff line number Diff line change
@@ -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:
//
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down
4 changes: 3 additions & 1 deletion src/percpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions src/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down
38 changes: 22 additions & 16 deletions src/vcpu.rs
Original file line number Diff line number Diff line change
@@ -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" {
Expand Down Expand Up @@ -179,7 +179,7 @@ impl<H: AxVCpuHal> RISCVVCpu<H> {
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}",
Expand All @@ -188,8 +188,14 @@ impl<H: AxVCpuHal> RISCVVCpu<H> {
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];
Expand Down Expand Up @@ -377,9 +383,9 @@ impl<H: AxVCpuHal> RISCVVCpu<H> {
// `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}",
Expand Down