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
2 changes: 1 addition & 1 deletion crates/vm-core/src/arch/aarch64/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion crates/vm-core/src/arch/aarch64/vcpu/reg/esr_el2.rs
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
2 changes: 1 addition & 1 deletion crates/vm-core/src/arch/aarch64/vm_exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion crates/vm-core/src/arch/mmu/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion crates/vm-core/src/arch/x86_64/vcpu.rs
Original file line number Diff line number Diff line change
@@ -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<kvm_regs, VcpuError>;
Expand Down
27 changes: 1 addition & 26 deletions crates/vm-core/src/cpu/error.rs
Original file line number Diff line number Diff line change
@@ -1,32 +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<dyn std::error::Error + Send + Sync>),

#[error("vcpu {0} not created")]
VcpuNotCreated(usize),

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,
}
112 changes: 90 additions & 22 deletions crates/vm-core/src/cpu/vcpu.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,53 @@
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;
use crate::virtualization::vcpu::command::VcpuCommandResponse;

pub struct Vcpu {
vcpu_id: usize,
command_tx: WeakSender<VcpuCommandRequest>,
vcpu_instance: Box<dyn HypervisorVcpu>,
booted: bool,
}

impl Vcpu {
pub fn new(vcpu_id: usize, vcpu_instance: Box<dyn HypervisorVcpu>) -> Self {
pub fn new(vcpu_instance: Box<dyn HypervisorVcpu>) -> Self {
Vcpu {
vcpu_id,
command_tx: vcpu_instance.command_tx(),
vcpu_instance,
booted: false,
}
}

pub fn vcpu_id(&self) -> usize {
self.vcpu_instance.vcpu_id()
}

pub async fn boot_vcpu(
&mut self,
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;

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?;
AArch64Registers::boot_registers(self.vcpu_id(), dtb_or_context_id, pc, register);
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;
Expand All @@ -43,42 +59,94 @@ impl Vcpu {
Ok(())
}

pub async fn read_registers(&mut self) -> Result<ArchRegisters, VcpuError> {
self.vcpu_instance.read_reigsters().await
pub async fn read_registers(&mut self) -> Result<ArchRegisters, CpuError> {
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<ArchCoreRegisters, VcpuError> {
self.vcpu_instance.read_core_registers().await
pub async fn read_core_registers(&mut self) -> Result<ArchCoreRegisters, CpuError> {
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
) -> Result<(), CpuError> {
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
pub async fn write_registers(&mut self, registers: ArchRegisters) -> Result<(), CpuError> {
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<Option<u64>, VcpuError> {
self.vcpu_instance.translate_gva_to_gpa(gva).await
pub async fn translate_gva_to_gpa(&self, gva: u64) -> Result<Option<u64>, CpuError> {
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> {
pub async fn resume(&mut self) -> Result<(), CpuError> {
if !self.booted {
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> {
pub async fn pause(&mut self) -> Result<(), CpuError> {
if !self.booted {
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<VcpuCommandResponse, CpuError> {
let (req, rx) = VcpuCommandRequest::new(command);

self.command_tx
.upgrade()
.ok_or(CpuError::VcpuCommandDisconnected)?
.send(req)
.await
.map_err(|_| CpuError::VcpuCommandDisconnected)?;

rx.await.map_err(|_| CpuError::VcpuCommandDisconnected)
}
}
13 changes: 6 additions & 7 deletions crates/vm-core/src/cpu/vcpu_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ 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;
use crate::virtualization::vm::VmError;
use crate::virtualization::vm::error::VmError;

pub struct VcpuManager {
vm_instance: Arc<dyn HypervisorVm>,
Expand All @@ -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(
Expand All @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion crates/vm-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// #![deny(warnings)]
#![deny(warnings)]

pub mod arch;
pub mod cpu;
Expand Down
2 changes: 1 addition & 1 deletion crates/vm-core/src/virtualization/hvp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading