1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub enum CpuArch {
8 X86_64,
10 Aarch64,
12}
13
14impl CpuArch {
15 #[must_use]
17 pub const fn native() -> Self {
18 #[cfg(target_arch = "x86_64")]
19 {
20 Self::X86_64
21 }
22 #[cfg(target_arch = "aarch64")]
23 {
24 Self::Aarch64
25 }
26 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
27 {
28 compile_error!("Unsupported CPU architecture")
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
35pub struct PlatformCapabilities {
36 pub supported_archs: Vec<CpuArch>,
38 pub max_vcpus: u32,
40 pub max_memory: u64,
42 pub nested_virt: bool,
44 pub rosetta: bool,
46}
47
48impl Default for PlatformCapabilities {
49 fn default() -> Self {
50 Self {
51 supported_archs: vec![CpuArch::native()],
52 max_vcpus: 1,
53 max_memory: 1024 * 1024 * 1024, nested_virt: false,
55 rosetta: false,
56 }
57 }
58}
59
60#[derive(Debug, Clone, Default, Serialize, Deserialize)]
62pub struct Registers {
63 pub rax: u64,
65 pub rbx: u64,
66 pub rcx: u64,
67 pub rdx: u64,
68 pub rsi: u64,
69 pub rdi: u64,
70 pub rsp: u64,
71 pub rbp: u64,
72 pub r8: u64,
73 pub r9: u64,
74 pub r10: u64,
75 pub r11: u64,
76 pub r12: u64,
77 pub r13: u64,
78 pub r14: u64,
79 pub r15: u64,
80
81 pub rip: u64,
83 pub rflags: u64,
84}
85
86#[derive(Debug, Clone)]
88pub enum VcpuExit {
89 Halt,
91 IoOut {
93 port: u16,
94 size: u8,
95 data: u64,
96 },
97 IoIn {
98 port: u16,
99 size: u8,
100 },
101 MmioRead {
103 addr: u64,
104 size: u8,
105 },
106 MmioWrite {
107 addr: u64,
108 size: u8,
109 data: u64,
110 },
111 Hypercall {
113 nr: u64,
114 args: [u64; 6],
115 },
116 SystemReset,
118 Shutdown,
120 Debug,
122 Unknown(i32),
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct VirtioDeviceConfig {
129 pub device_type: VirtioDeviceType,
131 pub config: Vec<u8>,
133 pub path: Option<String>,
135 pub read_only: bool,
137 pub tag: Option<String>,
139 #[serde(skip)]
141 pub net_fd: Option<i32>,
142}
143
144impl VirtioDeviceConfig {
145 pub fn block(path: impl Into<String>, read_only: bool) -> Self {
147 Self {
148 device_type: VirtioDeviceType::Block,
149 config: Vec::new(),
150 path: Some(path.into()),
151 read_only,
152 tag: None,
153 net_fd: None,
154 }
155 }
156
157 #[must_use]
159 pub const fn network() -> Self {
160 Self {
161 device_type: VirtioDeviceType::Net,
162 config: Vec::new(),
163 path: None,
164 read_only: false,
165 tag: None,
166 net_fd: None,
167 }
168 }
169
170 #[must_use]
175 pub const fn network_file_handle(fd: i32) -> Self {
176 Self {
177 device_type: VirtioDeviceType::Net,
178 config: Vec::new(),
179 path: None,
180 read_only: false,
181 tag: None,
182 net_fd: Some(fd),
183 }
184 }
185
186 #[must_use]
188 pub const fn console() -> Self {
189 Self {
190 device_type: VirtioDeviceType::Console,
191 config: Vec::new(),
192 path: None,
193 read_only: false,
194 tag: None,
195 net_fd: None,
196 }
197 }
198
199 pub fn filesystem(path: impl Into<String>, tag: impl Into<String>, read_only: bool) -> Self {
201 Self {
202 device_type: VirtioDeviceType::Fs,
203 config: Vec::new(),
204 path: Some(path.into()),
205 read_only,
206 tag: Some(tag.into()),
207 net_fd: None,
208 }
209 }
210
211 #[must_use]
213 pub const fn vsock() -> Self {
214 Self {
215 device_type: VirtioDeviceType::Vsock,
216 config: Vec::new(),
217 path: None,
218 read_only: false,
219 tag: None,
220 net_fd: None,
221 }
222 }
223
224 #[must_use]
226 pub const fn entropy() -> Self {
227 Self {
228 device_type: VirtioDeviceType::Rng,
229 config: Vec::new(),
230 path: None,
231 read_only: false,
232 tag: None,
233 net_fd: None,
234 }
235 }
236}
237
238#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
240pub enum VirtioDeviceType {
241 Block,
243 Net,
245 Console,
247 Fs,
249 Vsock,
251 Rng,
253 Balloon,
255 Gpu,
257}
258
259#[derive(Debug, Clone, Default, Serialize, Deserialize)]
265pub struct BalloonStats {
266 pub target_bytes: u64,
270
271 pub current_bytes: u64,
276
277 pub configured_bytes: u64,
282}
283
284impl BalloonStats {
285 #[must_use]
289 pub const fn effective_memory(&self) -> u64 {
290 self.configured_bytes.saturating_sub(self.current_bytes)
291 }
292
293 #[must_use]
295 pub fn target_percent(&self) -> f64 {
296 if self.configured_bytes == 0 {
297 return 100.0;
298 }
299 (self.target_bytes as f64 / self.configured_bytes as f64) * 100.0
300 }
301}
302
303impl VirtioDeviceConfig {
304 #[must_use]
309 pub const fn balloon() -> Self {
310 Self {
311 device_type: VirtioDeviceType::Balloon,
312 config: Vec::new(),
313 path: None,
314 read_only: false,
315 tag: None,
316 net_fd: None,
317 }
318 }
319}
320
321#[derive(Debug, Clone, Default, Serialize, Deserialize)]
327pub struct Arm64Registers {
328 pub x: [u64; 31],
330 pub sp: u64,
332 pub pc: u64,
334 pub pstate: u64,
336 pub fpcr: u64,
338 pub fpsr: u64,
340 pub v: [[u64; 2]; 32],
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct VcpuSnapshot {
347 pub id: u32,
349 pub arch: CpuArch,
351 pub x86_regs: Option<Registers>,
353 pub arm64_regs: Option<Arm64Registers>,
355 pub extra_state: Vec<u8>,
357}
358
359impl VcpuSnapshot {
360 #[must_use]
362 pub const fn new_x86(id: u32, regs: Registers) -> Self {
363 Self {
364 id,
365 arch: CpuArch::X86_64,
366 x86_regs: Some(regs),
367 arm64_regs: None,
368 extra_state: Vec::new(),
369 }
370 }
371
372 #[must_use]
374 pub const fn new_arm64(id: u32, regs: Arm64Registers) -> Self {
375 Self {
376 id,
377 arch: CpuArch::Aarch64,
378 x86_regs: None,
379 arm64_regs: Some(regs),
380 extra_state: Vec::new(),
381 }
382 }
383
384 #[must_use]
388 pub fn is_placeholder(&self) -> bool {
389 match (&self.x86_regs, &self.arm64_regs) {
390 (Some(regs), _) => regs.rip == 0 && regs.rsp == 0 && regs.rflags == 0,
391 (_, Some(regs)) => regs.pc == 0 && regs.sp == 0 && regs.pstate == 0,
392 (None, None) => true,
393 }
394 }
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
399pub struct DeviceSnapshot {
400 pub device_type: VirtioDeviceType,
402 pub name: String,
404 pub state: Vec<u8>,
406}
407
408#[derive(Debug, Clone, Serialize, Deserialize)]
410pub struct MemoryRegionSnapshot {
411 pub guest_addr: u64,
413 pub size: u64,
415 pub read_only: bool,
417 pub file_offset: u64,
419}
420
421#[derive(Debug, Clone)]
423pub struct DirtyPageInfo {
424 pub guest_addr: u64,
426 pub size: u64,
428}
429
430#[derive(Debug, Clone, Serialize, Deserialize)]
432pub struct VmSnapshot {
433 pub version: u32,
435 pub arch: CpuArch,
437 pub vcpus: Vec<VcpuSnapshot>,
439 pub devices: Vec<DeviceSnapshot>,
441 pub memory_regions: Vec<MemoryRegionSnapshot>,
443 pub total_memory: u64,
445 pub compressed: bool,
447 pub compression: Option<String>,
449 pub parent_id: Option<String>,
451}