Skip to main content

arcbox_hypervisor/
traits.rs

1//! Core traits for hypervisor abstraction.
2//!
3//! These traits define the platform-agnostic interface that all hypervisor
4//! backends must implement.
5
6use std::any::Any;
7
8use crate::{
9    config::VmConfig,
10    error::HypervisorError,
11    memory::GuestAddress,
12    types::{
13        DeviceSnapshot, DirtyPageInfo, PlatformCapabilities, Registers, VcpuExit, VcpuSnapshot,
14        VirtioDeviceConfig,
15    },
16};
17
18/// Main hypervisor trait for creating and managing virtual machines.
19///
20/// Each platform (macOS, Linux) provides its own implementation.
21pub trait Hypervisor: Send + Sync + 'static {
22    /// The virtual machine type created by this hypervisor.
23    type Vm: VirtualMachine;
24
25    /// Returns the platform capabilities.
26    fn capabilities(&self) -> &PlatformCapabilities;
27
28    /// Creates a new virtual machine with the given configuration.
29    ///
30    /// # Errors
31    ///
32    /// Returns an error if the VM cannot be created.
33    fn create_vm(&self, config: VmConfig) -> Result<Self::Vm, HypervisorError>;
34}
35
36/// Virtual machine trait for managing VM lifecycle and devices.
37pub trait VirtualMachine: Send + Sync {
38    /// The vCPU type for this VM.
39    type Vcpu: Vcpu;
40    /// The guest memory type for this VM.
41    type Memory: GuestMemory;
42
43    /// Returns whether this VM uses managed execution.
44    ///
45    /// **Managed execution** (returns `true`):
46    /// - The hypervisor manages vCPU execution internally
47    /// - `start()` begins VM execution, `stop()` ends it
48    /// - `create_vcpu()` is optional/placeholder
49    /// - Examples: macOS Virtualization.framework
50    ///
51    /// **Manual execution** (returns `false`):
52    /// - The caller must create vCPU threads and call `vcpu.run()` in a loop
53    /// - `start()` and `stop()` are optional state markers
54    /// - Examples: Linux KVM
55    fn is_managed_execution(&self) -> bool {
56        false // Default to manual execution (KVM-style)
57    }
58
59    /// Returns a reference to the guest memory.
60    fn memory(&self) -> &Self::Memory;
61
62    /// Creates a new vCPU.
63    ///
64    /// For managed execution VMs, this may return a placeholder vCPU.
65    ///
66    /// # Errors
67    ///
68    /// Returns an error if the vCPU cannot be created.
69    fn create_vcpu(&mut self, id: u32) -> Result<Self::Vcpu, HypervisorError>;
70
71    /// Adds a `VirtIO` device to the VM.
72    ///
73    /// # Errors
74    ///
75    /// Returns an error if the device cannot be added.
76    fn add_virtio_device(&mut self, device: VirtioDeviceConfig) -> Result<(), HypervisorError>;
77
78    /// Starts the VM.
79    ///
80    /// # Errors
81    ///
82    /// Returns an error if the VM cannot be started.
83    fn start(&mut self) -> Result<(), HypervisorError>;
84
85    /// Pauses the VM.
86    ///
87    /// # Errors
88    ///
89    /// Returns an error if the VM cannot be paused.
90    fn pause(&mut self) -> Result<(), HypervisorError>;
91
92    /// Resumes a paused VM.
93    ///
94    /// # Errors
95    ///
96    /// Returns an error if the VM cannot be resumed.
97    fn resume(&mut self) -> Result<(), HypervisorError>;
98
99    /// Stops the VM.
100    ///
101    /// # Errors
102    ///
103    /// Returns an error if the VM cannot be stopped.
104    fn stop(&mut self) -> Result<(), HypervisorError>;
105
106    /// Returns the VM as a reference to `Any` for downcasting.
107    ///
108    /// This allows the caller to downcast the VM to its concrete type
109    /// for platform-specific operations like IRQ injection.
110    fn as_any(&self) -> &dyn Any;
111
112    /// Returns the VM as a mutable reference to `Any` for downcasting.
113    fn as_any_mut(&mut self) -> &mut dyn Any;
114
115    /// Returns the number of vCPUs in the VM.
116    fn vcpu_count(&self) -> u32;
117
118    /// Gets snapshots of all device states.
119    ///
120    /// # Errors
121    ///
122    /// Returns an error if device states cannot be captured.
123    fn snapshot_devices(&self) -> Result<Vec<DeviceSnapshot>, HypervisorError>;
124
125    /// Restores device states from snapshots.
126    ///
127    /// # Errors
128    ///
129    /// Returns an error if device states cannot be restored.
130    fn restore_devices(&mut self, snapshots: &[DeviceSnapshot]) -> Result<(), HypervisorError>;
131}
132
133/// Virtual CPU trait for executing guest code.
134pub trait Vcpu: Send {
135    /// Runs the vCPU until a VM exit occurs.
136    ///
137    /// # Errors
138    ///
139    /// Returns an error if vCPU execution fails.
140    fn run(&mut self) -> Result<VcpuExit, HypervisorError>;
141
142    /// Gets the current register state.
143    ///
144    /// # Errors
145    ///
146    /// Returns an error if registers cannot be read.
147    fn get_regs(&self) -> Result<Registers, HypervisorError>;
148
149    /// Sets the register state.
150    ///
151    /// # Errors
152    ///
153    /// Returns an error if registers cannot be set.
154    fn set_regs(&mut self, regs: &Registers) -> Result<(), HypervisorError>;
155
156    /// Gets the vCPU ID.
157    fn id(&self) -> u32;
158
159    /// Sets the result of an I/O read operation.
160    ///
161    /// This is called after handling an `IoIn` exit to provide the value
162    /// that should be returned to the guest.
163    ///
164    /// # Errors
165    ///
166    /// Returns an error if the result cannot be set.
167    fn set_io_result(&mut self, value: u64) -> Result<(), HypervisorError>;
168
169    /// Sets the result of an MMIO read operation.
170    ///
171    /// This is called after handling an `MmioRead` exit to provide the value
172    /// that should be returned to the guest.
173    ///
174    /// # Errors
175    ///
176    /// Returns an error if the result cannot be set.
177    fn set_mmio_result(&mut self, value: u64) -> Result<(), HypervisorError>;
178
179    /// Creates a snapshot of the vCPU state.
180    ///
181    /// # Errors
182    ///
183    /// Returns an error if the snapshot cannot be created.
184    fn snapshot(&self) -> Result<VcpuSnapshot, HypervisorError>;
185
186    /// Restores the vCPU state from a snapshot.
187    ///
188    /// # Errors
189    ///
190    /// Returns an error if the state cannot be restored.
191    fn restore(&mut self, snapshot: &VcpuSnapshot) -> Result<(), HypervisorError>;
192}
193
194/// Guest memory trait for reading/writing guest physical memory.
195pub trait GuestMemory: Send + Sync {
196    /// Reads bytes from guest memory.
197    ///
198    /// # Errors
199    ///
200    /// Returns an error if the read fails.
201    fn read(&self, addr: GuestAddress, buf: &mut [u8]) -> Result<(), HypervisorError>;
202
203    /// Writes bytes to guest memory.
204    ///
205    /// # Errors
206    ///
207    /// Returns an error if the write fails.
208    fn write(&self, addr: GuestAddress, buf: &[u8]) -> Result<(), HypervisorError>;
209
210    /// Gets the host virtual address for a guest physical address.
211    ///
212    /// This is used for zero-copy operations.
213    ///
214    /// # Safety
215    ///
216    /// The returned pointer is only valid while the memory mapping exists.
217    ///
218    /// # Errors
219    ///
220    /// Returns an error if the address is not mapped.
221    fn get_host_address(&self, addr: GuestAddress) -> Result<*mut u8, HypervisorError>;
222
223    /// Returns the total size of guest memory in bytes.
224    fn size(&self) -> u64;
225
226    /// Enables dirty page tracking.
227    ///
228    /// After enabling, use `get_dirty_pages()` to retrieve modified pages.
229    ///
230    /// # Errors
231    ///
232    /// Returns an error if dirty tracking cannot be enabled.
233    fn enable_dirty_tracking(&mut self) -> Result<(), HypervisorError>;
234
235    /// Disables dirty page tracking.
236    ///
237    /// # Errors
238    ///
239    /// Returns an error if dirty tracking cannot be disabled.
240    fn disable_dirty_tracking(&mut self) -> Result<(), HypervisorError>;
241
242    /// Gets and clears the list of dirty pages since the last call.
243    ///
244    /// This resets the dirty bitmap after returning.
245    ///
246    /// # Errors
247    ///
248    /// Returns an error if dirty pages cannot be retrieved.
249    fn get_dirty_pages(&mut self) -> Result<Vec<DirtyPageInfo>, HypervisorError>;
250
251    /// Reads all guest memory into a buffer.
252    ///
253    /// # Errors
254    ///
255    /// Returns an error if memory cannot be read.
256    fn dump_all(&self, buf: &mut [u8]) -> Result<(), HypervisorError>;
257}