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