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