From fa844896cd12517509d7b2612e06a2f385800e7d Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Sun, 13 Oct 2024 23:56:26 +0700 Subject: [PATCH] Initializes CPU interruption from debugger (#1035) --- gui/src/vmm/cpu/controller.rs | 63 ++++++++++++++++-- gui/src/vmm/cpu/mod.rs | 31 ++++++--- gui/src/vmm/hv/linux/cpu.rs | 13 +++- gui/src/vmm/hv/macos/cpu.rs | 39 ++++++----- gui/src/vmm/hv/mod.rs | 16 +++-- gui/src/vmm/hv/windows/cpu.rs | 13 +++- gui/src/vmm/hw/console/mod.rs | 6 +- gui/src/vmm/hw/debugger/context.rs | 103 ++++++++++++++++++++++++----- gui/src/vmm/hw/debugger/mod.rs | 8 +-- gui/src/vmm/hw/mod.rs | 8 +-- gui/src/vmm/hw/vmm/mod.rs | 6 +- 11 files changed, 234 insertions(+), 72 deletions(-) diff --git a/gui/src/vmm/cpu/controller.rs b/gui/src/vmm/cpu/controller.rs index 03c1b72e..88bca398 100644 --- a/gui/src/vmm/cpu/controller.rs +++ b/gui/src/vmm/cpu/controller.rs @@ -1,19 +1,57 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use std::mem::ManuallyDrop; -use std::sync::{Arc, Mutex}; +use std::ops::{Deref, DerefMut}; +use std::sync::{Arc, Condvar, Mutex}; use std::thread::JoinHandle; /// Contains objects to control a CPU from outside. pub struct CpuController { thread: ManuallyDrop>, - state: Arc>, + debug: Arc<(Mutex, Condvar)>, + wakeup: bool, } impl CpuController { - pub fn new(thread: JoinHandle<()>, state: Arc>) -> Self { + pub fn new(thread: JoinHandle<()>, debug: Arc<(Mutex, Condvar)>) -> Self { Self { thread: ManuallyDrop::new(thread), - state, + debug, + wakeup: false, + } + } + + pub fn debug_states(&mut self, f: impl FnOnce(&GdbRegs) -> R) -> R { + // Request from the CPU if not available. + let mut s = self.debug.0.lock().unwrap(); + + loop { + s = match s.deref() { + DebugStates::None => { + *s = DebugStates::Request; + + self.wakeup = true; + self.debug.1.wait(s).unwrap() + } + DebugStates::Request => self.debug.1.wait(s).unwrap(), + DebugStates::DebuggerOwned(v) => break f(v), + DebugStates::CpuOwned(_) => { + // The CPU is not pickup the previous value yet. + self.debug.1.wait(s).unwrap() + } + }; + } + } + + pub fn release(&mut self) { + let mut s = self.debug.0.lock().unwrap(); + + match std::mem::take(s.deref_mut()) { + DebugStates::DebuggerOwned(v) => *s = DebugStates::CpuOwned(v), + _ => unreachable!(), + } + + if std::mem::take(&mut self.wakeup) { + self.debug.1.notify_one(); } } } @@ -24,7 +62,18 @@ impl Drop for CpuController { } } -/// State of a CPU. -pub enum CpuState { - Running, +/// Debugging states of a CPU. +#[derive(Default)] +pub enum DebugStates { + #[default] + None, + Request, + DebuggerOwned(GdbRegs), + CpuOwned(GdbRegs), } + +#[cfg(target_arch = "aarch64")] +type GdbRegs = gdbstub_arch::aarch64::reg::AArch64CoreRegs; + +#[cfg(target_arch = "x86_64")] +type GdbRegs = gdbstub_arch::x86::reg::X86_64CoreRegs; diff --git a/gui/src/vmm/cpu/mod.rs b/gui/src/vmm/cpu/mod.rs index 2f36c158..93bcd34c 100644 --- a/gui/src/vmm/cpu/mod.rs +++ b/gui/src/vmm/cpu/mod.rs @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -pub use self::controller::CpuState; +pub use self::controller::DebugStates; use self::controller::CpuController; -use super::hv::{Cpu, CpuExit, CpuIo, Hypervisor}; +use super::hv::{Cpu, CpuExit, CpuIo, CpuRun, Hypervisor}; use super::hw::{DeviceContext, DeviceTree}; use super::ram::RamMap; use super::screen::Screen; @@ -13,7 +13,7 @@ use std::error::Error; use std::num::NonZero; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Condvar, Mutex}; #[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")] #[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")] @@ -59,24 +59,29 @@ impl CpuManager { }; // Spawn thread to drive vCPU. - let state = Arc::new(Mutex::new(CpuState::Running)); + let debug = Arc::new((Mutex::default(), Condvar::new())); let t = match map { Some(map) => std::thread::spawn({ - let state = state.clone(); + let debug = debug.clone(); - move || Self::main_cpu(args, state, start, map) + move || Self::main_cpu(args, debug, start, map) }), None => todo!(), }; - self.cpus.push(CpuController::new(t, state)); + self.cpus.push(CpuController::new(t, debug)); } pub fn debug_lock(&mut self) -> DebugLock { DebugLock(self) } - fn main_cpu(args: Args, state: Arc>, entry: usize, map: RamMap) { + fn main_cpu( + args: Args, + debug: Arc<(Mutex, Condvar)>, + entry: usize, + map: RamMap, + ) { let mut cpu = match args.hv.create_cpu(0) { Ok(v) => v, Err(e) => { @@ -92,10 +97,14 @@ impl CpuManager { return; } - Self::run_cpu(&args, &state, cpu); + Self::run_cpu(&args, &debug, cpu); } - fn run_cpu<'a>(args: &'a Args, state: &'a Mutex, mut cpu: H::Cpu<'a>) { + fn run_cpu<'a>( + args: &'a Args, + debug: &'a (Mutex, Condvar), + mut cpu: H::Cpu<'a>, + ) { // Build device contexts for this CPU. let mut devices = args .devices @@ -103,7 +112,7 @@ impl CpuManager { .map(|(addr, dev)| { let end = dev.len().checked_add(addr).unwrap(); - (addr, (dev.create_context(&args.hv, state), end)) + (addr, (dev.create_context(&args.hv, debug), end)) }) .collect::>>, NonZero)>>(); diff --git a/gui/src/vmm/hv/linux/cpu.rs b/gui/src/vmm/hv/linux/cpu.rs index b457d9bc..9cc2d93c 100644 --- a/gui/src/vmm/hv/linux/cpu.rs +++ b/gui/src/vmm/hv/linux/cpu.rs @@ -2,7 +2,7 @@ use super::arch::{KvmStates, StatesError}; use super::ffi::kvm_run; use super::run::KvmRun; -use crate::vmm::hv::{Cpu, CpuExit, CpuIo, IoBuf}; +use crate::vmm::hv::{Cpu, CpuExit, CpuIo, CpuRun, IoBuf}; use libc::munmap; use std::os::fd::{AsRawFd, OwnedFd}; use std::sync::MutexGuard; @@ -38,11 +38,14 @@ impl<'a> Cpu for KvmCpu<'a> { type States<'b> = KvmStates<'b> where Self: 'b; type GetStatesErr = StatesError; type Exit<'b> = KvmExit<'b, 'a> where Self: 'b; - type RunErr = std::io::Error; fn states(&mut self) -> Result, Self::GetStatesErr> { KvmStates::from_cpu(&mut self.fd) } +} + +impl<'a> CpuRun for KvmCpu<'a> { + type RunErr = std::io::Error; fn run(&mut self) -> Result, Self::RunErr> { match unsafe { kvm_run(self.fd.as_raw_fd()) } { @@ -56,6 +59,7 @@ impl<'a> Cpu for KvmCpu<'a> { pub struct KvmExit<'a, 'b>(&'a mut KvmCpu<'b>); impl<'a, 'b> CpuExit for KvmExit<'a, 'b> { + type Cpu = KvmCpu<'b>; type Io = KvmIo<'a, 'b>; #[cfg(target_arch = "x86_64")] @@ -80,6 +84,7 @@ impl<'a, 'b> CpuExit for KvmExit<'a, 'b> { pub struct KvmIo<'a, 'b>(&'a mut KvmCpu<'b>); impl<'a, 'b> CpuIo for KvmIo<'a, 'b> { + type Cpu = KvmCpu<'b>; type TranslateErr = std::io::Error; fn addr(&self) -> usize { @@ -118,6 +123,10 @@ impl<'a, 'b> CpuIo for KvmIo<'a, 'b> { _ => return Err(std::io::Error::last_os_error()), } } + + fn cpu(&mut self) -> &mut Self::Cpu { + self.0 + } } #[cfg(target_arch = "x86_64")] diff --git a/gui/src/vmm/hv/macos/cpu.rs b/gui/src/vmm/hv/macos/cpu.rs index b6cf0343..95db91ac 100644 --- a/gui/src/vmm/hv/macos/cpu.rs +++ b/gui/src/vmm/hv/macos/cpu.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::vmm::hv::{Cpu, CpuExit, CpuIo, CpuStates, IoBuf}; +use crate::vmm::hv::{Cpu, CpuExit, CpuIo, CpuRun, CpuStates, IoBuf}; use applevisor_sys::hv_reg_t::{HV_REG_CPSR, HV_REG_PC, HV_REG_X0, HV_REG_X1}; use applevisor_sys::hv_sys_reg_t::{ HV_SYS_REG_MAIR_EL1, HV_SYS_REG_SCTLR_EL1, HV_SYS_REG_SP_EL1, HV_SYS_REG_TCR_EL1, @@ -30,11 +30,20 @@ impl<'a> HvfCpu<'a> { } } +impl<'a> Drop for HvfCpu<'a> { + fn drop(&mut self) { + let ret = unsafe { hv_vcpu_destroy(self.instance) }; + + if ret != 0 { + panic!("hv_vcpu_destroy() fails with {ret:#x}"); + } + } +} + impl<'a> Cpu for HvfCpu<'a> { type States<'b> = HvfStates<'b, 'a> where Self: 'b; type GetStatesErr = StatesError; type Exit<'b> = HvfExit<'b, 'a> where Self: 'b; - type RunErr = RunError; fn states(&mut self) -> Result, Self::GetStatesErr> { Ok(HvfStates { @@ -51,6 +60,10 @@ impl<'a> Cpu for HvfCpu<'a> { x1: State::None, }) } +} + +impl<'a> CpuRun for HvfCpu<'a> { + type RunErr = RunError; fn run(&mut self) -> Result, Self::RunErr> { match NonZero::new(unsafe { hv_vcpu_run(self.instance) }) { @@ -60,16 +73,6 @@ impl<'a> Cpu for HvfCpu<'a> { } } -impl<'a> Drop for HvfCpu<'a> { - fn drop(&mut self) { - let ret = unsafe { hv_vcpu_destroy(self.instance) }; - - if ret != 0 { - panic!("hv_vcpu_destroy() fails with {ret:#x}"); - } - } -} - /// Implementation of [`Cpu::States`] for Hypervisor Framework. pub struct HvfStates<'a, 'b> { cpu: &'a mut HvfCpu<'b>, @@ -207,7 +210,8 @@ impl<'a, 'b> HvfExit<'a, 'b> { } impl<'a, 'b> CpuExit for HvfExit<'a, 'b> { - type Io = HvfIo; + type Cpu = HvfCpu<'b>; + type Io = HvfIo<'a, 'b>; fn into_io(self) -> Result { todo!(); @@ -215,9 +219,10 @@ impl<'a, 'b> CpuExit for HvfExit<'a, 'b> { } /// Implementation of [`CpuIo`] for Hypervisor Framework. -pub struct HvfIo {} +pub struct HvfIo<'a, 'b>(&'a mut HvfCpu<'b>); -impl CpuIo for HvfIo { +impl<'a, 'b> CpuIo for HvfIo<'a, 'b> { + type Cpu = HvfCpu<'b>; type TranslateErr = std::io::Error; fn addr(&self) -> usize { @@ -231,6 +236,10 @@ impl CpuIo for HvfIo { fn translate(&self, vaddr: usize) -> Result { todo!(); } + + fn cpu(&mut self) -> &mut Self::Cpu { + self.0 + } } /// Implementation of [`Cpu::RunErr`]. diff --git a/gui/src/vmm/hv/mod.rs b/gui/src/vmm/hv/mod.rs index 1b710719..c3b3fc42 100644 --- a/gui/src/vmm/hv/mod.rs +++ b/gui/src/vmm/hv/mod.rs @@ -24,7 +24,7 @@ pub type Default = self::os::Whp; /// Underlying hypervisor (e.g. KVM on Linux). pub trait Hypervisor: Send + Sync + 'static { - type Cpu<'a>: Cpu + type Cpu<'a>: CpuRun where Self: 'a; type CpuErr: Error + Send + 'static; @@ -45,12 +45,17 @@ pub trait Cpu { where Self: 'a; type GetStatesErr: Error + Send + 'static; - type Exit<'a>: CpuExit + type Exit<'a>: CpuExit where Self: 'a; - type RunErr: Error + Send + 'static; fn states(&mut self) -> Result, Self::GetStatesErr>; +} + +/// Provides a method to run the CPU. +pub trait CpuRun: Cpu { + type RunErr: Error + Send + 'static; + fn run(&mut self) -> Result, Self::RunErr>; } @@ -139,7 +144,8 @@ pub trait CpuStates { /// Contains information when VM exited. pub trait CpuExit: Sized { - type Io: CpuIo; + type Cpu: Cpu; + type Io: CpuIo; #[cfg(target_arch = "x86_64")] fn into_hlt(self) -> Result<(), Self>; @@ -149,12 +155,14 @@ pub trait CpuExit: Sized { /// Contains information when a VM exited because of memory-mapped I/O. pub trait CpuIo { + type Cpu: Cpu; type TranslateErr: Error + Send + 'static; /// Returns physical address where the VM try to access. fn addr(&self) -> usize; fn buffer(&mut self) -> IoBuf; fn translate(&self, vaddr: usize) -> Result; + fn cpu(&mut self) -> &mut Self::Cpu; } /// Encapsulates a buffer for memory-mapped I/O. diff --git a/gui/src/vmm/hv/windows/cpu.rs b/gui/src/vmm/hv/windows/cpu.rs index ee010f57..bbc13fa4 100644 --- a/gui/src/vmm/hv/windows/cpu.rs +++ b/gui/src/vmm/hv/windows/cpu.rs @@ -1,4 +1,4 @@ -use crate::vmm::hv::{Cpu, CpuExit, CpuIo, CpuStates, IoBuf}; +use crate::vmm::hv::{Cpu, CpuExit, CpuIo, CpuRun, CpuStates, IoBuf}; use std::error::Error; use std::marker::PhantomData; use std::mem::{size_of, zeroed, MaybeUninit}; @@ -46,7 +46,6 @@ impl<'a> Cpu for WhpCpu<'a> { type States<'b> = WhpStates<'b, 'a> where Self: 'b; type GetStatesErr = StatesError; type Exit<'b> = WhpExit<'b, 'a> where Self: 'b; - type RunErr = RunError; fn states(&mut self) -> Result, Self::GetStatesErr> { let mut values: [WHV_REGISTER_VALUE; REGISTERS] = unsafe { zeroed() }; @@ -70,6 +69,10 @@ impl<'a> Cpu for WhpCpu<'a> { }) } } +} + +impl<'a> CpuRun for WhpCpu<'a> { + type RunErr = RunError; fn run(&mut self) -> Result, Self::RunErr> { let mut cx = MaybeUninit::::uninit(); @@ -279,6 +282,7 @@ pub struct WhpExit<'a, 'b> { } impl<'a, 'b> CpuExit for WhpExit<'a, 'b> { + type Cpu = WhpCpu<'b>; type Io = WhpIo<'a, 'b>; #[cfg(target_arch = "x86_64")] @@ -301,6 +305,7 @@ pub struct WhpIo<'a, 'b> { } impl<'a, 'b> CpuIo for WhpIo<'a, 'b> { + type Cpu = WhpCpu<'b>; type TranslateErr = std::io::Error; fn addr(&self) -> usize { @@ -314,6 +319,10 @@ impl<'a, 'b> CpuIo for WhpIo<'a, 'b> { fn translate(&self, vaddr: usize) -> Result { todo!() } + + fn cpu(&mut self) -> &mut Self::Cpu { + todo!(); + } } /// Implementation of [`Cpu::GetStatesErr`] and [`CpuStates::Err`]. diff --git a/gui/src/vmm/hw/console/mod.rs b/gui/src/vmm/hw/console/mod.rs index 7cd92281..9734d78e 100644 --- a/gui/src/vmm/hw/console/mod.rs +++ b/gui/src/vmm/hw/console/mod.rs @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use self::context::Context; use super::{Device, DeviceContext}; -use crate::vmm::cpu::CpuState; +use crate::vmm::cpu::DebugStates; use crate::vmm::hv::Hypervisor; use crate::vmm::VmmEventHandler; use obconf::ConsoleMemory; use std::num::NonZero; -use std::sync::Mutex; +use std::sync::{Condvar, Mutex}; mod context; @@ -40,7 +40,7 @@ impl Device for Console { fn create_context<'a>( &'a self, hv: &'a H, - _: &'a Mutex, + _: &'a (Mutex, Condvar), ) -> Box> + 'a> { Box::new(Context::new(self, hv)) } diff --git a/gui/src/vmm/hw/debugger/context.rs b/gui/src/vmm/hw/debugger/context.rs index ef4c66ca..9d3f76c2 100644 --- a/gui/src/vmm/hw/debugger/context.rs +++ b/gui/src/vmm/hw/debugger/context.rs @@ -1,25 +1,105 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use super::Debugger; -use crate::vmm::cpu::CpuState; +use crate::vmm::cpu::DebugStates; use crate::vmm::hv::{Cpu, CpuExit, CpuIo}; use crate::vmm::hw::{read_u8, DeviceContext, MmioError}; use crate::vmm::VmmEvent; use obconf::{DebuggerMemory, StopReason}; use std::error::Error; use std::mem::offset_of; +use std::ops::Deref; use std::ptr::null_mut; -use std::sync::Mutex; +use std::sync::{Condvar, Mutex}; use thiserror::Error; /// Implementation of [`DeviceContext`]. pub struct Context<'a> { dev: &'a Debugger, - state: &'a Mutex, + debug: &'a (Mutex, Condvar), } impl<'a> Context<'a> { - pub fn new(dev: &'a Debugger, state: &'a Mutex) -> Self { - Self { dev, state } + pub fn new(dev: &'a Debugger, debug: &'a (Mutex, Condvar)) -> Self { + Self { dev, debug } + } + + fn exec_stop( + &mut self, + exit: &mut as CpuExit>::Io, + off: usize, + ) -> Result<(), ExecError> { + // Read stop reason. + let stop = read_u8(exit).map_err(|e| ExecError::ReadFailed(off, e))?; + let stop: StopReason = stop.try_into().map_err(|_| ExecError::InvalidStop(stop))?; + + self.set_states::(exit, stop)?; + + // Notify GUI. This will block until the debugger works are completed. + let stop = match stop { + StopReason::WaitForDebugger => null_mut(), + }; + + unsafe { self.dev.event.invoke(VmmEvent::Breakpoint { stop }) }; + + Ok(()) + } + + fn set_states( + &mut self, + exit: &mut as CpuExit>::Io, + r: StopReason, + ) -> Result<(), ExecError> { + // Get states. + let next = match r { + StopReason::WaitForDebugger => Self::get_states(exit.cpu())?, + }; + + // Set states. + let mut s = self.debug.0.lock().unwrap(); + + if matches!(s.deref(), DebugStates::None) { + *s = DebugStates::DebuggerOwned(next); + return Ok(()); + } + + // Wait until the debugger release us. + assert!(matches!(s.deref(), DebugStates::Request)); + + *s = DebugStates::DebuggerOwned(next); + + self.debug.1.notify_one(); + + loop { + s = match s.deref() { + DebugStates::DebuggerOwned(_) => self.debug.1.wait(s).unwrap(), + DebugStates::CpuOwned(v) => { + // Two possible cases here: + // + // 1. CpuController::debug_states waiting for us to unlock. + // 2. CpuController::debug_states waiting for us to notify. + // + // Condvar::notify_one only wakeup the thread that already waiting. + *s = DebugStates::DebuggerOwned(v.clone()); + self.debug.1.notify_one(); + break; + } + _ => unreachable!(), + }; + } + + Ok(()) + } + + #[cfg(target_arch = "aarch64")] + fn get_states( + _: &mut impl Cpu, + ) -> Result { + todo!() + } + + #[cfg(target_arch = "x86_64")] + fn get_states(_: &mut impl Cpu) -> Result { + todo!() } } @@ -29,18 +109,7 @@ impl<'a, C: Cpu> DeviceContext for Context<'a> { let off = exit.addr() - self.dev.addr; if off == offset_of!(DebuggerMemory, stop) { - // Read stop reason. - let stop = read_u8(exit).map_err(|e| ExecError::ReadFailed(off, e))?; - let stop: StopReason = stop - .try_into() - .map_err(|_| Box::new(ExecError::InvalidStop(stop)))?; - - // Notify GUI. - let stop = match stop { - StopReason::WaitForDebugger => null_mut(), - }; - - unsafe { self.dev.event.invoke(VmmEvent::Breakpoint { stop }) }; + self.exec_stop::(exit, off)?; } else { return Err(Box::new(ExecError::UnknownField(off))); } diff --git a/gui/src/vmm/hw/debugger/mod.rs b/gui/src/vmm/hw/debugger/mod.rs index bf7c07d2..d4fe20cc 100644 --- a/gui/src/vmm/hw/debugger/mod.rs +++ b/gui/src/vmm/hw/debugger/mod.rs @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use self::context::Context; use super::{Device, DeviceContext}; -use crate::vmm::cpu::CpuState; +use crate::vmm::cpu::DebugStates; use crate::vmm::hv::Hypervisor; use crate::vmm::VmmEventHandler; use obconf::DebuggerMemory; use std::num::NonZero; -use std::sync::Mutex; +use std::sync::{Condvar, Mutex}; mod context; @@ -40,8 +40,8 @@ impl Device for Debugger { fn create_context<'a>( &'a self, _: &'a H, - state: &'a Mutex, + debug: &'a (Mutex, Condvar), ) -> Box> + 'a> { - Box::new(Context::new(self, state)) + Box::new(Context::new(self, debug)) } } diff --git a/gui/src/vmm/hw/mod.rs b/gui/src/vmm/hw/mod.rs index 9f508eef..6982aa56 100644 --- a/gui/src/vmm/hw/mod.rs +++ b/gui/src/vmm/hw/mod.rs @@ -3,13 +3,13 @@ pub use self::console::*; pub use self::debugger::*; pub use self::vmm::*; -use super::cpu::CpuState; +use super::cpu::DebugStates; use super::hv::{Cpu, CpuExit, CpuIo, Hypervisor, IoBuf}; use super::VmmEventHandler; use std::collections::BTreeMap; use std::error::Error; use std::num::NonZero; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Condvar, Mutex}; use thiserror::Error; mod console; @@ -130,7 +130,7 @@ pub trait Device: Send + Sync { fn create_context<'a>( &'a self, hv: &'a H, - state: &'a Mutex, + debug: &'a (Mutex, Condvar), ) -> Box> + 'a>; } @@ -139,7 +139,7 @@ pub trait DeviceContext { fn exec(&mut self, exit: &mut as CpuExit>::Io) -> Result>; } -/// Struct to build virtual device map. +/// Struct to build a map of virtual device. struct MapBuilder { map: BTreeMap>>, next: usize, diff --git a/gui/src/vmm/hw/vmm/mod.rs b/gui/src/vmm/hw/vmm/mod.rs index 5ec2efcf..1a797907 100644 --- a/gui/src/vmm/hw/vmm/mod.rs +++ b/gui/src/vmm/hw/vmm/mod.rs @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use self::context::Context; use super::{Device, DeviceContext}; -use crate::vmm::cpu::CpuState; +use crate::vmm::cpu::DebugStates; use crate::vmm::hv::Hypervisor; use crate::vmm::VmmEventHandler; use obconf::VmmMemory; use std::num::NonZero; -use std::sync::Mutex; +use std::sync::{Condvar, Mutex}; mod context; @@ -40,7 +40,7 @@ impl Device for Vmm { fn create_context<'a>( &'a self, _: &'a H, - _: &'a Mutex, + _: &'a (Mutex, Condvar), ) -> Box> + 'a> { Box::new(Context::new(self)) }