Skip to main content

vmi_core/handler/
mod.rs

1mod termination;
2
3use std::{
4    ops::ControlFlow,
5    sync::{Arc, atomic::AtomicBool},
6    time::{Duration, Instant},
7};
8
9pub use self::termination::VmiTerminationHandler;
10use crate::{VmiContext, VmiEventResponse, VmiOs, VmiSession};
11
12/// A trait for handling VMI events.
13///
14/// A factory that creates a handler implementing this trait is passed to
15/// the [`VmiSession::handle`] method to handle VMI events.
16///
17/// [`VmiSession::handle`]: crate::VmiSession::handle
18pub trait VmiHandler<Os>
19where
20    Os: VmiOs,
21{
22    /// The output type of the handler.
23    type Output;
24
25    /// Called for each VMI event.
26    ///
27    /// The returned [`VmiEventResponse`] tells the hypervisor how to resume
28    /// the vCPU that triggered the event.
29    fn handle_event(&mut self, event: VmiContext<Os>) -> VmiEventResponse<Os::Architecture>;
30
31    /// Called when the event loop times out waiting for the next event.
32    ///
33    /// This is useful for periodic housekeeping while the guest is idle.
34    fn handle_timeout(&mut self, _session: &VmiSession<Os>) {}
35
36    /// Called when the event loop is interrupted by a signal.
37    ///
38    /// Typically used to initiate a graceful shutdown. If the handler can be
39    /// torn down now, this method should return [`ControlFlow::Break`].
40    /// Otherwise, for example while a hijacked thread still runs injected
41    /// code, it should return [`ControlFlow::Continue`]. The event loop then
42    /// keeps handling events until [`poll`](Self::poll) returns `Some`, or
43    /// until a second signal arrives.
44    fn handle_interrupted(&mut self, _session: &VmiSession<Os>) -> ControlFlow<()> {
45        ControlFlow::Break(())
46    }
47
48    /// Called once before the session tears down monitoring.
49    ///
50    /// This gives the handler an opportunity to release resources that
51    /// depend on the session (views, memory access permissions, event
52    /// monitors) before the session calls [`reset_state`].
53    ///
54    /// # Notes
55    ///
56    /// The guest is paused while this method runs. Do not wait here for the
57    /// guest to do something, because it cannot run until the cleanup is
58    /// done.
59    ///
60    /// [`reset_state`]: crate::VmiCore::reset_state
61    fn cleanup(&mut self, _session: &VmiSession<Os>) {}
62
63    /// Checks if the handler has completed.
64    ///
65    /// This method is called after each event is handled. If the handler
66    /// has completed, this method should return the output of the handler.
67    /// Otherwise, it should return `None`.
68    fn poll(&mut self) -> Option<Self::Output> {
69        None
70    }
71}
72
73/// Extension methods on [`VmiHandler`].
74///
75/// The blanket impl is the only impl of this trait, so implementors of
76/// [`VmiHandler`] cannot override the default bodies.
77pub trait VmiHandlerExt<Os>: VmiHandler<Os> + Sized
78where
79    Os: VmiOs,
80{
81    /// Wraps the handler in a [`VmiTerminationHandler`] that interrupts it
82    /// at `deadline`.
83    fn with_deadline(self, deadline: Instant) -> VmiTerminationHandler<Self> {
84        VmiTerminationHandler::new(self).with_deadline(deadline)
85    }
86
87    /// Wraps the handler in a [`VmiTerminationHandler`] with a flag that
88    /// interrupts it once the flag becomes `true`.
89    fn with_termination_flag(
90        self,
91        termination_flag: Arc<AtomicBool>,
92    ) -> VmiTerminationHandler<Self> {
93        VmiTerminationHandler::new(self).with_termination_flag(termination_flag)
94    }
95
96    /// Wraps the handler in a [`VmiTerminationHandler`] that gives it
97    /// `termination_timeout` to finish once interrupted.
98    fn with_termination_timeout(
99        self,
100        termination_timeout: Duration,
101    ) -> VmiTerminationHandler<Self> {
102        VmiTerminationHandler::new(self).with_termination_timeout(termination_timeout)
103    }
104}
105
106impl<Os, Handler> VmiHandlerExt<Os> for Handler
107where
108    Os: VmiOs,
109    Handler: VmiHandler<Os>,
110{
111}