xref: /cloud-hypervisor/vmm/src/lib.rs (revision 3ce0fef7fd546467398c914dbc74d8542e45cf6f)
1 // Copyright © 2019 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 
6 #[macro_use]
7 extern crate event_monitor;
8 #[macro_use]
9 extern crate log;
10 
11 use crate::api::{
12     ApiRequest, ApiResponse, RequestHandler, VmInfoResponse, VmReceiveMigrationData,
13     VmSendMigrationData, VmmPingResponse,
14 };
15 use crate::config::{
16     add_to_config, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, RestoreConfig,
17     UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
18 };
19 #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
20 use crate::coredump::GuestDebuggable;
21 use crate::memory_manager::MemoryManager;
22 #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
23 use crate::migration::get_vm_snapshot;
24 use crate::migration::{recv_vm_config, recv_vm_state};
25 use crate::seccomp_filters::{get_seccomp_filter, Thread};
26 use crate::vm::{Error as VmError, Vm, VmState};
27 use anyhow::anyhow;
28 #[cfg(feature = "dbus_api")]
29 use api::dbus::{DBusApiOptions, DBusApiShutdownChannels};
30 use libc::{tcsetattr, termios, EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW};
31 use memory_manager::MemoryManagerSnapshotData;
32 use pci::PciBdf;
33 use seccompiler::{apply_filter, SeccompAction};
34 use serde::ser::{SerializeStruct, Serializer};
35 use serde::{Deserialize, Serialize};
36 use signal_hook::iterator::{Handle, Signals};
37 use std::collections::HashMap;
38 use std::fs::File;
39 use std::io;
40 use std::io::{stdout, Read, Write};
41 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
42 use std::os::unix::net::UnixListener;
43 use std::os::unix::net::UnixStream;
44 use std::panic::AssertUnwindSafe;
45 use std::path::PathBuf;
46 use std::rc::Rc;
47 use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
48 use std::sync::{Arc, Mutex};
49 use std::time::Instant;
50 use std::{result, thread};
51 use thiserror::Error;
52 use tracer::trace_scoped;
53 use vm_memory::bitmap::AtomicBitmap;
54 use vm_memory::{ReadVolatile, WriteVolatile};
55 use vm_migration::{protocol::*, Migratable};
56 use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
57 use vmm_sys_util::eventfd::EventFd;
58 use vmm_sys_util::signal::unblock_signal;
59 use vmm_sys_util::sock_ctrl_msg::ScmSocket;
60 
61 mod acpi;
62 pub mod api;
63 mod clone3;
64 pub mod config;
65 #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
66 mod coredump;
67 pub mod cpu;
68 pub mod device_manager;
69 pub mod device_tree;
70 #[cfg(feature = "guest_debug")]
71 mod gdb;
72 #[cfg(feature = "igvm")]
73 mod igvm;
74 pub mod interrupt;
75 pub mod memory_manager;
76 pub mod migration;
77 mod pci_segment;
78 pub mod seccomp_filters;
79 mod serial_manager;
80 mod sigwinch_listener;
81 pub mod vm;
82 pub mod vm_config;
83 
84 type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
85 type GuestRegionMmap = vm_memory::GuestRegionMmap<AtomicBitmap>;
86 
87 /// Errors associated with VMM management
88 #[derive(Debug, Error)]
89 pub enum Error {
90     /// API request receive error
91     #[error("Error receiving API request: {0}")]
92     ApiRequestRecv(#[source] RecvError),
93 
94     /// API response send error
95     #[error("Error sending API request: {0}")]
96     ApiResponseSend(#[source] SendError<ApiResponse>),
97 
98     /// Cannot bind to the UNIX domain socket path
99     #[error("Error binding to UNIX domain socket: {0}")]
100     Bind(#[source] io::Error),
101 
102     /// Cannot clone EventFd.
103     #[error("Error cloning EventFd: {0}")]
104     EventFdClone(#[source] io::Error),
105 
106     /// Cannot create EventFd.
107     #[error("Error creating EventFd: {0}")]
108     EventFdCreate(#[source] io::Error),
109 
110     /// Cannot read from EventFd.
111     #[error("Error reading from EventFd: {0}")]
112     EventFdRead(#[source] io::Error),
113 
114     /// Cannot create epoll context.
115     #[error("Error creating epoll context: {0}")]
116     Epoll(#[source] io::Error),
117 
118     /// Cannot create HTTP thread
119     #[error("Error spawning HTTP thread: {0}")]
120     HttpThreadSpawn(#[source] io::Error),
121 
122     /// Cannot create D-Bus thread
123     #[cfg(feature = "dbus_api")]
124     #[error("Error spawning D-Bus thread: {0}")]
125     DBusThreadSpawn(#[source] io::Error),
126 
127     /// Cannot start D-Bus session
128     #[cfg(feature = "dbus_api")]
129     #[error("Error starting D-Bus session: {0}")]
130     CreateDBusSession(#[source] zbus::Error),
131 
132     /// Cannot create `event-monitor` thread
133     #[error("Error spawning `event-monitor` thread: {0}")]
134     EventMonitorThreadSpawn(#[source] io::Error),
135 
136     /// Cannot handle the VM STDIN stream
137     #[error("Error handling VM stdin: {0:?}")]
138     Stdin(VmError),
139 
140     /// Cannot handle the VM pty stream
141     #[error("Error handling VM pty: {0:?}")]
142     Pty(VmError),
143 
144     /// Cannot reboot the VM
145     #[error("Error rebooting VM: {0:?}")]
146     VmReboot(VmError),
147 
148     /// Cannot create VMM thread
149     #[error("Error spawning VMM thread {0:?}")]
150     VmmThreadSpawn(#[source] io::Error),
151 
152     /// Cannot shut the VMM down
153     #[error("Error shutting down VMM: {0:?}")]
154     VmmShutdown(VmError),
155 
156     /// Cannot create seccomp filter
157     #[error("Error creating seccomp filter: {0}")]
158     CreateSeccompFilter(seccompiler::Error),
159 
160     /// Cannot apply seccomp filter
161     #[error("Error applying seccomp filter: {0}")]
162     ApplySeccompFilter(seccompiler::Error),
163 
164     /// Error activating virtio devices
165     #[error("Error activating virtio devices: {0:?}")]
166     ActivateVirtioDevices(VmError),
167 
168     /// Error creating API server
169     #[error("Error creating API server {0:?}")]
170     CreateApiServer(micro_http::ServerError),
171 
172     /// Error binding API server socket
173     #[error("Error creation API server's socket {0:?}")]
174     CreateApiServerSocket(#[source] io::Error),
175 
176     #[cfg(feature = "guest_debug")]
177     #[error("Failed to start the GDB thread: {0}")]
178     GdbThreadSpawn(io::Error),
179 
180     /// GDB request receive error
181     #[cfg(feature = "guest_debug")]
182     #[error("Error receiving GDB request: {0}")]
183     GdbRequestRecv(#[source] RecvError),
184 
185     /// GDB response send error
186     #[cfg(feature = "guest_debug")]
187     #[error("Error sending GDB request: {0}")]
188     GdbResponseSend(#[source] SendError<gdb::GdbResponse>),
189 
190     #[error("Cannot spawn a signal handler thread: {0}")]
191     SignalHandlerSpawn(#[source] io::Error),
192 
193     #[error("Failed to join on threads: {0:?}")]
194     ThreadCleanup(std::boxed::Box<dyn std::any::Any + std::marker::Send>),
195 }
196 pub type Result<T> = result::Result<T, Error>;
197 
198 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
199 #[repr(u64)]
200 pub enum EpollDispatch {
201     Exit = 0,
202     Reset = 1,
203     Api = 2,
204     ActivateVirtioDevices = 3,
205     Debug = 4,
206     Unknown,
207 }
208 
209 impl From<u64> for EpollDispatch {
210     fn from(v: u64) -> Self {
211         use EpollDispatch::*;
212         match v {
213             0 => Exit,
214             1 => Reset,
215             2 => Api,
216             3 => ActivateVirtioDevices,
217             4 => Debug,
218             _ => Unknown,
219         }
220     }
221 }
222 
223 pub struct EpollContext {
224     epoll_file: File,
225 }
226 
227 impl EpollContext {
228     pub fn new() -> result::Result<EpollContext, io::Error> {
229         let epoll_fd = epoll::create(true)?;
230         // Use 'File' to enforce closing on 'epoll_fd'
231         // SAFETY: the epoll_fd returned by epoll::create is valid and owned by us.
232         let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
233 
234         Ok(EpollContext { epoll_file })
235     }
236 
237     pub fn add_event<T>(&mut self, fd: &T, token: EpollDispatch) -> result::Result<(), io::Error>
238     where
239         T: AsRawFd,
240     {
241         let dispatch_index = token as u64;
242         epoll::ctl(
243             self.epoll_file.as_raw_fd(),
244             epoll::ControlOptions::EPOLL_CTL_ADD,
245             fd.as_raw_fd(),
246             epoll::Event::new(epoll::Events::EPOLLIN, dispatch_index),
247         )?;
248 
249         Ok(())
250     }
251 
252     #[cfg(fuzzing)]
253     pub fn add_event_custom<T>(
254         &mut self,
255         fd: &T,
256         id: u64,
257         evts: epoll::Events,
258     ) -> result::Result<(), io::Error>
259     where
260         T: AsRawFd,
261     {
262         epoll::ctl(
263             self.epoll_file.as_raw_fd(),
264             epoll::ControlOptions::EPOLL_CTL_ADD,
265             fd.as_raw_fd(),
266             epoll::Event::new(evts, id),
267         )?;
268 
269         Ok(())
270     }
271 }
272 
273 impl AsRawFd for EpollContext {
274     fn as_raw_fd(&self) -> RawFd {
275         self.epoll_file.as_raw_fd()
276     }
277 }
278 
279 pub struct PciDeviceInfo {
280     pub id: String,
281     pub bdf: PciBdf,
282 }
283 
284 impl Serialize for PciDeviceInfo {
285     fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
286     where
287         S: Serializer,
288     {
289         let bdf_str = self.bdf.to_string();
290 
291         // Serialize the structure.
292         let mut state = serializer.serialize_struct("PciDeviceInfo", 2)?;
293         state.serialize_field("id", &self.id)?;
294         state.serialize_field("bdf", &bdf_str)?;
295         state.end()
296     }
297 }
298 
299 pub fn feature_list() -> Vec<String> {
300     vec![
301         #[cfg(feature = "dbus_api")]
302         "dbus_api".to_string(),
303         #[cfg(feature = "dhat-heap")]
304         "dhat-heap".to_string(),
305         #[cfg(feature = "guest_debug")]
306         "guest_debug".to_string(),
307         #[cfg(feature = "igvm")]
308         "igvm".to_string(),
309         #[cfg(feature = "io_uring")]
310         "io_uring".to_string(),
311         #[cfg(feature = "kvm")]
312         "kvm".to_string(),
313         #[cfg(feature = "mshv")]
314         "mshv".to_string(),
315         #[cfg(feature = "sev_snp")]
316         "sev_snp".to_string(),
317         #[cfg(feature = "tdx")]
318         "tdx".to_string(),
319         #[cfg(feature = "tracing")]
320         "tracing".to_string(),
321     ]
322 }
323 
324 pub fn start_event_monitor_thread(
325     mut monitor: event_monitor::Monitor,
326     seccomp_action: &SeccompAction,
327     hypervisor_type: hypervisor::HypervisorType,
328     exit_event: EventFd,
329 ) -> Result<thread::JoinHandle<Result<()>>> {
330     // Retrieve seccomp filter
331     let seccomp_filter = get_seccomp_filter(seccomp_action, Thread::EventMonitor, hypervisor_type)
332         .map_err(Error::CreateSeccompFilter)?;
333 
334     thread::Builder::new()
335         .name("event-monitor".to_owned())
336         .spawn(move || {
337             // Apply seccomp filter
338             if !seccomp_filter.is_empty() {
339                 apply_filter(&seccomp_filter)
340                     .map_err(Error::ApplySeccompFilter)
341                     .map_err(|e| {
342                         error!("Error applying seccomp filter: {:?}", e);
343                         exit_event.write(1).ok();
344                         e
345                     })?;
346             }
347 
348             std::panic::catch_unwind(AssertUnwindSafe(move || {
349                 while let Ok(event) = monitor.rx.recv() {
350                     let event = Arc::new(event);
351 
352                     if let Some(ref mut file) = monitor.file {
353                         file.write_all(event.as_bytes().as_ref()).ok();
354                         file.write_all(b"\n\n").ok();
355                     }
356 
357                     for tx in monitor.broadcast.iter() {
358                         tx.send(event.clone()).ok();
359                     }
360                 }
361             }))
362             .map_err(|_| {
363                 error!("`event-monitor` thread panicked");
364                 exit_event.write(1).ok();
365             })
366             .ok();
367 
368             Ok(())
369         })
370         .map_err(Error::EventMonitorThreadSpawn)
371 }
372 
373 #[allow(unused_variables)]
374 #[allow(clippy::too_many_arguments)]
375 pub fn start_vmm_thread(
376     vmm_version: VmmVersionInfo,
377     http_path: &Option<String>,
378     http_fd: Option<RawFd>,
379     #[cfg(feature = "dbus_api")] dbus_options: Option<DBusApiOptions>,
380     api_event: EventFd,
381     api_sender: Sender<ApiRequest>,
382     api_receiver: Receiver<ApiRequest>,
383     #[cfg(feature = "guest_debug")] debug_path: Option<PathBuf>,
384     #[cfg(feature = "guest_debug")] debug_event: EventFd,
385     #[cfg(feature = "guest_debug")] vm_debug_event: EventFd,
386     exit_event: EventFd,
387     seccomp_action: &SeccompAction,
388     hypervisor: Arc<dyn hypervisor::Hypervisor>,
389 ) -> Result<VmmThreadHandle> {
390     #[cfg(feature = "guest_debug")]
391     let gdb_hw_breakpoints = hypervisor.get_guest_debug_hw_bps();
392     #[cfg(feature = "guest_debug")]
393     let (gdb_sender, gdb_receiver) = std::sync::mpsc::channel();
394     #[cfg(feature = "guest_debug")]
395     let gdb_debug_event = debug_event.try_clone().map_err(Error::EventFdClone)?;
396     #[cfg(feature = "guest_debug")]
397     let gdb_vm_debug_event = vm_debug_event.try_clone().map_err(Error::EventFdClone)?;
398 
399     let api_event_clone = api_event.try_clone().map_err(Error::EventFdClone)?;
400     let hypervisor_type = hypervisor.hypervisor_type();
401 
402     // Retrieve seccomp filter
403     let vmm_seccomp_filter = get_seccomp_filter(seccomp_action, Thread::Vmm, hypervisor_type)
404         .map_err(Error::CreateSeccompFilter)?;
405 
406     let vmm_seccomp_action = seccomp_action.clone();
407     let thread = {
408         let exit_event = exit_event.try_clone().map_err(Error::EventFdClone)?;
409         thread::Builder::new()
410             .name("vmm".to_string())
411             .spawn(move || {
412                 // Apply seccomp filter for VMM thread.
413                 if !vmm_seccomp_filter.is_empty() {
414                     apply_filter(&vmm_seccomp_filter).map_err(Error::ApplySeccompFilter)?;
415                 }
416 
417                 let mut vmm = Vmm::new(
418                     vmm_version,
419                     api_event,
420                     #[cfg(feature = "guest_debug")]
421                     debug_event,
422                     #[cfg(feature = "guest_debug")]
423                     vm_debug_event,
424                     vmm_seccomp_action,
425                     hypervisor,
426                     exit_event,
427                 )?;
428 
429                 vmm.setup_signal_handler()?;
430 
431                 vmm.control_loop(
432                     Rc::new(api_receiver),
433                     #[cfg(feature = "guest_debug")]
434                     Rc::new(gdb_receiver),
435                 )
436             })
437             .map_err(Error::VmmThreadSpawn)?
438     };
439 
440     // The VMM thread is started, we can start the dbus thread
441     // and start serving HTTP requests
442     #[cfg(feature = "dbus_api")]
443     let dbus_shutdown_chs = match dbus_options {
444         Some(opts) => {
445             let (_, chs) = api::start_dbus_thread(
446                 opts,
447                 api_event_clone.try_clone().map_err(Error::EventFdClone)?,
448                 api_sender.clone(),
449                 seccomp_action,
450                 exit_event.try_clone().map_err(Error::EventFdClone)?,
451                 hypervisor_type,
452             )?;
453             Some(chs)
454         }
455         None => None,
456     };
457 
458     if let Some(http_path) = http_path {
459         api::start_http_path_thread(
460             http_path,
461             api_event_clone,
462             api_sender,
463             seccomp_action,
464             exit_event,
465             hypervisor_type,
466         )?;
467     } else if let Some(http_fd) = http_fd {
468         api::start_http_fd_thread(
469             http_fd,
470             api_event_clone,
471             api_sender,
472             seccomp_action,
473             exit_event,
474             hypervisor_type,
475         )?;
476     }
477 
478     #[cfg(feature = "guest_debug")]
479     if let Some(debug_path) = debug_path {
480         let target = gdb::GdbStub::new(
481             gdb_sender,
482             gdb_debug_event,
483             gdb_vm_debug_event,
484             gdb_hw_breakpoints,
485         );
486         thread::Builder::new()
487             .name("gdb".to_owned())
488             .spawn(move || gdb::gdb_thread(target, &debug_path))
489             .map_err(Error::GdbThreadSpawn)?;
490     }
491 
492     Ok(VmmThreadHandle {
493         thread_handle: thread,
494         #[cfg(feature = "dbus_api")]
495         dbus_shutdown_chs,
496     })
497 }
498 
499 #[derive(Clone, Deserialize, Serialize)]
500 struct VmMigrationConfig {
501     vm_config: Arc<Mutex<VmConfig>>,
502     #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
503     common_cpuid: Vec<hypervisor::arch::x86::CpuIdEntry>,
504     memory_manager_data: MemoryManagerSnapshotData,
505 }
506 
507 #[derive(Debug, Clone)]
508 pub struct VmmVersionInfo {
509     pub build_version: String,
510     pub version: String,
511 }
512 
513 impl VmmVersionInfo {
514     pub fn new(build_version: &str, version: &str) -> Self {
515         Self {
516             build_version: build_version.to_owned(),
517             version: version.to_owned(),
518         }
519     }
520 }
521 
522 pub struct VmmThreadHandle {
523     pub thread_handle: thread::JoinHandle<Result<()>>,
524     #[cfg(feature = "dbus_api")]
525     pub dbus_shutdown_chs: Option<DBusApiShutdownChannels>,
526 }
527 
528 pub struct Vmm {
529     epoll: EpollContext,
530     exit_evt: EventFd,
531     reset_evt: EventFd,
532     api_evt: EventFd,
533     #[cfg(feature = "guest_debug")]
534     debug_evt: EventFd,
535     #[cfg(feature = "guest_debug")]
536     vm_debug_evt: EventFd,
537     version: VmmVersionInfo,
538     vm: Option<Vm>,
539     vm_config: Option<Arc<Mutex<VmConfig>>>,
540     seccomp_action: SeccompAction,
541     hypervisor: Arc<dyn hypervisor::Hypervisor>,
542     activate_evt: EventFd,
543     signals: Option<Handle>,
544     threads: Vec<thread::JoinHandle<()>>,
545     original_termios_opt: Arc<Mutex<Option<termios>>>,
546 }
547 
548 impl Vmm {
549     pub const HANDLED_SIGNALS: [i32; 2] = [SIGTERM, SIGINT];
550 
551     fn signal_handler(
552         mut signals: Signals,
553         original_termios_opt: Arc<Mutex<Option<termios>>>,
554         exit_evt: &EventFd,
555     ) {
556         for sig in &Self::HANDLED_SIGNALS {
557             unblock_signal(*sig).unwrap();
558         }
559 
560         for signal in signals.forever() {
561             match signal {
562                 SIGTERM | SIGINT => {
563                     if exit_evt.write(1).is_err() {
564                         // Resetting the terminal is usually done as the VMM exits
565                         if let Ok(lock) = original_termios_opt.lock() {
566                             if let Some(termios) = *lock {
567                                 // SAFETY: FFI call
568                                 let _ = unsafe {
569                                     tcsetattr(stdout().lock().as_raw_fd(), TCSANOW, &termios)
570                                 };
571                             }
572                         } else {
573                             warn!("Failed to lock original termios");
574                         }
575 
576                         std::process::exit(1);
577                     }
578                 }
579                 _ => (),
580             }
581         }
582     }
583 
584     fn setup_signal_handler(&mut self) -> Result<()> {
585         let signals = Signals::new(Self::HANDLED_SIGNALS);
586         match signals {
587             Ok(signals) => {
588                 self.signals = Some(signals.handle());
589                 let exit_evt = self.exit_evt.try_clone().map_err(Error::EventFdClone)?;
590                 let original_termios_opt = Arc::clone(&self.original_termios_opt);
591 
592                 let signal_handler_seccomp_filter = get_seccomp_filter(
593                     &self.seccomp_action,
594                     Thread::SignalHandler,
595                     self.hypervisor.hypervisor_type(),
596                 )
597                 .map_err(Error::CreateSeccompFilter)?;
598                 self.threads.push(
599                     thread::Builder::new()
600                         .name("vmm_signal_handler".to_string())
601                         .spawn(move || {
602                             if !signal_handler_seccomp_filter.is_empty() {
603                                 if let Err(e) = apply_filter(&signal_handler_seccomp_filter)
604                                     .map_err(Error::ApplySeccompFilter)
605                                 {
606                                     error!("Error applying seccomp filter: {:?}", e);
607                                     exit_evt.write(1).ok();
608                                     return;
609                                 }
610                             }
611                             std::panic::catch_unwind(AssertUnwindSafe(|| {
612                                 Vmm::signal_handler(signals, original_termios_opt, &exit_evt);
613                             }))
614                             .map_err(|_| {
615                                 error!("vmm signal_handler thread panicked");
616                                 exit_evt.write(1).ok()
617                             })
618                             .ok();
619                         })
620                         .map_err(Error::SignalHandlerSpawn)?,
621                 );
622             }
623             Err(e) => error!("Signal not found {}", e),
624         }
625         Ok(())
626     }
627 
628     fn new(
629         vmm_version: VmmVersionInfo,
630         api_evt: EventFd,
631         #[cfg(feature = "guest_debug")] debug_evt: EventFd,
632         #[cfg(feature = "guest_debug")] vm_debug_evt: EventFd,
633         seccomp_action: SeccompAction,
634         hypervisor: Arc<dyn hypervisor::Hypervisor>,
635         exit_evt: EventFd,
636     ) -> Result<Self> {
637         let mut epoll = EpollContext::new().map_err(Error::Epoll)?;
638         let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
639         let activate_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
640 
641         epoll
642             .add_event(&exit_evt, EpollDispatch::Exit)
643             .map_err(Error::Epoll)?;
644 
645         epoll
646             .add_event(&reset_evt, EpollDispatch::Reset)
647             .map_err(Error::Epoll)?;
648 
649         epoll
650             .add_event(&activate_evt, EpollDispatch::ActivateVirtioDevices)
651             .map_err(Error::Epoll)?;
652 
653         epoll
654             .add_event(&api_evt, EpollDispatch::Api)
655             .map_err(Error::Epoll)?;
656 
657         #[cfg(feature = "guest_debug")]
658         epoll
659             .add_event(&debug_evt, EpollDispatch::Debug)
660             .map_err(Error::Epoll)?;
661 
662         Ok(Vmm {
663             epoll,
664             exit_evt,
665             reset_evt,
666             api_evt,
667             #[cfg(feature = "guest_debug")]
668             debug_evt,
669             #[cfg(feature = "guest_debug")]
670             vm_debug_evt,
671             version: vmm_version,
672             vm: None,
673             vm_config: None,
674             seccomp_action,
675             hypervisor,
676             activate_evt,
677             signals: None,
678             threads: vec![],
679             original_termios_opt: Arc::new(Mutex::new(None)),
680         })
681     }
682 
683     fn vm_receive_config<T>(
684         &mut self,
685         req: &Request,
686         socket: &mut T,
687         existing_memory_files: Option<HashMap<u32, File>>,
688     ) -> std::result::Result<Arc<Mutex<MemoryManager>>, MigratableError>
689     where
690         T: Read + Write,
691     {
692         // Read in config data along with memory manager data
693         let mut data: Vec<u8> = Vec::new();
694         data.resize_with(req.length() as usize, Default::default);
695         socket
696             .read_exact(&mut data)
697             .map_err(MigratableError::MigrateSocket)?;
698 
699         let vm_migration_config: VmMigrationConfig =
700             serde_json::from_slice(&data).map_err(|e| {
701                 MigratableError::MigrateReceive(anyhow!("Error deserialising config: {}", e))
702             })?;
703 
704         #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
705         self.vm_check_cpuid_compatibility(
706             &vm_migration_config.vm_config,
707             &vm_migration_config.common_cpuid,
708         )?;
709 
710         let config = vm_migration_config.vm_config.clone();
711         self.vm_config = Some(vm_migration_config.vm_config);
712 
713         let vm = Vm::create_hypervisor_vm(
714             &self.hypervisor,
715             #[cfg(feature = "tdx")]
716             false,
717             #[cfg(feature = "sev_snp")]
718             false,
719         )
720         .map_err(|e| {
721             MigratableError::MigrateReceive(anyhow!(
722                 "Error creating hypervisor VM from snapshot: {:?}",
723                 e
724             ))
725         })?;
726 
727         let phys_bits =
728             vm::physical_bits(&self.hypervisor, config.lock().unwrap().cpus.max_phys_bits);
729 
730         let memory_manager = MemoryManager::new(
731             vm,
732             &config.lock().unwrap().memory.clone(),
733             None,
734             phys_bits,
735             #[cfg(feature = "tdx")]
736             false,
737             Some(&vm_migration_config.memory_manager_data),
738             existing_memory_files,
739             #[cfg(target_arch = "x86_64")]
740             None,
741         )
742         .map_err(|e| {
743             MigratableError::MigrateReceive(anyhow!(
744                 "Error creating MemoryManager from snapshot: {:?}",
745                 e
746             ))
747         })?;
748 
749         Response::ok().write_to(socket)?;
750 
751         Ok(memory_manager)
752     }
753 
754     fn vm_receive_state<T>(
755         &mut self,
756         req: &Request,
757         socket: &mut T,
758         mm: Arc<Mutex<MemoryManager>>,
759     ) -> std::result::Result<(), MigratableError>
760     where
761         T: Read + Write,
762     {
763         // Read in state data
764         let mut data: Vec<u8> = Vec::new();
765         data.resize_with(req.length() as usize, Default::default);
766         socket
767             .read_exact(&mut data)
768             .map_err(MigratableError::MigrateSocket)?;
769         let snapshot: Snapshot = serde_json::from_slice(&data).map_err(|e| {
770             MigratableError::MigrateReceive(anyhow!("Error deserialising snapshot: {}", e))
771         })?;
772 
773         let exit_evt = self.exit_evt.try_clone().map_err(|e| {
774             MigratableError::MigrateReceive(anyhow!("Error cloning exit EventFd: {}", e))
775         })?;
776         let reset_evt = self.reset_evt.try_clone().map_err(|e| {
777             MigratableError::MigrateReceive(anyhow!("Error cloning reset EventFd: {}", e))
778         })?;
779         #[cfg(feature = "guest_debug")]
780         let debug_evt = self.vm_debug_evt.try_clone().map_err(|e| {
781             MigratableError::MigrateReceive(anyhow!("Error cloning debug EventFd: {}", e))
782         })?;
783         let activate_evt = self.activate_evt.try_clone().map_err(|e| {
784             MigratableError::MigrateReceive(anyhow!("Error cloning activate EventFd: {}", e))
785         })?;
786 
787         let timestamp = Instant::now();
788         let hypervisor_vm = mm.lock().unwrap().vm.clone();
789         let mut vm = Vm::new_from_memory_manager(
790             self.vm_config.clone().unwrap(),
791             mm,
792             hypervisor_vm,
793             exit_evt,
794             reset_evt,
795             #[cfg(feature = "guest_debug")]
796             debug_evt,
797             &self.seccomp_action,
798             self.hypervisor.clone(),
799             activate_evt,
800             timestamp,
801             None,
802             None,
803             None,
804             Arc::clone(&self.original_termios_opt),
805             Some(snapshot),
806         )
807         .map_err(|e| {
808             MigratableError::MigrateReceive(anyhow!("Error creating VM from snapshot: {:?}", e))
809         })?;
810 
811         // Create VM
812         vm.restore().map_err(|e| {
813             Response::error().write_to(socket).ok();
814             MigratableError::MigrateReceive(anyhow!("Failed restoring the Vm: {}", e))
815         })?;
816         self.vm = Some(vm);
817 
818         Response::ok().write_to(socket)?;
819 
820         Ok(())
821     }
822 
823     fn vm_receive_memory<T>(
824         &mut self,
825         req: &Request,
826         socket: &mut T,
827         memory_manager: &mut MemoryManager,
828     ) -> std::result::Result<(), MigratableError>
829     where
830         T: Read + ReadVolatile + Write,
831     {
832         // Read table
833         let table = MemoryRangeTable::read_from(socket, req.length())?;
834 
835         // And then read the memory itself
836         memory_manager
837             .receive_memory_regions(&table, socket)
838             .map_err(|e| {
839                 Response::error().write_to(socket).ok();
840                 e
841             })?;
842         Response::ok().write_to(socket)?;
843         Ok(())
844     }
845 
846     fn socket_url_to_path(url: &str) -> result::Result<PathBuf, MigratableError> {
847         url.strip_prefix("unix:")
848             .ok_or_else(|| {
849                 MigratableError::MigrateSend(anyhow!("Could not extract path from URL: {}", url))
850             })
851             .map(|s| s.into())
852     }
853 
854     // Returns true if there were dirty pages to send
855     fn vm_maybe_send_dirty_pages<T>(
856         vm: &mut Vm,
857         socket: &mut T,
858     ) -> result::Result<bool, MigratableError>
859     where
860         T: Read + Write + WriteVolatile,
861     {
862         // Send (dirty) memory table
863         let table = vm.dirty_log()?;
864 
865         // But if there are no regions go straight to pause
866         if table.regions().is_empty() {
867             return Ok(false);
868         }
869 
870         Request::memory(table.length()).write_to(socket).unwrap();
871         table.write_to(socket)?;
872         // And then the memory itself
873         vm.send_memory_regions(&table, socket)?;
874         let res = Response::read_from(socket)?;
875         if res.status() != Status::Ok {
876             warn!("Error during dirty memory migration");
877             Request::abandon().write_to(socket)?;
878             Response::read_from(socket).ok();
879             return Err(MigratableError::MigrateSend(anyhow!(
880                 "Error during dirty memory migration"
881             )));
882         }
883 
884         Ok(true)
885     }
886 
887     fn send_migration(
888         vm: &mut Vm,
889         #[cfg(all(feature = "kvm", target_arch = "x86_64"))] hypervisor: Arc<
890             dyn hypervisor::Hypervisor,
891         >,
892         send_data_migration: VmSendMigrationData,
893     ) -> result::Result<(), MigratableError> {
894         let path = Self::socket_url_to_path(&send_data_migration.destination_url)?;
895         let mut socket = UnixStream::connect(path).map_err(|e| {
896             MigratableError::MigrateSend(anyhow!("Error connecting to UNIX socket: {}", e))
897         })?;
898 
899         // Start the migration
900         Request::start().write_to(&mut socket)?;
901         let res = Response::read_from(&mut socket)?;
902         if res.status() != Status::Ok {
903             warn!("Error starting migration");
904             Request::abandon().write_to(&mut socket)?;
905             Response::read_from(&mut socket).ok();
906             return Err(MigratableError::MigrateSend(anyhow!(
907                 "Error starting migration"
908             )));
909         }
910 
911         // Send config
912         let vm_config = vm.get_config();
913         #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
914         let common_cpuid = {
915             #[cfg(feature = "tdx")]
916             if vm_config.lock().unwrap().is_tdx_enabled() {
917                 return Err(MigratableError::MigrateSend(anyhow!(
918                     "Live Migration is not supported when TDX is enabled"
919                 )));
920             };
921 
922             let amx = vm_config.lock().unwrap().cpus.features.amx;
923             let phys_bits =
924                 vm::physical_bits(&hypervisor, vm_config.lock().unwrap().cpus.max_phys_bits);
925             arch::generate_common_cpuid(
926                 &hypervisor,
927                 &arch::CpuidConfig {
928                     sgx_epc_sections: None,
929                     phys_bits,
930                     kvm_hyperv: vm_config.lock().unwrap().cpus.kvm_hyperv,
931                     #[cfg(feature = "tdx")]
932                     tdx: false,
933                     amx,
934                 },
935             )
936             .map_err(|e| {
937                 MigratableError::MigrateSend(anyhow!("Error generating common cpuid': {:?}", e))
938             })?
939         };
940 
941         if send_data_migration.local {
942             vm.send_memory_fds(&mut socket)?;
943         }
944 
945         let vm_migration_config = VmMigrationConfig {
946             vm_config,
947             #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
948             common_cpuid,
949             memory_manager_data: vm.memory_manager_data(),
950         };
951         let config_data = serde_json::to_vec(&vm_migration_config).unwrap();
952         Request::config(config_data.len() as u64).write_to(&mut socket)?;
953         socket
954             .write_all(&config_data)
955             .map_err(MigratableError::MigrateSocket)?;
956         let res = Response::read_from(&mut socket)?;
957         if res.status() != Status::Ok {
958             warn!("Error during config migration");
959             Request::abandon().write_to(&mut socket)?;
960             Response::read_from(&mut socket).ok();
961             return Err(MigratableError::MigrateSend(anyhow!(
962                 "Error during config migration"
963             )));
964         }
965 
966         // Let every Migratable object know about the migration being started.
967         vm.start_migration()?;
968 
969         if send_data_migration.local {
970             // Now pause VM
971             vm.pause()?;
972         } else {
973             // Start logging dirty pages
974             vm.start_dirty_log()?;
975 
976             // Send memory table
977             let table = vm.memory_range_table()?;
978             Request::memory(table.length())
979                 .write_to(&mut socket)
980                 .unwrap();
981             table.write_to(&mut socket)?;
982             // And then the memory itself
983             vm.send_memory_regions(&table, &mut socket)?;
984             let res = Response::read_from(&mut socket)?;
985             if res.status() != Status::Ok {
986                 warn!("Error during memory migration");
987                 Request::abandon().write_to(&mut socket)?;
988                 Response::read_from(&mut socket).ok();
989                 return Err(MigratableError::MigrateSend(anyhow!(
990                     "Error during memory migration"
991                 )));
992             }
993 
994             // Try at most 5 passes of dirty memory sending
995             const MAX_DIRTY_MIGRATIONS: usize = 5;
996             for i in 0..MAX_DIRTY_MIGRATIONS {
997                 info!("Dirty memory migration {} of {}", i, MAX_DIRTY_MIGRATIONS);
998                 if !Self::vm_maybe_send_dirty_pages(vm, &mut socket)? {
999                     break;
1000                 }
1001             }
1002 
1003             // Now pause VM
1004             vm.pause()?;
1005 
1006             // Send last batch of dirty pages
1007             Self::vm_maybe_send_dirty_pages(vm, &mut socket)?;
1008 
1009             // Stop logging dirty pages
1010             vm.stop_dirty_log()?;
1011         }
1012         // Capture snapshot and send it
1013         let vm_snapshot = vm.snapshot()?;
1014         let snapshot_data = serde_json::to_vec(&vm_snapshot).unwrap();
1015         Request::state(snapshot_data.len() as u64).write_to(&mut socket)?;
1016         socket
1017             .write_all(&snapshot_data)
1018             .map_err(MigratableError::MigrateSocket)?;
1019         let res = Response::read_from(&mut socket)?;
1020         if res.status() != Status::Ok {
1021             warn!("Error during state migration");
1022             Request::abandon().write_to(&mut socket)?;
1023             Response::read_from(&mut socket).ok();
1024             return Err(MigratableError::MigrateSend(anyhow!(
1025                 "Error during state migration"
1026             )));
1027         }
1028 
1029         // Complete the migration
1030         Request::complete().write_to(&mut socket)?;
1031         let res = Response::read_from(&mut socket)?;
1032         if res.status() != Status::Ok {
1033             warn!("Error completing migration");
1034             Request::abandon().write_to(&mut socket)?;
1035             Response::read_from(&mut socket).ok();
1036             return Err(MigratableError::MigrateSend(anyhow!(
1037                 "Error completing migration"
1038             )));
1039         }
1040         info!("Migration complete");
1041 
1042         // Let every Migratable object know about the migration being complete
1043         vm.complete_migration()
1044     }
1045 
1046     #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
1047     fn vm_check_cpuid_compatibility(
1048         &self,
1049         src_vm_config: &Arc<Mutex<VmConfig>>,
1050         src_vm_cpuid: &[hypervisor::arch::x86::CpuIdEntry],
1051     ) -> result::Result<(), MigratableError> {
1052         #[cfg(feature = "tdx")]
1053         if src_vm_config.lock().unwrap().is_tdx_enabled() {
1054             return Err(MigratableError::MigrateReceive(anyhow!(
1055                 "Live Migration is not supported when TDX is enabled"
1056             )));
1057         };
1058 
1059         // We check the `CPUID` compatibility of between the source vm and destination, which is
1060         // mostly about feature compatibility and "topology/sgx" leaves are not relevant.
1061         let dest_cpuid = &{
1062             let vm_config = &src_vm_config.lock().unwrap();
1063 
1064             let phys_bits = vm::physical_bits(&self.hypervisor, vm_config.cpus.max_phys_bits);
1065             arch::generate_common_cpuid(
1066                 &self.hypervisor.clone(),
1067                 &arch::CpuidConfig {
1068                     sgx_epc_sections: None,
1069                     phys_bits,
1070                     kvm_hyperv: vm_config.cpus.kvm_hyperv,
1071                     #[cfg(feature = "tdx")]
1072                     tdx: false,
1073                     amx: vm_config.cpus.features.amx,
1074                 },
1075             )
1076             .map_err(|e| {
1077                 MigratableError::MigrateReceive(anyhow!("Error generating common cpuid: {:?}", e))
1078             })?
1079         };
1080         arch::CpuidFeatureEntry::check_cpuid_compatibility(src_vm_cpuid, dest_cpuid).map_err(|e| {
1081             MigratableError::MigrateReceive(anyhow!(
1082                 "Error checking cpu feature compatibility': {:?}",
1083                 e
1084             ))
1085         })
1086     }
1087 
1088     fn control_loop(
1089         &mut self,
1090         api_receiver: Rc<Receiver<ApiRequest>>,
1091         #[cfg(feature = "guest_debug")] gdb_receiver: Rc<Receiver<gdb::GdbRequest>>,
1092     ) -> Result<()> {
1093         const EPOLL_EVENTS_LEN: usize = 100;
1094 
1095         let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
1096         let epoll_fd = self.epoll.as_raw_fd();
1097 
1098         'outer: loop {
1099             let num_events = match epoll::wait(epoll_fd, -1, &mut events[..]) {
1100                 Ok(res) => res,
1101                 Err(e) => {
1102                     if e.kind() == io::ErrorKind::Interrupted {
1103                         // It's well defined from the epoll_wait() syscall
1104                         // documentation that the epoll loop can be interrupted
1105                         // before any of the requested events occurred or the
1106                         // timeout expired. In both those cases, epoll_wait()
1107                         // returns an error of type EINTR, but this should not
1108                         // be considered as a regular error. Instead it is more
1109                         // appropriate to retry, by calling into epoll_wait().
1110                         continue;
1111                     }
1112                     return Err(Error::Epoll(e));
1113                 }
1114             };
1115 
1116             for event in events.iter().take(num_events) {
1117                 let dispatch_event: EpollDispatch = event.data.into();
1118                 match dispatch_event {
1119                     EpollDispatch::Unknown => {
1120                         let event = event.data;
1121                         warn!("Unknown VMM loop event: {}", event);
1122                     }
1123                     EpollDispatch::Exit => {
1124                         info!("VM exit event");
1125                         // Consume the event.
1126                         self.exit_evt.read().map_err(Error::EventFdRead)?;
1127                         self.vmm_shutdown().map_err(Error::VmmShutdown)?;
1128 
1129                         break 'outer;
1130                     }
1131                     EpollDispatch::Reset => {
1132                         info!("VM reset event");
1133                         // Consume the event.
1134                         self.reset_evt.read().map_err(Error::EventFdRead)?;
1135                         self.vm_reboot().map_err(Error::VmReboot)?;
1136                     }
1137                     EpollDispatch::ActivateVirtioDevices => {
1138                         if let Some(ref vm) = self.vm {
1139                             let count = self.activate_evt.read().map_err(Error::EventFdRead)?;
1140                             info!(
1141                                 "Trying to activate pending virtio devices: count = {}",
1142                                 count
1143                             );
1144                             vm.activate_virtio_devices()
1145                                 .map_err(Error::ActivateVirtioDevices)?;
1146                         }
1147                     }
1148                     EpollDispatch::Api => {
1149                         // Consume the events.
1150                         for _ in 0..self.api_evt.read().map_err(Error::EventFdRead)? {
1151                             // Read from the API receiver channel
1152                             let api_request = api_receiver.recv().map_err(Error::ApiRequestRecv)?;
1153 
1154                             if api_request(self)? {
1155                                 break 'outer;
1156                             }
1157                         }
1158                     }
1159                     #[cfg(feature = "guest_debug")]
1160                     EpollDispatch::Debug => {
1161                         // Consume the events.
1162                         for _ in 0..self.debug_evt.read().map_err(Error::EventFdRead)? {
1163                             // Read from the API receiver channel
1164                             let gdb_request = gdb_receiver.recv().map_err(Error::GdbRequestRecv)?;
1165 
1166                             let response = if let Some(ref mut vm) = self.vm {
1167                                 vm.debug_request(&gdb_request.payload, gdb_request.cpu_id)
1168                             } else {
1169                                 Err(VmError::VmNotRunning)
1170                             }
1171                             .map_err(gdb::Error::Vm);
1172 
1173                             gdb_request
1174                                 .sender
1175                                 .send(response)
1176                                 .map_err(Error::GdbResponseSend)?;
1177                         }
1178                     }
1179                     #[cfg(not(feature = "guest_debug"))]
1180                     EpollDispatch::Debug => {}
1181                 }
1182             }
1183         }
1184 
1185         // Trigger the termination of the signal_handler thread
1186         if let Some(signals) = self.signals.take() {
1187             signals.close();
1188         }
1189 
1190         // Wait for all the threads to finish
1191         for thread in self.threads.drain(..) {
1192             thread.join().map_err(Error::ThreadCleanup)?
1193         }
1194 
1195         Ok(())
1196     }
1197 }
1198 
1199 impl RequestHandler for Vmm {
1200     fn vm_create(&mut self, config: Arc<Mutex<VmConfig>>) -> result::Result<(), VmError> {
1201         // We only store the passed VM config.
1202         // The VM will be created when being asked to boot it.
1203         if self.vm_config.is_none() {
1204             self.vm_config = Some(config);
1205             Ok(())
1206         } else {
1207             Err(VmError::VmAlreadyCreated)
1208         }
1209     }
1210 
1211     fn vm_boot(&mut self) -> result::Result<(), VmError> {
1212         tracer::start();
1213         let r = {
1214             trace_scoped!("vm_boot");
1215             // If we don't have a config, we can not boot a VM.
1216             if self.vm_config.is_none() {
1217                 return Err(VmError::VmMissingConfig);
1218             };
1219 
1220             // Create a new VM if we don't have one yet.
1221             if self.vm.is_none() {
1222                 let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
1223                 let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
1224                 #[cfg(feature = "guest_debug")]
1225                 let vm_debug_evt = self
1226                     .vm_debug_evt
1227                     .try_clone()
1228                     .map_err(VmError::EventFdClone)?;
1229                 let activate_evt = self
1230                     .activate_evt
1231                     .try_clone()
1232                     .map_err(VmError::EventFdClone)?;
1233 
1234                 if let Some(ref vm_config) = self.vm_config {
1235                     let vm = Vm::new(
1236                         Arc::clone(vm_config),
1237                         exit_evt,
1238                         reset_evt,
1239                         #[cfg(feature = "guest_debug")]
1240                         vm_debug_evt,
1241                         &self.seccomp_action,
1242                         self.hypervisor.clone(),
1243                         activate_evt,
1244                         None,
1245                         None,
1246                         None,
1247                         Arc::clone(&self.original_termios_opt),
1248                         None,
1249                         None,
1250                         None,
1251                     )?;
1252 
1253                     self.vm = Some(vm);
1254                 }
1255             }
1256 
1257             // Now we can boot the VM.
1258             if let Some(ref mut vm) = self.vm {
1259                 vm.boot()
1260             } else {
1261                 Err(VmError::VmNotCreated)
1262             }
1263         };
1264         tracer::end();
1265         r
1266     }
1267 
1268     fn vm_pause(&mut self) -> result::Result<(), VmError> {
1269         if let Some(ref mut vm) = self.vm {
1270             vm.pause().map_err(VmError::Pause)
1271         } else {
1272             Err(VmError::VmNotRunning)
1273         }
1274     }
1275 
1276     fn vm_resume(&mut self) -> result::Result<(), VmError> {
1277         if let Some(ref mut vm) = self.vm {
1278             vm.resume().map_err(VmError::Resume)
1279         } else {
1280             Err(VmError::VmNotRunning)
1281         }
1282     }
1283 
1284     fn vm_snapshot(&mut self, destination_url: &str) -> result::Result<(), VmError> {
1285         if let Some(ref mut vm) = self.vm {
1286             vm.snapshot()
1287                 .map_err(VmError::Snapshot)
1288                 .and_then(|snapshot| {
1289                     vm.send(&snapshot, destination_url)
1290                         .map_err(VmError::SnapshotSend)
1291                 })
1292         } else {
1293             Err(VmError::VmNotRunning)
1294         }
1295     }
1296 
1297     fn vm_restore(&mut self, restore_cfg: RestoreConfig) -> result::Result<(), VmError> {
1298         if self.vm.is_some() || self.vm_config.is_some() {
1299             return Err(VmError::VmAlreadyCreated);
1300         }
1301 
1302         let source_url = restore_cfg.source_url.as_path().to_str();
1303         if source_url.is_none() {
1304             return Err(VmError::InvalidRestoreSourceUrl);
1305         }
1306         // Safe to unwrap as we checked it was Some(&str).
1307         let source_url = source_url.unwrap();
1308 
1309         let vm_config = Arc::new(Mutex::new(
1310             recv_vm_config(source_url).map_err(VmError::Restore)?,
1311         ));
1312         let snapshot = recv_vm_state(source_url).map_err(VmError::Restore)?;
1313         #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
1314         let vm_snapshot = get_vm_snapshot(&snapshot).map_err(VmError::Restore)?;
1315 
1316         #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
1317         self.vm_check_cpuid_compatibility(&vm_config, &vm_snapshot.common_cpuid)
1318             .map_err(VmError::Restore)?;
1319 
1320         self.vm_config = Some(Arc::clone(&vm_config));
1321 
1322         let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
1323         let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
1324         #[cfg(feature = "guest_debug")]
1325         let debug_evt = self
1326             .vm_debug_evt
1327             .try_clone()
1328             .map_err(VmError::EventFdClone)?;
1329         let activate_evt = self
1330             .activate_evt
1331             .try_clone()
1332             .map_err(VmError::EventFdClone)?;
1333 
1334         let vm = Vm::new(
1335             vm_config,
1336             exit_evt,
1337             reset_evt,
1338             #[cfg(feature = "guest_debug")]
1339             debug_evt,
1340             &self.seccomp_action,
1341             self.hypervisor.clone(),
1342             activate_evt,
1343             None,
1344             None,
1345             None,
1346             Arc::clone(&self.original_termios_opt),
1347             Some(snapshot),
1348             Some(source_url),
1349             Some(restore_cfg.prefault),
1350         )?;
1351         self.vm = Some(vm);
1352 
1353         // Now we can restore the rest of the VM.
1354         if let Some(ref mut vm) = self.vm {
1355             vm.restore()
1356         } else {
1357             Err(VmError::VmNotCreated)
1358         }
1359     }
1360 
1361     #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
1362     fn vm_coredump(&mut self, destination_url: &str) -> result::Result<(), VmError> {
1363         if let Some(ref mut vm) = self.vm {
1364             vm.coredump(destination_url).map_err(VmError::Coredump)
1365         } else {
1366             Err(VmError::VmNotRunning)
1367         }
1368     }
1369 
1370     fn vm_shutdown(&mut self) -> result::Result<(), VmError> {
1371         if let Some(ref mut vm) = self.vm.take() {
1372             vm.shutdown()
1373         } else {
1374             Err(VmError::VmNotRunning)
1375         }
1376     }
1377 
1378     fn vm_reboot(&mut self) -> result::Result<(), VmError> {
1379         // First we stop the current VM
1380         let (config, serial_pty, console_pty, console_resize_pipe) =
1381             if let Some(mut vm) = self.vm.take() {
1382                 let config = vm.get_config();
1383                 let serial_pty = vm.serial_pty();
1384                 let console_pty = vm.console_pty();
1385                 let console_resize_pipe = vm
1386                     .console_resize_pipe()
1387                     .as_ref()
1388                     .map(|pipe| pipe.try_clone().unwrap());
1389                 vm.shutdown()?;
1390                 (config, serial_pty, console_pty, console_resize_pipe)
1391             } else {
1392                 return Err(VmError::VmNotCreated);
1393             };
1394 
1395         let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
1396         let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
1397         #[cfg(feature = "guest_debug")]
1398         let debug_evt = self
1399             .vm_debug_evt
1400             .try_clone()
1401             .map_err(VmError::EventFdClone)?;
1402         let activate_evt = self
1403             .activate_evt
1404             .try_clone()
1405             .map_err(VmError::EventFdClone)?;
1406 
1407         // The Linux kernel fires off an i8042 reset after doing the ACPI reset so there may be
1408         // an event sitting in the shared reset_evt. Without doing this we get very early reboots
1409         // during the boot process.
1410         if self.reset_evt.read().is_ok() {
1411             warn!("Spurious second reset event received. Ignoring.");
1412         }
1413 
1414         // Then we create the new VM
1415         let mut vm = Vm::new(
1416             config,
1417             exit_evt,
1418             reset_evt,
1419             #[cfg(feature = "guest_debug")]
1420             debug_evt,
1421             &self.seccomp_action,
1422             self.hypervisor.clone(),
1423             activate_evt,
1424             serial_pty,
1425             console_pty,
1426             console_resize_pipe,
1427             Arc::clone(&self.original_termios_opt),
1428             None,
1429             None,
1430             None,
1431         )?;
1432 
1433         // And we boot it
1434         vm.boot()?;
1435 
1436         self.vm = Some(vm);
1437 
1438         Ok(())
1439     }
1440 
1441     fn vm_info(&self) -> result::Result<VmInfoResponse, VmError> {
1442         match &self.vm_config {
1443             Some(config) => {
1444                 let state = match &self.vm {
1445                     Some(vm) => vm.get_state()?,
1446                     None => VmState::Created,
1447                 };
1448 
1449                 let config = Arc::clone(config);
1450 
1451                 let mut memory_actual_size = config.lock().unwrap().memory.total_size();
1452                 if let Some(vm) = &self.vm {
1453                     memory_actual_size -= vm.balloon_size();
1454                 }
1455 
1456                 let device_tree = self.vm.as_ref().map(|vm| vm.device_tree());
1457 
1458                 Ok(VmInfoResponse {
1459                     config,
1460                     state,
1461                     memory_actual_size,
1462                     device_tree,
1463                 })
1464             }
1465             None => Err(VmError::VmNotCreated),
1466         }
1467     }
1468 
1469     fn vmm_ping(&self) -> VmmPingResponse {
1470         let VmmVersionInfo {
1471             build_version,
1472             version,
1473         } = self.version.clone();
1474 
1475         VmmPingResponse {
1476             build_version,
1477             version,
1478             pid: std::process::id() as i64,
1479             features: feature_list(),
1480         }
1481     }
1482 
1483     fn vm_delete(&mut self) -> result::Result<(), VmError> {
1484         if self.vm_config.is_none() {
1485             return Ok(());
1486         }
1487 
1488         // If a VM is booted, we first try to shut it down.
1489         if self.vm.is_some() {
1490             self.vm_shutdown()?;
1491         }
1492 
1493         self.vm_config = None;
1494 
1495         event!("vm", "deleted");
1496 
1497         Ok(())
1498     }
1499 
1500     fn vmm_shutdown(&mut self) -> result::Result<(), VmError> {
1501         self.vm_delete()?;
1502         event!("vmm", "shutdown");
1503         Ok(())
1504     }
1505 
1506     fn vm_resize(
1507         &mut self,
1508         desired_vcpus: Option<u8>,
1509         desired_ram: Option<u64>,
1510         desired_balloon: Option<u64>,
1511     ) -> result::Result<(), VmError> {
1512         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1513 
1514         if let Some(ref mut vm) = self.vm {
1515             if let Err(e) = vm.resize(desired_vcpus, desired_ram, desired_balloon) {
1516                 error!("Error when resizing VM: {:?}", e);
1517                 Err(e)
1518             } else {
1519                 Ok(())
1520             }
1521         } else {
1522             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1523             if let Some(desired_vcpus) = desired_vcpus {
1524                 config.cpus.boot_vcpus = desired_vcpus;
1525             }
1526             if let Some(desired_ram) = desired_ram {
1527                 config.memory.size = desired_ram;
1528             }
1529             if let Some(desired_balloon) = desired_balloon {
1530                 if let Some(balloon_config) = &mut config.balloon {
1531                     balloon_config.size = desired_balloon;
1532                 }
1533             }
1534             Ok(())
1535         }
1536     }
1537 
1538     fn vm_resize_zone(&mut self, id: String, desired_ram: u64) -> result::Result<(), VmError> {
1539         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1540 
1541         if let Some(ref mut vm) = self.vm {
1542             if let Err(e) = vm.resize_zone(id, desired_ram) {
1543                 error!("Error when resizing VM: {:?}", e);
1544                 Err(e)
1545             } else {
1546                 Ok(())
1547             }
1548         } else {
1549             // Update VmConfig by setting the new desired ram.
1550             let memory_config = &mut self.vm_config.as_ref().unwrap().lock().unwrap().memory;
1551 
1552             if let Some(zones) = &mut memory_config.zones {
1553                 for zone in zones.iter_mut() {
1554                     if zone.id == id {
1555                         zone.size = desired_ram;
1556                         return Ok(());
1557                     }
1558                 }
1559             }
1560 
1561             error!("Could not find the memory zone {} for the resize", id);
1562             Err(VmError::ResizeZone)
1563         }
1564     }
1565 
1566     fn vm_add_device(
1567         &mut self,
1568         device_cfg: DeviceConfig,
1569     ) -> result::Result<Option<Vec<u8>>, VmError> {
1570         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1571 
1572         {
1573             // Validate the configuration change in a cloned configuration
1574             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1575             add_to_config(&mut config.devices, device_cfg.clone());
1576             config.validate().map_err(VmError::ConfigValidation)?;
1577         }
1578 
1579         if let Some(ref mut vm) = self.vm {
1580             let info = vm.add_device(device_cfg).map_err(|e| {
1581                 error!("Error when adding new device to the VM: {:?}", e);
1582                 e
1583             })?;
1584             serde_json::to_vec(&info)
1585                 .map(Some)
1586                 .map_err(VmError::SerializeJson)
1587         } else {
1588             // Update VmConfig by adding the new device.
1589             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1590             add_to_config(&mut config.devices, device_cfg);
1591             Ok(None)
1592         }
1593     }
1594 
1595     fn vm_add_user_device(
1596         &mut self,
1597         device_cfg: UserDeviceConfig,
1598     ) -> result::Result<Option<Vec<u8>>, VmError> {
1599         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1600 
1601         {
1602             // Validate the configuration change in a cloned configuration
1603             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1604             add_to_config(&mut config.user_devices, device_cfg.clone());
1605             config.validate().map_err(VmError::ConfigValidation)?;
1606         }
1607 
1608         if let Some(ref mut vm) = self.vm {
1609             let info = vm.add_user_device(device_cfg).map_err(|e| {
1610                 error!("Error when adding new user device to the VM: {:?}", e);
1611                 e
1612             })?;
1613             serde_json::to_vec(&info)
1614                 .map(Some)
1615                 .map_err(VmError::SerializeJson)
1616         } else {
1617             // Update VmConfig by adding the new device.
1618             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1619             add_to_config(&mut config.user_devices, device_cfg);
1620             Ok(None)
1621         }
1622     }
1623 
1624     fn vm_remove_device(&mut self, id: String) -> result::Result<(), VmError> {
1625         if let Some(ref mut vm) = self.vm {
1626             if let Err(e) = vm.remove_device(id) {
1627                 error!("Error when removing device from the VM: {:?}", e);
1628                 Err(e)
1629             } else {
1630                 Ok(())
1631             }
1632         } else if let Some(ref config) = self.vm_config {
1633             let mut config = config.lock().unwrap();
1634             if config.remove_device(&id) {
1635                 Ok(())
1636             } else {
1637                 Err(VmError::NoDeviceToRemove(id))
1638             }
1639         } else {
1640             Err(VmError::VmNotCreated)
1641         }
1642     }
1643 
1644     fn vm_add_disk(&mut self, disk_cfg: DiskConfig) -> result::Result<Option<Vec<u8>>, VmError> {
1645         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1646 
1647         {
1648             // Validate the configuration change in a cloned configuration
1649             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1650             add_to_config(&mut config.disks, disk_cfg.clone());
1651             config.validate().map_err(VmError::ConfigValidation)?;
1652         }
1653 
1654         if let Some(ref mut vm) = self.vm {
1655             let info = vm.add_disk(disk_cfg).map_err(|e| {
1656                 error!("Error when adding new disk to the VM: {:?}", e);
1657                 e
1658             })?;
1659             serde_json::to_vec(&info)
1660                 .map(Some)
1661                 .map_err(VmError::SerializeJson)
1662         } else {
1663             // Update VmConfig by adding the new device.
1664             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1665             add_to_config(&mut config.disks, disk_cfg);
1666             Ok(None)
1667         }
1668     }
1669 
1670     fn vm_add_fs(&mut self, fs_cfg: FsConfig) -> result::Result<Option<Vec<u8>>, VmError> {
1671         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1672 
1673         {
1674             // Validate the configuration change in a cloned configuration
1675             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1676             add_to_config(&mut config.fs, fs_cfg.clone());
1677             config.validate().map_err(VmError::ConfigValidation)?;
1678         }
1679 
1680         if let Some(ref mut vm) = self.vm {
1681             let info = vm.add_fs(fs_cfg).map_err(|e| {
1682                 error!("Error when adding new fs to the VM: {:?}", e);
1683                 e
1684             })?;
1685             serde_json::to_vec(&info)
1686                 .map(Some)
1687                 .map_err(VmError::SerializeJson)
1688         } else {
1689             // Update VmConfig by adding the new device.
1690             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1691             add_to_config(&mut config.fs, fs_cfg);
1692             Ok(None)
1693         }
1694     }
1695 
1696     fn vm_add_pmem(&mut self, pmem_cfg: PmemConfig) -> result::Result<Option<Vec<u8>>, VmError> {
1697         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1698 
1699         {
1700             // Validate the configuration change in a cloned configuration
1701             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1702             add_to_config(&mut config.pmem, pmem_cfg.clone());
1703             config.validate().map_err(VmError::ConfigValidation)?;
1704         }
1705 
1706         if let Some(ref mut vm) = self.vm {
1707             let info = vm.add_pmem(pmem_cfg).map_err(|e| {
1708                 error!("Error when adding new pmem device to the VM: {:?}", e);
1709                 e
1710             })?;
1711             serde_json::to_vec(&info)
1712                 .map(Some)
1713                 .map_err(VmError::SerializeJson)
1714         } else {
1715             // Update VmConfig by adding the new device.
1716             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1717             add_to_config(&mut config.pmem, pmem_cfg);
1718             Ok(None)
1719         }
1720     }
1721 
1722     fn vm_add_net(&mut self, net_cfg: NetConfig) -> result::Result<Option<Vec<u8>>, VmError> {
1723         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1724 
1725         {
1726             // Validate the configuration change in a cloned configuration
1727             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1728             add_to_config(&mut config.net, net_cfg.clone());
1729             config.validate().map_err(VmError::ConfigValidation)?;
1730         }
1731 
1732         if let Some(ref mut vm) = self.vm {
1733             let info = vm.add_net(net_cfg).map_err(|e| {
1734                 error!("Error when adding new network device to the VM: {:?}", e);
1735                 e
1736             })?;
1737             serde_json::to_vec(&info)
1738                 .map(Some)
1739                 .map_err(VmError::SerializeJson)
1740         } else {
1741             // Update VmConfig by adding the new device.
1742             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1743             add_to_config(&mut config.net, net_cfg);
1744             Ok(None)
1745         }
1746     }
1747 
1748     fn vm_add_vdpa(&mut self, vdpa_cfg: VdpaConfig) -> result::Result<Option<Vec<u8>>, VmError> {
1749         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1750 
1751         {
1752             // Validate the configuration change in a cloned configuration
1753             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1754             add_to_config(&mut config.vdpa, vdpa_cfg.clone());
1755             config.validate().map_err(VmError::ConfigValidation)?;
1756         }
1757 
1758         if let Some(ref mut vm) = self.vm {
1759             let info = vm.add_vdpa(vdpa_cfg).map_err(|e| {
1760                 error!("Error when adding new vDPA device to the VM: {:?}", e);
1761                 e
1762             })?;
1763             serde_json::to_vec(&info)
1764                 .map(Some)
1765                 .map_err(VmError::SerializeJson)
1766         } else {
1767             // Update VmConfig by adding the new device.
1768             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1769             add_to_config(&mut config.vdpa, vdpa_cfg);
1770             Ok(None)
1771         }
1772     }
1773 
1774     fn vm_add_vsock(&mut self, vsock_cfg: VsockConfig) -> result::Result<Option<Vec<u8>>, VmError> {
1775         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
1776 
1777         {
1778             // Validate the configuration change in a cloned configuration
1779             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
1780 
1781             if config.vsock.is_some() {
1782                 return Err(VmError::TooManyVsockDevices);
1783             }
1784 
1785             config.vsock = Some(vsock_cfg.clone());
1786             config.validate().map_err(VmError::ConfigValidation)?;
1787         }
1788 
1789         if let Some(ref mut vm) = self.vm {
1790             let info = vm.add_vsock(vsock_cfg).map_err(|e| {
1791                 error!("Error when adding new vsock device to the VM: {:?}", e);
1792                 e
1793             })?;
1794             serde_json::to_vec(&info)
1795                 .map(Some)
1796                 .map_err(VmError::SerializeJson)
1797         } else {
1798             // Update VmConfig by adding the new device.
1799             let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
1800             config.vsock = Some(vsock_cfg);
1801             Ok(None)
1802         }
1803     }
1804 
1805     fn vm_counters(&mut self) -> result::Result<Option<Vec<u8>>, VmError> {
1806         if let Some(ref mut vm) = self.vm {
1807             let info = vm.counters().map_err(|e| {
1808                 error!("Error when getting counters from the VM: {:?}", e);
1809                 e
1810             })?;
1811             serde_json::to_vec(&info)
1812                 .map(Some)
1813                 .map_err(VmError::SerializeJson)
1814         } else {
1815             Err(VmError::VmNotRunning)
1816         }
1817     }
1818 
1819     fn vm_power_button(&mut self) -> result::Result<(), VmError> {
1820         if let Some(ref mut vm) = self.vm {
1821             vm.power_button()
1822         } else {
1823             Err(VmError::VmNotRunning)
1824         }
1825     }
1826 
1827     fn vm_receive_migration(
1828         &mut self,
1829         receive_data_migration: VmReceiveMigrationData,
1830     ) -> result::Result<(), MigratableError> {
1831         info!(
1832             "Receiving migration: receiver_url = {}",
1833             receive_data_migration.receiver_url
1834         );
1835 
1836         let path = Self::socket_url_to_path(&receive_data_migration.receiver_url)?;
1837         let listener = UnixListener::bind(&path).map_err(|e| {
1838             MigratableError::MigrateReceive(anyhow!("Error binding to UNIX socket: {}", e))
1839         })?;
1840         let (mut socket, _addr) = listener.accept().map_err(|e| {
1841             MigratableError::MigrateReceive(anyhow!("Error accepting on UNIX socket: {}", e))
1842         })?;
1843         std::fs::remove_file(&path).map_err(|e| {
1844             MigratableError::MigrateReceive(anyhow!("Error unlinking UNIX socket: {}", e))
1845         })?;
1846 
1847         let mut started = false;
1848         let mut memory_manager: Option<Arc<Mutex<MemoryManager>>> = None;
1849         let mut existing_memory_files = None;
1850         loop {
1851             let req = Request::read_from(&mut socket)?;
1852             match req.command() {
1853                 Command::Invalid => info!("Invalid Command Received"),
1854                 Command::Start => {
1855                     info!("Start Command Received");
1856                     started = true;
1857 
1858                     Response::ok().write_to(&mut socket)?;
1859                 }
1860                 Command::Config => {
1861                     info!("Config Command Received");
1862 
1863                     if !started {
1864                         warn!("Migration not started yet");
1865                         Response::error().write_to(&mut socket)?;
1866                         continue;
1867                     }
1868                     memory_manager = Some(self.vm_receive_config(
1869                         &req,
1870                         &mut socket,
1871                         existing_memory_files.take(),
1872                     )?);
1873                 }
1874                 Command::State => {
1875                     info!("State Command Received");
1876 
1877                     if !started {
1878                         warn!("Migration not started yet");
1879                         Response::error().write_to(&mut socket)?;
1880                         continue;
1881                     }
1882                     if let Some(mm) = memory_manager.take() {
1883                         self.vm_receive_state(&req, &mut socket, mm)?;
1884                     } else {
1885                         warn!("Configuration not sent yet");
1886                         Response::error().write_to(&mut socket)?;
1887                     }
1888                 }
1889                 Command::Memory => {
1890                     info!("Memory Command Received");
1891 
1892                     if !started {
1893                         warn!("Migration not started yet");
1894                         Response::error().write_to(&mut socket)?;
1895                         continue;
1896                     }
1897                     if let Some(mm) = memory_manager.as_ref() {
1898                         self.vm_receive_memory(&req, &mut socket, &mut mm.lock().unwrap())?;
1899                     } else {
1900                         warn!("Configuration not sent yet");
1901                         Response::error().write_to(&mut socket)?;
1902                     }
1903                 }
1904                 Command::MemoryFd => {
1905                     info!("MemoryFd Command Received");
1906 
1907                     if !started {
1908                         warn!("Migration not started yet");
1909                         Response::error().write_to(&mut socket)?;
1910                         continue;
1911                     }
1912 
1913                     let mut buf = [0u8; 4];
1914                     let (_, file) = socket.recv_with_fd(&mut buf).map_err(|e| {
1915                         MigratableError::MigrateReceive(anyhow!(
1916                             "Error receiving slot from socket: {}",
1917                             e
1918                         ))
1919                     })?;
1920 
1921                     if existing_memory_files.is_none() {
1922                         existing_memory_files = Some(HashMap::default())
1923                     }
1924 
1925                     if let Some(ref mut existing_memory_files) = existing_memory_files {
1926                         let slot = u32::from_le_bytes(buf);
1927                         existing_memory_files.insert(slot, file.unwrap());
1928                     }
1929 
1930                     Response::ok().write_to(&mut socket)?;
1931                 }
1932                 Command::Complete => {
1933                     info!("Complete Command Received");
1934                     if let Some(ref mut vm) = self.vm.as_mut() {
1935                         vm.resume()?;
1936                         Response::ok().write_to(&mut socket)?;
1937                     } else {
1938                         warn!("VM not created yet");
1939                         Response::error().write_to(&mut socket)?;
1940                     }
1941                     break;
1942                 }
1943                 Command::Abandon => {
1944                     info!("Abandon Command Received");
1945                     self.vm = None;
1946                     self.vm_config = None;
1947                     Response::ok().write_to(&mut socket).ok();
1948                     break;
1949                 }
1950             }
1951         }
1952 
1953         Ok(())
1954     }
1955 
1956     fn vm_send_migration(
1957         &mut self,
1958         send_data_migration: VmSendMigrationData,
1959     ) -> result::Result<(), MigratableError> {
1960         info!(
1961             "Sending migration: destination_url = {}, local = {}",
1962             send_data_migration.destination_url, send_data_migration.local
1963         );
1964 
1965         if !self
1966             .vm_config
1967             .as_ref()
1968             .unwrap()
1969             .lock()
1970             .unwrap()
1971             .backed_by_shared_memory()
1972             && send_data_migration.local
1973         {
1974             return Err(MigratableError::MigrateSend(anyhow!(
1975                 "Local migration requires shared memory or hugepages enabled"
1976             )));
1977         }
1978 
1979         if let Some(vm) = self.vm.as_mut() {
1980             Self::send_migration(
1981                 vm,
1982                 #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
1983                 self.hypervisor.clone(),
1984                 send_data_migration,
1985             )
1986             .map_err(|migration_err| {
1987                 error!("Migration failed: {:?}", migration_err);
1988 
1989                 // Stop logging dirty pages
1990                 if let Err(e) = vm.stop_dirty_log() {
1991                     return e;
1992                 }
1993 
1994                 if vm.get_state().unwrap() == VmState::Paused {
1995                     if let Err(e) = vm.resume() {
1996                         return e;
1997                     }
1998                 }
1999 
2000                 migration_err
2001             })?;
2002 
2003             // Shutdown the VM after the migration succeeded
2004             self.exit_evt.write(1).map_err(|e| {
2005                 MigratableError::MigrateSend(anyhow!(
2006                     "Failed shutting down the VM after migration: {:?}",
2007                     e
2008                 ))
2009             })
2010         } else {
2011             Err(MigratableError::MigrateSend(anyhow!("VM is not running")))
2012         }
2013     }
2014 }
2015 
2016 const CPU_MANAGER_SNAPSHOT_ID: &str = "cpu-manager";
2017 const MEMORY_MANAGER_SNAPSHOT_ID: &str = "memory-manager";
2018 const DEVICE_MANAGER_SNAPSHOT_ID: &str = "device-manager";
2019 
2020 #[cfg(test)]
2021 mod unit_tests {
2022     use super::*;
2023     use config::{
2024         ConsoleConfig, ConsoleOutputMode, CpusConfig, HotplugMethod, MemoryConfig, PayloadConfig,
2025         RngConfig, VmConfig,
2026     };
2027 
2028     fn create_dummy_vmm() -> Vmm {
2029         Vmm::new(
2030             VmmVersionInfo::new("dummy", "dummy"),
2031             EventFd::new(EFD_NONBLOCK).unwrap(),
2032             #[cfg(feature = "guest_debug")]
2033             EventFd::new(EFD_NONBLOCK).unwrap(),
2034             #[cfg(feature = "guest_debug")]
2035             EventFd::new(EFD_NONBLOCK).unwrap(),
2036             SeccompAction::Allow,
2037             hypervisor::new().unwrap(),
2038             EventFd::new(EFD_NONBLOCK).unwrap(),
2039         )
2040         .unwrap()
2041     }
2042 
2043     fn create_dummy_vm_config() -> Arc<Mutex<VmConfig>> {
2044         Arc::new(Mutex::new(VmConfig {
2045             cpus: CpusConfig {
2046                 boot_vcpus: 1,
2047                 max_vcpus: 1,
2048                 topology: None,
2049                 kvm_hyperv: false,
2050                 max_phys_bits: 46,
2051                 affinity: None,
2052                 features: config::CpuFeatures::default(),
2053             },
2054             memory: MemoryConfig {
2055                 size: 536_870_912,
2056                 mergeable: false,
2057                 hotplug_method: HotplugMethod::Acpi,
2058                 hotplug_size: None,
2059                 hotplugged_size: None,
2060                 shared: true,
2061                 hugepages: false,
2062                 hugepage_size: None,
2063                 prefault: false,
2064                 zones: None,
2065                 thp: true,
2066             },
2067             payload: Some(PayloadConfig {
2068                 kernel: Some(PathBuf::from("/path/to/kernel")),
2069                 firmware: None,
2070                 cmdline: None,
2071                 initramfs: None,
2072                 #[cfg(feature = "igvm")]
2073                 igvm: None,
2074             }),
2075             rate_limit_groups: None,
2076             disks: None,
2077             net: None,
2078             rng: RngConfig {
2079                 src: PathBuf::from("/dev/urandom"),
2080                 iommu: false,
2081             },
2082             balloon: None,
2083             fs: None,
2084             pmem: None,
2085             serial: ConsoleConfig {
2086                 file: None,
2087                 mode: ConsoleOutputMode::Null,
2088                 iommu: false,
2089                 socket: None,
2090             },
2091             console: ConsoleConfig {
2092                 file: None,
2093                 mode: ConsoleOutputMode::Tty,
2094                 iommu: false,
2095                 socket: None,
2096             },
2097             devices: None,
2098             user_devices: None,
2099             vdpa: None,
2100             vsock: None,
2101             pvpanic: false,
2102             iommu: false,
2103             #[cfg(target_arch = "x86_64")]
2104             sgx_epc: None,
2105             numa: None,
2106             watchdog: false,
2107             #[cfg(feature = "guest_debug")]
2108             gdb: false,
2109             platform: None,
2110             tpm: None,
2111             preserved_fds: None,
2112         }))
2113     }
2114 
2115     #[test]
2116     fn test_vmm_vm_create() {
2117         let mut vmm = create_dummy_vmm();
2118         let config = create_dummy_vm_config();
2119 
2120         assert!(matches!(vmm.vm_create(config.clone()), Ok(())));
2121         assert!(matches!(
2122             vmm.vm_create(config),
2123             Err(VmError::VmAlreadyCreated)
2124         ));
2125     }
2126 
2127     #[test]
2128     fn test_vmm_vm_cold_add_device() {
2129         let mut vmm = create_dummy_vmm();
2130         let device_config = DeviceConfig::parse("path=/path/to/device").unwrap();
2131 
2132         assert!(matches!(
2133             vmm.vm_add_device(device_config.clone()),
2134             Err(VmError::VmNotCreated)
2135         ));
2136 
2137         let _ = vmm.vm_create(create_dummy_vm_config());
2138         assert!(vmm
2139             .vm_config
2140             .as_ref()
2141             .unwrap()
2142             .lock()
2143             .unwrap()
2144             .devices
2145             .is_none());
2146 
2147         let result = vmm.vm_add_device(device_config.clone());
2148         assert!(result.is_ok());
2149         assert!(result.unwrap().is_none());
2150         assert_eq!(
2151             vmm.vm_config
2152                 .as_ref()
2153                 .unwrap()
2154                 .lock()
2155                 .unwrap()
2156                 .devices
2157                 .clone()
2158                 .unwrap()
2159                 .len(),
2160             1
2161         );
2162         assert_eq!(
2163             vmm.vm_config
2164                 .as_ref()
2165                 .unwrap()
2166                 .lock()
2167                 .unwrap()
2168                 .devices
2169                 .clone()
2170                 .unwrap()[0],
2171             device_config
2172         );
2173     }
2174 
2175     #[test]
2176     fn test_vmm_vm_cold_add_user_device() {
2177         let mut vmm = create_dummy_vmm();
2178         let user_device_config =
2179             UserDeviceConfig::parse("socket=/path/to/socket,id=8,pci_segment=2").unwrap();
2180 
2181         assert!(matches!(
2182             vmm.vm_add_user_device(user_device_config.clone()),
2183             Err(VmError::VmNotCreated)
2184         ));
2185 
2186         let _ = vmm.vm_create(create_dummy_vm_config());
2187         assert!(vmm
2188             .vm_config
2189             .as_ref()
2190             .unwrap()
2191             .lock()
2192             .unwrap()
2193             .user_devices
2194             .is_none());
2195 
2196         let result = vmm.vm_add_user_device(user_device_config.clone());
2197         assert!(result.is_ok());
2198         assert!(result.unwrap().is_none());
2199         assert_eq!(
2200             vmm.vm_config
2201                 .as_ref()
2202                 .unwrap()
2203                 .lock()
2204                 .unwrap()
2205                 .user_devices
2206                 .clone()
2207                 .unwrap()
2208                 .len(),
2209             1
2210         );
2211         assert_eq!(
2212             vmm.vm_config
2213                 .as_ref()
2214                 .unwrap()
2215                 .lock()
2216                 .unwrap()
2217                 .user_devices
2218                 .clone()
2219                 .unwrap()[0],
2220             user_device_config
2221         );
2222     }
2223 
2224     #[test]
2225     fn test_vmm_vm_cold_add_disk() {
2226         let mut vmm = create_dummy_vmm();
2227         let disk_config = DiskConfig::parse("path=/path/to_file").unwrap();
2228 
2229         assert!(matches!(
2230             vmm.vm_add_disk(disk_config.clone()),
2231             Err(VmError::VmNotCreated)
2232         ));
2233 
2234         let _ = vmm.vm_create(create_dummy_vm_config());
2235         assert!(vmm
2236             .vm_config
2237             .as_ref()
2238             .unwrap()
2239             .lock()
2240             .unwrap()
2241             .disks
2242             .is_none());
2243 
2244         let result = vmm.vm_add_disk(disk_config.clone());
2245         assert!(result.is_ok());
2246         assert!(result.unwrap().is_none());
2247         assert_eq!(
2248             vmm.vm_config
2249                 .as_ref()
2250                 .unwrap()
2251                 .lock()
2252                 .unwrap()
2253                 .disks
2254                 .clone()
2255                 .unwrap()
2256                 .len(),
2257             1
2258         );
2259         assert_eq!(
2260             vmm.vm_config
2261                 .as_ref()
2262                 .unwrap()
2263                 .lock()
2264                 .unwrap()
2265                 .disks
2266                 .clone()
2267                 .unwrap()[0],
2268             disk_config
2269         );
2270     }
2271 
2272     #[test]
2273     fn test_vmm_vm_cold_add_fs() {
2274         let mut vmm = create_dummy_vmm();
2275         let fs_config = FsConfig::parse("tag=mytag,socket=/tmp/sock").unwrap();
2276 
2277         assert!(matches!(
2278             vmm.vm_add_fs(fs_config.clone()),
2279             Err(VmError::VmNotCreated)
2280         ));
2281 
2282         let _ = vmm.vm_create(create_dummy_vm_config());
2283         assert!(vmm.vm_config.as_ref().unwrap().lock().unwrap().fs.is_none());
2284 
2285         let result = vmm.vm_add_fs(fs_config.clone());
2286         assert!(result.is_ok());
2287         assert!(result.unwrap().is_none());
2288         assert_eq!(
2289             vmm.vm_config
2290                 .as_ref()
2291                 .unwrap()
2292                 .lock()
2293                 .unwrap()
2294                 .fs
2295                 .clone()
2296                 .unwrap()
2297                 .len(),
2298             1
2299         );
2300         assert_eq!(
2301             vmm.vm_config
2302                 .as_ref()
2303                 .unwrap()
2304                 .lock()
2305                 .unwrap()
2306                 .fs
2307                 .clone()
2308                 .unwrap()[0],
2309             fs_config
2310         );
2311     }
2312 
2313     #[test]
2314     fn test_vmm_vm_cold_add_pmem() {
2315         let mut vmm = create_dummy_vmm();
2316         let pmem_config = PmemConfig::parse("file=/tmp/pmem,size=128M").unwrap();
2317 
2318         assert!(matches!(
2319             vmm.vm_add_pmem(pmem_config.clone()),
2320             Err(VmError::VmNotCreated)
2321         ));
2322 
2323         let _ = vmm.vm_create(create_dummy_vm_config());
2324         assert!(vmm
2325             .vm_config
2326             .as_ref()
2327             .unwrap()
2328             .lock()
2329             .unwrap()
2330             .pmem
2331             .is_none());
2332 
2333         let result = vmm.vm_add_pmem(pmem_config.clone());
2334         assert!(result.is_ok());
2335         assert!(result.unwrap().is_none());
2336         assert_eq!(
2337             vmm.vm_config
2338                 .as_ref()
2339                 .unwrap()
2340                 .lock()
2341                 .unwrap()
2342                 .pmem
2343                 .clone()
2344                 .unwrap()
2345                 .len(),
2346             1
2347         );
2348         assert_eq!(
2349             vmm.vm_config
2350                 .as_ref()
2351                 .unwrap()
2352                 .lock()
2353                 .unwrap()
2354                 .pmem
2355                 .clone()
2356                 .unwrap()[0],
2357             pmem_config
2358         );
2359     }
2360 
2361     #[test]
2362     fn test_vmm_vm_cold_add_net() {
2363         let mut vmm = create_dummy_vmm();
2364         let net_config = NetConfig::parse(
2365             "mac=de:ad:be:ef:12:34,host_mac=12:34:de:ad:be:ef,vhost_user=true,socket=/tmp/sock",
2366         )
2367         .unwrap();
2368 
2369         assert!(matches!(
2370             vmm.vm_add_net(net_config.clone()),
2371             Err(VmError::VmNotCreated)
2372         ));
2373 
2374         let _ = vmm.vm_create(create_dummy_vm_config());
2375         assert!(vmm
2376             .vm_config
2377             .as_ref()
2378             .unwrap()
2379             .lock()
2380             .unwrap()
2381             .net
2382             .is_none());
2383 
2384         let result = vmm.vm_add_net(net_config.clone());
2385         assert!(result.is_ok());
2386         assert!(result.unwrap().is_none());
2387         assert_eq!(
2388             vmm.vm_config
2389                 .as_ref()
2390                 .unwrap()
2391                 .lock()
2392                 .unwrap()
2393                 .net
2394                 .clone()
2395                 .unwrap()
2396                 .len(),
2397             1
2398         );
2399         assert_eq!(
2400             vmm.vm_config
2401                 .as_ref()
2402                 .unwrap()
2403                 .lock()
2404                 .unwrap()
2405                 .net
2406                 .clone()
2407                 .unwrap()[0],
2408             net_config
2409         );
2410     }
2411 
2412     #[test]
2413     fn test_vmm_vm_cold_add_vdpa() {
2414         let mut vmm = create_dummy_vmm();
2415         let vdpa_config = VdpaConfig::parse("path=/dev/vhost-vdpa,num_queues=2").unwrap();
2416 
2417         assert!(matches!(
2418             vmm.vm_add_vdpa(vdpa_config.clone()),
2419             Err(VmError::VmNotCreated)
2420         ));
2421 
2422         let _ = vmm.vm_create(create_dummy_vm_config());
2423         assert!(vmm
2424             .vm_config
2425             .as_ref()
2426             .unwrap()
2427             .lock()
2428             .unwrap()
2429             .vdpa
2430             .is_none());
2431 
2432         let result = vmm.vm_add_vdpa(vdpa_config.clone());
2433         assert!(result.is_ok());
2434         assert!(result.unwrap().is_none());
2435         assert_eq!(
2436             vmm.vm_config
2437                 .as_ref()
2438                 .unwrap()
2439                 .lock()
2440                 .unwrap()
2441                 .vdpa
2442                 .clone()
2443                 .unwrap()
2444                 .len(),
2445             1
2446         );
2447         assert_eq!(
2448             vmm.vm_config
2449                 .as_ref()
2450                 .unwrap()
2451                 .lock()
2452                 .unwrap()
2453                 .vdpa
2454                 .clone()
2455                 .unwrap()[0],
2456             vdpa_config
2457         );
2458     }
2459 
2460     #[test]
2461     fn test_vmm_vm_cold_add_vsock() {
2462         let mut vmm = create_dummy_vmm();
2463         let vsock_config = VsockConfig::parse("socket=/tmp/sock,cid=3,iommu=on").unwrap();
2464 
2465         assert!(matches!(
2466             vmm.vm_add_vsock(vsock_config.clone()),
2467             Err(VmError::VmNotCreated)
2468         ));
2469 
2470         let _ = vmm.vm_create(create_dummy_vm_config());
2471         assert!(vmm
2472             .vm_config
2473             .as_ref()
2474             .unwrap()
2475             .lock()
2476             .unwrap()
2477             .vsock
2478             .is_none());
2479 
2480         let result = vmm.vm_add_vsock(vsock_config.clone());
2481         assert!(result.is_ok());
2482         assert!(result.unwrap().is_none());
2483         assert_eq!(
2484             vmm.vm_config
2485                 .as_ref()
2486                 .unwrap()
2487                 .lock()
2488                 .unwrap()
2489                 .vsock
2490                 .clone()
2491                 .unwrap(),
2492             vsock_config
2493         );
2494     }
2495 }
2496