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