• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Handles IPC for controlling the main VM process.
6 //!
7 //! The VM Control IPC protocol is synchronous, meaning that each `VmRequest` sent over a connection
8 //! will receive a `VmResponse` for that request next time data is received over that connection.
9 //!
10 //! The wire message format is a little-endian C-struct of fixed size, along with a file descriptor
11 //! if the request type expects one.
12 
13 #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))]
14 pub mod gdb;
15 #[cfg(feature = "gpu")]
16 pub mod gpu;
17 
18 #[cfg(unix)]
19 use base::MemoryMappingBuilderUnix;
20 #[cfg(windows)]
21 use base::MemoryMappingBuilderWindows;
22 
23 pub mod client;
24 pub mod display;
25 pub mod sys;
26 
27 use std::collections::BTreeSet;
28 use std::convert::TryInto;
29 use std::fmt;
30 use std::fmt::Display;
31 use std::fs::File;
32 use std::path::PathBuf;
33 use std::result::Result as StdResult;
34 use std::str::FromStr;
35 use std::sync::mpsc;
36 use std::sync::Arc;
37 
38 use anyhow::bail;
39 use anyhow::Context;
40 pub use balloon_control::BalloonStats;
41 #[cfg(feature = "balloon")]
42 use balloon_control::BalloonTubeCommand;
43 #[cfg(feature = "balloon")]
44 use balloon_control::BalloonTubeResult;
45 pub use balloon_control::BalloonWSS;
46 pub use balloon_control::WSSBucket;
47 use base::error;
48 use base::info;
49 use base::warn;
50 use base::with_as_descriptor;
51 use base::AsRawDescriptor;
52 use base::Error as SysError;
53 use base::Event;
54 use base::ExternalMapping;
55 use base::IntoRawDescriptor;
56 use base::MappedRegion;
57 use base::MemoryMappingBuilder;
58 use base::MmapError;
59 use base::Protection;
60 use base::Result;
61 use base::SafeDescriptor;
62 use base::SharedMemory;
63 use base::Tube;
64 use hypervisor::Datamatch;
65 use hypervisor::IoEventAddress;
66 use hypervisor::IrqRoute;
67 use hypervisor::IrqSource;
68 pub use hypervisor::MemSlot;
69 use hypervisor::VcpuSnapshot;
70 use hypervisor::Vm;
71 use libc::EINVAL;
72 use libc::EIO;
73 use libc::ENODEV;
74 use libc::ENOTSUP;
75 use libc::ERANGE;
76 use remain::sorted;
77 use resources::Alloc;
78 use resources::SystemAllocator;
79 use rutabaga_gfx::DeviceId;
80 use rutabaga_gfx::RutabagaDescriptor;
81 use rutabaga_gfx::RutabagaFromRawDescriptor;
82 use rutabaga_gfx::RutabagaGralloc;
83 use rutabaga_gfx::RutabagaHandle;
84 use rutabaga_gfx::RutabagaMappedRegion;
85 use rutabaga_gfx::VulkanInfo;
86 use serde::Deserialize;
87 use serde::Serialize;
88 use sync::Mutex;
89 #[cfg(unix)]
90 pub use sys::FsMappingRequest;
91 #[cfg(unix)]
92 pub use sys::VmMsyncRequest;
93 #[cfg(unix)]
94 pub use sys::VmMsyncResponse;
95 use thiserror::Error;
96 use vm_memory::GuestAddress;
97 
98 use crate::display::AspectRatio;
99 use crate::display::DisplaySize;
100 use crate::display::GuestDisplayDensity;
101 use crate::display::MouseMode;
102 use crate::display::WindowEvent;
103 use crate::display::WindowMode;
104 use crate::display::WindowVisibility;
105 #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))]
106 pub use crate::gdb::VcpuDebug;
107 #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))]
108 pub use crate::gdb::VcpuDebugStatus;
109 #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))]
110 pub use crate::gdb::VcpuDebugStatusMessage;
111 #[cfg(feature = "gpu")]
112 use crate::gpu::GpuControlCommand;
113 #[cfg(feature = "gpu")]
114 use crate::gpu::GpuControlResult;
115 
116 /// Control the state of a particular VM CPU.
117 #[derive(Clone, Debug)]
118 pub enum VcpuControl {
119     #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))]
120     Debug(VcpuDebug),
121     RunState(VmRunMode),
122     MakeRT,
123     // Request the current state of the vCPU. The result is sent back over the included channel.
124     GetStates(mpsc::Sender<VmRunMode>),
125     Snapshot(mpsc::Sender<anyhow::Result<VcpuSnapshot>>),
126     Restore(mpsc::Sender<anyhow::Result<()>>, Box<VcpuSnapshot>),
127 }
128 
129 /// Mode of execution for the VM.
130 #[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
131 pub enum VmRunMode {
132     /// The default run mode indicating the VCPUs are running.
133     #[default]
134     Running,
135     /// Indicates that the VCPUs are suspending execution until the `Running` mode is set.
136     Suspending,
137     /// Indicates that the VM is exiting all processes.
138     Exiting,
139     /// Indicates that the VM is in a breakpoint waiting for the debugger to do continue.
140     Breakpoint,
141 }
142 
143 impl Display for VmRunMode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result144     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145         use self::VmRunMode::*;
146 
147         match self {
148             Running => write!(f, "running"),
149             Suspending => write!(f, "suspending"),
150             Exiting => write!(f, "exiting"),
151             Breakpoint => write!(f, "breakpoint"),
152         }
153     }
154 }
155 
156 // Trait for devices that get notification on specific GPE trigger
157 pub trait GpeNotify: Send {
notify(&mut self)158     fn notify(&mut self) {}
159 }
160 
161 // Trait for devices that get notification on specific PCI PME
162 pub trait PmeNotify: Send {
notify(&mut self, _requester_id: u16)163     fn notify(&mut self, _requester_id: u16) {}
164 }
165 
166 pub trait PmResource {
pwrbtn_evt(&mut self)167     fn pwrbtn_evt(&mut self) {}
slpbtn_evt(&mut self)168     fn slpbtn_evt(&mut self) {}
rtc_evt(&mut self)169     fn rtc_evt(&mut self) {}
gpe_evt(&mut self, _gpe: u32)170     fn gpe_evt(&mut self, _gpe: u32) {}
pme_evt(&mut self, _requester_id: u16)171     fn pme_evt(&mut self, _requester_id: u16) {}
register_gpe_notify_dev(&mut self, _gpe: u32, _notify_dev: Arc<Mutex<dyn GpeNotify>>)172     fn register_gpe_notify_dev(&mut self, _gpe: u32, _notify_dev: Arc<Mutex<dyn GpeNotify>>) {}
register_pme_notify_dev(&mut self, _bus: u8, _notify_dev: Arc<Mutex<dyn PmeNotify>>)173     fn register_pme_notify_dev(&mut self, _bus: u8, _notify_dev: Arc<Mutex<dyn PmeNotify>>) {}
174 }
175 
176 /// The maximum number of devices that can be listed in one `UsbControlCommand`.
177 ///
178 /// This value was set to be equal to `xhci_regs::MAX_PORTS` for convenience, but it is not
179 /// necessary for correctness. Importing that value directly would be overkill because it would
180 /// require adding a big dependency for a single const.
181 pub const USB_CONTROL_MAX_PORTS: usize = 16;
182 
183 // Balloon commands that are sent on the crosvm control socket.
184 #[derive(Serialize, Deserialize, Debug)]
185 pub enum BalloonControlCommand {
186     /// Set the size of the VM's balloon.
187     Adjust {
188         num_bytes: u64,
189     },
190     Stats,
191     WorkingSetSize,
192 }
193 
194 // BalloonControlResult holds results for BalloonControlCommand defined above.
195 #[derive(Serialize, Deserialize, Debug)]
196 pub enum BalloonControlResult {
197     Stats {
198         stats: BalloonStats,
199         balloon_actual: u64,
200     },
201     WorkingSetSize {
202         wss: BalloonWSS,
203     },
204 }
205 
206 #[derive(Serialize, Deserialize, Debug)]
207 pub enum DiskControlCommand {
208     /// Resize a disk to `new_size` in bytes.
209     Resize { new_size: u64 },
210 }
211 
212 impl Display for DiskControlCommand {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result213     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214         use self::DiskControlCommand::*;
215 
216         match self {
217             Resize { new_size } => write!(f, "disk_resize {}", new_size),
218         }
219     }
220 }
221 
222 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
223 pub enum DiskControlResult {
224     Ok,
225     Err(SysError),
226 }
227 
228 #[derive(Serialize, Deserialize, Debug)]
229 pub enum UsbControlCommand {
230     AttachDevice {
231         #[serde(with = "with_as_descriptor")]
232         file: File,
233     },
234     DetachDevice {
235         port: u8,
236     },
237     ListDevice {
238         ports: [u8; USB_CONTROL_MAX_PORTS],
239     },
240 }
241 
242 #[derive(Serialize, Deserialize, Copy, Clone, Debug, Default)]
243 pub struct UsbControlAttachedDevice {
244     pub port: u8,
245     pub vendor_id: u16,
246     pub product_id: u16,
247 }
248 
249 impl UsbControlAttachedDevice {
valid(self) -> bool250     pub fn valid(self) -> bool {
251         self.port != 0
252     }
253 }
254 
255 #[derive(Serialize, Deserialize, Debug, Clone)]
256 pub enum UsbControlResult {
257     Ok { port: u8 },
258     NoAvailablePort,
259     NoSuchDevice,
260     NoSuchPort,
261     FailedToOpenDevice,
262     Devices([UsbControlAttachedDevice; USB_CONTROL_MAX_PORTS]),
263     FailedToInitHostDevice,
264 }
265 
266 impl Display for UsbControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result267     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
268         use self::UsbControlResult::*;
269 
270         match self {
271             UsbControlResult::Ok { port } => write!(f, "ok {}", port),
272             NoAvailablePort => write!(f, "no_available_port"),
273             NoSuchDevice => write!(f, "no_such_device"),
274             NoSuchPort => write!(f, "no_such_port"),
275             FailedToOpenDevice => write!(f, "failed_to_open_device"),
276             Devices(devices) => {
277                 write!(f, "devices")?;
278                 for d in devices.iter().filter(|d| d.valid()) {
279                     write!(f, " {} {:04x} {:04x}", d.port, d.vendor_id, d.product_id)?;
280                 }
281                 std::result::Result::Ok(())
282             }
283             FailedToInitHostDevice => write!(f, "failed_to_init_host_device"),
284         }
285     }
286 }
287 
288 /// Commands for snapshot feature
289 #[derive(Serialize, Deserialize, Debug)]
290 pub enum SnapshotCommand {
291     Take { snapshot_path: PathBuf },
292 }
293 
294 /// Commands for restore feature
295 #[derive(Serialize, Deserialize, Debug)]
296 pub enum RestoreCommand {
297     Apply { restore_path: PathBuf },
298 }
299 
300 /// Commands for actions on devices and the devices control thread.
301 #[derive(Serialize, Deserialize, Debug)]
302 pub enum DeviceControlCommand {
303     SleepDevices,
304     WakeDevices,
305     SnapshotDevices { snapshot_path: PathBuf },
306     RestoreDevices { restore_path: PathBuf },
307     Exit,
308 }
309 
310 /// Commands to control the IRQ handler thread.
311 #[derive(Serialize, Deserialize)]
312 pub enum IrqHandlerRequest {
313     /// No response is sent for this command.
314     AddIrqControlTubes(Vec<Tube>),
315     WakeAndNotifyIteration,
316     /// No response is sent for this command.
317     Exit,
318 }
319 
320 const EXPECTED_MAX_IRQ_FLUSH_ITERATIONS: usize = 100;
321 
322 /// Response for [IrqHandlerRequest].
323 #[derive(Serialize, Deserialize, Debug)]
324 pub enum IrqHandlerResponse {
325     /// Specifies the number of tokens serviced in the requested iteration
326     /// (less the token for the `WakeAndNotifyIteration` request).
327     HandlerIterationComplete(usize),
328 }
329 
330 /// Source of a `VmMemoryRequest::RegisterMemory` mapping.
331 #[derive(Serialize, Deserialize)]
332 pub enum VmMemorySource {
333     /// Register shared memory represented by the given descriptor.
334     /// On Windows, descriptor MUST be a mapping handle.
335     SharedMemory(SharedMemory),
336     /// Register a file mapping from the given descriptor.
337     Descriptor {
338         /// File descriptor to map.
339         descriptor: SafeDescriptor,
340         /// Offset within the file in bytes.
341         offset: u64,
342         /// Size of the mapping in bytes.
343         size: u64,
344     },
345     /// Register memory mapped by Vulkano.
346     Vulkan {
347         descriptor: SafeDescriptor,
348         handle_type: u32,
349         memory_idx: u32,
350         device_id: DeviceId,
351         size: u64,
352     },
353     /// Register the current rutabaga external mapping.
354     ExternalMapping { ptr: u64, size: u64 },
355 }
356 
357 // The following are wrappers to avoid base dependencies in the rutabaga crate
to_rutabaga_desciptor(s: SafeDescriptor) -> RutabagaDescriptor358 fn to_rutabaga_desciptor(s: SafeDescriptor) -> RutabagaDescriptor {
359     // Safe because we own the SafeDescriptor at this point.
360     unsafe { RutabagaDescriptor::from_raw_descriptor(s.into_raw_descriptor()) }
361 }
362 
363 struct RutabagaMemoryRegion {
364     region: Box<dyn RutabagaMappedRegion>,
365 }
366 
367 impl RutabagaMemoryRegion {
new(region: Box<dyn RutabagaMappedRegion>) -> RutabagaMemoryRegion368     pub fn new(region: Box<dyn RutabagaMappedRegion>) -> RutabagaMemoryRegion {
369         RutabagaMemoryRegion { region }
370     }
371 }
372 
373 unsafe impl MappedRegion for RutabagaMemoryRegion {
as_ptr(&self) -> *mut u8374     fn as_ptr(&self) -> *mut u8 {
375         self.region.as_ptr()
376     }
377 
size(&self) -> usize378     fn size(&self) -> usize {
379         self.region.size()
380     }
381 }
382 
383 impl VmMemorySource {
384     /// Map the resource and return its mapping and size in bytes.
map( self, gralloc: &mut RutabagaGralloc, prot: Protection, ) -> Result<(Box<dyn MappedRegion>, u64, Option<SafeDescriptor>)>385     pub fn map(
386         self,
387         gralloc: &mut RutabagaGralloc,
388         prot: Protection,
389     ) -> Result<(Box<dyn MappedRegion>, u64, Option<SafeDescriptor>)> {
390         let (mem_region, size, descriptor) = match self {
391             VmMemorySource::Descriptor {
392                 descriptor,
393                 offset,
394                 size,
395             } => (
396                 map_descriptor(&descriptor, offset, size, prot)?,
397                 size,
398                 Some(descriptor),
399             ),
400 
401             VmMemorySource::SharedMemory(shm) => {
402                 (map_descriptor(&shm, 0, shm.size(), prot)?, shm.size(), None)
403             }
404             VmMemorySource::Vulkan {
405                 descriptor,
406                 handle_type,
407                 memory_idx,
408                 device_id,
409                 size,
410             } => {
411                 let mapped_region = match gralloc.import_and_map(
412                     RutabagaHandle {
413                         os_handle: to_rutabaga_desciptor(descriptor),
414                         handle_type,
415                     },
416                     VulkanInfo {
417                         memory_idx,
418                         device_id,
419                     },
420                     size,
421                 ) {
422                     Ok(mapped_region) => {
423                         let mapped_region: Box<dyn MappedRegion> =
424                             Box::new(RutabagaMemoryRegion::new(mapped_region));
425                         mapped_region
426                     }
427                     Err(e) => {
428                         error!("gralloc failed to import and map: {}", e);
429                         return Err(SysError::new(EINVAL));
430                     }
431                 };
432                 (mapped_region, size, None)
433             }
434             VmMemorySource::ExternalMapping { ptr, size } => {
435                 let mapped_region: Box<dyn MappedRegion> = Box::new(ExternalMapping {
436                     ptr,
437                     size: size as usize,
438                 });
439                 (mapped_region, size, None)
440             }
441         };
442         Ok((mem_region, size, descriptor))
443     }
444 }
445 
446 /// Destination of a `VmMemoryRequest::RegisterMemory` mapping in guest address space.
447 #[derive(Serialize, Deserialize)]
448 pub enum VmMemoryDestination {
449     /// Map at an offset within an existing PCI BAR allocation.
450     ExistingAllocation { allocation: Alloc, offset: u64 },
451     /// Map at the specified guest physical address.
452     GuestPhysicalAddress(u64),
453 }
454 
455 impl VmMemoryDestination {
456     /// Allocate and return the guest address of a memory mapping destination.
allocate(self, allocator: &mut SystemAllocator, size: u64) -> Result<GuestAddress>457     pub fn allocate(self, allocator: &mut SystemAllocator, size: u64) -> Result<GuestAddress> {
458         let addr = match self {
459             VmMemoryDestination::ExistingAllocation { allocation, offset } => allocator
460                 .mmio_allocator_any()
461                 .address_from_pci_offset(allocation, offset, size)
462                 .map_err(|_e| SysError::new(EINVAL))?,
463             VmMemoryDestination::GuestPhysicalAddress(gpa) => gpa,
464         };
465         Ok(GuestAddress(addr))
466     }
467 }
468 
469 /// Request to register or unregister an ioevent.
470 #[derive(Serialize, Deserialize)]
471 pub struct IoEventUpdateRequest {
472     pub event: Event,
473     pub addr: u64,
474     pub datamatch: Datamatch,
475     pub register: bool,
476 }
477 
478 #[derive(Serialize, Deserialize)]
479 pub enum VmMemoryRequest {
480     RegisterMemory {
481         /// Source of the memory to register (mapped file descriptor, shared memory region, etc.)
482         source: VmMemorySource,
483         /// Where to map the memory in the guest.
484         dest: VmMemoryDestination,
485         /// Whether to map the memory read only (true) or read-write (false).
486         prot: Protection,
487     },
488     /// Call hypervisor to free the given memory range.
489     DynamicallyFreeMemoryRange {
490         guest_address: GuestAddress,
491         size: u64,
492     },
493     /// Call hypervisor to reclaim a priorly freed memory range.
494     DynamicallyReclaimMemoryRange {
495         guest_address: GuestAddress,
496         size: u64,
497     },
498     /// Unregister the given memory slot that was previously registered with `RegisterMemory`.
499     UnregisterMemory(MemSlot),
500     /// Register an ioeventfd by looking up using Alloc info.
501     IoEventWithAlloc {
502         evt: Event,
503         allocation: Alloc,
504         offset: u64,
505         datamatch: Datamatch,
506         register: bool,
507     },
508     /// Register an eventfd with raw guest memory address.
509     IoEventRaw(IoEventUpdateRequest),
510 }
511 
512 /// Struct for managing `VmMemoryRequest`s IOMMU related state.
513 pub struct VmMemoryRequestIommuClient<'a> {
514     tube: &'a Tube,
515     gpu_memory: BTreeSet<MemSlot>,
516 }
517 
518 impl<'a> VmMemoryRequestIommuClient<'a> {
519     /// Constructs `VmMemoryRequestIommuClient` from a tube for communication with the viommu.
new(tube: &'a Tube) -> Self520     pub fn new(tube: &'a Tube) -> Self {
521         Self {
522             tube,
523             gpu_memory: BTreeSet::new(),
524         }
525     }
526 }
527 
528 impl VmMemoryRequest {
529     /// Executes this request on the given Vm.
530     ///
531     /// # Arguments
532     /// * `vm` - The `Vm` to perform the request on.
533     /// * `allocator` - Used to allocate addresses.
534     ///
535     /// This does not return a result, instead encapsulating the success or failure in a
536     /// `VmMemoryResponse` with the intended purpose of sending the response back over the socket
537     /// that received this `VmMemoryResponse`.
execute( self, vm: &mut impl Vm, sys_allocator: &mut SystemAllocator, gralloc: &mut RutabagaGralloc, iommu_client: Option<&mut VmMemoryRequestIommuClient>, ) -> VmMemoryResponse538     pub fn execute(
539         self,
540         vm: &mut impl Vm,
541         sys_allocator: &mut SystemAllocator,
542         gralloc: &mut RutabagaGralloc,
543         iommu_client: Option<&mut VmMemoryRequestIommuClient>,
544     ) -> VmMemoryResponse {
545         use self::VmMemoryRequest::*;
546         match self {
547             RegisterMemory { source, dest, prot } => {
548                 // Correct on Windows because callers of this IPC guarantee descriptor is a mapping
549                 // handle.
550                 let (mapped_region, size, descriptor) = match source.map(gralloc, prot) {
551                     Ok((region, size, descriptor)) => (region, size, descriptor),
552                     Err(e) => return VmMemoryResponse::Err(e),
553                 };
554 
555                 let guest_addr = match dest.allocate(sys_allocator, size) {
556                     Ok(addr) => addr,
557                     Err(e) => return VmMemoryResponse::Err(e),
558                 };
559 
560                 let slot = match vm.add_memory_region(
561                     guest_addr,
562                     mapped_region,
563                     prot == Protection::read(),
564                     false,
565                 ) {
566                     Ok(slot) => slot,
567                     Err(e) => return VmMemoryResponse::Err(e),
568                 };
569 
570                 if let (Some(descriptor), Some(iommu_client)) = (descriptor, iommu_client) {
571                     let request =
572                         VirtioIOMMURequest::VfioCommand(VirtioIOMMUVfioCommand::VfioDmabufMap {
573                             mem_slot: slot,
574                             gfn: guest_addr.0 >> 12,
575                             size,
576                             dma_buf: descriptor,
577                         });
578 
579                     match virtio_iommu_request(iommu_client.tube, &request) {
580                         Ok(VirtioIOMMUResponse::VfioResponse(VirtioIOMMUVfioResult::Ok)) => (),
581                         resp => {
582                             error!("Unexpected message response: {:?}", resp);
583                             // Ignore the result because there is nothing we can do with a failure.
584                             let _ = vm.remove_memory_region(slot);
585                             return VmMemoryResponse::Err(SysError::new(EINVAL));
586                         }
587                     };
588 
589                     iommu_client.gpu_memory.insert(slot);
590                 }
591 
592                 let pfn = guest_addr.0 >> 12;
593                 VmMemoryResponse::RegisterMemory { pfn, slot }
594             }
595             UnregisterMemory(slot) => match vm.remove_memory_region(slot) {
596                 Ok(_) => {
597                     if let Some(iommu_client) = iommu_client {
598                         if iommu_client.gpu_memory.remove(&slot) {
599                             let request = VirtioIOMMURequest::VfioCommand(
600                                 VirtioIOMMUVfioCommand::VfioDmabufUnmap(slot),
601                             );
602 
603                             match virtio_iommu_request(iommu_client.tube, &request) {
604                                 Ok(VirtioIOMMUResponse::VfioResponse(
605                                     VirtioIOMMUVfioResult::Ok,
606                                 )) => VmMemoryResponse::Ok,
607                                 resp => {
608                                     error!("Unexpected message response: {:?}", resp);
609                                     VmMemoryResponse::Err(SysError::new(EINVAL))
610                                 }
611                             }
612                         } else {
613                             VmMemoryResponse::Ok
614                         }
615                     } else {
616                         VmMemoryResponse::Ok
617                     }
618                 }
619                 Err(e) => VmMemoryResponse::Err(e),
620             },
621             DynamicallyFreeMemoryRange {
622                 guest_address,
623                 size,
624             } => match vm.handle_inflate(guest_address, size) {
625                 Ok(_) => VmMemoryResponse::Ok,
626                 Err(e) => VmMemoryResponse::Err(e),
627             },
628             DynamicallyReclaimMemoryRange {
629                 guest_address,
630                 size,
631             } => match vm.handle_deflate(guest_address, size) {
632                 Ok(_) => VmMemoryResponse::Ok,
633                 Err(e) => VmMemoryResponse::Err(e),
634             },
635             IoEventWithAlloc {
636                 evt,
637                 allocation,
638                 offset,
639                 datamatch,
640                 register,
641             } => {
642                 let len = match datamatch {
643                     Datamatch::AnyLength => 1,
644                     Datamatch::U8(_) => 1,
645                     Datamatch::U16(_) => 2,
646                     Datamatch::U32(_) => 4,
647                     Datamatch::U64(_) => 8,
648                 };
649                 let addr = match sys_allocator
650                     .mmio_allocator_any()
651                     .address_from_pci_offset(allocation, offset, len)
652                 {
653                     Ok(addr) => addr,
654                     Err(e) => {
655                         error!("error getting target address: {:#}", e);
656                         return VmMemoryResponse::Err(SysError::new(EINVAL));
657                     }
658                 };
659                 let res = if register {
660                     vm.register_ioevent(&evt, IoEventAddress::Mmio(addr), datamatch)
661                 } else {
662                     vm.unregister_ioevent(&evt, IoEventAddress::Mmio(addr), datamatch)
663                 };
664                 match res {
665                     Ok(_) => VmMemoryResponse::Ok,
666                     Err(e) => VmMemoryResponse::Err(e),
667                 }
668             }
669             IoEventRaw(request) => {
670                 let res = if request.register {
671                     vm.register_ioevent(
672                         &request.event,
673                         IoEventAddress::Mmio(request.addr),
674                         request.datamatch,
675                     )
676                 } else {
677                     vm.unregister_ioevent(
678                         &request.event,
679                         IoEventAddress::Mmio(request.addr),
680                         request.datamatch,
681                     )
682                 };
683                 match res {
684                     Ok(_) => VmMemoryResponse::Ok,
685                     Err(e) => VmMemoryResponse::Err(e),
686                 }
687             }
688         }
689     }
690 }
691 
692 #[derive(Serialize, Deserialize, Debug)]
693 pub enum VmMemoryResponse {
694     /// The request to register memory into guest address space was successfully done at page frame
695     /// number `pfn` and memory slot number `slot`.
696     RegisterMemory {
697         pfn: u64,
698         slot: MemSlot,
699     },
700     Ok,
701     Err(SysError),
702 }
703 
704 #[derive(Serialize, Deserialize, Debug)]
705 pub enum VmIrqRequest {
706     /// Allocate one gsi, and associate gsi to irqfd with register_irqfd()
707     AllocateOneMsi {
708         irqfd: Event,
709         device_id: u32,
710         queue_id: usize,
711         device_name: String,
712     },
713     /// Allocate a specific gsi to irqfd with register_irqfd(). This must only
714     /// be used when it is known that the gsi is free. Only the snapshot
715     /// subsystem can make this guarantee, and use of this request by any other
716     /// caller is strongly discouraged.
717     AllocateOneMsiAtGsi {
718         irqfd: Event,
719         gsi: u32,
720         device_id: u32,
721         queue_id: usize,
722         device_name: String,
723     },
724     /// Add one msi route entry into the IRQ chip.
725     AddMsiRoute {
726         gsi: u32,
727         msi_address: u64,
728         msi_data: u32,
729     },
730     // unregister_irqfs() and release gsi
731     ReleaseOneIrq {
732         gsi: u32,
733         irqfd: Event,
734     },
735 }
736 
737 /// Data to set up an IRQ event or IRQ route on the IRQ chip.
738 /// VmIrqRequest::execute can't take an `IrqChip` argument, because of a dependency cycle between
739 /// devices and vm_control, so it takes a Fn that processes an `IrqSetup`.
740 pub enum IrqSetup<'a> {
741     Event(u32, &'a Event, u32, usize, String),
742     Route(IrqRoute),
743     UnRegister(u32, &'a Event),
744 }
745 
746 impl VmIrqRequest {
747     /// Executes this request on the given Vm.
748     ///
749     /// # Arguments
750     /// * `set_up_irq` - A function that applies an `IrqSetup` to an IRQ chip.
751     ///
752     /// This does not return a result, instead encapsulating the success or failure in a
753     /// `VmIrqResponse` with the intended purpose of sending the response back over the socket
754     /// that received this `VmIrqResponse`.
execute<F>(&self, set_up_irq: F, sys_allocator: &mut SystemAllocator) -> VmIrqResponse where F: FnOnce(IrqSetup) -> Result<()>,755     pub fn execute<F>(&self, set_up_irq: F, sys_allocator: &mut SystemAllocator) -> VmIrqResponse
756     where
757         F: FnOnce(IrqSetup) -> Result<()>,
758     {
759         use self::VmIrqRequest::*;
760         match *self {
761             AllocateOneMsi {
762                 ref irqfd,
763                 device_id,
764                 queue_id,
765                 ref device_name,
766             } => {
767                 if let Some(irq_num) = sys_allocator.allocate_irq() {
768                     match set_up_irq(IrqSetup::Event(
769                         irq_num,
770                         irqfd,
771                         device_id,
772                         queue_id,
773                         device_name.clone(),
774                     )) {
775                         Ok(_) => VmIrqResponse::AllocateOneMsi { gsi: irq_num },
776                         Err(e) => VmIrqResponse::Err(e),
777                     }
778                 } else {
779                     VmIrqResponse::Err(SysError::new(EINVAL))
780                 }
781             }
782             AllocateOneMsiAtGsi {
783                 ref irqfd,
784                 gsi,
785                 device_id,
786                 queue_id,
787                 ref device_name,
788             } => {
789                 match set_up_irq(IrqSetup::Event(
790                     gsi,
791                     irqfd,
792                     device_id,
793                     queue_id,
794                     device_name.clone(),
795                 )) {
796                     Ok(_) => VmIrqResponse::Ok,
797                     Err(e) => VmIrqResponse::Err(e),
798                 }
799             }
800             AddMsiRoute {
801                 gsi,
802                 msi_address,
803                 msi_data,
804             } => {
805                 let route = IrqRoute {
806                     gsi,
807                     source: IrqSource::Msi {
808                         address: msi_address,
809                         data: msi_data,
810                     },
811                 };
812                 match set_up_irq(IrqSetup::Route(route)) {
813                     Ok(_) => VmIrqResponse::Ok,
814                     Err(e) => VmIrqResponse::Err(e),
815                 }
816             }
817             ReleaseOneIrq { gsi, ref irqfd } => {
818                 let _ = set_up_irq(IrqSetup::UnRegister(gsi, irqfd));
819                 sys_allocator.release_irq(gsi);
820                 VmIrqResponse::Ok
821             }
822         }
823     }
824 }
825 
826 #[derive(Serialize, Deserialize, Debug)]
827 pub enum VmIrqResponse {
828     AllocateOneMsi { gsi: u32 },
829     Ok,
830     Err(SysError),
831 }
832 
833 #[derive(Serialize, Deserialize, Debug, Clone)]
834 pub enum BatControlResult {
835     Ok,
836     NoBatDevice,
837     NoSuchHealth,
838     NoSuchProperty,
839     NoSuchStatus,
840     NoSuchBatType,
841     StringParseIntErr,
842 }
843 
844 impl Display for BatControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result845     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
846         use self::BatControlResult::*;
847 
848         match self {
849             Ok => write!(f, "Setting battery property successfully"),
850             NoBatDevice => write!(f, "No battery device created"),
851             NoSuchHealth => write!(f, "Invalid Battery health setting. Only support: unknown/good/overheat/dead/overvoltage/unexpectedfailure/cold/watchdogtimerexpire/safetytimerexpire/overcurrent"),
852             NoSuchProperty => write!(f, "Battery doesn't have such property. Only support: status/health/present/capacity/aconline"),
853             NoSuchStatus => write!(f, "Invalid Battery status setting. Only support: unknown/charging/discharging/notcharging/full"),
854             NoSuchBatType => write!(f, "Invalid Battery type setting. Only support: goldfish"),
855             StringParseIntErr => write!(f, "Battery property target ParseInt error"),
856         }
857     }
858 }
859 
860 #[derive(Serialize, Deserialize, Copy, Clone, Debug, Default, PartialEq, Eq)]
861 #[serde(rename_all = "kebab-case")]
862 pub enum BatteryType {
863     #[default]
864     Goldfish,
865 }
866 
867 impl FromStr for BatteryType {
868     type Err = BatControlResult;
869 
from_str(s: &str) -> StdResult<Self, Self::Err>870     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
871         match s {
872             "goldfish" => Ok(BatteryType::Goldfish),
873             _ => Err(BatControlResult::NoSuchBatType),
874         }
875     }
876 }
877 
878 #[derive(Serialize, Deserialize, Debug)]
879 pub enum BatProperty {
880     Status,
881     Health,
882     Present,
883     Capacity,
884     ACOnline,
885 }
886 
887 impl FromStr for BatProperty {
888     type Err = BatControlResult;
889 
from_str(s: &str) -> StdResult<Self, Self::Err>890     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
891         match s {
892             "status" => Ok(BatProperty::Status),
893             "health" => Ok(BatProperty::Health),
894             "present" => Ok(BatProperty::Present),
895             "capacity" => Ok(BatProperty::Capacity),
896             "aconline" => Ok(BatProperty::ACOnline),
897             _ => Err(BatControlResult::NoSuchProperty),
898         }
899     }
900 }
901 
902 #[derive(Serialize, Deserialize, Debug)]
903 pub enum BatStatus {
904     Unknown,
905     Charging,
906     DisCharging,
907     NotCharging,
908     Full,
909 }
910 
911 impl BatStatus {
new(status: String) -> std::result::Result<Self, BatControlResult>912     pub fn new(status: String) -> std::result::Result<Self, BatControlResult> {
913         match status.as_str() {
914             "unknown" => Ok(BatStatus::Unknown),
915             "charging" => Ok(BatStatus::Charging),
916             "discharging" => Ok(BatStatus::DisCharging),
917             "notcharging" => Ok(BatStatus::NotCharging),
918             "full" => Ok(BatStatus::Full),
919             _ => Err(BatControlResult::NoSuchStatus),
920         }
921     }
922 }
923 
924 impl FromStr for BatStatus {
925     type Err = BatControlResult;
926 
from_str(s: &str) -> StdResult<Self, Self::Err>927     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
928         match s {
929             "unknown" => Ok(BatStatus::Unknown),
930             "charging" => Ok(BatStatus::Charging),
931             "discharging" => Ok(BatStatus::DisCharging),
932             "notcharging" => Ok(BatStatus::NotCharging),
933             "full" => Ok(BatStatus::Full),
934             _ => Err(BatControlResult::NoSuchStatus),
935         }
936     }
937 }
938 
939 impl From<BatStatus> for u32 {
from(status: BatStatus) -> Self940     fn from(status: BatStatus) -> Self {
941         status as u32
942     }
943 }
944 
945 #[derive(Serialize, Deserialize, Debug)]
946 pub enum BatHealth {
947     Unknown,
948     Good,
949     Overheat,
950     Dead,
951     OverVoltage,
952     UnexpectedFailure,
953     Cold,
954     WatchdogTimerExpire,
955     SafetyTimerExpire,
956     OverCurrent,
957 }
958 
959 impl FromStr for BatHealth {
960     type Err = BatControlResult;
961 
from_str(s: &str) -> StdResult<Self, Self::Err>962     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
963         match s {
964             "unknown" => Ok(BatHealth::Unknown),
965             "good" => Ok(BatHealth::Good),
966             "overheat" => Ok(BatHealth::Overheat),
967             "dead" => Ok(BatHealth::Dead),
968             "overvoltage" => Ok(BatHealth::OverVoltage),
969             "unexpectedfailure" => Ok(BatHealth::UnexpectedFailure),
970             "cold" => Ok(BatHealth::Cold),
971             "watchdogtimerexpire" => Ok(BatHealth::WatchdogTimerExpire),
972             "safetytimerexpire" => Ok(BatHealth::SafetyTimerExpire),
973             "overcurrent" => Ok(BatHealth::OverCurrent),
974             _ => Err(BatControlResult::NoSuchHealth),
975         }
976     }
977 }
978 
979 impl From<BatHealth> for u32 {
from(status: BatHealth) -> Self980     fn from(status: BatHealth) -> Self {
981         status as u32
982     }
983 }
984 
985 #[derive(Serialize, Deserialize, Debug)]
986 pub enum BatControlCommand {
987     SetStatus(BatStatus),
988     SetHealth(BatHealth),
989     SetPresent(u32),
990     SetCapacity(u32),
991     SetACOnline(u32),
992 }
993 
994 impl BatControlCommand {
new(property: String, target: String) -> std::result::Result<Self, BatControlResult>995     pub fn new(property: String, target: String) -> std::result::Result<Self, BatControlResult> {
996         let cmd = property.parse::<BatProperty>()?;
997         match cmd {
998             BatProperty::Status => Ok(BatControlCommand::SetStatus(target.parse::<BatStatus>()?)),
999             BatProperty::Health => Ok(BatControlCommand::SetHealth(target.parse::<BatHealth>()?)),
1000             BatProperty::Present => Ok(BatControlCommand::SetPresent(
1001                 target
1002                     .parse::<u32>()
1003                     .map_err(|_| BatControlResult::StringParseIntErr)?,
1004             )),
1005             BatProperty::Capacity => Ok(BatControlCommand::SetCapacity(
1006                 target
1007                     .parse::<u32>()
1008                     .map_err(|_| BatControlResult::StringParseIntErr)?,
1009             )),
1010             BatProperty::ACOnline => Ok(BatControlCommand::SetACOnline(
1011                 target
1012                     .parse::<u32>()
1013                     .map_err(|_| BatControlResult::StringParseIntErr)?,
1014             )),
1015         }
1016     }
1017 }
1018 
1019 /// Used for VM to control battery properties.
1020 pub struct BatControl {
1021     pub type_: BatteryType,
1022     pub control_tube: Tube,
1023 }
1024 
1025 // Used to mark hotplug pci device's device type
1026 #[derive(Serialize, Deserialize, Debug, Clone)]
1027 pub enum HotPlugDeviceType {
1028     UpstreamPort,
1029     DownstreamPort,
1030     EndPoint,
1031 }
1032 
1033 // Used for VM to hotplug pci devices
1034 #[derive(Serialize, Deserialize, Debug, Clone)]
1035 pub struct HotPlugDeviceInfo {
1036     pub device_type: HotPlugDeviceType,
1037     pub path: PathBuf,
1038     pub hp_interrupt: bool,
1039 }
1040 
1041 /// Message for communicating a suspend or resume to the virtio-pvclock device.
1042 #[derive(Serialize, Deserialize, Debug)]
1043 pub enum PvClockCommand {
1044     Suspend,
1045     Resume,
1046 }
1047 
1048 /// Message used by virtio-pvclock to communicate command results.
1049 #[derive(Serialize, Deserialize, Debug)]
1050 pub enum PvClockCommandResponse {
1051     Ok,
1052     Err(SysError),
1053 }
1054 
1055 /// Commands for vmm-swap feature
1056 #[derive(Serialize, Deserialize, Debug)]
1057 pub enum SwapCommand {
1058     Enable,
1059     Trim,
1060     SwapOut,
1061     Disable,
1062     Status,
1063 }
1064 
1065 cfg_if::cfg_if! {
1066     if #[cfg(feature = "swap")] {
1067         use swap::Status as SwapStatus;
1068     } else {
1069         #[derive(Serialize, Deserialize, Debug, Clone)]
1070         pub enum SwapStatus {}
1071     }
1072 }
1073 
1074 ///
1075 /// A request to the main process to perform some operation on the VM.
1076 ///
1077 /// Unless otherwise noted, each request should expect a `VmResponse::Ok` to be received on success.
1078 #[derive(Serialize, Deserialize, Debug)]
1079 pub enum VmRequest {
1080     /// Break the VM's run loop and exit.
1081     Exit,
1082     /// Trigger a power button event in the guest.
1083     Powerbtn,
1084     /// Trigger a sleep button event in the guest.
1085     Sleepbtn,
1086     /// Trigger a RTC interrupt in the guest.
1087     Rtc,
1088     /// Suspend the VM's VCPUs until resume.
1089     Suspend,
1090     /// Swap the memory content into files on a disk
1091     Swap(SwapCommand),
1092     /// Resume the VM's VCPUs that were previously suspended.
1093     Resume,
1094     /// Inject a general-purpose event.
1095     Gpe(u32),
1096     /// Inject a PCI PME
1097     PciPme(u16),
1098     /// Make the VM's RT VCPU real-time.
1099     MakeRT,
1100     /// Command for balloon driver.
1101     BalloonCommand(BalloonControlCommand),
1102     /// Send a command to a disk chosen by `disk_index`.
1103     /// `disk_index` is a 0-based count of `--disk`, `--rwdisk`, and `-r` command-line options.
1104     DiskCommand {
1105         disk_index: usize,
1106         command: DiskControlCommand,
1107     },
1108     /// Command to use controller.
1109     UsbCommand(UsbControlCommand),
1110     #[cfg(feature = "gpu")]
1111     /// Command to modify the gpu.
1112     GpuCommand(GpuControlCommand),
1113     /// Command to set battery.
1114     BatCommand(BatteryType, BatControlCommand),
1115     /// Command to add/remove multiple pci devices
1116     HotPlugCommand {
1117         device: HotPlugDeviceInfo,
1118         add: bool,
1119     },
1120     /// Command to Snapshot devices
1121     Snapshot(SnapshotCommand),
1122     /// Command to Restore devices
1123     Restore(RestoreCommand),
1124     /// Register for event notification
1125     RegisterListener {
1126         socket_addr: String,
1127         event: RegisteredEvent,
1128     },
1129     /// Unregister for notifications for event
1130     UnregisterListener {
1131         socket_addr: String,
1132         event: RegisteredEvent,
1133     },
1134     /// Unregister for all event notification
1135     Unregister { socket_addr: String },
1136 }
1137 
1138 /// NOTE: when making any changes to this enum please also update
1139 /// RegisteredEventFfi in crosvm_control/src/lib.rs
1140 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
1141 pub enum RegisteredEvent {
1142     VirtioBalloonWssReport,
1143     VirtioBalloonResize,
1144     VirtioBalloonOOMDeflation,
1145 }
1146 
handle_disk_command(command: &DiskControlCommand, disk_host_tube: &Tube) -> VmResponse1147 pub fn handle_disk_command(command: &DiskControlCommand, disk_host_tube: &Tube) -> VmResponse {
1148     // Forward the request to the block device process via its control socket.
1149     if let Err(e) = disk_host_tube.send(command) {
1150         error!("disk socket send failed: {}", e);
1151         return VmResponse::Err(SysError::new(EINVAL));
1152     }
1153 
1154     // Wait for the disk control command to be processed
1155     match disk_host_tube.recv() {
1156         Ok(DiskControlResult::Ok) => VmResponse::Ok,
1157         Ok(DiskControlResult::Err(e)) => VmResponse::Err(e),
1158         Err(e) => {
1159             error!("disk socket recv failed: {}", e);
1160             VmResponse::Err(SysError::new(EINVAL))
1161         }
1162     }
1163 }
1164 
1165 /// WARNING: descriptor must be a mapping handle on Windows.
map_descriptor( descriptor: &dyn AsRawDescriptor, offset: u64, size: u64, prot: Protection, ) -> Result<Box<dyn MappedRegion>>1166 fn map_descriptor(
1167     descriptor: &dyn AsRawDescriptor,
1168     offset: u64,
1169     size: u64,
1170     prot: Protection,
1171 ) -> Result<Box<dyn MappedRegion>> {
1172     let size: usize = size.try_into().map_err(|_e| SysError::new(ERANGE))?;
1173     match MemoryMappingBuilder::new(size)
1174         .from_descriptor(descriptor)
1175         .offset(offset)
1176         .protection(prot)
1177         .build()
1178     {
1179         Ok(mmap) => Ok(Box::new(mmap)),
1180         Err(MmapError::SystemCallFailed(e)) => Err(e),
1181         _ => Err(SysError::new(EINVAL)),
1182     }
1183 }
1184 
1185 // Get vCPU state. vCPUs are expected to all hold the same state.
1186 // In this function, there may be a time where vCPUs are not
get_vcpu_state(kick_vcpus: impl Fn(VcpuControl), vcpu_num: usize) -> anyhow::Result<VmRunMode>1187 fn get_vcpu_state(kick_vcpus: impl Fn(VcpuControl), vcpu_num: usize) -> anyhow::Result<VmRunMode> {
1188     let (send_chan, recv_chan) = mpsc::channel();
1189     kick_vcpus(VcpuControl::GetStates(send_chan));
1190     if vcpu_num == 0 {
1191         bail!("vcpu_num is zero");
1192     }
1193     let mut current_mode_vec: Vec<VmRunMode> = Vec::new();
1194     for _ in 0..vcpu_num {
1195         match recv_chan.recv() {
1196             Ok(state) => current_mode_vec.push(state),
1197             Err(e) => {
1198                 bail!("Failed to get vCPU state: {}", e);
1199             }
1200         };
1201     }
1202     let first_state = current_mode_vec[0];
1203     if first_state == VmRunMode::Exiting {
1204         panic!("Attempt to snapshot while exiting.");
1205     }
1206     if current_mode_vec.iter().any(|x| *x != first_state) {
1207         // We do not panic here. It could be that vCPUs are transitioning from one mode to another.
1208         bail!("Unknown VM state: vCPUs hold different states.");
1209     }
1210     Ok(first_state)
1211 }
1212 
1213 /// A guard to guarantee that all the vCPUs are suspended during the scope.
1214 ///
1215 /// When this guard is dropped, it rolls back the state of CPUs.
1216 pub struct VcpuSuspendGuard<'a> {
1217     saved_run_mode: VmRunMode,
1218     kick_vcpus: &'a dyn Fn(VcpuControl),
1219 }
1220 
1221 impl<'a> VcpuSuspendGuard<'a> {
1222     /// Check the all vCPU state and suspend the vCPUs if they are running.
1223     ///
1224     /// This returns [VcpuSuspendGuard] to rollback the vcpu state.
1225     ///
1226     /// # Arguments
1227     ///
1228     /// * `kick_vcpus` - A funtion to send [VcpuControl] message to all the vCPUs and interrupt
1229     ///   them.
1230     /// * `vcpu_num` - The number of vCPUs.
new(kick_vcpus: &'a impl Fn(VcpuControl), vcpu_num: usize) -> anyhow::Result<Self>1231     pub fn new(kick_vcpus: &'a impl Fn(VcpuControl), vcpu_num: usize) -> anyhow::Result<Self> {
1232         // get initial vcpu state
1233         let saved_run_mode = get_vcpu_state(kick_vcpus, vcpu_num)?;
1234         match saved_run_mode {
1235             VmRunMode::Running => {
1236                 kick_vcpus(VcpuControl::RunState(VmRunMode::Suspending));
1237                 // Blocking call, waiting for response to ensure vCPU state was updated.
1238                 // In case of failure, where a vCPU still has the state running, start up vcpus and
1239                 // abort operation.
1240                 let current_mode = get_vcpu_state(kick_vcpus, vcpu_num)?;
1241                 if current_mode != VmRunMode::Suspending {
1242                     kick_vcpus(VcpuControl::RunState(saved_run_mode));
1243                     bail!("vCPUs failed to all suspend. Kicking back all vCPUs to their previous state: {saved_run_mode}");
1244                 }
1245             }
1246             VmRunMode::Suspending => {
1247                 // do nothing. keep the state suspending.
1248             }
1249             other => {
1250                 bail!("vcpus are not in running/suspending state, but {}", other);
1251             }
1252         };
1253         Ok(Self {
1254             saved_run_mode,
1255             kick_vcpus,
1256         })
1257     }
1258 }
1259 
1260 impl Drop for VcpuSuspendGuard<'_> {
drop(&mut self)1261     fn drop(&mut self) {
1262         if self.saved_run_mode != VmRunMode::Suspending {
1263             (self.kick_vcpus)(VcpuControl::RunState(self.saved_run_mode));
1264         }
1265     }
1266 }
1267 
1268 /// A guard to guarantee that all devices are sleeping during its scope.
1269 ///
1270 /// When this guard is dropped, it wakes the devices.
1271 pub struct DeviceSleepGuard<'a> {
1272     device_control_tube: &'a Tube,
1273 }
1274 
1275 impl<'a> DeviceSleepGuard<'a> {
new(device_control_tube: &'a Tube) -> anyhow::Result<Self>1276     fn new(device_control_tube: &'a Tube) -> anyhow::Result<Self> {
1277         device_control_tube
1278             .send(&DeviceControlCommand::SleepDevices)
1279             .context("send command to devices control socket")?;
1280         match device_control_tube
1281             .recv()
1282             .context("receive from devices control socket")?
1283         {
1284             VmResponse::Ok => (),
1285             resp => bail!("device sleep failed: {}", resp),
1286         }
1287         Ok(Self {
1288             device_control_tube,
1289         })
1290     }
1291 }
1292 
1293 impl Drop for DeviceSleepGuard<'_> {
drop(&mut self)1294     fn drop(&mut self) {
1295         if let Err(e) = self
1296             .device_control_tube
1297             .send(&DeviceControlCommand::WakeDevices)
1298         {
1299             panic!("failed to request device wake after snapshot: {}", e);
1300         }
1301         match self.device_control_tube.recv() {
1302             Ok(VmResponse::Ok) => (),
1303             Ok(resp) => panic!("unexpected response to device wake request: {}", resp),
1304             Err(e) => panic!("failed to get reply for device wake request: {}", e),
1305         }
1306     }
1307 }
1308 
1309 impl VmRequest {
1310     /// Executes this request on the given Vm and other mutable state.
1311     ///
1312     /// This does not return a result, instead encapsulating the success or failure in a
1313     /// `VmResponse` with the intended purpose of sending the response back over the  socket that
1314     /// received this `VmRequest`.
execute( &self, run_mode: &mut Option<VmRunMode>, #[cfg(feature = "balloon")] balloon_host_tube: Option<&Tube>, #[cfg(feature = "balloon")] balloon_wss_host_tube: Option<&Tube>, #[cfg(feature = "balloon")] balloon_stats_id: &mut u64, #[cfg(feature = "balloon")] balloon_wss_id: &mut u64, disk_host_tubes: &[Tube], pm: &mut Option<Arc<Mutex<dyn PmResource + Send>>>, #[cfg(feature = "gpu")] gpu_control_tube: &Tube, usb_control_tube: Option<&Tube>, bat_control: &mut Option<BatControl>, kick_vcpus: impl Fn(VcpuControl), kick_vcpu: impl Fn(VcpuControl, usize), force_s2idle: bool, #[cfg(feature = "swap")] swap_controller: Option<&swap::SwapController>, device_control_tube: &Tube, vcpu_size: usize, irq_handler_control: &Tube, ) -> VmResponse1315     pub fn execute(
1316         &self,
1317         run_mode: &mut Option<VmRunMode>,
1318         #[cfg(feature = "balloon")] balloon_host_tube: Option<&Tube>,
1319         #[cfg(feature = "balloon")] balloon_wss_host_tube: Option<&Tube>,
1320         #[cfg(feature = "balloon")] balloon_stats_id: &mut u64,
1321         #[cfg(feature = "balloon")] balloon_wss_id: &mut u64,
1322         disk_host_tubes: &[Tube],
1323         pm: &mut Option<Arc<Mutex<dyn PmResource + Send>>>,
1324         #[cfg(feature = "gpu")] gpu_control_tube: &Tube,
1325         usb_control_tube: Option<&Tube>,
1326         bat_control: &mut Option<BatControl>,
1327         kick_vcpus: impl Fn(VcpuControl),
1328         kick_vcpu: impl Fn(VcpuControl, usize),
1329         force_s2idle: bool,
1330         #[cfg(feature = "swap")] swap_controller: Option<&swap::SwapController>,
1331         device_control_tube: &Tube,
1332         vcpu_size: usize,
1333         irq_handler_control: &Tube,
1334     ) -> VmResponse {
1335         match *self {
1336             VmRequest::Exit => {
1337                 *run_mode = Some(VmRunMode::Exiting);
1338                 VmResponse::Ok
1339             }
1340             VmRequest::Powerbtn => {
1341                 if let Some(pm) = pm {
1342                     pm.lock().pwrbtn_evt();
1343                     VmResponse::Ok
1344                 } else {
1345                     error!("{:#?} not supported", *self);
1346                     VmResponse::Err(SysError::new(ENOTSUP))
1347                 }
1348             }
1349             VmRequest::Sleepbtn => {
1350                 if let Some(pm) = pm {
1351                     pm.lock().slpbtn_evt();
1352                     VmResponse::Ok
1353                 } else {
1354                     error!("{:#?} not supported", *self);
1355                     VmResponse::Err(SysError::new(ENOTSUP))
1356                 }
1357             }
1358             VmRequest::Rtc => {
1359                 if let Some(pm) = pm {
1360                     pm.lock().rtc_evt();
1361                     VmResponse::Ok
1362                 } else {
1363                     error!("{:#?} not supported", *self);
1364                     VmResponse::Err(SysError::new(ENOTSUP))
1365                 }
1366             }
1367             VmRequest::Suspend => {
1368                 *run_mode = Some(VmRunMode::Suspending);
1369                 VmResponse::Ok
1370             }
1371             VmRequest::Swap(SwapCommand::Enable) => {
1372                 #[cfg(feature = "swap")]
1373                 if let Some(swap_controller) = swap_controller {
1374                     // Suspend all vcpus and devices while vmm-swap is enabling (move the guest
1375                     // memory contents to the staging memory) to guarantee no processes other than
1376                     // the swap monitor process access the guest memory.
1377                     let _vcpu_guard = match VcpuSuspendGuard::new(&kick_vcpus, vcpu_size) {
1378                         Ok(guard) => guard,
1379                         Err(e) => {
1380                             error!("failed to suspend vcpus: {:?}", e);
1381                             return VmResponse::Err(SysError::new(EINVAL));
1382                         }
1383                     };
1384                     // TODO(b/253386409): Use `devices::Suspendable::sleep()` instead of sending
1385                     // `SIGSTOP` signal.
1386                     let _devices_guard = match swap_controller.suspend_devices() {
1387                         Ok(guard) => guard,
1388                         Err(e) => {
1389                             error!("failed to suspend devices: {:?}", e);
1390                             return VmResponse::Err(SysError::new(EINVAL));
1391                         }
1392                     };
1393 
1394                     return match swap_controller.enable() {
1395                         Ok(()) => VmResponse::Ok,
1396                         Err(e) => {
1397                             error!("swap enable failed: {}", e);
1398                             VmResponse::Err(SysError::new(EINVAL))
1399                         }
1400                     };
1401                 }
1402                 VmResponse::Err(SysError::new(ENOTSUP))
1403             }
1404             VmRequest::Swap(SwapCommand::Trim) => {
1405                 #[cfg(feature = "swap")]
1406                 if let Some(swap_controller) = swap_controller {
1407                     return match swap_controller.trim() {
1408                         Ok(()) => VmResponse::Ok,
1409                         Err(e) => {
1410                             error!("swap trim failed: {}", e);
1411                             VmResponse::Err(SysError::new(EINVAL))
1412                         }
1413                     };
1414                 }
1415                 VmResponse::Err(SysError::new(ENOTSUP))
1416             }
1417             VmRequest::Swap(SwapCommand::SwapOut) => {
1418                 #[cfg(feature = "swap")]
1419                 if let Some(swap_controller) = swap_controller {
1420                     return match swap_controller.swap_out() {
1421                         Ok(()) => VmResponse::Ok,
1422                         Err(e) => {
1423                             error!("swap out failed: {}", e);
1424                             VmResponse::Err(SysError::new(EINVAL))
1425                         }
1426                     };
1427                 }
1428                 VmResponse::Err(SysError::new(ENOTSUP))
1429             }
1430             VmRequest::Swap(SwapCommand::Disable) => {
1431                 #[cfg(feature = "swap")]
1432                 if let Some(swap_controller) = swap_controller {
1433                     return match swap_controller.disable() {
1434                         Ok(()) => VmResponse::Ok,
1435                         Err(e) => {
1436                             error!("swap disable failed: {}", e);
1437                             VmResponse::Err(SysError::new(EINVAL))
1438                         }
1439                     };
1440                 }
1441                 VmResponse::Err(SysError::new(ENOTSUP))
1442             }
1443             VmRequest::Swap(SwapCommand::Status) => {
1444                 #[cfg(feature = "swap")]
1445                 if let Some(swap_controller) = swap_controller {
1446                     return match swap_controller.status() {
1447                         Ok(status) => VmResponse::SwapStatus(status),
1448                         Err(e) => {
1449                             error!("swap status failed: {}", e);
1450                             VmResponse::Err(SysError::new(EINVAL))
1451                         }
1452                     };
1453                 }
1454                 VmResponse::Err(SysError::new(ENOTSUP))
1455             }
1456             VmRequest::Resume => {
1457                 *run_mode = Some(VmRunMode::Running);
1458 
1459                 if force_s2idle {
1460                     // During resume also emulate powerbtn event which will allow to wakeup fully
1461                     // suspended guest.
1462                     if let Some(pm) = pm {
1463                         pm.lock().pwrbtn_evt();
1464                     } else {
1465                         error!("triggering power btn during resume not supported");
1466                         return VmResponse::Err(SysError::new(ENOTSUP));
1467                     }
1468                 }
1469 
1470                 VmResponse::Ok
1471             }
1472             VmRequest::Gpe(gpe) => {
1473                 if let Some(pm) = pm.as_ref() {
1474                     pm.lock().gpe_evt(gpe);
1475                     VmResponse::Ok
1476                 } else {
1477                     error!("{:#?} not supported", *self);
1478                     VmResponse::Err(SysError::new(ENOTSUP))
1479                 }
1480             }
1481             VmRequest::PciPme(requester_id) => {
1482                 if let Some(pm) = pm.as_ref() {
1483                     pm.lock().pme_evt(requester_id);
1484                     VmResponse::Ok
1485                 } else {
1486                     error!("{:#?} not supported", *self);
1487                     VmResponse::Err(SysError::new(ENOTSUP))
1488                 }
1489             }
1490             VmRequest::MakeRT => {
1491                 kick_vcpus(VcpuControl::MakeRT);
1492                 VmResponse::Ok
1493             }
1494             #[cfg(feature = "balloon")]
1495             VmRequest::BalloonCommand(BalloonControlCommand::Adjust { num_bytes }) => {
1496                 if let Some(balloon_host_tube) = balloon_host_tube {
1497                     match balloon_host_tube.send(&BalloonTubeCommand::Adjust {
1498                         num_bytes,
1499                         allow_failure: false,
1500                     }) {
1501                         Ok(_) => VmResponse::Ok,
1502                         Err(_) => VmResponse::Err(SysError::last()),
1503                     }
1504                 } else {
1505                     VmResponse::Err(SysError::new(ENOTSUP))
1506                 }
1507             }
1508             #[cfg(feature = "balloon")]
1509             VmRequest::BalloonCommand(BalloonControlCommand::Stats) => {
1510                 if let Some(balloon_host_tube) = balloon_host_tube {
1511                     // NB: There are a few reasons stale balloon stats could be left
1512                     // in balloon_host_tube:
1513                     //  - the send succeeds, but the recv fails because the device
1514                     //      is not ready yet. So when the device is ready, there are
1515                     //      extra stats requests queued.
1516                     //  - the send succeed, but the recv times out. When the device
1517                     //      does return the stats, there will be no consumer.
1518                     //
1519                     // To guard against this, add an `id` to the stats request. If
1520                     // the id returned to us doesn't match, we keep trying to read
1521                     // until it does.
1522                     *balloon_stats_id = (*balloon_stats_id).wrapping_add(1);
1523                     let sent_id = *balloon_stats_id;
1524                     match balloon_host_tube.send(&BalloonTubeCommand::Stats { id: sent_id }) {
1525                         Ok(_) => {
1526                             loop {
1527                                 match balloon_host_tube.recv() {
1528                                     Ok(BalloonTubeResult::Stats {
1529                                         stats,
1530                                         balloon_actual,
1531                                         id,
1532                                     }) => {
1533                                         if sent_id != id {
1534                                             // Keep trying to get the fresh stats.
1535                                             continue;
1536                                         }
1537                                         break VmResponse::BalloonStats {
1538                                             stats,
1539                                             balloon_actual,
1540                                         };
1541                                     }
1542                                     Err(e) => {
1543                                         error!("balloon socket recv for stats failed: {}", e);
1544                                         break VmResponse::Err(SysError::last());
1545                                     }
1546                                     Ok(BalloonTubeResult::Adjusted { .. }) => {
1547                                         unreachable!("unexpected adjusted response")
1548                                     }
1549                                     Ok(BalloonTubeResult::WorkingSetSize { .. }) => {
1550                                         unreachable!("unexpected wss response")
1551                                     }
1552                                 }
1553                             }
1554                         }
1555                         Err(_) => VmResponse::Err(SysError::last()),
1556                     }
1557                 } else {
1558                     VmResponse::Err(SysError::new(ENOTSUP))
1559                 }
1560             }
1561             #[cfg(feature = "balloon")]
1562             VmRequest::BalloonCommand(BalloonControlCommand::WorkingSetSize) => {
1563                 if let Some(balloon_wss_host_tube) = balloon_wss_host_tube {
1564                     // NB: There are a few reasons stale balloon wss could be left
1565                     // in balloon_wss_host_tube:
1566                     //  - the send succeeds, but the recv fails because the device
1567                     //      is not ready yet. So when the device is ready, there are
1568                     //      extra ess requests queued.
1569                     //  - the send succeed, but the recv times out. When the device
1570                     //      does return the stats, there will be no consumer.
1571                     //
1572                     // To guard against this, add an `id` to the wss request. If
1573                     // the id returned to us doesn't match, we keep trying to read
1574                     // until it does.
1575                     *balloon_wss_id = (*balloon_wss_id).wrapping_add(1);
1576                     let sent_id = *balloon_wss_id;
1577                     match balloon_wss_host_tube
1578                         .send(&BalloonTubeCommand::WorkingSetSize { id: sent_id })
1579                     {
1580                         Ok(_) => {
1581                             loop {
1582                                 match balloon_wss_host_tube.recv() {
1583                                     Ok(BalloonTubeResult::WorkingSetSize { wss, id }) => {
1584                                         if sent_id != id {
1585                                             // Keep trying to get fresh stats.
1586                                             continue;
1587                                         }
1588                                         break VmResponse::BalloonWSS { wss };
1589                                     }
1590                                     Err(e) => {
1591                                         error!("balloon socket recv for wss failed: {}", e);
1592                                         break VmResponse::Err(SysError::last());
1593                                     }
1594                                     Ok(BalloonTubeResult::Adjusted { .. }) => {
1595                                         unreachable!("unexpected adjusted response")
1596                                     }
1597                                     Ok(BalloonTubeResult::Stats { .. }) => {
1598                                         unreachable!("unexpected stats response")
1599                                     }
1600                                 }
1601                             }
1602                         }
1603                         Err(_) => VmResponse::Err(SysError::last()),
1604                     }
1605                 } else {
1606                     VmResponse::Err(SysError::new(ENOTSUP))
1607                 }
1608             }
1609             #[cfg(not(feature = "balloon"))]
1610             VmRequest::BalloonCommand(_) => VmResponse::Err(SysError::new(ENOTSUP)),
1611             VmRequest::DiskCommand {
1612                 disk_index,
1613                 ref command,
1614             } => match &disk_host_tubes.get(disk_index) {
1615                 Some(tube) => handle_disk_command(command, tube),
1616                 None => VmResponse::Err(SysError::new(ENODEV)),
1617             },
1618             #[cfg(feature = "gpu")]
1619             VmRequest::GpuCommand(ref cmd) => {
1620                 let res = gpu_control_tube.send(cmd);
1621                 if let Err(e) = res {
1622                     error!("fail to send command to gpu control socket: {}", e);
1623                     return VmResponse::Err(SysError::new(EIO));
1624                 }
1625                 match gpu_control_tube.recv() {
1626                     Ok(response) => VmResponse::GpuResponse(response),
1627                     Err(e) => {
1628                         error!("fail to recv command from gpu control socket: {}", e);
1629                         VmResponse::Err(SysError::new(EIO))
1630                     }
1631                 }
1632             }
1633             VmRequest::UsbCommand(ref cmd) => {
1634                 let usb_control_tube = match usb_control_tube {
1635                     Some(t) => t,
1636                     None => {
1637                         error!("attempted to execute USB request without control tube");
1638                         return VmResponse::Err(SysError::new(ENODEV));
1639                     }
1640                 };
1641                 let res = usb_control_tube.send(cmd);
1642                 if let Err(e) = res {
1643                     error!("fail to send command to usb control socket: {}", e);
1644                     return VmResponse::Err(SysError::new(EIO));
1645                 }
1646                 match usb_control_tube.recv() {
1647                     Ok(response) => VmResponse::UsbResponse(response),
1648                     Err(e) => {
1649                         error!("fail to recv command from usb control socket: {}", e);
1650                         VmResponse::Err(SysError::new(EIO))
1651                     }
1652                 }
1653             }
1654             VmRequest::BatCommand(type_, ref cmd) => {
1655                 match bat_control {
1656                     Some(battery) => {
1657                         if battery.type_ != type_ {
1658                             error!("ignored battery command due to battery type: expected {:?}, got {:?}", battery.type_, type_);
1659                             return VmResponse::Err(SysError::new(EINVAL));
1660                         }
1661 
1662                         let res = battery.control_tube.send(cmd);
1663                         if let Err(e) = res {
1664                             error!("fail to send command to bat control socket: {}", e);
1665                             return VmResponse::Err(SysError::new(EIO));
1666                         }
1667 
1668                         match battery.control_tube.recv() {
1669                             Ok(response) => VmResponse::BatResponse(response),
1670                             Err(e) => {
1671                                 error!("fail to recv command from bat control socket: {}", e);
1672                                 VmResponse::Err(SysError::new(EIO))
1673                             }
1674                         }
1675                     }
1676                     None => VmResponse::BatResponse(BatControlResult::NoBatDevice),
1677                 }
1678             }
1679             VmRequest::HotPlugCommand { device: _, add: _ } => VmResponse::Ok,
1680             VmRequest::Snapshot(SnapshotCommand::Take { ref snapshot_path }) => {
1681                 let f = || -> anyhow::Result<VmResponse> {
1682                     let _vcpu_guard = VcpuSuspendGuard::new(&kick_vcpus, vcpu_size)?;
1683                     let _device_guard = DeviceSleepGuard::new(device_control_tube)?;
1684 
1685                     // We want to flush all pending IRQs to the LAPICs. There are two cases:
1686                     //
1687                     // MSIs: these are directly delivered to the LAPIC. We must verify the handler
1688                     // thread cycles once to deliver these interrupts.
1689                     //
1690                     // Legacy interrupts: in the case of a split IRQ chip, these interrupts may
1691                     // flow through the userspace IOAPIC. If the hypervisor does not support
1692                     // irqfds (e.g. WHPX), a single iteration will only flush the IRQ to the
1693                     // IOAPIC. The underlying MSI will be asserted at this point, but if the
1694                     // IRQ handler doesn't run another iteration, it won't be delivered to the
1695                     // LAPIC. This is why we cycle the handler thread twice (doing so ensures we
1696                     // process the underlying MSI).
1697                     //
1698                     // We can handle both of these cases by iterating until there are no tokens
1699                     // serviced on the requested iteration. Note that in the legacy case, this
1700                     // ensures at least two iterations.
1701                     //
1702                     // Note: within CrosVM, *all* interrupts are eventually converted into the
1703                     // same mechanicism that MSIs use. This is why we say "underlying" MSI for
1704                     // a legacy IRQ.
1705                     let mut flush_attempts = 0;
1706                     loop {
1707                         irq_handler_control
1708                             .send(&IrqHandlerRequest::WakeAndNotifyIteration)
1709                             .context("failed to send flush command to IRQ handler thread")?;
1710                         let resp = irq_handler_control
1711                             .recv()
1712                             .context("failed to recv flush response from IRQ handler thread")?;
1713                         match resp {
1714                             IrqHandlerResponse::HandlerIterationComplete(tokens_serviced) => {
1715                                 if tokens_serviced == 0 {
1716                                     break;
1717                                 }
1718                             }
1719                         }
1720                         flush_attempts += 1;
1721                         if flush_attempts > EXPECTED_MAX_IRQ_FLUSH_ITERATIONS {
1722                             warn!("flushing IRQs for snapshot may be stalled after iteration {}, expected <= {} iterations", flush_attempts, EXPECTED_MAX_IRQ_FLUSH_ITERATIONS);
1723                         }
1724                     }
1725                     info!("flushed IRQs in {} iterations", flush_attempts);
1726                     let vcpu_path = snapshot_path.with_extension("vcpu");
1727                     let cpu_file = File::create(&vcpu_path)
1728                         .with_context(|| format!("failed to open path {}", vcpu_path.display()))?;
1729                     let (send_chan, recv_chan) = mpsc::channel();
1730                     kick_vcpus(VcpuControl::Snapshot(send_chan));
1731                     // Validate all Vcpus snapshot successfully
1732                     let mut cpu_vec = Vec::with_capacity(vcpu_size);
1733                     for _ in 0..vcpu_size {
1734                         match recv_chan
1735                             .recv()
1736                             .context("Failed to snapshot Vcpu, aborting snapshot")?
1737                         {
1738                             Ok(snap) => {
1739                                 cpu_vec.push(snap);
1740                             }
1741                             Err(e) => bail!("Failed to snapshot Vcpu, aborting snapshot: {}", e),
1742                         }
1743                     }
1744                     serde_json::to_writer(cpu_file, &cpu_vec).expect("Failed to write Vcpu state");
1745                     device_control_tube
1746                         .send(&DeviceControlCommand::SnapshotDevices {
1747                             snapshot_path: snapshot_path.clone(),
1748                         })
1749                         .context("send command to devices control socket")?;
1750                     device_control_tube
1751                         .recv()
1752                         .context("receive from devices control socket")
1753                 };
1754                 match f() {
1755                     Ok(r) => r,
1756                     Err(e) => {
1757                         error!("failed to handle snapshot: {:?}", e);
1758                         VmResponse::Err(SysError::new(EIO))
1759                     }
1760                 }
1761             }
1762             VmRequest::Restore(RestoreCommand::Apply { ref restore_path }) => {
1763                 match do_restore(
1764                     restore_path.clone(),
1765                     kick_vcpus,
1766                     kick_vcpu,
1767                     device_control_tube,
1768                     vcpu_size,
1769                 ) {
1770                     Ok(()) => VmResponse::Ok,
1771                     Err(e) => {
1772                         error!("failed to handle restore: {:?}", e);
1773                         VmResponse::Err(SysError::new(EIO))
1774                     }
1775                 }
1776             }
1777             VmRequest::RegisterListener {
1778                 socket_addr: _,
1779                 event: _,
1780             } => VmResponse::Ok,
1781             VmRequest::UnregisterListener {
1782                 socket_addr: _,
1783                 event: _,
1784             } => VmResponse::Ok,
1785             VmRequest::Unregister { socket_addr: _ } => VmResponse::Ok,
1786         }
1787     }
1788 }
1789 
1790 /// Restore the VM to the snapshot at `restore_path`.
1791 ///
1792 /// Same as `VmRequest::execute` with a `VmRequest::Restore`. Exposed as a separate function
1793 /// because not all the `VmRequest::execute` arguments are available in the "cold restore" flow.
do_restore( restore_path: PathBuf, kick_vcpus: impl Fn(VcpuControl), kick_vcpu: impl Fn(VcpuControl, usize), device_control_tube: &Tube, vcpu_size: usize, ) -> anyhow::Result<()>1794 pub fn do_restore(
1795     restore_path: PathBuf,
1796     kick_vcpus: impl Fn(VcpuControl),
1797     kick_vcpu: impl Fn(VcpuControl, usize),
1798     device_control_tube: &Tube,
1799     vcpu_size: usize,
1800 ) -> anyhow::Result<()> {
1801     let _guard = VcpuSuspendGuard::new(&kick_vcpus, vcpu_size)?;
1802     let _device_guard = DeviceSleepGuard::new(device_control_tube)?;
1803     let vcpu_path = restore_path.with_extension("vcpu");
1804     let cpu_file = File::open(&vcpu_path)
1805         .with_context(|| format!("failed to open path {}", vcpu_path.display()))?;
1806     let vcpu_snapshots: Vec<VcpuSnapshot> = serde_json::from_reader(cpu_file)?;
1807     if vcpu_snapshots.len() != vcpu_size {
1808         bail!(
1809             "bad cpu count in snapshot: expected={} got={}",
1810             vcpu_size,
1811             vcpu_snapshots.len()
1812         );
1813     }
1814     let (send_chan, recv_chan) = mpsc::channel();
1815     for vcpu_snap in vcpu_snapshots {
1816         let vcpu_id = vcpu_snap.vcpu_id;
1817         kick_vcpu(
1818             VcpuControl::Restore(send_chan.clone(), Box::new(vcpu_snap)),
1819             vcpu_id,
1820         );
1821     }
1822     for _ in 0..vcpu_size {
1823         if let Err(e) = recv_chan.recv() {
1824             bail!("Failed to restore vcpu: {}", e);
1825         }
1826     }
1827     device_control_tube
1828         .send(&DeviceControlCommand::RestoreDevices { restore_path })
1829         .context("send command to devices control socket")?;
1830     let resp = device_control_tube
1831         .recv()
1832         .context("receive from devices control socket")?;
1833     match resp {
1834         VmResponse::Ok => Ok(()),
1835         _ => bail!("unexpected RestoreDevices response: {resp}"),
1836     }
1837 }
1838 
1839 /// Indication of success or failure of a `VmRequest`.
1840 ///
1841 /// Success is usually indicated `VmResponse::Ok` unless there is data associated with the response.
1842 #[derive(Serialize, Deserialize, Debug, Clone)]
1843 #[must_use]
1844 pub enum VmResponse {
1845     /// Indicates the request was executed successfully.
1846     Ok,
1847     /// Indicates the request encountered some error during execution.
1848     Err(SysError),
1849     /// Indicates the request encountered some error during execution.
1850     ErrString(String),
1851     /// The request to register memory into guest address space was successfully done at page frame
1852     /// number `pfn` and memory slot number `slot`.
1853     RegisterMemory { pfn: u64, slot: u32 },
1854     /// Results of balloon control commands.
1855     BalloonStats {
1856         stats: BalloonStats,
1857         balloon_actual: u64,
1858     },
1859     /// Results of balloon WSS-R command
1860     BalloonWSS { wss: BalloonWSS },
1861     /// Results of usb control commands.
1862     UsbResponse(UsbControlResult),
1863     #[cfg(feature = "gpu")]
1864     /// Results of gpu control commands.
1865     GpuResponse(GpuControlResult),
1866     /// Results of battery control commands.
1867     BatResponse(BatControlResult),
1868     /// Results of swap status command.
1869     SwapStatus(SwapStatus),
1870 }
1871 
1872 impl Display for VmResponse {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1873     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1874         use self::VmResponse::*;
1875 
1876         match self {
1877             Ok => write!(f, "ok"),
1878             Err(e) => write!(f, "error: {}", e),
1879             ErrString(e) => write!(f, "error: {}", e),
1880             RegisterMemory { pfn, slot } => write!(
1881                 f,
1882                 "memory registered to page frame number {:#x} and memory slot {}",
1883                 pfn, slot
1884             ),
1885             VmResponse::BalloonStats {
1886                 stats,
1887                 balloon_actual,
1888             } => {
1889                 write!(
1890                     f,
1891                     "stats: {}\nballoon_actual: {}",
1892                     serde_json::to_string_pretty(&stats)
1893                         .unwrap_or_else(|_| "invalid_response".to_string()),
1894                     balloon_actual
1895                 )
1896             }
1897             VmResponse::BalloonWSS { wss } => {
1898                 write!(
1899                     f,
1900                     "wss: {}",
1901                     serde_json::to_string_pretty(&wss)
1902                         .unwrap_or_else(|_| "invalid_response".to_string())
1903                 )
1904             }
1905             UsbResponse(result) => write!(f, "usb control request get result {:?}", result),
1906             #[cfg(feature = "gpu")]
1907             GpuResponse(result) => write!(f, "gpu control request result {:?}", result),
1908             BatResponse(result) => write!(f, "{}", result),
1909             SwapStatus(status) => {
1910                 write!(
1911                     f,
1912                     "{}",
1913                     serde_json::to_string(&status)
1914                         .unwrap_or_else(|_| "invalid_response".to_string()),
1915                 )
1916             }
1917         }
1918     }
1919 }
1920 
1921 /// Enum that comes from the Gpu device that will be received by the main event loop.
1922 #[derive(Serialize, Deserialize, Debug)]
1923 pub enum GpuSendToService {
1924     SendWindowState {
1925         window_event: Option<WindowEvent>,
1926         hwnd: usize,
1927         visibility: WindowVisibility,
1928         mode: WindowMode,
1929         aspect_ratio: AspectRatio,
1930         // TODO(b/203662783): Once we make the controller decide the initial size, this can be removed.
1931         initial_guest_display_size: DisplaySize,
1932         recommended_guest_display_density: GuestDisplayDensity,
1933     },
1934     SendExitWindowRequest,
1935     SendMouseModeState {
1936         mouse_mode: MouseMode,
1937     },
1938     SendGpuDevice {
1939         description: String,
1940     },
1941 }
1942 
1943 /// Enum that serves as a general purose Gpu device message that is sent to the main loop.
1944 #[derive(Serialize, Deserialize, Debug)]
1945 pub enum GpuSendToMain {
1946     // Send these messages to the controller.
1947     SendToService(GpuSendToService),
1948     // Send to Ac97 device to set mute state.
1949     MuteAc97(bool),
1950 }
1951 
1952 /// Enum to send control requests to all Ac97 audio devices.
1953 #[derive(Serialize, Deserialize, Debug)]
1954 pub enum Ac97Control {
1955     Mute(bool),
1956 }
1957 
1958 /// Enum that send controller Ipc requests from the main event loop to the GPU device.
1959 #[derive(Serialize, Deserialize, Debug)]
1960 pub enum ServiceSendToGpu {
1961     ShowWindow {
1962         mode: WindowMode,
1963         aspect_ratio: AspectRatio,
1964         guest_display_size: DisplaySize,
1965     },
1966     HideWindow,
1967     Shutdown,
1968     MouseInputMode {
1969         mouse_mode: MouseMode,
1970     },
1971 }
1972 
1973 #[cfg(test)]
1974 mod tests {
1975     use base::Event;
1976 
1977     use super::*;
1978 
1979     #[test]
sock_send_recv_event()1980     fn sock_send_recv_event() {
1981         let (req, res) = Tube::pair().unwrap();
1982         let e1 = Event::new().unwrap();
1983         res.send(&e1).unwrap();
1984 
1985         let recv_event: Event = req.recv().unwrap();
1986         recv_event.signal().unwrap();
1987         e1.wait().unwrap();
1988     }
1989 }
1990 
1991 #[sorted]
1992 #[derive(Error, Debug)]
1993 pub enum VirtioIOMMUVfioError {
1994     #[error("socket failed")]
1995     SocketFailed,
1996     #[error("unexpected response: {0}")]
1997     UnexpectedResponse(VirtioIOMMUResponse),
1998     #[error("unknown command: `{0}`")]
1999     UnknownCommand(String),
2000     #[error("{0}")]
2001     VfioControl(VirtioIOMMUVfioResult),
2002 }
2003 
2004 #[derive(Serialize, Deserialize, Debug)]
2005 pub enum VirtioIOMMUVfioCommand {
2006     // Add the vfio device attached to virtio-iommu.
2007     VfioDeviceAdd {
2008         endpoint_addr: u32,
2009         wrapper_id: u32,
2010         #[serde(with = "with_as_descriptor")]
2011         container: File,
2012     },
2013     // Delete the vfio device attached to virtio-iommu.
2014     VfioDeviceDel {
2015         endpoint_addr: u32,
2016     },
2017     // Map a dma-buf into vfio iommu table
2018     VfioDmabufMap {
2019         mem_slot: MemSlot,
2020         gfn: u64,
2021         size: u64,
2022         dma_buf: SafeDescriptor,
2023     },
2024     // Unmap a dma-buf from vfio iommu table
2025     VfioDmabufUnmap(MemSlot),
2026 }
2027 
2028 #[derive(Serialize, Deserialize, Debug)]
2029 pub enum VirtioIOMMUVfioResult {
2030     Ok,
2031     NotInPCIRanges,
2032     NoAvailableContainer,
2033     NoSuchDevice,
2034     NoSuchMappedDmabuf,
2035     InvalidParam,
2036 }
2037 
2038 impl Display for VirtioIOMMUVfioResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2039     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2040         use self::VirtioIOMMUVfioResult::*;
2041 
2042         match self {
2043             Ok => write!(f, "successfully"),
2044             NotInPCIRanges => write!(f, "not in the pci ranges of virtio-iommu"),
2045             NoAvailableContainer => write!(f, "no available vfio container"),
2046             NoSuchDevice => write!(f, "no such a vfio device"),
2047             NoSuchMappedDmabuf => write!(f, "no such a mapped dmabuf"),
2048             InvalidParam => write!(f, "invalid parameters"),
2049         }
2050     }
2051 }
2052 
2053 /// A request to the virtio-iommu process to perform some operations.
2054 ///
2055 /// Unless otherwise noted, each request should expect a `VirtioIOMMUResponse::Ok` to be received on
2056 /// success.
2057 #[derive(Serialize, Deserialize, Debug)]
2058 pub enum VirtioIOMMURequest {
2059     /// Command for vfio related operations.
2060     VfioCommand(VirtioIOMMUVfioCommand),
2061 }
2062 
2063 /// Indication of success or failure of a `VirtioIOMMURequest`.
2064 ///
2065 /// Success is usually indicated `VirtioIOMMUResponse::Ok` unless there is data associated with the
2066 /// response.
2067 #[derive(Serialize, Deserialize, Debug)]
2068 pub enum VirtioIOMMUResponse {
2069     /// Indicates the request was executed successfully.
2070     Ok,
2071     /// Indicates the request encountered some error during execution.
2072     Err(SysError),
2073     /// Results for Vfio commands.
2074     VfioResponse(VirtioIOMMUVfioResult),
2075 }
2076 
2077 impl Display for VirtioIOMMUResponse {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2078     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2079         use self::VirtioIOMMUResponse::*;
2080         match self {
2081             Ok => write!(f, "ok"),
2082             Err(e) => write!(f, "error: {}", e),
2083             VfioResponse(result) => write!(
2084                 f,
2085                 "The vfio-related virtio-iommu request got result: {:?}",
2086                 result
2087             ),
2088         }
2089     }
2090 }
2091 
2092 /// Send VirtioIOMMURequest without waiting for the response
virtio_iommu_request_async( iommu_control_tube: &Tube, req: &VirtioIOMMURequest, ) -> VirtioIOMMUResponse2093 pub fn virtio_iommu_request_async(
2094     iommu_control_tube: &Tube,
2095     req: &VirtioIOMMURequest,
2096 ) -> VirtioIOMMUResponse {
2097     match iommu_control_tube.send(&req) {
2098         Ok(_) => VirtioIOMMUResponse::Ok,
2099         Err(e) => {
2100             error!("virtio-iommu socket send failed: {:?}", e);
2101             VirtioIOMMUResponse::Err(SysError::last())
2102         }
2103     }
2104 }
2105 
2106 pub type VirtioIOMMURequestResult = std::result::Result<VirtioIOMMUResponse, ()>;
2107 
2108 /// Send VirtioIOMMURequest and wait to get the response
virtio_iommu_request( iommu_control_tube: &Tube, req: &VirtioIOMMURequest, ) -> VirtioIOMMURequestResult2109 pub fn virtio_iommu_request(
2110     iommu_control_tube: &Tube,
2111     req: &VirtioIOMMURequest,
2112 ) -> VirtioIOMMURequestResult {
2113     let response = match virtio_iommu_request_async(iommu_control_tube, req) {
2114         VirtioIOMMUResponse::Ok => match iommu_control_tube.recv() {
2115             Ok(response) => response,
2116             Err(e) => {
2117                 error!("virtio-iommu socket recv failed: {:?}", e);
2118                 VirtioIOMMUResponse::Err(SysError::last())
2119             }
2120         },
2121         resp => resp,
2122     };
2123     Ok(response)
2124 }
2125