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