diff --git a/gui/src/hv/linux/run.rs b/gui/src/hv/linux/run.rs index 701594466..a3a2ce7cf 100644 --- a/gui/src/hv/linux/run.rs +++ b/gui/src/hv/linux/run.rs @@ -23,7 +23,7 @@ pub union Exit { fail_entry: ManuallyDrop, ex: ManuallyDrop, pub io: Io, - pub debug: ManuallyDrop, + pub debug: Debug, pub mmio: Mmio, iocsr_io: ManuallyDrop, hypercall: ManuallyDrop, diff --git a/gui/src/main.rs b/gui/src/main.rs index 9c8a571f5..ee353a321 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -215,7 +215,7 @@ async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> { }; // Wait for debugger. - let mut debugger = if let Some(addr) = debug { + let mut gdb_con = if let Some(addr) = debug { let v = wait_for_debugger(addr).await?; if v.is_none() { @@ -243,17 +243,17 @@ async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> { .build(&profile, attrs, &shutdown) .map_err(ProgramError::BuildGraphicsEngine)?; let (mut vmm, main) = self::vmm::create_channel(); - let mut buf = [0; 1024]; + let mut gdb_in = [0; 1024]; loop { // Prepare futures to poll. let mut vmm = pin!(vmm.recv()); - let mut debugger = debugger.as_mut().map(|v| v.read(&mut buf)); + let mut debug = gdb_con.as_mut().map(|v| v.read(&mut gdb_in)); // Poll all futures. let (vmm, debug) = std::future::poll_fn(move |cx| { let vmm = vmm.as_mut().poll(cx); - let debug = match &mut debugger { + let debug = match &mut debug { Some(v) => v.poll_unpin(cx), None => Poll::Pending, }; @@ -267,8 +267,23 @@ async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> { }) .await; - todo!() + // Process VMM event. + if let Some(vmm) = vmm { + let vmm = match vmm { + Some(v) => v, + None => break, + }; + + todo!() + } + + // Process debugger requests. + if let Some(debug) = debug { + todo!() + } } + + Ok(()) } async fn run_launcher( diff --git a/gui/src/vmm/debug/mod.rs b/gui/src/vmm/debug/mod.rs deleted file mode 100644 index 960a9c767..000000000 --- a/gui/src/vmm/debug/mod.rs +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -use super::cpu::{CpuManager, GdbError}; -use crate::gdb::DebugClient; -use crate::hv::Hypervisor; -use gdbstub::stub::state_machine::state::{Idle, Running}; -use gdbstub::stub::state_machine::{GdbStubStateMachine, GdbStubStateMachineInner}; -use gdbstub::stub::MultiThreadStopReason; -use thiserror::Error; - -impl<'a, 'b, H: Hypervisor> CpuManager<'a, 'b, H> { - pub(super) fn dispatch_gdb_idle( - &mut self, - mut state: GdbStubStateMachineInner< - 'static, - Idle>, - CpuManager<'a, 'b, H>, - DebugClient, - >, - ) -> Result< - Result< - GdbStubStateMachine<'static, CpuManager<'a, 'b, H>, DebugClient>, - GdbStubStateMachineInner< - 'static, - Idle>, - CpuManager<'a, 'b, H>, - DebugClient, - >, - >, - DispatchGdbIdleError, - > { - let b = match state.borrow_conn().read() { - Ok(v) => v, - Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => return Ok(Err(state)), - Err(e) => return Err(DispatchGdbIdleError::ReadData(e)), - }; - - state - .incoming_data(self, b) - .map(Ok) - .map_err(DispatchGdbIdleError::ProcessData) - } - - pub(super) fn dispatch_gdb_running( - &mut self, - mut state: GdbStubStateMachineInner<'static, Running, CpuManager<'a, 'b, H>, DebugClient>, - stop: Option>, - ) -> Result< - Result< - GdbStubStateMachine<'static, CpuManager<'a, 'b, H>, DebugClient>, - GdbStubStateMachineInner<'static, Running, CpuManager<'a, 'b, H>, DebugClient>, - >, - DispatchGdbRunningError, - > { - // Check If we are here because of a breakpoint. - if let Some(r) = stop { - return state - .report_stop(self, r) - .map(Ok) - .map_err(DispatchGdbRunningError::ReportStopReason); - } - - // Check for pending command. - let b = match state.borrow_conn().read() { - Ok(v) => v, - Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => return Ok(Err(state)), - Err(e) => return Err(DispatchGdbRunningError::ReadData(e)), - }; - - state - .incoming_data(self, b) - .map(Ok) - .map_err(DispatchGdbRunningError::ProcessData) - } -} - -#[derive(Debug, Error)] -pub(super) enum DispatchGdbIdleError { - #[error("couldn't read data from the debugger")] - ReadData(#[source] std::io::Error), - - #[error("couldn't process data from the debugger")] - ProcessData(#[source] gdbstub::stub::GdbStubError), -} - -#[derive(Debug, Error)] -pub(super) enum DispatchGdbRunningError { - #[error("couldn't report stop reason to the debugger")] - ReportStopReason(#[source] gdbstub::stub::GdbStubError), - - #[error("couldn't read data from the debugger")] - ReadData(#[source] std::io::Error), - - #[error("couldn't process data from the debugger")] - ProcessData(#[source] gdbstub::stub::GdbStubError), -} diff --git a/gui/src/vmm/mod.rs b/gui/src/vmm/mod.rs index 3af5621c6..cde43b356 100644 --- a/gui/src/vmm/mod.rs +++ b/gui/src/vmm/mod.rs @@ -10,10 +10,7 @@ use self::ram::RamBuilder; use crate::gdb::DebugClient; use crate::hv::{Hypervisor, Ram}; use crate::profile::Profile; -use cpu::GdbError; -use gdbstub::common::Signal; -use gdbstub::stub::state_machine::GdbStubStateMachine; -use gdbstub::stub::{GdbStubError, MultiThreadStopReason}; +use gdbstub::stub::MultiThreadStopReason; use kernel::{KernelError, ProgramHeaderError}; use obconf::{BootEnv, ConsoleType, Vm}; use std::cmp::max; @@ -32,7 +29,6 @@ use winit::event_loop::EventLoopProxy; mod arch; mod channel; mod cpu; -mod debug; mod hw; mod kernel; mod ram; @@ -62,7 +58,6 @@ fn get_page_size() -> Result, std::io::Error> { /// Manage a virtual machine that run the kernel. pub struct Vmm<'a, 'b> { cpu: CpuManager<'a, 'b, crate::hv::Default>, // Drop first. - gdb: Option, DebugClient>>, shutdown: Arc, } @@ -296,74 +291,15 @@ impl<'a, 'b> Vmm<'a, 'b> { let shutdown = Arc::new(AtomicBool::new(false)); let mut cpu = CpuManager::new(Arc::new(hv), args.el, scope, devices, shutdown.clone()); - // Setup GDB stub. - let gdb = debugger - .map(|client| { - gdbstub::stub::GdbStub::new(client) - .run_state_machine(&mut cpu) - .map_err(VmmError::SetupGdbStub) - }) - .transpose()?; - // Spawn main CPU. cpu.spawn( map.kern_vaddr + kernel_img.entry(), Some(map), - gdb.is_some(), + debugger.is_some(), ); // Create VMM. - Ok(Self { cpu, gdb, shutdown }) - } - - fn dispatch_debug( - &mut self, - mut stop: Option>, - ) -> Result { - loop { - // Check current state. - let r = match self.gdb.take().unwrap() { - GdbStubStateMachine::Idle(s) => { - match self.cpu.dispatch_gdb_idle(s) { - Ok(Ok(v)) => Ok(v), - Ok(Err(v)) => { - // No pending data from the debugger. - self.gdb = Some(v.into()); - return Ok(DispatchDebugResult::Ok); - } - Err(e) => Err(DispatchDebugError::DispatchIdle(e)), - } - } - GdbStubStateMachine::Running(s) => { - match self.cpu.dispatch_gdb_running(s, stop.take()) { - Ok(Ok(v)) => Ok(v), - Ok(Err(v)) => { - // No pending data from the debugger. - self.gdb = Some(v.into()); - return Ok(DispatchDebugResult::Ok); - } - Err(e) => Err(DispatchDebugError::DispatchRunning(e)), - } - } - GdbStubStateMachine::CtrlCInterrupt(s) => { - self.cpu.lock(); - - s.interrupt_handled( - &mut self.cpu, - Some(MultiThreadStopReason::Signal(Signal::SIGINT)), - ) - .map_err(DispatchDebugError::HandleInterrupt) - } - GdbStubStateMachine::Disconnected(_) => { - return Ok(DispatchDebugResult::Disconnected) - } - }; - - match r { - Ok(v) => self.gdb = Some(v), - Err(e) => return Err(e), - } - } + Ok(Self { cpu, shutdown }) } } @@ -406,23 +342,6 @@ impl VmmEvent { } } -pub enum DispatchDebugResult { - Ok, - Disconnected, -} - -#[derive(Debug, Error)] -enum DispatchDebugError { - #[error("couldn't dispatch idle state")] - DispatchIdle(#[source] debug::DispatchGdbIdleError), - - #[error("couldn't dispatch running state")] - DispatchRunning(#[source] debug::DispatchGdbRunningError), - - #[error("couldn't handle CTRL+C interrupt")] - HandleInterrupt(#[source] gdbstub::stub::GdbStubError), -} - #[derive(Debug, Error)] pub enum VmmError { #[error("couldn't open kernel path {1}")] @@ -523,11 +442,6 @@ pub enum VmmError { #[error("couldn't build RAM")] BuildRam(#[source] ram::RamBuilderError), - - #[error("couldn't setup a GDB stub")] - SetupGdbStub( - #[source] GdbStubError::Error>, - ), } /// Represents an error when [`main_cpu()`] fails to reach event loop.