From 32468a1c36ec9be59892e7207c6878878381f793 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 22:25:12 +0800 Subject: [PATCH 1/3] refine: Refine APIs of VcpuMananger --- crates/vm-core/src/cpu/error.rs | 3 --- crates/vm-core/src/cpu/vcpu.rs | 10 ++++++---- crates/vm-core/src/cpu/vcpu_manager.rs | 11 +++++------ crates/vm-core/src/virtualization/vm.rs | 3 +++ crates/vm-vmm/src/vmm/command.rs | 16 ++++++++++++---- 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/crates/vm-core/src/cpu/error.rs b/crates/vm-core/src/cpu/error.rs index 3bcbe2c..2af51ce 100644 --- a/crates/vm-core/src/cpu/error.rs +++ b/crates/vm-core/src/cpu/error.rs @@ -7,9 +7,6 @@ pub enum VcpuError { #[error("Failed to create vcpu: {0}")] FailedToCreateVcpu(#[from] Box), - #[error("vcpu {0} not created")] - VcpuNotCreated(usize), - #[error("Vcpu command channel disconnected")] VcpuCommandDisconnected, diff --git a/crates/vm-core/src/cpu/vcpu.rs b/crates/vm-core/src/cpu/vcpu.rs index 9b6a172..c403856 100644 --- a/crates/vm-core/src/cpu/vcpu.rs +++ b/crates/vm-core/src/cpu/vcpu.rs @@ -4,20 +4,22 @@ use crate::cpu::error::VcpuError; use crate::virtualization::vcpu::HypervisorVcpu; pub struct Vcpu { - vcpu_id: usize, vcpu_instance: Box, booted: bool, } impl Vcpu { - pub fn new(vcpu_id: usize, vcpu_instance: Box) -> Self { + pub fn new(vcpu_instance: Box) -> Self { Vcpu { - vcpu_id, vcpu_instance, booted: false, } } + pub fn vcpu_id(&self) -> usize { + self.vcpu_instance.vcpu_id() + } + pub async fn boot_vcpu( &mut self, pc: u64, @@ -30,7 +32,7 @@ impl Vcpu { let register = self.vcpu_instance.read_reigsters().await?; let registers = - AArch64Registers::boot_registers(self.vcpu_id, dtb_or_context_id, pc, register); + AArch64Registers::boot_registers(self.vcpu_id(), dtb_or_context_id, pc, register); self.vcpu_instance.write_registers(registers).await?; } diff --git a/crates/vm-core/src/cpu/vcpu_manager.rs b/crates/vm-core/src/cpu/vcpu_manager.rs index 6e4cf44..72f71d0 100644 --- a/crates/vm-core/src/cpu/vcpu_manager.rs +++ b/crates/vm-core/src/cpu/vcpu_manager.rs @@ -2,7 +2,6 @@ use std::sync::Arc; use vm_mm::manager::MemoryAddressSpace; -use crate::cpu::error::VcpuError; use crate::cpu::vcpu::Vcpu; use crate::cpu::vm_exit::VmExit; use crate::virtualization::vm::HypervisorVm; @@ -25,16 +24,16 @@ impl VcpuManager { self.vcpus.len() } - pub fn get_vcpu(&self, vcpu_id: usize) -> Result<&Vcpu, VcpuError> { + pub fn get_vcpu(&self, vcpu_id: usize) -> Result<&Vcpu, VmError> { self.vcpus .get(vcpu_id) - .ok_or(VcpuError::VcpuNotCreated(vcpu_id)) + .ok_or(VmError::VcpuNotCreated(vcpu_id)) } - pub fn get_vcpu_mut(&mut self, vcpu_id: usize) -> Result<&mut Vcpu, VcpuError> { + pub fn get_vcpu_mut(&mut self, vcpu_id: usize) -> Result<&mut Vcpu, VmError> { self.vcpus .get_mut(vcpu_id) - .ok_or(VcpuError::VcpuNotCreated(vcpu_id)) + .ok_or(VmError::VcpuNotCreated(vcpu_id)) } pub fn create_vcpu( @@ -45,7 +44,7 @@ impl VcpuManager { ) -> Result<(), VmError> { let vcpu_instance = self.vm_instance.create_vcpu(vcpu_id, mm, vm_exit_handler)?; - let vcpu = Vcpu::new(vcpu_id, vcpu_instance); + let vcpu = Vcpu::new(vcpu_instance); self.vcpus.push(vcpu); diff --git a/crates/vm-core/src/virtualization/vm.rs b/crates/vm-core/src/virtualization/vm.rs index 5efe973..abcbf73 100644 --- a/crates/vm-core/src/virtualization/vm.rs +++ b/crates/vm-core/src/virtualization/vm.rs @@ -14,6 +14,9 @@ pub enum SetUserMemoryRegionFlags { #[derive(Error, Debug)] pub enum VmError { + #[error("Vcpu {0} is not exists")] + VcpuNotCreated(usize), + #[error("Failed to create irq_chip: {0}")] CreateIrqChipError(String), diff --git a/crates/vm-vmm/src/vmm/command.rs b/crates/vm-vmm/src/vmm/command.rs index 948d64b..d2c916d 100644 --- a/crates/vm-vmm/src/vmm/command.rs +++ b/crates/vm-vmm/src/vmm/command.rs @@ -51,7 +51,9 @@ impl Vmm { let vcpu_manager = self.try_get_vm()?.vcpu_manager(); let mut vcpu_manager = vcpu_manager.lock().await; - let vcpu = vcpu_manager.get_vcpu_mut(vcpu_id)?; + let vcpu = vcpu_manager + .get_vcpu_mut(vcpu_id) + .map_err(|_| CommandError::VcpuNotExists { vcpu_id })?; let registers = vcpu.read_core_registers().await.unwrap(); @@ -64,7 +66,9 @@ impl Vmm { let vcpu_manager = self.try_get_vm_mut()?.vcpu_manager(); let mut vcpu_manager = vcpu_manager.lock().await; - let vcpu = vcpu_manager.get_vcpu_mut(vcpu_id)?; + let vcpu = vcpu_manager + .get_vcpu_mut(vcpu_id) + .map_err(|_| CommandError::VcpuNotExists { vcpu_id })?; vcpu.write_core_registers((*registers).into()).await?; @@ -76,7 +80,9 @@ impl Vmm { let vm = self.try_get_vm_mut()?; let vcpu_manager = vm.vcpu_manager(); let vcpu_manager = vcpu_manager.lock().await; - let vcpu = vcpu_manager.get_vcpu(vcpu_id)?; + let vcpu = vcpu_manager + .get_vcpu(vcpu_id) + .map_err(|_| CommandError::VcpuNotExists { vcpu_id })?; let mut len = len; let mut buf = Vec::with_capacity(len); @@ -99,7 +105,9 @@ impl Vmm { let vm = self.try_get_vm_mut()?; let vcpu_manager = vm.vcpu_manager(); let vcpu_manager = vcpu_manager.lock().await; - let _vcpu = vcpu_manager.get_vcpu(vcpu_id)?; + let _vcpu = vcpu_manager + .get_vcpu(vcpu_id) + .map_err(|_| CommandError::VcpuNotExists { vcpu_id })?; let _buf = todo!(); From 92b528febe7adecbf7fb2b309fdb94edbe3822a2 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 23:13:33 +0800 Subject: [PATCH 2/3] refine: Refine vcpu and vcpu_manager --- crates/vm-core/src/cpu/vcpu.rs | 84 ++++++- crates/vm-core/src/lib.rs | 2 +- crates/vm-core/src/virtualization/hvp/vcpu.rs | 233 ++++++------------ crates/vm-core/src/virtualization/vcpu.rs | 21 +- crates/vm-vmm/src/vm.rs | 4 +- 5 files changed, 163 insertions(+), 181 deletions(-) diff --git a/crates/vm-core/src/cpu/vcpu.rs b/crates/vm-core/src/cpu/vcpu.rs index c403856..bd48089 100644 --- a/crates/vm-core/src/cpu/vcpu.rs +++ b/crates/vm-core/src/cpu/vcpu.rs @@ -1,9 +1,15 @@ +use tokio::sync::mpsc::WeakSender; + use crate::arch::registers::ArchCoreRegisters; use crate::arch::registers::ArchRegisters; use crate::cpu::error::VcpuError; use crate::virtualization::vcpu::HypervisorVcpu; +use crate::virtualization::vcpu::command::VcpuCommand; +use crate::virtualization::vcpu::command::VcpuCommandRequest; +use crate::virtualization::vcpu::command::VcpuCommandResponse; pub struct Vcpu { + command_tx: WeakSender, vcpu_instance: Box, booted: bool, } @@ -11,6 +17,7 @@ pub struct Vcpu { impl Vcpu { pub fn new(vcpu_instance: Box) -> Self { Vcpu { + command_tx: vcpu_instance.command_tx(), vcpu_instance, booted: false, } @@ -30,10 +37,17 @@ impl Vcpu { { use crate::arch::registers::aarch64::AArch64Registers; - let register = self.vcpu_instance.read_reigsters().await?; + let register = self.read_registers().await?; let registers = AArch64Registers::boot_registers(self.vcpu_id(), dtb_or_context_id, pc, register); - self.vcpu_instance.write_registers(registers).await?; + self.write_registers(registers).await?; + } + + #[cfg(target_arch = "x86_64")] + { + use std::hint::black_box; + + black_box((pc, dtb_or_context_id)); } self.booted = true; @@ -46,26 +60,56 @@ impl Vcpu { } pub async fn read_registers(&mut self) -> Result { - self.vcpu_instance.read_reigsters().await + match self + .send_command_and_then_wait(VcpuCommand::ReadRegisters) + .await? + { + VcpuCommandResponse::Registers(regs) => Ok(*regs), + _ => unreachable!(), + } } pub async fn read_core_registers(&mut self) -> Result { - self.vcpu_instance.read_core_registers().await + match self + .send_command_and_then_wait(VcpuCommand::ReadCoreRegisters) + .await? + { + VcpuCommandResponse::CoreRegisters(regs) => Ok(*regs), + _ => unreachable!(), + } } pub async fn write_core_registers( &mut self, registers: ArchCoreRegisters, ) -> Result<(), VcpuError> { - self.vcpu_instance.write_core_registers(registers).await + match self + .send_command_and_then_wait(VcpuCommand::WriteCoreRegisters(registers)) + .await? + { + VcpuCommandResponse::Empty => Ok(()), + _ => unreachable!(), + } } pub async fn write_registers(&mut self, registers: ArchRegisters) -> Result<(), VcpuError> { - self.vcpu_instance.write_registers(registers).await + match self + .send_command_and_then_wait(VcpuCommand::WriteRegisters(registers)) + .await? + { + VcpuCommandResponse::Empty => Ok(()), + _ => unreachable!(), + } } pub async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError> { - self.vcpu_instance.translate_gva_to_gpa(gva).await + match self + .send_command_and_then_wait(VcpuCommand::TranslateGvaToGpa(gva)) + .await? + { + VcpuCommandResponse::TranslateGvaToGpa(gpa) => Ok(gpa), + _ => unreachable!(), + } } pub async fn resume(&mut self) -> Result<(), VcpuError> { @@ -73,7 +117,10 @@ impl Vcpu { return Ok(()); } - self.vcpu_instance.resume().await + match self.send_command_and_then_wait(VcpuCommand::Resume).await? { + VcpuCommandResponse::Empty => Ok(()), + _ => unreachable!(), + } } pub async fn pause(&mut self) -> Result<(), VcpuError> { @@ -81,6 +128,25 @@ impl Vcpu { return Ok(()); } - self.vcpu_instance.pause().await + match self.send_command_and_then_wait(VcpuCommand::Pause).await? { + VcpuCommandResponse::Empty => Ok(()), + _ => unreachable!(), + } + } + + async fn send_command_and_then_wait( + &self, + command: VcpuCommand, + ) -> Result { + let (req, rx) = VcpuCommandRequest::new(command); + + self.command_tx + .upgrade() + .ok_or(VcpuError::VcpuCommandDisconnected)? + .send(req) + .await + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + + rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected) } } diff --git a/crates/vm-core/src/lib.rs b/crates/vm-core/src/lib.rs index 6e4b1df..4eb8d1c 100644 --- a/crates/vm-core/src/lib.rs +++ b/crates/vm-core/src/lib.rs @@ -1,4 +1,4 @@ -// #![deny(warnings)] +#![deny(warnings)] pub mod arch; pub mod cpu; diff --git a/crates/vm-core/src/virtualization/hvp/vcpu.rs b/crates/vm-core/src/virtualization/hvp/vcpu.rs index cf46f5f..f966ca0 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu.rs @@ -1,9 +1,6 @@ use std::ptr::null_mut; use std::sync::Arc; use std::sync::Mutex; -use std::sync::mpsc; -use std::sync::mpsc::Sender; -use std::sync::mpsc::TryRecvError; use applevisor_sys::hv_error_t; use applevisor_sys::hv_vcpu_create; @@ -17,7 +14,10 @@ use applevisor_sys::hv_vcpu_set_simd_fp_reg; use applevisor_sys::hv_vcpu_set_sys_reg; use applevisor_sys::hv_vcpu_t; use applevisor_sys::hv_vcpus_exit; -use async_trait::async_trait; +use tokio::sync::mpsc::Sender; +use tokio::sync::mpsc::WeakSender; +use tokio::sync::mpsc::error::TryRecvError; +use tracing::error; use vm_aarch64::register::id_aa64mmfr0_el1::IdAa64mmfr0El1; use vm_aarch64::register::tcr_el1::TcrEl1; use vm_aarch64::register::ttbr1_el1::Ttbr1El1; @@ -186,6 +186,74 @@ impl AArch64Vcpu for HvpVcpuInternal { } } +fn handle_command( + running: &mut bool, + hvp_vcpu_handler: Arc>, + cmd: VcpuCommandRequest, +) -> Result<(), VcpuError> { + match cmd.cmd { + VcpuCommand::ReadRegisters => { + let mut handler = hvp_vcpu_handler.lock().unwrap(); + + let registers = handler.read_registers()?; + + cmd.response + .send(VcpuCommandResponse::Registers(Box::new(registers))) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + VcpuCommand::WriteRegisters(registers) => { + let mut handler = hvp_vcpu_handler.lock().unwrap(); + + handler.write_registers(registers)?; + + cmd.response + .send(VcpuCommandResponse::Empty) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + VcpuCommand::ReadCoreRegisters => { + let mut handler = hvp_vcpu_handler.lock().unwrap(); + + let registers = handler.read_core_registers()?; + + cmd.response + .send(VcpuCommandResponse::CoreRegisters(Box::new(registers))) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + VcpuCommand::WriteCoreRegisters(registers) => { + let mut handler = hvp_vcpu_handler.lock().unwrap(); + + handler.write_core_registers(registers)?; + + cmd.response + .send(VcpuCommandResponse::Empty) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + VcpuCommand::TranslateGvaToGpa(gva) => { + let handler = hvp_vcpu_handler.lock().unwrap(); + + let gpa = handler.translate_gva_to_gpa(gva)?; + + cmd.response + .send(VcpuCommandResponse::TranslateGvaToGpa(gpa)) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + VcpuCommand::Resume => { + *running = true; + cmd.response + .send(VcpuCommandResponse::Empty) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + VcpuCommand::Pause => { + *running = false; + cmd.response + .send(VcpuCommandResponse::Empty) + .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + } + } + + Ok(()) +} + pub struct HvpVcpu { vcpu_id: usize, handler: Arc>, @@ -198,8 +266,8 @@ impl HvpVcpu { mm: Arc, vm_exit_handler: Arc, ) -> Result { - let (handler_tx, handler_rx) = mpsc::channel(); - let (command_tx, command_rx) = mpsc::channel(); + let (handler_tx, handler_rx) = std::sync::mpsc::channel(); + let (command_tx, mut command_rx) = tokio::sync::mpsc::channel(8); let _join_handler = std::thread::spawn(move || -> Result<(), VcpuError> { let mut vcpu = 0; @@ -244,68 +312,12 @@ impl HvpVcpu { } } else { cmd = command_rx - .recv() - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + .blocking_recv() + .ok_or(VcpuError::VcpuCommandDisconnected)?; } - match cmd.cmd { - VcpuCommand::ReadRegisters => { - let mut handler = hvp_vcpu_handler.lock().unwrap(); - - let registers = handler.read_registers()?; - - cmd.response - .send(VcpuCommandResponse::Registers(Box::new(registers))) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } - VcpuCommand::WriteRegisters(registers) => { - let mut handler = hvp_vcpu_handler.lock().unwrap(); - - handler.write_registers(registers)?; - - cmd.response - .send(VcpuCommandResponse::Empty) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } - VcpuCommand::ReadCoreRegisters => { - let mut handler = hvp_vcpu_handler.lock().unwrap(); - - let registers = handler.read_core_registers()?; - - cmd.response - .send(VcpuCommandResponse::CoreRegisters(Box::new(registers))) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } - VcpuCommand::WriteCoreRegisters(registers) => { - let mut handler = hvp_vcpu_handler.lock().unwrap(); - - handler.write_core_registers(registers)?; - - cmd.response - .send(VcpuCommandResponse::Empty) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } - VcpuCommand::TranslateGvaToGpa(gva) => { - let handler = hvp_vcpu_handler.lock().unwrap(); - - let gpa = handler.translate_gva_to_gpa(gva)?; - - cmd.response - .send(VcpuCommandResponse::TranslateGvaToGpa(gpa)) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } - VcpuCommand::Resume => { - running = true; - cmd.response - .send(VcpuCommandResponse::Empty) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } - VcpuCommand::Pause => { - running = false; - cmd.response - .send(VcpuCommandResponse::Empty) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - } + if let Err(err) = handle_command(&mut running, hvp_vcpu_handler.clone(), cmd) { + error!(?err, "Failed to handle cmd") } } }); @@ -322,97 +334,16 @@ impl HvpVcpu { } } -#[async_trait] impl HypervisorVcpu for HvpVcpu { fn vcpu_id(&self) -> usize { self.vcpu_id } - async fn read_reigsters(&mut self) -> Result { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::ReadRegisters); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - match rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)? { - VcpuCommandResponse::Registers(registers) => Ok(*registers), - _ => unreachable!(), - } - } - - async fn write_registers(&mut self, registers: AArch64Registers) -> Result<(), VcpuError> { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::WriteRegisters(registers)); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - Ok(()) - } - - async fn read_core_registers(&mut self) -> Result { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::ReadCoreRegisters); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - match rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)? { - VcpuCommandResponse::CoreRegisters(registers) => Ok(*registers), - _ => unreachable!(), - } - } - - async fn write_core_registers( - &mut self, - registers: AArch64CoreRegisters, - ) -> Result<(), VcpuError> { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::WriteCoreRegisters(registers)); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - Ok(()) - } - - async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError> { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::TranslateGvaToGpa(gva)); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - match rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)? { - VcpuCommandResponse::TranslateGvaToGpa(gpa) => Ok(gpa), - _ => unreachable!(), - } + fn command_tx(&self) -> WeakSender { + self.command_tx.downgrade() } - async fn resume(&mut self) -> Result<(), VcpuError> { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::Resume); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)?; - - Ok(()) - } - - async fn pause(&mut self) -> Result<(), VcpuError> { - let (cmd, rx) = VcpuCommandRequest::new(VcpuCommand::Pause); - - self.command_tx - .send(cmd) - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; - + fn tick(&mut self) -> Result<(), VcpuError> { let handlers = [self.handler.lock().unwrap().vcpu]; hv_unsafe_call!(hv_vcpus_exit( @@ -420,8 +351,6 @@ impl HypervisorVcpu for HvpVcpu { handlers.len().try_into().unwrap() ))?; - rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected)?; - Ok(()) } } diff --git a/crates/vm-core/src/virtualization/vcpu.rs b/crates/vm-core/src/virtualization/vcpu.rs index 82a2368..8d96c20 100644 --- a/crates/vm-core/src/virtualization/vcpu.rs +++ b/crates/vm-core/src/virtualization/vcpu.rs @@ -1,27 +1,14 @@ -use async_trait::async_trait; +use tokio::sync::mpsc::WeakSender; -use crate::arch::registers::ArchCoreRegisters; -use crate::arch::registers::ArchRegisters; use crate::cpu::error::VcpuError; +use crate::virtualization::vcpu::command::VcpuCommandRequest; pub(crate) mod command; -#[async_trait] pub trait HypervisorVcpu: Send { fn vcpu_id(&self) -> usize; - async fn read_reigsters(&mut self) -> Result; + fn command_tx(&self) -> WeakSender; - async fn write_registers(&mut self, registers: ArchRegisters) -> Result<(), VcpuError>; - - async fn read_core_registers(&mut self) -> Result; - - async fn write_core_registers(&mut self, registers: ArchCoreRegisters) - -> Result<(), VcpuError>; - - async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError>; - - async fn resume(&mut self) -> Result<(), VcpuError>; - - async fn pause(&mut self) -> Result<(), VcpuError>; + fn tick(&mut self) -> Result<(), VcpuError>; } diff --git a/crates/vm-vmm/src/vm.rs b/crates/vm-vmm/src/vm.rs index a50d66e..657f3e3 100644 --- a/crates/vm-vmm/src/vm.rs +++ b/crates/vm-vmm/src/vm.rs @@ -197,6 +197,8 @@ impl Vm { .get_vcpu_mut(0)? .boot_vcpu(self.start_pc, DTB_START, stop_on_boot) .await?; + + Ok(()) } #[cfg(not(target_arch = "aarch64"))] @@ -204,8 +206,6 @@ impl Vm { black_box(stop_on_boot); todo!(); } - - Ok(()) } pub async fn pause(&mut self) -> Result<()> { From 6349a35274cef8fee0afd698d5ab17189eae4d11 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 26 Apr 2026 23:43:17 +0800 Subject: [PATCH 3/3] refine: Refine errors --- crates/vm-core/src/arch/aarch64/vcpu.rs | 2 +- .../src/arch/aarch64/vcpu/reg/esr_el2.rs | 2 +- crates/vm-core/src/arch/aarch64/vm_exit.rs | 2 +- crates/vm-core/src/arch/mmu/aarch64.rs | 2 +- crates/vm-core/src/arch/x86_64/vcpu.rs | 2 +- crates/vm-core/src/cpu/error.rs | 24 +---------------- crates/vm-core/src/cpu/vcpu.rs | 26 +++++++++--------- crates/vm-core/src/cpu/vcpu_manager.rs | 2 +- crates/vm-core/src/virtualization/hvp.rs | 2 +- crates/vm-core/src/virtualization/hvp/vcpu.rs | 6 ++--- .../src/virtualization/hvp/vcpu/register.rs | 2 +- .../src/virtualization/hvp/vcpu/vm_exit.rs | 2 +- crates/vm-core/src/virtualization/hvp/vm.rs | 7 +++-- .../vm-core/src/virtualization/hypervisor.rs | 9 ++----- .../src/virtualization/hypervisor/error.rs | 7 +++++ crates/vm-core/src/virtualization/vcpu.rs | 4 ++- .../vm-core/src/virtualization/vcpu/error.rs | 26 ++++++++++++++++++ crates/vm-core/src/virtualization/vm.rs | 27 +++---------------- crates/vm-core/src/virtualization/vm/error.rs | 25 +++++++++++++++++ crates/vm-vmm/src/error.rs | 10 +++---- crates/vm-vmm/src/vmm/command.rs | 8 +++--- 21 files changed, 105 insertions(+), 92 deletions(-) create mode 100644 crates/vm-core/src/virtualization/hypervisor/error.rs create mode 100644 crates/vm-core/src/virtualization/vcpu/error.rs create mode 100644 crates/vm-core/src/virtualization/vm/error.rs diff --git a/crates/vm-core/src/arch/aarch64/vcpu.rs b/crates/vm-core/src/arch/aarch64/vcpu.rs index c14a8e7..303ad69 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu.rs @@ -7,7 +7,7 @@ use crate::arch::aarch64::vcpu::reg::SysRegister; use crate::arch::registers::aarch64::AArch64CoreRegisters; use crate::arch::registers::aarch64::AArch64Registers; use crate::arch::registers::aarch64::AArch64SysRegisters; -use crate::cpu::error::VcpuError; +use crate::virtualization::vcpu::error::VcpuError; pub mod reg; diff --git a/crates/vm-core/src/arch/aarch64/vcpu/reg/esr_el2.rs b/crates/vm-core/src/arch/aarch64/vcpu/reg/esr_el2.rs index 37472b9..e621269 100644 --- a/crates/vm-core/src/arch/aarch64/vcpu/reg/esr_el2.rs +++ b/crates/vm-core/src/arch/aarch64/vcpu/reg/esr_el2.rs @@ -1,6 +1,6 @@ use strum_macros::FromRepr; -use crate::cpu::error::VcpuError; +use crate::virtualization::vcpu::error::VcpuError; #[derive(Debug)] pub struct EsrEl2(u64); diff --git a/crates/vm-core/src/arch/aarch64/vm_exit.rs b/crates/vm-core/src/arch/aarch64/vm_exit.rs index ccd4ea8..f27cd37 100644 --- a/crates/vm-core/src/arch/aarch64/vm_exit.rs +++ b/crates/vm-core/src/arch/aarch64/vm_exit.rs @@ -3,8 +3,8 @@ use tracing::trace; use crate::arch::aarch64::vcpu::AArch64Vcpu; use crate::arch::aarch64::vcpu::reg::CoreRegister; use crate::arch::aarch64::vcpu::reg::SysRegister; -use crate::cpu::error::VcpuError; use crate::cpu::vm_exit::VmExit; +use crate::virtualization::vcpu::error::VcpuError; #[derive(Debug)] pub enum VmExitReason { diff --git a/crates/vm-core/src/arch/mmu/aarch64.rs b/crates/vm-core/src/arch/mmu/aarch64.rs index 11f21a1..4e98f3b 100644 --- a/crates/vm-core/src/arch/mmu/aarch64.rs +++ b/crates/vm-core/src/arch/mmu/aarch64.rs @@ -3,7 +3,7 @@ use vm_aarch64::register::tcr_el1::TcrEl1; use vm_aarch64::register::ttbr1_el1::Ttbr1El1; use vm_mm::manager::MemoryAddressSpace; -use crate::cpu::error::VcpuError; +use crate::virtualization::vcpu::error::VcpuError; #[allow(clippy::too_many_arguments)] fn walk( diff --git a/crates/vm-core/src/arch/x86_64/vcpu.rs b/crates/vm-core/src/arch/x86_64/vcpu.rs index 2ec0a1b..a1c6312 100644 --- a/crates/vm-core/src/arch/x86_64/vcpu.rs +++ b/crates/vm-core/src/arch/x86_64/vcpu.rs @@ -1,7 +1,7 @@ use kvm_bindings::kvm_regs; use kvm_bindings::kvm_sregs; -use crate::cpu::error::VcpuError; +use crate::virtualization::vcpu::error::VcpuError; pub trait X86_64Vcpu { fn get_regs(&self) -> Result; diff --git a/crates/vm-core/src/cpu/error.rs b/crates/vm-core/src/cpu/error.rs index 2af51ce..7c961ed 100644 --- a/crates/vm-core/src/cpu/error.rs +++ b/crates/vm-core/src/cpu/error.rs @@ -1,29 +1,7 @@ use thiserror::Error; -use crate::cpu::vm_exit::VmExitHandlerError; - #[derive(Error, Debug)] -pub enum VcpuError { - #[error("Failed to create vcpu: {0}")] - FailedToCreateVcpu(#[from] Box), - +pub enum CpuError { #[error("Vcpu command channel disconnected")] VcpuCommandDisconnected, - - #[cfg(feature = "hvp")] - #[error("{0}")] - ApplevisorError(#[from] applevisor::error::HypervisorError), - - #[cfg(feature = "kvm")] - #[error("{0}")] - KvmError(#[from] kvm_ioctls::Error), - - #[error("{0}")] - GuestError(String), - - #[error("{0}")] - VmExitHandlerErr(#[from] VmExitHandlerError), - - #[error("Failed to translate va to pa")] - TranslateErr, } diff --git a/crates/vm-core/src/cpu/vcpu.rs b/crates/vm-core/src/cpu/vcpu.rs index bd48089..bc7544b 100644 --- a/crates/vm-core/src/cpu/vcpu.rs +++ b/crates/vm-core/src/cpu/vcpu.rs @@ -2,7 +2,7 @@ use tokio::sync::mpsc::WeakSender; use crate::arch::registers::ArchCoreRegisters; use crate::arch::registers::ArchRegisters; -use crate::cpu::error::VcpuError; +use crate::cpu::error::CpuError; use crate::virtualization::vcpu::HypervisorVcpu; use crate::virtualization::vcpu::command::VcpuCommand; use crate::virtualization::vcpu::command::VcpuCommandRequest; @@ -32,7 +32,7 @@ impl Vcpu { pc: u64, dtb_or_context_id: u64, stop_on_boot: bool, - ) -> Result<(), VcpuError> { + ) -> Result<(), CpuError> { #[cfg(target_arch = "aarch64")] { use crate::arch::registers::aarch64::AArch64Registers; @@ -59,7 +59,7 @@ impl Vcpu { Ok(()) } - pub async fn read_registers(&mut self) -> Result { + pub async fn read_registers(&mut self) -> Result { match self .send_command_and_then_wait(VcpuCommand::ReadRegisters) .await? @@ -69,7 +69,7 @@ impl Vcpu { } } - pub async fn read_core_registers(&mut self) -> Result { + pub async fn read_core_registers(&mut self) -> Result { match self .send_command_and_then_wait(VcpuCommand::ReadCoreRegisters) .await? @@ -82,7 +82,7 @@ impl Vcpu { pub async fn write_core_registers( &mut self, registers: ArchCoreRegisters, - ) -> Result<(), VcpuError> { + ) -> Result<(), CpuError> { match self .send_command_and_then_wait(VcpuCommand::WriteCoreRegisters(registers)) .await? @@ -92,7 +92,7 @@ impl Vcpu { } } - pub async fn write_registers(&mut self, registers: ArchRegisters) -> Result<(), VcpuError> { + pub async fn write_registers(&mut self, registers: ArchRegisters) -> Result<(), CpuError> { match self .send_command_and_then_wait(VcpuCommand::WriteRegisters(registers)) .await? @@ -102,7 +102,7 @@ impl Vcpu { } } - pub async fn translate_gva_to_gpa(&self, gva: u64) -> Result, VcpuError> { + pub async fn translate_gva_to_gpa(&self, gva: u64) -> Result, CpuError> { match self .send_command_and_then_wait(VcpuCommand::TranslateGvaToGpa(gva)) .await? @@ -112,7 +112,7 @@ impl Vcpu { } } - pub async fn resume(&mut self) -> Result<(), VcpuError> { + pub async fn resume(&mut self) -> Result<(), CpuError> { if !self.booted { return Ok(()); } @@ -123,7 +123,7 @@ impl Vcpu { } } - pub async fn pause(&mut self) -> Result<(), VcpuError> { + pub async fn pause(&mut self) -> Result<(), CpuError> { if !self.booted { return Ok(()); } @@ -137,16 +137,16 @@ impl Vcpu { async fn send_command_and_then_wait( &self, command: VcpuCommand, - ) -> Result { + ) -> Result { let (req, rx) = VcpuCommandRequest::new(command); self.command_tx .upgrade() - .ok_or(VcpuError::VcpuCommandDisconnected)? + .ok_or(CpuError::VcpuCommandDisconnected)? .send(req) .await - .map_err(|_| VcpuError::VcpuCommandDisconnected)?; + .map_err(|_| CpuError::VcpuCommandDisconnected)?; - rx.await.map_err(|_| VcpuError::VcpuCommandDisconnected) + rx.await.map_err(|_| CpuError::VcpuCommandDisconnected) } } diff --git a/crates/vm-core/src/cpu/vcpu_manager.rs b/crates/vm-core/src/cpu/vcpu_manager.rs index 72f71d0..a2b9fb5 100644 --- a/crates/vm-core/src/cpu/vcpu_manager.rs +++ b/crates/vm-core/src/cpu/vcpu_manager.rs @@ -5,7 +5,7 @@ use vm_mm::manager::MemoryAddressSpace; use crate::cpu::vcpu::Vcpu; use crate::cpu::vm_exit::VmExit; use crate::virtualization::vm::HypervisorVm; -use crate::virtualization::vm::VmError; +use crate::virtualization::vm::error::VmError; pub struct VcpuManager { vm_instance: Arc, diff --git a/crates/vm-core/src/virtualization/hvp.rs b/crates/vm-core/src/virtualization/hvp.rs index d3de80c..e3e5834 100644 --- a/crates/vm-core/src/virtualization/hvp.rs +++ b/crates/vm-core/src/virtualization/hvp.rs @@ -7,7 +7,7 @@ use applevisor_sys::hv_vm_create; use crate::virtualization::hvp::vm::AppleHypervisorVm; use crate::virtualization::hypervisor::Hypervisor; -use crate::virtualization::hypervisor::HypervisorError; +use crate::virtualization::hypervisor::error::HypervisorError; use crate::virtualization::vm::HypervisorVm; mod irq_chip; diff --git a/crates/vm-core/src/virtualization/hvp/vcpu.rs b/crates/vm-core/src/virtualization/hvp/vcpu.rs index f966ca0..bab51f2 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu.rs @@ -33,7 +33,6 @@ use crate::arch::mmu::aarch64::translate_gva_to_gpa; use crate::arch::registers::aarch64::AArch64CoreRegisters; use crate::arch::registers::aarch64::AArch64Registers; use crate::arch::registers::aarch64::AArch64SysRegisters; -use crate::cpu::error::VcpuError; use crate::cpu::vm_exit::VmExit; use crate::virtualization::hvp::hv_unsafe_call; use crate::virtualization::hvp::vcpu::register::HvpReg; @@ -42,6 +41,7 @@ use crate::virtualization::vcpu::HypervisorVcpu; use crate::virtualization::vcpu::command::VcpuCommand; use crate::virtualization::vcpu::command::VcpuCommandRequest; use crate::virtualization::vcpu::command::VcpuCommandResponse; +use crate::virtualization::vcpu::error::VcpuError; mod register; mod vm_exit; @@ -322,9 +322,7 @@ impl HvpVcpu { } }); - let handler = handler_rx - .recv() - .map_err(|err| VcpuError::FailedToCreateVcpu(Box::new(err)))?; + let handler = handler_rx.recv().unwrap(); Ok(HvpVcpu { vcpu_id, diff --git a/crates/vm-core/src/virtualization/hvp/vcpu/register.rs b/crates/vm-core/src/virtualization/hvp/vcpu/register.rs index dfc627e..fd1f72e 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu/register.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu/register.rs @@ -7,8 +7,8 @@ use applevisor_sys::hv_vcpu_get_reg; use crate::arch::aarch64::vcpu::reg::CoreRegister; use crate::arch::aarch64::vcpu::reg::FpRegister; use crate::arch::aarch64::vcpu::reg::SysRegister; -use crate::cpu::error::VcpuError; use crate::virtualization::hvp::hv_unsafe_call; +use crate::virtualization::vcpu::error::VcpuError; pub enum HvpReg { CoreReg(hv_reg_t), diff --git a/crates/vm-core/src/virtualization/hvp/vcpu/vm_exit.rs b/crates/vm-core/src/virtualization/hvp/vcpu/vm_exit.rs index 8aeefc2..1f57964 100644 --- a/crates/vm-core/src/virtualization/hvp/vcpu/vm_exit.rs +++ b/crates/vm-core/src/virtualization/hvp/vcpu/vm_exit.rs @@ -8,8 +8,8 @@ use crate::arch::aarch64::vcpu::reg::SysRegister; use crate::arch::aarch64::vcpu::reg::esr_el2::EsrEl2; use crate::arch::aarch64::vcpu::reg::esr_el2::{self}; use crate::arch::aarch64::vm_exit::VmExitReason; -use crate::cpu::error::VcpuError; use crate::virtualization::hvp::vcpu::register::get_reg; +use crate::virtualization::vcpu::error::VcpuError; pub fn to_vm_exit(vcpu: u64, exit_info: hv_vcpu_exit_t) -> Result { match exit_info.reason { diff --git a/crates/vm-core/src/virtualization/hvp/vm.rs b/crates/vm-core/src/virtualization/hvp/vm.rs index e08b97c..4739377 100644 --- a/crates/vm-core/src/virtualization/hvp/vm.rs +++ b/crates/vm-core/src/virtualization/hvp/vm.rs @@ -25,7 +25,7 @@ use crate::virtualization::hvp::vcpu::HvpVcpu; use crate::virtualization::vcpu::HypervisorVcpu; use crate::virtualization::vm::HypervisorVm; use crate::virtualization::vm::SetUserMemoryRegionFlags; -use crate::virtualization::vm::VmError; +use crate::virtualization::vm::error::VmError; impl From for MemPerms { fn from(flags: SetUserMemoryRegionFlags) -> Self { @@ -45,7 +45,10 @@ impl HypervisorVm for AppleHypervisorVm { mm: Arc, vm_exit_handler: Arc, ) -> Result, VmError> { - let vcpu = Box::new(HvpVcpu::new(vcpu_id, mm, vm_exit_handler)?); + let vcpu = Box::new( + HvpVcpu::new(vcpu_id, mm, vm_exit_handler) + .map_err(|err| VmError::CreateVcpuError(Box::new(err)))?, + ); Ok(vcpu as _) } diff --git a/crates/vm-core/src/virtualization/hypervisor.rs b/crates/vm-core/src/virtualization/hypervisor.rs index e435ead..e4f42a0 100644 --- a/crates/vm-core/src/virtualization/hypervisor.rs +++ b/crates/vm-core/src/virtualization/hypervisor.rs @@ -1,14 +1,9 @@ use std::sync::Arc; -use thiserror::Error; - +use crate::virtualization::hypervisor::error::HypervisorError; use crate::virtualization::vm::HypervisorVm; -#[derive(Error, Debug)] -pub enum HypervisorError { - #[error("Failed to create vm: {0}")] - CreateVm(String), -} +pub mod error; pub trait Hypervisor { fn create_vm(&self) -> Result, HypervisorError>; diff --git a/crates/vm-core/src/virtualization/hypervisor/error.rs b/crates/vm-core/src/virtualization/hypervisor/error.rs new file mode 100644 index 0000000..114c96d --- /dev/null +++ b/crates/vm-core/src/virtualization/hypervisor/error.rs @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum HypervisorError { + #[error("Failed to create vm: {0}")] + CreateVm(String), +} diff --git a/crates/vm-core/src/virtualization/vcpu.rs b/crates/vm-core/src/virtualization/vcpu.rs index 8d96c20..48c8b77 100644 --- a/crates/vm-core/src/virtualization/vcpu.rs +++ b/crates/vm-core/src/virtualization/vcpu.rs @@ -1,7 +1,9 @@ use tokio::sync::mpsc::WeakSender; -use crate::cpu::error::VcpuError; use crate::virtualization::vcpu::command::VcpuCommandRequest; +use crate::virtualization::vcpu::error::VcpuError; + +pub mod error; pub(crate) mod command; diff --git a/crates/vm-core/src/virtualization/vcpu/error.rs b/crates/vm-core/src/virtualization/vcpu/error.rs new file mode 100644 index 0000000..db2d5d6 --- /dev/null +++ b/crates/vm-core/src/virtualization/vcpu/error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::cpu::vm_exit::VmExitHandlerError; + +#[derive(Error, Debug)] +pub enum VcpuError { + #[error("Vcpu command channel disconnected")] + VcpuCommandDisconnected, + + #[cfg(feature = "hvp")] + #[error("{0}")] + ApplevisorError(#[from] applevisor::error::HypervisorError), + + #[cfg(feature = "kvm")] + #[error("{0}")] + KvmError(#[from] kvm_ioctls::Error), + + #[error("{0}")] + VmExitHandlerError(#[from] VmExitHandlerError), + + #[error("Guest error: {0}")] + GuestError(String), + + #[error("Failed to translate gpa")] + TranslateErr, +} diff --git a/crates/vm-core/src/virtualization/vm.rs b/crates/vm-core/src/virtualization/vm.rs index abcbf73..31a8fca 100644 --- a/crates/vm-core/src/virtualization/vm.rs +++ b/crates/vm-core/src/virtualization/vm.rs @@ -1,39 +1,18 @@ use std::sync::Arc; -use thiserror::Error; use vm_mm::manager::MemoryAddressSpace; use crate::arch::irq::InterruptController; -use crate::cpu::error::VcpuError; use crate::cpu::vm_exit::VmExit; use crate::virtualization::vcpu::HypervisorVcpu; +use crate::virtualization::vm::error::VmError; + +pub mod error; pub enum SetUserMemoryRegionFlags { ReadWriteExec, } -#[derive(Error, Debug)] -pub enum VmError { - #[error("Vcpu {0} is not exists")] - VcpuNotCreated(usize), - - #[error("Failed to create irq_chip: {0}")] - CreateIrqChipError(String), - - #[error("Failed to set_user_memory_region: {0}")] - SetUserMemoryRegionError(String), - - #[cfg(feature = "hvp")] - #[error("Applevisor error: {0}")] - ApplevisorError(#[from] applevisor::error::HypervisorError), - - #[error("Vcpu error: {0}")] - VcpuError(#[from] VcpuError), - - #[error("Internal error: {0}")] - Internal(&'static str), -} - pub trait HypervisorVm: Send + Sync { fn create_vcpu( &self, diff --git a/crates/vm-core/src/virtualization/vm/error.rs b/crates/vm-core/src/virtualization/vm/error.rs new file mode 100644 index 0000000..5f3cfb6 --- /dev/null +++ b/crates/vm-core/src/virtualization/vm/error.rs @@ -0,0 +1,25 @@ +use thiserror::Error; + +use crate::cpu::error::CpuError; + +#[derive(Error, Debug)] +pub enum VmError { + #[error("Vcpu {0} is not exists")] + VcpuNotCreated(usize), + + #[error("Failed to create vcpu: {0}")] + CreateVcpuError(Box), + + #[error("Failed to create irq_chip: {0}")] + CreateIrqChipError(String), + + #[error("Failed to set_user_memory_region: {0}")] + SetUserMemoryRegionError(String), + + #[cfg(feature = "hvp")] + #[error("Applevisor error: {0}")] + ApplevisorError(#[from] applevisor::error::HypervisorError), + + #[error("Cpu error: {0}")] + CpuError(#[from] CpuError), +} diff --git a/crates/vm-vmm/src/error.rs b/crates/vm-vmm/src/error.rs index 6a92152..c49cdad 100644 --- a/crates/vm-vmm/src/error.rs +++ b/crates/vm-vmm/src/error.rs @@ -1,9 +1,9 @@ use thiserror::Error; -use vm_core::cpu::error::VcpuError; +use vm_core::cpu::error::CpuError; use vm_core::monitor::MonitorError; use vm_core::utils::address_space::AddressSpaceError; -use vm_core::virtualization::hypervisor::HypervisorError; -use vm_core::virtualization::vm::VmError; +use vm_core::virtualization::hypervisor::error::HypervisorError; +use vm_core::virtualization::vm::error::VmError; use crate::service::gdbstub::error::VmGdbStubError; @@ -21,8 +21,8 @@ pub enum Error { #[error("Vm error: {0}")] VmError(#[from] VmError), - #[error("Vcpu error: {0}")] - VcpuError(#[from] VcpuError), + #[error("Cpu error: {0}")] + CpuError(#[from] CpuError), #[error("Gdb error: {0}")] GdbError(#[from] VmGdbStubError), diff --git a/crates/vm-vmm/src/vmm/command.rs b/crates/vm-vmm/src/vmm/command.rs index d2c916d..25271dc 100644 --- a/crates/vm-vmm/src/vmm/command.rs +++ b/crates/vm-vmm/src/vmm/command.rs @@ -1,7 +1,7 @@ use thiserror::Error; use tracing::error; use tracing::trace; -use vm_core::cpu::error::VcpuError; +use vm_core::cpu::error::CpuError; use crate::service::gdbstub::command::GdbStubCommand; use crate::service::gdbstub::command::GdbStubCommandError; @@ -22,12 +22,12 @@ pub enum CommandError { #[error("vCPU with ID {vcpu_id} does not exist")] VcpuNotExists { vcpu_id: usize }, - #[error("Vcpu error: {0}")] - VcpuError(#[from] VcpuError), - #[error("Vm error: {0}")] VmError(#[from] crate::error::Error), + #[error("Cpu error: {0}")] + CpuError(#[from] CpuError), + #[error("Failed to send response to command request")] FailedToSendResponse, }