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