• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
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(target_arch = "x86_64", feature = "gdb"))]
14 pub mod gdb;
15 
16 pub mod client;
17 
18 use std::convert::TryInto;
19 use std::fmt::{self, Display};
20 use std::fs::File;
21 use std::os::raw::c_int;
22 use std::path::PathBuf;
23 use std::result::Result as StdResult;
24 use std::str::FromStr;
25 use std::sync::{mpsc, Arc};
26 
27 use std::thread::JoinHandle;
28 
29 use remain::sorted;
30 use thiserror::Error;
31 
32 use libc::{EINVAL, EIO, ENODEV, ENOTSUP, ERANGE};
33 use serde::{Deserialize, Serialize};
34 
35 pub use balloon_control::BalloonStats;
36 use balloon_control::{BalloonTubeCommand, BalloonTubeResult};
37 
38 use base::{
39     error, with_as_descriptor, AsRawDescriptor, Error as SysError, Event, ExternalMapping,
40     FromRawDescriptor, IntoRawDescriptor, Killable, MappedRegion, MemoryMappingArena,
41     MemoryMappingBuilder, MemoryMappingBuilderUnix, MmapError, Protection, Result, SafeDescriptor,
42     SharedMemory, Tube, SIGRTMIN,
43 };
44 use hypervisor::{IrqRoute, IrqSource, Vm};
45 use resources::{Alloc, MmioType, SystemAllocator};
46 use rutabaga_gfx::{
47     DrmFormat, ImageAllocationInfo, RutabagaGralloc, RutabagaGrallocFlags, RutabagaHandle,
48     VulkanInfo,
49 };
50 use sync::Mutex;
51 use vm_memory::GuestAddress;
52 
53 /// Struct that describes the offset and stride of a plane located in GPU memory.
54 #[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize)]
55 pub struct GpuMemoryPlaneDesc {
56     pub stride: u32,
57     pub offset: u32,
58 }
59 
60 /// Struct that describes a GPU memory allocation that consists of up to 3 planes.
61 #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
62 pub struct GpuMemoryDesc {
63     pub planes: [GpuMemoryPlaneDesc; 3],
64 }
65 
66 #[cfg(all(target_arch = "x86_64", feature = "gdb"))]
67 pub use crate::gdb::*;
68 pub use hypervisor::MemSlot;
69 
70 /// Control the state of a particular VM CPU.
71 #[derive(Clone, Debug)]
72 pub enum VcpuControl {
73     #[cfg(all(target_arch = "x86_64", feature = "gdb"))]
74     Debug(VcpuDebug),
75     RunState(VmRunMode),
76     MakeRT,
77 }
78 
79 /// Mode of execution for the VM.
80 #[derive(Debug, Clone, PartialEq)]
81 pub enum VmRunMode {
82     /// The default run mode indicating the VCPUs are running.
83     Running,
84     /// Indicates that the VCPUs are suspending execution until the `Running` mode is set.
85     Suspending,
86     /// Indicates that the VM is exiting all processes.
87     Exiting,
88     /// Indicates that the VM is in a breakpoint waiting for the debugger to do continue.
89     Breakpoint,
90 }
91 
92 impl Display for VmRunMode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result93     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94         use self::VmRunMode::*;
95 
96         match self {
97             Running => write!(f, "running"),
98             Suspending => write!(f, "suspending"),
99             Exiting => write!(f, "exiting"),
100             Breakpoint => write!(f, "breakpoint"),
101         }
102     }
103 }
104 
105 impl Default for VmRunMode {
default() -> Self106     fn default() -> Self {
107         VmRunMode::Running
108     }
109 }
110 
111 // Trait for devices that get notification on specific GPE trigger
112 pub trait GpeNotify: Send {
notify(&mut self)113     fn notify(&mut self) {}
114 }
115 
116 pub trait PmResource {
pwrbtn_evt(&mut self)117     fn pwrbtn_evt(&mut self) {}
gpe_evt(&mut self, _gpe: u32)118     fn gpe_evt(&mut self, _gpe: u32) {}
register_gpe_notify_dev(&mut self, _gpe: u32, _notify_dev: Arc<Mutex<dyn GpeNotify>>)119     fn register_gpe_notify_dev(&mut self, _gpe: u32, _notify_dev: Arc<Mutex<dyn GpeNotify>>) {}
120 }
121 
122 /// The maximum number of devices that can be listed in one `UsbControlCommand`.
123 ///
124 /// This value was set to be equal to `xhci_regs::MAX_PORTS` for convenience, but it is not
125 /// necessary for correctness. Importing that value directly would be overkill because it would
126 /// require adding a big dependency for a single const.
127 pub const USB_CONTROL_MAX_PORTS: usize = 16;
128 
129 // Balloon commands that are sent on the crosvm control socket.
130 #[derive(Serialize, Deserialize, Debug)]
131 pub enum BalloonControlCommand {
132     /// Set the size of the VM's balloon.
133     Adjust {
134         num_bytes: u64,
135     },
136     Stats,
137 }
138 
139 // BalloonControlResult holds results for BalloonControlCommand defined above.
140 #[derive(Serialize, Deserialize, Debug)]
141 pub enum BalloonControlResult {
142     Stats {
143         stats: BalloonStats,
144         balloon_actual: u64,
145     },
146 }
147 
148 #[derive(Serialize, Deserialize, Debug)]
149 pub enum DiskControlCommand {
150     /// Resize a disk to `new_size` in bytes.
151     Resize { new_size: u64 },
152 }
153 
154 impl Display for DiskControlCommand {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result155     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156         use self::DiskControlCommand::*;
157 
158         match self {
159             Resize { new_size } => write!(f, "disk_resize {}", new_size),
160         }
161     }
162 }
163 
164 #[derive(Serialize, Deserialize, Debug, Clone)]
165 pub enum DiskControlResult {
166     Ok,
167     Err(SysError),
168 }
169 
170 #[derive(Serialize, Deserialize, Debug)]
171 pub enum UsbControlCommand {
172     AttachDevice {
173         bus: u8,
174         addr: u8,
175         vid: u16,
176         pid: u16,
177         #[serde(with = "with_as_descriptor")]
178         file: File,
179     },
180     DetachDevice {
181         port: u8,
182     },
183     ListDevice {
184         ports: [u8; USB_CONTROL_MAX_PORTS],
185     },
186 }
187 
188 #[derive(Serialize, Deserialize, Copy, Clone, Debug, Default)]
189 pub struct UsbControlAttachedDevice {
190     pub port: u8,
191     pub vendor_id: u16,
192     pub product_id: u16,
193 }
194 
195 impl UsbControlAttachedDevice {
valid(self) -> bool196     pub fn valid(self) -> bool {
197         self.port != 0
198     }
199 }
200 
201 #[derive(Serialize, Deserialize, Debug)]
202 pub enum UsbControlResult {
203     Ok { port: u8 },
204     NoAvailablePort,
205     NoSuchDevice,
206     NoSuchPort,
207     FailedToOpenDevice,
208     Devices([UsbControlAttachedDevice; USB_CONTROL_MAX_PORTS]),
209     FailedToInitHostDevice,
210 }
211 
212 impl Display for UsbControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result213     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214         use self::UsbControlResult::*;
215 
216         match self {
217             UsbControlResult::Ok { port } => write!(f, "ok {}", port),
218             NoAvailablePort => write!(f, "no_available_port"),
219             NoSuchDevice => write!(f, "no_such_device"),
220             NoSuchPort => write!(f, "no_such_port"),
221             FailedToOpenDevice => write!(f, "failed_to_open_device"),
222             Devices(devices) => {
223                 write!(f, "devices")?;
224                 for d in devices.iter().filter(|d| d.valid()) {
225                     write!(f, " {} {:04x} {:04x}", d.port, d.vendor_id, d.product_id)?;
226                 }
227                 std::result::Result::Ok(())
228             }
229             FailedToInitHostDevice => write!(f, "failed_to_init_host_device"),
230         }
231     }
232 }
233 
234 /// Source of a `VmMemoryRequest::RegisterMemory` mapping.
235 #[derive(Serialize, Deserialize)]
236 pub enum VmMemorySource {
237     /// Register shared memory represented by the given descriptor.
238     SharedMemory(SharedMemory),
239     /// Register a file mapping from the given descriptor.
240     Descriptor {
241         /// File descriptor to map.
242         descriptor: SafeDescriptor,
243         /// Offset within the file in bytes.
244         offset: u64,
245         /// Size of the mapping in bytes.
246         size: u64,
247     },
248     /// Register memory mapped by Vulkano.
249     Vulkan {
250         descriptor: SafeDescriptor,
251         handle_type: u32,
252         memory_idx: u32,
253         physical_device_idx: u32,
254         size: u64,
255     },
256     /// Register the current rutabaga external mapping.
257     ExternalMapping { size: u64 },
258 }
259 
260 impl VmMemorySource {
261     /// Map the resource and return its mapping and size in bytes.
map( self, map_request: Arc<Mutex<Option<ExternalMapping>>>, gralloc: &mut RutabagaGralloc, read_only: bool, ) -> Result<(Box<dyn MappedRegion>, u64)>262     pub fn map(
263         self,
264         map_request: Arc<Mutex<Option<ExternalMapping>>>,
265         gralloc: &mut RutabagaGralloc,
266         read_only: bool,
267     ) -> Result<(Box<dyn MappedRegion>, u64)> {
268         let (mem_region, size) = match self {
269             VmMemorySource::Descriptor {
270                 descriptor,
271                 offset,
272                 size,
273             } => (map_descriptor(&descriptor, offset, size, read_only)?, size),
274             VmMemorySource::SharedMemory(shm) => {
275                 (map_descriptor(&shm, 0, shm.size(), read_only)?, shm.size())
276             }
277             VmMemorySource::Vulkan {
278                 descriptor,
279                 handle_type,
280                 memory_idx,
281                 physical_device_idx,
282                 size,
283             } => {
284                 let mapped_region = match gralloc.import_and_map(
285                     RutabagaHandle {
286                         os_handle: descriptor,
287                         handle_type,
288                     },
289                     VulkanInfo {
290                         memory_idx,
291                         physical_device_idx,
292                     },
293                     size,
294                 ) {
295                     Ok(mapped_region) => mapped_region,
296                     Err(e) => {
297                         error!("gralloc failed to import and map: {}", e);
298                         return Err(SysError::new(EINVAL));
299                     }
300                 };
301                 (mapped_region, size)
302             }
303             VmMemorySource::ExternalMapping { size } => {
304                 let mem = map_request
305                     .lock()
306                     .take()
307                     .ok_or_else(|| VmMemoryResponse::Err(SysError::new(EINVAL)))
308                     .unwrap();
309                 let mapped_region: Box<dyn MappedRegion> = Box::new(mem);
310                 (mapped_region, size)
311             }
312         };
313         Ok((mem_region, size))
314     }
315 }
316 
317 /// Destination of a `VmMemoryRequest::RegisterMemory` mapping in guest address space.
318 #[derive(Serialize, Deserialize)]
319 pub enum VmMemoryDestination {
320     /// Map at an offset within an existing PCI BAR allocation.
321     ExistingAllocation { allocation: Alloc, offset: u64 },
322     /// Create a new anonymous allocation in MMIO space.
323     NewAllocation,
324     /// Map at the specified guest physical address.
325     GuestPhysicalAddress(u64),
326 }
327 
328 impl VmMemoryDestination {
329     /// Allocate and return the guest address of a memory mapping destination.
allocate(self, allocator: &mut SystemAllocator, size: u64) -> Result<GuestAddress>330     pub fn allocate(self, allocator: &mut SystemAllocator, size: u64) -> Result<GuestAddress> {
331         let addr = match self {
332             VmMemoryDestination::ExistingAllocation { allocation, offset } => allocator
333                 .mmio_allocator(MmioType::High)
334                 .address_from_pci_offset(allocation, offset, size)
335                 .map_err(|_e| SysError::new(EINVAL))?,
336             VmMemoryDestination::NewAllocation => {
337                 let alloc = allocator.get_anon_alloc();
338                 allocator
339                     .mmio_allocator(MmioType::High)
340                     .allocate(size, alloc, "vmcontrol_register_memory".to_string())
341                     .map_err(|_e| SysError::new(EINVAL))?
342             }
343             VmMemoryDestination::GuestPhysicalAddress(gpa) => gpa,
344         };
345         Ok(GuestAddress(addr))
346     }
347 }
348 
349 #[derive(Serialize, Deserialize)]
350 pub enum VmMemoryRequest {
351     RegisterMemory {
352         /// Source of the memory to register (mapped file descriptor, shared memory region, etc.)
353         source: VmMemorySource,
354         /// Where to map the memory in the guest.
355         dest: VmMemoryDestination,
356         /// Whether to map the memory read only (true) or read-write (false).
357         read_only: bool,
358     },
359     /// Allocate GPU buffer of a given size/format and register the memory into guest address space.
360     /// The response variant is `VmResponse::AllocateAndRegisterGpuMemory`
361     AllocateAndRegisterGpuMemory {
362         width: u32,
363         height: u32,
364         format: u32,
365         /// Where to map the memory in the guest.
366         dest: VmMemoryDestination,
367     },
368     /// Unregister the given memory slot that was previously registered with `RegisterMemory`.
369     UnregisterMemory(MemSlot),
370 }
371 
372 impl VmMemoryRequest {
373     /// Executes this request on the given Vm.
374     ///
375     /// # Arguments
376     /// * `vm` - The `Vm` to perform the request on.
377     /// * `allocator` - Used to allocate addresses.
378     ///
379     /// This does not return a result, instead encapsulating the success or failure in a
380     /// `VmMemoryResponse` with the intended purpose of sending the response back over the socket
381     /// that received this `VmMemoryResponse`.
execute( self, vm: &mut impl Vm, sys_allocator: &mut SystemAllocator, map_request: Arc<Mutex<Option<ExternalMapping>>>, gralloc: &mut RutabagaGralloc, ) -> VmMemoryResponse382     pub fn execute(
383         self,
384         vm: &mut impl Vm,
385         sys_allocator: &mut SystemAllocator,
386         map_request: Arc<Mutex<Option<ExternalMapping>>>,
387         gralloc: &mut RutabagaGralloc,
388     ) -> VmMemoryResponse {
389         use self::VmMemoryRequest::*;
390         match self {
391             RegisterMemory {
392                 source,
393                 dest,
394                 read_only,
395             } => {
396                 let (mapped_region, size) = match source.map(map_request, gralloc, read_only) {
397                     Ok((region, size)) => (region, size),
398                     Err(e) => return VmMemoryResponse::Err(e),
399                 };
400 
401                 let guest_addr = match dest.allocate(sys_allocator, size) {
402                     Ok(addr) => addr,
403                     Err(e) => return VmMemoryResponse::Err(e),
404                 };
405 
406                 let slot = match vm.add_memory_region(guest_addr, mapped_region, read_only, false) {
407                     Ok(slot) => slot,
408                     Err(e) => return VmMemoryResponse::Err(e),
409                 };
410                 let pfn = guest_addr.0 >> 12;
411                 VmMemoryResponse::RegisterMemory { pfn, slot }
412             }
413             UnregisterMemory(slot) => match vm.remove_memory_region(slot) {
414                 Ok(_) => VmMemoryResponse::Ok,
415                 Err(e) => VmMemoryResponse::Err(e),
416             },
417             AllocateAndRegisterGpuMemory {
418                 width,
419                 height,
420                 format,
421                 dest,
422             } => {
423                 let (mapped_region, size, descriptor, gpu_desc) =
424                     match Self::allocate_gpu_memory(gralloc, width, height, format) {
425                         Ok(v) => v,
426                         Err(e) => return VmMemoryResponse::Err(e),
427                     };
428 
429                 let guest_addr = match dest.allocate(sys_allocator, size) {
430                     Ok(addr) => addr,
431                     Err(e) => return VmMemoryResponse::Err(e),
432                 };
433 
434                 let slot = match vm.add_memory_region(guest_addr, mapped_region, false, false) {
435                     Ok(slot) => slot,
436                     Err(e) => return VmMemoryResponse::Err(e),
437                 };
438                 let pfn = guest_addr.0 >> 12;
439 
440                 VmMemoryResponse::AllocateAndRegisterGpuMemory {
441                     descriptor,
442                     pfn,
443                     slot,
444                     desc: gpu_desc,
445                 }
446             }
447         }
448     }
449 
allocate_gpu_memory( gralloc: &mut RutabagaGralloc, width: u32, height: u32, format: u32, ) -> Result<(Box<dyn MappedRegion>, u64, SafeDescriptor, GpuMemoryDesc)>450     fn allocate_gpu_memory(
451         gralloc: &mut RutabagaGralloc,
452         width: u32,
453         height: u32,
454         format: u32,
455     ) -> Result<(Box<dyn MappedRegion>, u64, SafeDescriptor, GpuMemoryDesc)> {
456         let img = ImageAllocationInfo {
457             width,
458             height,
459             drm_format: DrmFormat::from(format),
460             // Linear layout is a requirement as virtio wayland guest expects
461             // this for CPU access to the buffer. Scanout and texturing are
462             // optional as the consumer (wayland compositor) is expected to
463             // fall-back to a less efficient meachnisms for presentation if
464             // neccesary. In practice, linear buffers for commonly used formats
465             // will also support scanout and texturing.
466             flags: RutabagaGrallocFlags::empty().use_linear(true),
467         };
468 
469         let reqs = match gralloc.get_image_memory_requirements(img) {
470             Ok(reqs) => reqs,
471             Err(e) => {
472                 error!("gralloc failed to get image requirements: {}", e);
473                 return Err(SysError::new(EINVAL));
474             }
475         };
476 
477         let handle = match gralloc.allocate_memory(reqs) {
478             Ok(handle) => handle,
479             Err(e) => {
480                 error!("gralloc failed to allocate memory: {}", e);
481                 return Err(SysError::new(EINVAL));
482             }
483         };
484 
485         let mut desc = GpuMemoryDesc::default();
486         for i in 0..3 {
487             desc.planes[i] = GpuMemoryPlaneDesc {
488                 stride: reqs.strides[i],
489                 offset: reqs.offsets[i],
490             }
491         }
492 
493         // Safe because ownership is transferred to SafeDescriptor via
494         // into_raw_descriptor
495         let descriptor =
496             unsafe { SafeDescriptor::from_raw_descriptor(handle.os_handle.into_raw_descriptor()) };
497 
498         let mapped_region = map_descriptor(&descriptor, 0, reqs.size, false)?;
499         Ok((mapped_region, reqs.size, descriptor, desc))
500     }
501 }
502 
503 #[derive(Serialize, Deserialize, Debug)]
504 pub enum VmMemoryResponse {
505     /// The request to register memory into guest address space was successfully done at page frame
506     /// number `pfn` and memory slot number `slot`.
507     RegisterMemory {
508         pfn: u64,
509         slot: MemSlot,
510     },
511     /// The request to allocate and register GPU memory into guest address space was successfully
512     /// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`.
513     AllocateAndRegisterGpuMemory {
514         descriptor: SafeDescriptor,
515         pfn: u64,
516         slot: MemSlot,
517         desc: GpuMemoryDesc,
518     },
519     Ok,
520     Err(SysError),
521 }
522 
523 #[derive(Serialize, Deserialize, Debug)]
524 pub enum VmIrqRequest {
525     /// Allocate one gsi, and associate gsi to irqfd with register_irqfd()
526     AllocateOneMsi {
527         irqfd: Event,
528         device_id: u32,
529         queue_id: usize,
530         device_name: String,
531     },
532     /// Add one msi route entry into the IRQ chip.
533     AddMsiRoute {
534         gsi: u32,
535         msi_address: u64,
536         msi_data: u32,
537     },
538     // unregister_irqfs() and release gsi
539     ReleaseOneIrq {
540         gsi: u32,
541         irqfd: Event,
542     },
543 }
544 
545 /// Data to set up an IRQ event or IRQ route on the IRQ chip.
546 /// VmIrqRequest::execute can't take an `IrqChip` argument, because of a dependency cycle between
547 /// devices and vm_control, so it takes a Fn that processes an `IrqSetup`.
548 pub enum IrqSetup<'a> {
549     Event(u32, &'a Event, u32, usize, String),
550     Route(IrqRoute),
551     UnRegister(u32, &'a Event),
552 }
553 
554 impl VmIrqRequest {
555     /// Executes this request on the given Vm.
556     ///
557     /// # Arguments
558     /// * `set_up_irq` - A function that applies an `IrqSetup` to an IRQ chip.
559     ///
560     /// This does not return a result, instead encapsulating the success or failure in a
561     /// `VmIrqResponse` with the intended purpose of sending the response back over the socket
562     /// that received this `VmIrqResponse`.
execute<F>(&self, set_up_irq: F, sys_allocator: &mut SystemAllocator) -> VmIrqResponse where F: FnOnce(IrqSetup) -> Result<()>,563     pub fn execute<F>(&self, set_up_irq: F, sys_allocator: &mut SystemAllocator) -> VmIrqResponse
564     where
565         F: FnOnce(IrqSetup) -> Result<()>,
566     {
567         use self::VmIrqRequest::*;
568         match *self {
569             AllocateOneMsi {
570                 ref irqfd,
571                 device_id,
572                 queue_id,
573                 ref device_name,
574             } => {
575                 if let Some(irq_num) = sys_allocator.allocate_irq() {
576                     match set_up_irq(IrqSetup::Event(
577                         irq_num,
578                         irqfd,
579                         device_id,
580                         queue_id,
581                         device_name.clone(),
582                     )) {
583                         Ok(_) => VmIrqResponse::AllocateOneMsi { gsi: irq_num },
584                         Err(e) => VmIrqResponse::Err(e),
585                     }
586                 } else {
587                     VmIrqResponse::Err(SysError::new(EINVAL))
588                 }
589             }
590             AddMsiRoute {
591                 gsi,
592                 msi_address,
593                 msi_data,
594             } => {
595                 let route = IrqRoute {
596                     gsi,
597                     source: IrqSource::Msi {
598                         address: msi_address,
599                         data: msi_data,
600                     },
601                 };
602                 match set_up_irq(IrqSetup::Route(route)) {
603                     Ok(_) => VmIrqResponse::Ok,
604                     Err(e) => VmIrqResponse::Err(e),
605                 }
606             }
607             ReleaseOneIrq { gsi, ref irqfd } => {
608                 let _ = set_up_irq(IrqSetup::UnRegister(gsi, irqfd));
609                 sys_allocator.release_irq(gsi);
610                 VmIrqResponse::Ok
611             }
612         }
613     }
614 }
615 
616 #[derive(Serialize, Deserialize, Debug)]
617 pub enum VmIrqResponse {
618     AllocateOneMsi { gsi: u32 },
619     Ok,
620     Err(SysError),
621 }
622 
623 #[derive(Serialize, Deserialize, Debug)]
624 pub enum VmMsyncRequest {
625     /// Flush the content of a memory mapping to its backing file.
626     /// `slot` selects the arena (as returned by `Vm::add_mmap_arena`).
627     /// `offset` is the offset of the mapping to sync within the arena.
628     /// `size` is the size of the mapping to sync within the arena.
629     MsyncArena {
630         slot: MemSlot,
631         offset: usize,
632         size: usize,
633     },
634 }
635 
636 #[derive(Serialize, Deserialize, Debug)]
637 pub enum VmMsyncResponse {
638     Ok,
639     Err(SysError),
640 }
641 
642 impl VmMsyncRequest {
643     /// Executes this request on the given Vm.
644     ///
645     /// # Arguments
646     /// * `vm` - The `Vm` to perform the request on.
647     ///
648     /// This does not return a result, instead encapsulating the success or failure in a
649     /// `VmMsyncResponse` with the intended purpose of sending the response back over the socket
650     /// that received this `VmMsyncResponse`.
execute(&self, vm: &mut impl Vm) -> VmMsyncResponse651     pub fn execute(&self, vm: &mut impl Vm) -> VmMsyncResponse {
652         use self::VmMsyncRequest::*;
653         match *self {
654             MsyncArena { slot, offset, size } => match vm.msync_memory_region(slot, offset, size) {
655                 Ok(()) => VmMsyncResponse::Ok,
656                 Err(e) => VmMsyncResponse::Err(e),
657             },
658         }
659     }
660 }
661 
662 #[derive(Serialize, Deserialize, Debug)]
663 pub enum BatControlResult {
664     Ok,
665     NoBatDevice,
666     NoSuchHealth,
667     NoSuchProperty,
668     NoSuchStatus,
669     NoSuchBatType,
670     StringParseIntErr,
671 }
672 
673 impl Display for BatControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result674     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
675         use self::BatControlResult::*;
676 
677         match self {
678             Ok => write!(f, "Setting battery property successfully"),
679             NoBatDevice => write!(f, "No battery device created"),
680             NoSuchHealth => write!(f, "Invalid Battery health setting. Only support: unknown/good/overheat/dead/overvoltage/unexpectedfailure/cold/watchdogtimerexpire/safetytimerexpire/overcurrent"),
681             NoSuchProperty => write!(f, "Battery doesn't have such property. Only support: status/health/present/capacity/aconline"),
682             NoSuchStatus => write!(f, "Invalid Battery status setting. Only support: unknown/charging/discharging/notcharging/full"),
683             NoSuchBatType => write!(f, "Invalid Battery type setting. Only support: goldfish"),
684             StringParseIntErr => write!(f, "Battery property target ParseInt error"),
685         }
686     }
687 }
688 
689 #[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
690 pub enum BatteryType {
691     Goldfish,
692 }
693 
694 impl Default for BatteryType {
default() -> Self695     fn default() -> Self {
696         BatteryType::Goldfish
697     }
698 }
699 
700 impl FromStr for BatteryType {
701     type Err = BatControlResult;
702 
from_str(s: &str) -> StdResult<Self, Self::Err>703     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
704         match s {
705             "goldfish" => Ok(BatteryType::Goldfish),
706             _ => Err(BatControlResult::NoSuchBatType),
707         }
708     }
709 }
710 
711 #[derive(Serialize, Deserialize, Debug)]
712 pub enum BatProperty {
713     Status,
714     Health,
715     Present,
716     Capacity,
717     ACOnline,
718 }
719 
720 impl FromStr for BatProperty {
721     type Err = BatControlResult;
722 
from_str(s: &str) -> StdResult<Self, Self::Err>723     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
724         match s {
725             "status" => Ok(BatProperty::Status),
726             "health" => Ok(BatProperty::Health),
727             "present" => Ok(BatProperty::Present),
728             "capacity" => Ok(BatProperty::Capacity),
729             "aconline" => Ok(BatProperty::ACOnline),
730             _ => Err(BatControlResult::NoSuchProperty),
731         }
732     }
733 }
734 
735 #[derive(Serialize, Deserialize, Debug)]
736 pub enum BatStatus {
737     Unknown,
738     Charging,
739     DisCharging,
740     NotCharging,
741     Full,
742 }
743 
744 impl BatStatus {
new(status: String) -> std::result::Result<Self, BatControlResult>745     pub fn new(status: String) -> std::result::Result<Self, BatControlResult> {
746         match status.as_str() {
747             "unknown" => Ok(BatStatus::Unknown),
748             "charging" => Ok(BatStatus::Charging),
749             "discharging" => Ok(BatStatus::DisCharging),
750             "notcharging" => Ok(BatStatus::NotCharging),
751             "full" => Ok(BatStatus::Full),
752             _ => Err(BatControlResult::NoSuchStatus),
753         }
754     }
755 }
756 
757 impl FromStr for BatStatus {
758     type Err = BatControlResult;
759 
from_str(s: &str) -> StdResult<Self, Self::Err>760     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
761         match s {
762             "unknown" => Ok(BatStatus::Unknown),
763             "charging" => Ok(BatStatus::Charging),
764             "discharging" => Ok(BatStatus::DisCharging),
765             "notcharging" => Ok(BatStatus::NotCharging),
766             "full" => Ok(BatStatus::Full),
767             _ => Err(BatControlResult::NoSuchStatus),
768         }
769     }
770 }
771 
772 impl From<BatStatus> for u32 {
from(status: BatStatus) -> Self773     fn from(status: BatStatus) -> Self {
774         status as u32
775     }
776 }
777 
778 #[derive(Serialize, Deserialize, Debug)]
779 pub enum BatHealth {
780     Unknown,
781     Good,
782     Overheat,
783     Dead,
784     OverVoltage,
785     UnexpectedFailure,
786     Cold,
787     WatchdogTimerExpire,
788     SafetyTimerExpire,
789     OverCurrent,
790 }
791 
792 impl FromStr for BatHealth {
793     type Err = BatControlResult;
794 
from_str(s: &str) -> StdResult<Self, Self::Err>795     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
796         match s {
797             "unknown" => Ok(BatHealth::Unknown),
798             "good" => Ok(BatHealth::Good),
799             "overheat" => Ok(BatHealth::Overheat),
800             "dead" => Ok(BatHealth::Dead),
801             "overvoltage" => Ok(BatHealth::OverVoltage),
802             "unexpectedfailure" => Ok(BatHealth::UnexpectedFailure),
803             "cold" => Ok(BatHealth::Cold),
804             "watchdogtimerexpire" => Ok(BatHealth::WatchdogTimerExpire),
805             "safetytimerexpire" => Ok(BatHealth::SafetyTimerExpire),
806             "overcurrent" => Ok(BatHealth::OverCurrent),
807             _ => Err(BatControlResult::NoSuchHealth),
808         }
809     }
810 }
811 
812 impl From<BatHealth> for u32 {
from(status: BatHealth) -> Self813     fn from(status: BatHealth) -> Self {
814         status as u32
815     }
816 }
817 
818 #[derive(Serialize, Deserialize, Debug)]
819 pub enum BatControlCommand {
820     SetStatus(BatStatus),
821     SetHealth(BatHealth),
822     SetPresent(u32),
823     SetCapacity(u32),
824     SetACOnline(u32),
825 }
826 
827 impl BatControlCommand {
new(property: String, target: String) -> std::result::Result<Self, BatControlResult>828     pub fn new(property: String, target: String) -> std::result::Result<Self, BatControlResult> {
829         let cmd = property.parse::<BatProperty>()?;
830         match cmd {
831             BatProperty::Status => Ok(BatControlCommand::SetStatus(target.parse::<BatStatus>()?)),
832             BatProperty::Health => Ok(BatControlCommand::SetHealth(target.parse::<BatHealth>()?)),
833             BatProperty::Present => Ok(BatControlCommand::SetPresent(
834                 target
835                     .parse::<u32>()
836                     .map_err(|_| BatControlResult::StringParseIntErr)?,
837             )),
838             BatProperty::Capacity => Ok(BatControlCommand::SetCapacity(
839                 target
840                     .parse::<u32>()
841                     .map_err(|_| BatControlResult::StringParseIntErr)?,
842             )),
843             BatProperty::ACOnline => Ok(BatControlCommand::SetACOnline(
844                 target
845                     .parse::<u32>()
846                     .map_err(|_| BatControlResult::StringParseIntErr)?,
847             )),
848         }
849     }
850 }
851 
852 /// Used for VM to control battery properties.
853 pub struct BatControl {
854     pub type_: BatteryType,
855     pub control_tube: Tube,
856 }
857 
858 #[derive(Serialize, Deserialize, Debug)]
859 pub enum FsMappingRequest {
860     /// Create an anonymous memory mapping that spans the entire region described by `Alloc`.
861     AllocateSharedMemoryRegion(Alloc),
862     /// Create a memory mapping.
863     CreateMemoryMapping {
864         /// The slot for a MemoryMappingArena, previously returned by a response to an
865         /// `AllocateSharedMemoryRegion` request.
866         slot: u32,
867         /// The file descriptor that should be mapped.
868         fd: SafeDescriptor,
869         /// The size of the mapping.
870         size: usize,
871         /// The offset into the file from where the mapping should start.
872         file_offset: u64,
873         /// The memory protection to be used for the mapping.  Protections other than readable and
874         /// writable will be silently dropped.
875         prot: u32,
876         /// The offset into the shared memory region where the mapping should be placed.
877         mem_offset: usize,
878     },
879     /// Remove a memory mapping.
880     RemoveMemoryMapping {
881         /// The slot for a MemoryMappingArena.
882         slot: u32,
883         /// The offset into the shared memory region.
884         offset: usize,
885         /// The size of the mapping.
886         size: usize,
887     },
888 }
889 
890 impl FsMappingRequest {
execute(&self, vm: &mut dyn Vm, allocator: &mut SystemAllocator) -> VmResponse891     pub fn execute(&self, vm: &mut dyn Vm, allocator: &mut SystemAllocator) -> VmResponse {
892         use self::FsMappingRequest::*;
893         match *self {
894             AllocateSharedMemoryRegion(Alloc::PciBar {
895                 bus,
896                 dev,
897                 func,
898                 bar,
899             }) => {
900                 match allocator
901                     .mmio_allocator(MmioType::High)
902                     .get(&Alloc::PciBar {
903                         bus,
904                         dev,
905                         func,
906                         bar,
907                     }) {
908                     Some((addr, length, _)) => {
909                         let arena = match MemoryMappingArena::new(*length as usize) {
910                             Ok(a) => a,
911                             Err(MmapError::SystemCallFailed(e)) => return VmResponse::Err(e),
912                             _ => return VmResponse::Err(SysError::new(EINVAL)),
913                         };
914 
915                         match vm.add_memory_region(
916                             GuestAddress(*addr),
917                             Box::new(arena),
918                             false,
919                             false,
920                         ) {
921                             Ok(slot) => VmResponse::RegisterMemory {
922                                 pfn: addr >> 12,
923                                 slot,
924                             },
925                             Err(e) => VmResponse::Err(e),
926                         }
927                     }
928                     None => VmResponse::Err(SysError::new(EINVAL)),
929                 }
930             }
931             CreateMemoryMapping {
932                 slot,
933                 ref fd,
934                 size,
935                 file_offset,
936                 prot,
937                 mem_offset,
938             } => {
939                 match vm.add_fd_mapping(
940                     slot,
941                     mem_offset,
942                     size,
943                     fd,
944                     file_offset,
945                     Protection::from(prot as c_int & (libc::PROT_READ | libc::PROT_WRITE)),
946                 ) {
947                     Ok(()) => VmResponse::Ok,
948                     Err(e) => VmResponse::Err(e),
949                 }
950             }
951             RemoveMemoryMapping { slot, offset, size } => {
952                 match vm.remove_mapping(slot, offset, size) {
953                     Ok(()) => VmResponse::Ok,
954                     Err(e) => VmResponse::Err(e),
955                 }
956             }
957             _ => VmResponse::Err(SysError::new(EINVAL)),
958         }
959     }
960 }
961 /// A request to the main process to perform some operation on the VM.
962 ///
963 /// Unless otherwise noted, each request should expect a `VmResponse::Ok` to be received on success.
964 #[derive(Serialize, Deserialize, Debug)]
965 pub enum VmRequest {
966     /// Break the VM's run loop and exit.
967     Exit,
968     /// Trigger a power button event in the guest.
969     Powerbtn,
970     /// Suspend the VM's VCPUs until resume.
971     Suspend,
972     /// Resume the VM's VCPUs that were previously suspended.
973     Resume,
974     /// Inject a general-purpose event.
975     Gpe(u32),
976     /// Make the VM's RT VCPU real-time.
977     MakeRT,
978     /// Command for balloon driver.
979     BalloonCommand(BalloonControlCommand),
980     /// Send a command to a disk chosen by `disk_index`.
981     /// `disk_index` is a 0-based count of `--disk`, `--rwdisk`, and `-r` command-line options.
982     DiskCommand {
983         disk_index: usize,
984         command: DiskControlCommand,
985     },
986     /// Command to use controller.
987     UsbCommand(UsbControlCommand),
988     /// Command to set battery.
989     BatCommand(BatteryType, BatControlCommand),
990     /// Command to add/remove vfio pci device
991     VfioCommand { vfio_path: PathBuf, add: bool },
992 }
993 
map_descriptor( descriptor: &dyn AsRawDescriptor, offset: u64, size: u64, read_only: bool, ) -> Result<Box<dyn MappedRegion>>994 fn map_descriptor(
995     descriptor: &dyn AsRawDescriptor,
996     offset: u64,
997     size: u64,
998     read_only: bool,
999 ) -> Result<Box<dyn MappedRegion>> {
1000     let size: usize = size.try_into().map_err(|_e| SysError::new(ERANGE))?;
1001     let prot = if read_only {
1002         Protection::read()
1003     } else {
1004         Protection::read_write()
1005     };
1006     match MemoryMappingBuilder::new(size)
1007         .from_descriptor(descriptor)
1008         .offset(offset)
1009         .protection(prot)
1010         .build()
1011     {
1012         Ok(mmap) => Ok(Box::new(mmap)),
1013         Err(MmapError::SystemCallFailed(e)) => Err(e),
1014         _ => Err(SysError::new(EINVAL)),
1015     }
1016 }
1017 
1018 impl VmRequest {
1019     /// Executes this request on the given Vm and other mutable state.
1020     ///
1021     /// This does not return a result, instead encapsulating the success or failure in a
1022     /// `VmResponse` with the intended purpose of sending the response back over the  socket that
1023     /// received this `VmRequest`.
execute( &self, run_mode: &mut Option<VmRunMode>, balloon_host_tube: Option<&Tube>, balloon_stats_id: &mut u64, disk_host_tubes: &[Tube], pm: &mut Option<Arc<Mutex<dyn PmResource>>>, usb_control_tube: Option<&Tube>, bat_control: &mut Option<BatControl>, vcpu_handles: &[(JoinHandle<()>, mpsc::Sender<VcpuControl>)], ) -> VmResponse1024     pub fn execute(
1025         &self,
1026         run_mode: &mut Option<VmRunMode>,
1027         balloon_host_tube: Option<&Tube>,
1028         balloon_stats_id: &mut u64,
1029         disk_host_tubes: &[Tube],
1030         pm: &mut Option<Arc<Mutex<dyn PmResource>>>,
1031         usb_control_tube: Option<&Tube>,
1032         bat_control: &mut Option<BatControl>,
1033         vcpu_handles: &[(JoinHandle<()>, mpsc::Sender<VcpuControl>)],
1034     ) -> VmResponse {
1035         match *self {
1036             VmRequest::Exit => {
1037                 *run_mode = Some(VmRunMode::Exiting);
1038                 VmResponse::Ok
1039             }
1040             VmRequest::Powerbtn => {
1041                 if pm.is_some() {
1042                     pm.as_ref().unwrap().lock().pwrbtn_evt();
1043                     VmResponse::Ok
1044                 } else {
1045                     error!("{:#?} not supported", *self);
1046                     VmResponse::Err(SysError::new(ENOTSUP))
1047                 }
1048             }
1049             VmRequest::Suspend => {
1050                 *run_mode = Some(VmRunMode::Suspending);
1051                 VmResponse::Ok
1052             }
1053             VmRequest::Resume => {
1054                 *run_mode = Some(VmRunMode::Running);
1055                 VmResponse::Ok
1056             }
1057             VmRequest::Gpe(gpe) => {
1058                 if pm.is_some() {
1059                     pm.as_ref().unwrap().lock().gpe_evt(gpe);
1060                     VmResponse::Ok
1061                 } else {
1062                     error!("{:#?} not supported", *self);
1063                     VmResponse::Err(SysError::new(ENOTSUP))
1064                 }
1065             }
1066             VmRequest::MakeRT => {
1067                 for (handle, channel) in vcpu_handles {
1068                     if let Err(e) = channel.send(VcpuControl::MakeRT) {
1069                         error!("failed to send MakeRT: {}", e);
1070                     }
1071                     let _ = handle.kill(SIGRTMIN() + 0);
1072                 }
1073                 VmResponse::Ok
1074             }
1075             VmRequest::BalloonCommand(BalloonControlCommand::Adjust { num_bytes }) => {
1076                 if let Some(balloon_host_tube) = balloon_host_tube {
1077                     match balloon_host_tube.send(&BalloonTubeCommand::Adjust {
1078                         num_bytes,
1079                         allow_failure: false,
1080                     }) {
1081                         Ok(_) => VmResponse::Ok,
1082                         Err(_) => VmResponse::Err(SysError::last()),
1083                     }
1084                 } else {
1085                     VmResponse::Err(SysError::new(ENOTSUP))
1086                 }
1087             }
1088             VmRequest::BalloonCommand(BalloonControlCommand::Stats) => {
1089                 if let Some(balloon_host_tube) = balloon_host_tube {
1090                     // NB: There are a few reasons stale balloon stats could be left
1091                     // in balloon_host_tube:
1092                     //  - the send succeeds, but the recv fails because the device
1093                     //      is not ready yet. So when the device is ready, there are
1094                     //      extra stats requests queued.
1095                     //  - the send succeed, but the recv times out. When the device
1096                     //      does return the stats, there will be no consumer.
1097                     //
1098                     // To guard against this, add an `id` to the stats request. If
1099                     // the id returned to us doesn't match, we keep trying to read
1100                     // until it does.
1101                     *balloon_stats_id = (*balloon_stats_id).wrapping_add(1);
1102                     let sent_id = *balloon_stats_id;
1103                     match balloon_host_tube.send(&BalloonTubeCommand::Stats { id: sent_id }) {
1104                         Ok(_) => {
1105                             loop {
1106                                 match balloon_host_tube.recv() {
1107                                     Ok(BalloonTubeResult::Stats {
1108                                         stats,
1109                                         balloon_actual,
1110                                         id,
1111                                     }) => {
1112                                         if sent_id != id {
1113                                             // Keep trying to get the fresh stats.
1114                                             continue;
1115                                         }
1116                                         break VmResponse::BalloonStats {
1117                                             stats,
1118                                             balloon_actual,
1119                                         };
1120                                     }
1121                                     Err(e) => {
1122                                         error!("balloon socket recv failed: {}", e);
1123                                         break VmResponse::Err(SysError::last());
1124                                     }
1125                                     Ok(BalloonTubeResult::Adjusted { .. }) => {
1126                                         unreachable!("unexpected adjusted response")
1127                                     }
1128                                 }
1129                             }
1130                         }
1131                         Err(_) => VmResponse::Err(SysError::last()),
1132                     }
1133                 } else {
1134                     VmResponse::Err(SysError::new(ENOTSUP))
1135                 }
1136             }
1137             VmRequest::DiskCommand {
1138                 disk_index,
1139                 ref command,
1140             } => {
1141                 // Forward the request to the block device process via its control socket.
1142                 if let Some(sock) = disk_host_tubes.get(disk_index) {
1143                     if let Err(e) = sock.send(command) {
1144                         error!("disk socket send failed: {}", e);
1145                         VmResponse::Err(SysError::new(EINVAL))
1146                     } else {
1147                         match sock.recv() {
1148                             Ok(DiskControlResult::Ok) => VmResponse::Ok,
1149                             Ok(DiskControlResult::Err(e)) => VmResponse::Err(e),
1150                             Err(e) => {
1151                                 error!("disk socket recv failed: {}", e);
1152                                 VmResponse::Err(SysError::new(EINVAL))
1153                             }
1154                         }
1155                     }
1156                 } else {
1157                     VmResponse::Err(SysError::new(ENODEV))
1158                 }
1159             }
1160             VmRequest::UsbCommand(ref cmd) => {
1161                 let usb_control_tube = match usb_control_tube {
1162                     Some(t) => t,
1163                     None => {
1164                         error!("attempted to execute USB request without control tube");
1165                         return VmResponse::Err(SysError::new(ENODEV));
1166                     }
1167                 };
1168                 let res = usb_control_tube.send(cmd);
1169                 if let Err(e) = res {
1170                     error!("fail to send command to usb control socket: {}", e);
1171                     return VmResponse::Err(SysError::new(EIO));
1172                 }
1173                 match usb_control_tube.recv() {
1174                     Ok(response) => VmResponse::UsbResponse(response),
1175                     Err(e) => {
1176                         error!("fail to recv command from usb control socket: {}", e);
1177                         VmResponse::Err(SysError::new(EIO))
1178                     }
1179                 }
1180             }
1181             VmRequest::BatCommand(type_, ref cmd) => {
1182                 match bat_control {
1183                     Some(battery) => {
1184                         if battery.type_ != type_ {
1185                             error!("ignored battery command due to battery type: expected {:?}, got {:?}", battery.type_, type_);
1186                             return VmResponse::Err(SysError::new(EINVAL));
1187                         }
1188 
1189                         let res = battery.control_tube.send(cmd);
1190                         if let Err(e) = res {
1191                             error!("fail to send command to bat control socket: {}", e);
1192                             return VmResponse::Err(SysError::new(EIO));
1193                         }
1194 
1195                         match battery.control_tube.recv() {
1196                             Ok(response) => VmResponse::BatResponse(response),
1197                             Err(e) => {
1198                                 error!("fail to recv command from bat control socket: {}", e);
1199                                 VmResponse::Err(SysError::new(EIO))
1200                             }
1201                         }
1202                     }
1203                     None => VmResponse::BatResponse(BatControlResult::NoBatDevice),
1204                 }
1205             }
1206             VmRequest::VfioCommand {
1207                 vfio_path: _,
1208                 add: _,
1209             } => VmResponse::Ok,
1210         }
1211     }
1212 }
1213 
1214 /// Indication of success or failure of a `VmRequest`.
1215 ///
1216 /// Success is usually indicated `VmResponse::Ok` unless there is data associated with the response.
1217 #[derive(Serialize, Deserialize, Debug)]
1218 pub enum VmResponse {
1219     /// Indicates the request was executed successfully.
1220     Ok,
1221     /// Indicates the request encountered some error during execution.
1222     Err(SysError),
1223     /// The request to register memory into guest address space was successfully done at page frame
1224     /// number `pfn` and memory slot number `slot`.
1225     RegisterMemory { pfn: u64, slot: u32 },
1226     /// The request to allocate and register GPU memory into guest address space was successfully
1227     /// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`.
1228     AllocateAndRegisterGpuMemory {
1229         descriptor: SafeDescriptor,
1230         pfn: u64,
1231         slot: u32,
1232         desc: GpuMemoryDesc,
1233     },
1234     /// Results of balloon control commands.
1235     BalloonStats {
1236         stats: BalloonStats,
1237         balloon_actual: u64,
1238     },
1239     /// Results of usb control commands.
1240     UsbResponse(UsbControlResult),
1241     /// Results of battery control commands.
1242     BatResponse(BatControlResult),
1243 }
1244 
1245 impl Display for VmResponse {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1246     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1247         use self::VmResponse::*;
1248 
1249         match self {
1250             Ok => write!(f, "ok"),
1251             Err(e) => write!(f, "error: {}", e),
1252             RegisterMemory { pfn, slot } => write!(
1253                 f,
1254                 "memory registered to page frame number {:#x} and memory slot {}",
1255                 pfn, slot
1256             ),
1257             AllocateAndRegisterGpuMemory { pfn, slot, .. } => write!(
1258                 f,
1259                 "gpu memory allocated and registered to page frame number {:#x} and memory slot {}",
1260                 pfn, slot
1261             ),
1262             VmResponse::BalloonStats {
1263                 stats,
1264                 balloon_actual,
1265             } => {
1266                 write!(
1267                     f,
1268                     "stats: {}\nballoon_actual: {}",
1269                     serde_json::to_string_pretty(&stats)
1270                         .unwrap_or_else(|_| "invalid_response".to_string()),
1271                     balloon_actual
1272                 )
1273             }
1274             UsbResponse(result) => write!(f, "usb control request get result {:?}", result),
1275             BatResponse(result) => write!(f, "{}", result),
1276         }
1277     }
1278 }
1279 
1280 #[sorted]
1281 #[derive(Error, Debug)]
1282 pub enum VirtioIOMMUVfioError {
1283     #[error("socket failed")]
1284     SocketFailed,
1285     #[error("unexpected response: {0}")]
1286     UnexpectedResponse(VirtioIOMMUResponse),
1287     #[error("unknown command: `{0}`")]
1288     UnknownCommand(String),
1289     #[error("{0}")]
1290     VfioControl(VirtioIOMMUVfioResult),
1291 }
1292 
1293 #[derive(Serialize, Deserialize, Debug)]
1294 pub enum VirtioIOMMUVfioCommand {
1295     // Add the vfio device attached to virtio-iommu.
1296     VfioDeviceAdd {
1297         endpoint_addr: u32,
1298         #[serde(with = "with_as_descriptor")]
1299         container: File,
1300     },
1301     // Delete the vfio device attached to virtio-iommu.
1302     VfioDeviceDel {
1303         endpoint_addr: u32,
1304     },
1305 }
1306 
1307 #[derive(Serialize, Deserialize, Debug)]
1308 pub enum VirtioIOMMUVfioResult {
1309     Ok,
1310     NotInPCIRanges,
1311     NoAvailableContainer,
1312     NoSuchDevice,
1313 }
1314 
1315 impl Display for VirtioIOMMUVfioResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1316     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1317         use self::VirtioIOMMUVfioResult::*;
1318 
1319         match self {
1320             Ok => write!(f, "successfully"),
1321             NotInPCIRanges => write!(f, "not in the pci ranges of virtio-iommu"),
1322             NoAvailableContainer => write!(f, "no available vfio container"),
1323             NoSuchDevice => write!(f, "no such a vfio device"),
1324         }
1325     }
1326 }
1327 
1328 /// A request to the virtio-iommu process to perform some operations.
1329 ///
1330 /// Unless otherwise noted, each request should expect a `VirtioIOMMUResponse::Ok` to be received on
1331 /// success.
1332 #[derive(Serialize, Deserialize, Debug)]
1333 pub enum VirtioIOMMURequest {
1334     /// Command for vfio related operations.
1335     VfioCommand(VirtioIOMMUVfioCommand),
1336 }
1337 
1338 /// Indication of success or failure of a `VirtioIOMMURequest`.
1339 ///
1340 /// Success is usually indicated `VirtioIOMMUResponse::Ok` unless there is data associated with the
1341 /// response.
1342 #[derive(Serialize, Deserialize, Debug)]
1343 pub enum VirtioIOMMUResponse {
1344     /// Indicates the request was executed successfully.
1345     Ok,
1346     /// Indicates the request encountered some error during execution.
1347     Err(SysError),
1348     /// Results for Vfio commands.
1349     VfioResponse(VirtioIOMMUVfioResult),
1350 }
1351 
1352 impl Display for VirtioIOMMUResponse {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1353     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1354         use self::VirtioIOMMUResponse::*;
1355         match self {
1356             Ok => write!(f, "ok"),
1357             Err(e) => write!(f, "error: {}", e),
1358             VfioResponse(result) => write!(
1359                 f,
1360                 "The vfio-related virtio-iommu request got result: {:?}",
1361                 result
1362             ),
1363         }
1364     }
1365 }
1366 
1367 /// Send VirtioIOMMURequest without waiting for the response
virtio_iommu_request_async( iommu_control_tube: &Tube, req: &VirtioIOMMURequest, ) -> VirtioIOMMUResponse1368 pub fn virtio_iommu_request_async(
1369     iommu_control_tube: &Tube,
1370     req: &VirtioIOMMURequest,
1371 ) -> VirtioIOMMUResponse {
1372     match iommu_control_tube.send(&req) {
1373         Ok(_) => VirtioIOMMUResponse::Ok,
1374         Err(e) => {
1375             error!("virtio-iommu socket send failed: {:?}", e);
1376             VirtioIOMMUResponse::Err(SysError::last())
1377         }
1378     }
1379 }
1380 
1381 pub type VirtioIOMMURequestResult = std::result::Result<VirtioIOMMUResponse, ()>;
1382 
1383 /// Send VirtioIOMMURequest and wait to get the response
virtio_iommu_request( iommu_control_tube: &Tube, req: &VirtioIOMMURequest, ) -> VirtioIOMMURequestResult1384 pub fn virtio_iommu_request(
1385     iommu_control_tube: &Tube,
1386     req: &VirtioIOMMURequest,
1387 ) -> VirtioIOMMURequestResult {
1388     let response = match virtio_iommu_request_async(iommu_control_tube, req) {
1389         VirtioIOMMUResponse::Ok => match iommu_control_tube.recv() {
1390             Ok(response) => response,
1391             Err(e) => {
1392                 error!("virtio-iommu socket recv failed: {:?}", e);
1393                 VirtioIOMMUResponse::Err(SysError::last())
1394             }
1395         },
1396         resp => resp,
1397     };
1398     Ok(response)
1399 }
1400