• 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::fmt::{self, Display};
19 use std::fs::File;
20 use std::os::raw::c_int;
21 use std::result::Result as StdResult;
22 use std::str::FromStr;
23 use std::sync::Arc;
24 
25 use libc::{EINVAL, EIO, ENODEV};
26 use serde::{Deserialize, Serialize};
27 
28 use base::{
29     error, with_as_descriptor, AsRawDescriptor, Error as SysError, Event, ExternalMapping, Fd,
30     FromRawDescriptor, IntoRawDescriptor, MappedRegion, MemoryMappingArena, MemoryMappingBuilder,
31     MemoryMappingBuilderUnix, MmapError, Protection, Result, SafeDescriptor, SharedMemory, Tube,
32 };
33 use hypervisor::{IrqRoute, IrqSource, Vm};
34 use resources::{Alloc, MmioType, SystemAllocator};
35 use rutabaga_gfx::{
36     DrmFormat, ImageAllocationInfo, RutabagaGralloc, RutabagaGrallocFlags, RutabagaHandle,
37     VulkanInfo,
38 };
39 use sync::Mutex;
40 use vm_memory::GuestAddress;
41 
42 /// Struct that describes the offset and stride of a plane located in GPU memory.
43 #[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize)]
44 pub struct GpuMemoryPlaneDesc {
45     pub stride: u32,
46     pub offset: u32,
47 }
48 
49 /// Struct that describes a GPU memory allocation that consists of up to 3 planes.
50 #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
51 pub struct GpuMemoryDesc {
52     pub planes: [GpuMemoryPlaneDesc; 3],
53 }
54 
55 #[cfg(all(target_arch = "x86_64", feature = "gdb"))]
56 pub use crate::gdb::*;
57 pub use hypervisor::MemSlot;
58 
59 /// Control the state of a particular VM CPU.
60 #[derive(Debug)]
61 pub enum VcpuControl {
62     #[cfg(all(target_arch = "x86_64", feature = "gdb"))]
63     Debug(VcpuDebug),
64     RunState(VmRunMode),
65 }
66 
67 /// Mode of execution for the VM.
68 #[derive(Debug, Clone, PartialEq)]
69 pub enum VmRunMode {
70     /// The default run mode indicating the VCPUs are running.
71     Running,
72     /// Indicates that the VCPUs are suspending execution until the `Running` mode is set.
73     Suspending,
74     /// Indicates that the VM is exiting all processes.
75     Exiting,
76     /// Indicates that the VM is in a breakpoint waiting for the debugger to do continue.
77     Breakpoint,
78 }
79 
80 impl Display for VmRunMode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result81     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82         use self::VmRunMode::*;
83 
84         match self {
85             Running => write!(f, "running"),
86             Suspending => write!(f, "suspending"),
87             Exiting => write!(f, "exiting"),
88             Breakpoint => write!(f, "breakpoint"),
89         }
90     }
91 }
92 
93 impl Default for VmRunMode {
default() -> Self94     fn default() -> Self {
95         VmRunMode::Running
96     }
97 }
98 
99 /// The maximum number of devices that can be listed in one `UsbControlCommand`.
100 ///
101 /// This value was set to be equal to `xhci_regs::MAX_PORTS` for convenience, but it is not
102 /// necessary for correctness. Importing that value directly would be overkill because it would
103 /// require adding a big dependency for a single const.
104 pub const USB_CONTROL_MAX_PORTS: usize = 16;
105 
106 #[derive(Serialize, Deserialize, Debug)]
107 pub enum BalloonControlCommand {
108     /// Set the size of the VM's balloon.
109     Adjust {
110         num_bytes: u64,
111     },
112     Stats,
113 }
114 
115 // BalloonStats holds stats returned from the stats_queue.
116 #[derive(Default, Serialize, Deserialize, Debug)]
117 pub struct BalloonStats {
118     pub swap_in: Option<u64>,
119     pub swap_out: Option<u64>,
120     pub major_faults: Option<u64>,
121     pub minor_faults: Option<u64>,
122     pub free_memory: Option<u64>,
123     pub total_memory: Option<u64>,
124     pub available_memory: Option<u64>,
125     pub disk_caches: Option<u64>,
126     pub hugetlb_allocations: Option<u64>,
127     pub hugetlb_failures: Option<u64>,
128 }
129 
130 impl Display for BalloonStats {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result131     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132         write!(f, "{{")?;
133         if let Some(swap_in) = self.swap_in {
134             write!(f, "\n    swap_in: {}", swap_in)?;
135         }
136         if let Some(swap_out) = self.swap_out {
137             write!(f, "\n    swap_out: {}", swap_out)?;
138         }
139         if let Some(major_faults) = self.major_faults {
140             write!(f, "\n    major_faults: {}", major_faults)?;
141         }
142         if let Some(minor_faults) = self.minor_faults {
143             write!(f, "\n    minor_faults: {}", minor_faults)?;
144         }
145         if let Some(free_memory) = self.free_memory {
146             write!(f, "\n    free_memory: {}", free_memory)?;
147         }
148         if let Some(total_memory) = self.total_memory {
149             write!(f, "\n    total_memory: {}", total_memory)?;
150         }
151         if let Some(available_memory) = self.available_memory {
152             write!(f, "\n    available_memory: {}", available_memory)?;
153         }
154         if let Some(disk_caches) = self.disk_caches {
155             write!(f, "\n    disk_caches: {}", disk_caches)?;
156         }
157         if let Some(hugetlb_allocations) = self.hugetlb_allocations {
158             write!(f, "\n    hugetlb_allocations: {}", hugetlb_allocations)?;
159         }
160         if let Some(hugetlb_failures) = self.hugetlb_failures {
161             write!(f, "\n    hugetlb_failures: {}", hugetlb_failures)?;
162         }
163         write!(f, "\n}}")
164     }
165 }
166 
167 #[derive(Serialize, Deserialize, Debug)]
168 pub enum BalloonControlResult {
169     Stats {
170         stats: BalloonStats,
171         balloon_actual: u64,
172     },
173 }
174 
175 #[derive(Serialize, Deserialize, Debug)]
176 pub enum DiskControlCommand {
177     /// Resize a disk to `new_size` in bytes.
178     Resize { new_size: u64 },
179 }
180 
181 impl Display for DiskControlCommand {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result182     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183         use self::DiskControlCommand::*;
184 
185         match self {
186             Resize { new_size } => write!(f, "disk_resize {}", new_size),
187         }
188     }
189 }
190 
191 #[derive(Serialize, Deserialize, Debug)]
192 pub enum DiskControlResult {
193     Ok,
194     Err(SysError),
195 }
196 
197 #[derive(Serialize, Deserialize, Debug)]
198 pub enum UsbControlCommand {
199     AttachDevice {
200         bus: u8,
201         addr: u8,
202         vid: u16,
203         pid: u16,
204         #[serde(with = "with_as_descriptor")]
205         file: File,
206     },
207     DetachDevice {
208         port: u8,
209     },
210     ListDevice {
211         ports: [u8; USB_CONTROL_MAX_PORTS],
212     },
213 }
214 
215 #[derive(Serialize, Deserialize, Copy, Clone, Debug, Default)]
216 pub struct UsbControlAttachedDevice {
217     pub port: u8,
218     pub vendor_id: u16,
219     pub product_id: u16,
220 }
221 
222 impl UsbControlAttachedDevice {
valid(self) -> bool223     pub fn valid(self) -> bool {
224         self.port != 0
225     }
226 }
227 
228 #[derive(Serialize, Deserialize, Debug)]
229 pub enum UsbControlResult {
230     Ok { port: u8 },
231     NoAvailablePort,
232     NoSuchDevice,
233     NoSuchPort,
234     FailedToOpenDevice,
235     Devices([UsbControlAttachedDevice; USB_CONTROL_MAX_PORTS]),
236 }
237 
238 impl Display for UsbControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result239     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240         use self::UsbControlResult::*;
241 
242         match self {
243             UsbControlResult::Ok { port } => write!(f, "ok {}", port),
244             NoAvailablePort => write!(f, "no_available_port"),
245             NoSuchDevice => write!(f, "no_such_device"),
246             NoSuchPort => write!(f, "no_such_port"),
247             FailedToOpenDevice => write!(f, "failed_to_open_device"),
248             Devices(devices) => {
249                 write!(f, "devices")?;
250                 for d in devices.iter().filter(|d| d.valid()) {
251                     write!(f, " {} {:04x} {:04x}", d.port, d.vendor_id, d.product_id)?;
252                 }
253                 std::result::Result::Ok(())
254             }
255         }
256     }
257 }
258 
259 #[derive(Serialize, Deserialize)]
260 pub enum VmMemoryRequest {
261     /// Register shared memory represented by the given descriptor into guest address space.
262     /// The response variant is `VmResponse::RegisterMemory`.
263     RegisterMemory(SharedMemory),
264     /// Similiar to `VmMemoryRequest::RegisterMemory`, but doesn't allocate new address space.
265     /// Useful for cases where the address space is already allocated (PCI regions).
266     RegisterFdAtPciBarOffset(Alloc, SafeDescriptor, usize, u64),
267     /// Similar to RegisterFdAtPciBarOffset, but is for buffers in the current address space.
268     RegisterHostPointerAtPciBarOffset(Alloc, u64),
269     /// Similiar to `RegisterFdAtPciBarOffset`, but uses Vulkano to map the resource instead of
270     /// the mmap system call.
271     RegisterVulkanMemoryAtPciBarOffset {
272         alloc: Alloc,
273         descriptor: SafeDescriptor,
274         handle_type: u32,
275         memory_idx: u32,
276         physical_device_idx: u32,
277         offset: u64,
278         size: u64,
279     },
280     /// Unregister the given memory slot that was previously registered with `RegisterMemory*`.
281     UnregisterMemory(MemSlot),
282     /// Allocate GPU buffer of a given size/format and register the memory into guest address space.
283     /// The response variant is `VmResponse::AllocateAndRegisterGpuMemory`
284     AllocateAndRegisterGpuMemory {
285         width: u32,
286         height: u32,
287         format: u32,
288     },
289     /// Register mmaped memory into the hypervisor's EPT.
290     RegisterMmapMemory {
291         descriptor: SafeDescriptor,
292         size: usize,
293         offset: u64,
294         gpa: u64,
295     },
296 }
297 
298 impl VmMemoryRequest {
299     /// Executes this request on the given Vm.
300     ///
301     /// # Arguments
302     /// * `vm` - The `Vm` to perform the request on.
303     /// * `allocator` - Used to allocate addresses.
304     ///
305     /// This does not return a result, instead encapsulating the success or failure in a
306     /// `VmMemoryResponse` with the intended purpose of sending the response back over the socket
307     /// that received this `VmMemoryResponse`.
execute( self, vm: &mut impl Vm, sys_allocator: &mut SystemAllocator, map_request: Arc<Mutex<Option<ExternalMapping>>>, gralloc: &mut RutabagaGralloc, ) -> VmMemoryResponse308     pub fn execute(
309         self,
310         vm: &mut impl Vm,
311         sys_allocator: &mut SystemAllocator,
312         map_request: Arc<Mutex<Option<ExternalMapping>>>,
313         gralloc: &mut RutabagaGralloc,
314     ) -> VmMemoryResponse {
315         use self::VmMemoryRequest::*;
316         match self {
317             RegisterMemory(ref shm) => {
318                 match register_memory(vm, sys_allocator, shm, shm.size() as usize, None) {
319                     Ok((pfn, slot)) => VmMemoryResponse::RegisterMemory { pfn, slot },
320                     Err(e) => VmMemoryResponse::Err(e),
321                 }
322             }
323             RegisterFdAtPciBarOffset(alloc, ref descriptor, size, offset) => {
324                 match register_memory(vm, sys_allocator, descriptor, size, Some((alloc, offset))) {
325                     Ok((pfn, slot)) => VmMemoryResponse::RegisterMemory { pfn, slot },
326                     Err(e) => VmMemoryResponse::Err(e),
327                 }
328             }
329             UnregisterMemory(slot) => match vm.remove_memory_region(slot) {
330                 Ok(_) => VmMemoryResponse::Ok,
331                 Err(e) => VmMemoryResponse::Err(e),
332             },
333             RegisterHostPointerAtPciBarOffset(alloc, offset) => {
334                 let mem = map_request
335                     .lock()
336                     .take()
337                     .ok_or_else(|| VmMemoryResponse::Err(SysError::new(EINVAL)))
338                     .unwrap();
339 
340                 match register_host_pointer(vm, sys_allocator, Box::new(mem), (alloc, offset)) {
341                     Ok((pfn, slot)) => VmMemoryResponse::RegisterMemory { pfn, slot },
342                     Err(e) => VmMemoryResponse::Err(e),
343                 }
344             }
345             RegisterVulkanMemoryAtPciBarOffset {
346                 alloc,
347                 descriptor,
348                 handle_type,
349                 memory_idx,
350                 physical_device_idx,
351                 offset,
352                 size,
353             } => {
354                 let mapped_region = match gralloc.import_and_map(
355                     RutabagaHandle {
356                         os_handle: descriptor,
357                         handle_type,
358                     },
359                     VulkanInfo {
360                         memory_idx,
361                         physical_device_idx,
362                     },
363                     size,
364                 ) {
365                     Ok(mapped_region) => mapped_region,
366                     Err(e) => {
367                         error!("gralloc failed to import and map: {}", e);
368                         return VmMemoryResponse::Err(SysError::new(EINVAL));
369                     }
370                 };
371 
372                 match register_host_pointer(vm, sys_allocator, mapped_region, (alloc, offset)) {
373                     Ok((pfn, slot)) => VmMemoryResponse::RegisterMemory { pfn, slot },
374                     Err(e) => VmMemoryResponse::Err(e),
375                 }
376             }
377             AllocateAndRegisterGpuMemory {
378                 width,
379                 height,
380                 format,
381             } => {
382                 let img = ImageAllocationInfo {
383                     width,
384                     height,
385                     drm_format: DrmFormat::from(format),
386                     // Linear layout is a requirement as virtio wayland guest expects
387                     // this for CPU access to the buffer. Scanout and texturing are
388                     // optional as the consumer (wayland compositor) is expected to
389                     // fall-back to a less efficient meachnisms for presentation if
390                     // neccesary. In practice, linear buffers for commonly used formats
391                     // will also support scanout and texturing.
392                     flags: RutabagaGrallocFlags::empty().use_linear(true),
393                 };
394 
395                 let reqs = match gralloc.get_image_memory_requirements(img) {
396                     Ok(reqs) => reqs,
397                     Err(e) => {
398                         error!("gralloc failed to get image requirements: {}", e);
399                         return VmMemoryResponse::Err(SysError::new(EINVAL));
400                     }
401                 };
402 
403                 let handle = match gralloc.allocate_memory(reqs) {
404                     Ok(handle) => handle,
405                     Err(e) => {
406                         error!("gralloc failed to allocate memory: {}", e);
407                         return VmMemoryResponse::Err(SysError::new(EINVAL));
408                     }
409                 };
410 
411                 let mut desc = GpuMemoryDesc::default();
412                 for i in 0..3 {
413                     desc.planes[i] = GpuMemoryPlaneDesc {
414                         stride: reqs.strides[i],
415                         offset: reqs.offsets[i],
416                     }
417                 }
418 
419                 match register_memory(
420                     vm,
421                     sys_allocator,
422                     &handle.os_handle,
423                     reqs.size as usize,
424                     None,
425                 ) {
426                     Ok((pfn, slot)) => VmMemoryResponse::AllocateAndRegisterGpuMemory {
427                         // Safe because ownership is transferred to SafeDescriptor via
428                         // into_raw_descriptor
429                         descriptor: unsafe {
430                             SafeDescriptor::from_raw_descriptor(
431                                 handle.os_handle.into_raw_descriptor(),
432                             )
433                         },
434                         pfn,
435                         slot,
436                         desc,
437                     },
438                     Err(e) => VmMemoryResponse::Err(e),
439                 }
440             }
441             RegisterMmapMemory {
442                 ref descriptor,
443                 size,
444                 offset,
445                 gpa,
446             } => {
447                 let mmap = match MemoryMappingBuilder::new(size)
448                     .from_descriptor(descriptor)
449                     .offset(offset as u64)
450                     .build()
451                 {
452                     Ok(v) => v,
453                     Err(_e) => return VmMemoryResponse::Err(SysError::new(EINVAL)),
454                 };
455                 match vm.add_memory_region(GuestAddress(gpa), Box::new(mmap), false, false) {
456                     Ok(_) => VmMemoryResponse::Ok,
457                     Err(e) => VmMemoryResponse::Err(e),
458                 }
459             }
460         }
461     }
462 }
463 
464 #[derive(Serialize, Deserialize, Debug)]
465 pub enum VmMemoryResponse {
466     /// The request to register memory into guest address space was successfully done at page frame
467     /// number `pfn` and memory slot number `slot`.
468     RegisterMemory {
469         pfn: u64,
470         slot: MemSlot,
471     },
472     /// The request to allocate and register GPU memory into guest address space was successfully
473     /// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`.
474     AllocateAndRegisterGpuMemory {
475         descriptor: SafeDescriptor,
476         pfn: u64,
477         slot: MemSlot,
478         desc: GpuMemoryDesc,
479     },
480     Ok,
481     Err(SysError),
482 }
483 
484 #[derive(Serialize, Deserialize, Debug)]
485 pub enum VmIrqRequest {
486     /// Allocate one gsi, and associate gsi to irqfd with register_irqfd()
487     AllocateOneMsi { irqfd: Event },
488     /// Add one msi route entry into the IRQ chip.
489     AddMsiRoute {
490         gsi: u32,
491         msi_address: u64,
492         msi_data: u32,
493     },
494 }
495 
496 /// Data to set up an IRQ event or IRQ route on the IRQ chip.
497 /// VmIrqRequest::execute can't take an `IrqChip` argument, because of a dependency cycle between
498 /// devices and vm_control, so it takes a Fn that processes an `IrqSetup`.
499 pub enum IrqSetup<'a> {
500     Event(u32, &'a Event),
501     Route(IrqRoute),
502 }
503 
504 impl VmIrqRequest {
505     /// Executes this request on the given Vm.
506     ///
507     /// # Arguments
508     /// * `set_up_irq` - A function that applies an `IrqSetup` to an IRQ chip.
509     ///
510     /// This does not return a result, instead encapsulating the success or failure in a
511     /// `VmIrqResponse` with the intended purpose of sending the response back over the socket
512     /// that received this `VmIrqResponse`.
execute<F>(&self, set_up_irq: F, sys_allocator: &mut SystemAllocator) -> VmIrqResponse where F: FnOnce(IrqSetup) -> Result<()>,513     pub fn execute<F>(&self, set_up_irq: F, sys_allocator: &mut SystemAllocator) -> VmIrqResponse
514     where
515         F: FnOnce(IrqSetup) -> Result<()>,
516     {
517         use self::VmIrqRequest::*;
518         match *self {
519             AllocateOneMsi { ref irqfd } => {
520                 if let Some(irq_num) = sys_allocator.allocate_irq() {
521                     match set_up_irq(IrqSetup::Event(irq_num, &irqfd)) {
522                         Ok(_) => VmIrqResponse::AllocateOneMsi { gsi: irq_num },
523                         Err(e) => VmIrqResponse::Err(e),
524                     }
525                 } else {
526                     VmIrqResponse::Err(SysError::new(EINVAL))
527                 }
528             }
529             AddMsiRoute {
530                 gsi,
531                 msi_address,
532                 msi_data,
533             } => {
534                 let route = IrqRoute {
535                     gsi,
536                     source: IrqSource::Msi {
537                         address: msi_address,
538                         data: msi_data,
539                     },
540                 };
541                 match set_up_irq(IrqSetup::Route(route)) {
542                     Ok(_) => VmIrqResponse::Ok,
543                     Err(e) => VmIrqResponse::Err(e),
544                 }
545             }
546         }
547     }
548 }
549 
550 #[derive(Serialize, Deserialize, Debug)]
551 pub enum VmIrqResponse {
552     AllocateOneMsi { gsi: u32 },
553     Ok,
554     Err(SysError),
555 }
556 
557 #[derive(Serialize, Deserialize, Debug)]
558 pub enum VmMsyncRequest {
559     /// Flush the content of a memory mapping to its backing file.
560     /// `slot` selects the arena (as returned by `Vm::add_mmap_arena`).
561     /// `offset` is the offset of the mapping to sync within the arena.
562     /// `size` is the size of the mapping to sync within the arena.
563     MsyncArena {
564         slot: MemSlot,
565         offset: usize,
566         size: usize,
567     },
568 }
569 
570 #[derive(Serialize, Deserialize, Debug)]
571 pub enum VmMsyncResponse {
572     Ok,
573     Err(SysError),
574 }
575 
576 impl VmMsyncRequest {
577     /// Executes this request on the given Vm.
578     ///
579     /// # Arguments
580     /// * `vm` - The `Vm` to perform the request on.
581     ///
582     /// This does not return a result, instead encapsulating the success or failure in a
583     /// `VmMsyncResponse` with the intended purpose of sending the response back over the socket
584     /// that received this `VmMsyncResponse`.
execute(&self, vm: &mut impl Vm) -> VmMsyncResponse585     pub fn execute(&self, vm: &mut impl Vm) -> VmMsyncResponse {
586         use self::VmMsyncRequest::*;
587         match *self {
588             MsyncArena { slot, offset, size } => match vm.msync_memory_region(slot, offset, size) {
589                 Ok(()) => VmMsyncResponse::Ok,
590                 Err(e) => VmMsyncResponse::Err(e),
591             },
592         }
593     }
594 }
595 
596 #[derive(Serialize, Deserialize, Debug)]
597 pub enum BatControlResult {
598     Ok,
599     NoBatDevice,
600     NoSuchHealth,
601     NoSuchProperty,
602     NoSuchStatus,
603     NoSuchBatType,
604     StringParseIntErr,
605 }
606 
607 impl Display for BatControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result608     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609         use self::BatControlResult::*;
610 
611         match self {
612             Ok => write!(f, "Setting battery property successfully"),
613             NoBatDevice => write!(f, "No battery device created"),
614             NoSuchHealth => write!(f, "Invalid Battery health setting. Only support: unknown/good/overheat/dead/overvoltage/unexpectedfailure/cold/watchdogtimerexpire/safetytimerexpire/overcurrent"),
615             NoSuchProperty => write!(f, "Battery doesn't have such property. Only support: status/health/present/capacity/aconline"),
616             NoSuchStatus => write!(f, "Invalid Battery status setting. Only support: unknown/charging/discharging/notcharging/full"),
617             NoSuchBatType => write!(f, "Invalid Battery type setting. Only support: goldfish"),
618             StringParseIntErr => write!(f, "Battery property target ParseInt error"),
619         }
620     }
621 }
622 
623 #[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
624 pub enum BatteryType {
625     Goldfish,
626 }
627 
628 impl Default for BatteryType {
default() -> Self629     fn default() -> Self {
630         BatteryType::Goldfish
631     }
632 }
633 
634 impl FromStr for BatteryType {
635     type Err = BatControlResult;
636 
from_str(s: &str) -> StdResult<Self, Self::Err>637     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
638         match s {
639             "goldfish" => Ok(BatteryType::Goldfish),
640             _ => Err(BatControlResult::NoSuchBatType),
641         }
642     }
643 }
644 
645 #[derive(Serialize, Deserialize, Debug)]
646 pub enum BatProperty {
647     Status,
648     Health,
649     Present,
650     Capacity,
651     ACOnline,
652 }
653 
654 impl FromStr for BatProperty {
655     type Err = BatControlResult;
656 
from_str(s: &str) -> StdResult<Self, Self::Err>657     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
658         match s {
659             "status" => Ok(BatProperty::Status),
660             "health" => Ok(BatProperty::Health),
661             "present" => Ok(BatProperty::Present),
662             "capacity" => Ok(BatProperty::Capacity),
663             "aconline" => Ok(BatProperty::ACOnline),
664             _ => Err(BatControlResult::NoSuchProperty),
665         }
666     }
667 }
668 
669 #[derive(Serialize, Deserialize, Debug)]
670 pub enum BatStatus {
671     Unknown,
672     Charging,
673     DisCharging,
674     NotCharging,
675     Full,
676 }
677 
678 impl BatStatus {
new(status: String) -> std::result::Result<Self, BatControlResult>679     pub fn new(status: String) -> std::result::Result<Self, BatControlResult> {
680         match status.as_str() {
681             "unknown" => Ok(BatStatus::Unknown),
682             "charging" => Ok(BatStatus::Charging),
683             "discharging" => Ok(BatStatus::DisCharging),
684             "notcharging" => Ok(BatStatus::NotCharging),
685             "full" => Ok(BatStatus::Full),
686             _ => Err(BatControlResult::NoSuchStatus),
687         }
688     }
689 }
690 
691 impl FromStr for BatStatus {
692     type Err = BatControlResult;
693 
from_str(s: &str) -> StdResult<Self, Self::Err>694     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
695         match s {
696             "unknown" => Ok(BatStatus::Unknown),
697             "charging" => Ok(BatStatus::Charging),
698             "discharging" => Ok(BatStatus::DisCharging),
699             "notcharging" => Ok(BatStatus::NotCharging),
700             "full" => Ok(BatStatus::Full),
701             _ => Err(BatControlResult::NoSuchStatus),
702         }
703     }
704 }
705 
706 impl From<BatStatus> for u32 {
from(status: BatStatus) -> Self707     fn from(status: BatStatus) -> Self {
708         status as u32
709     }
710 }
711 
712 #[derive(Serialize, Deserialize, Debug)]
713 pub enum BatHealth {
714     Unknown,
715     Good,
716     Overheat,
717     Dead,
718     OverVoltage,
719     UnexpectedFailure,
720     Cold,
721     WatchdogTimerExpire,
722     SafetyTimerExpire,
723     OverCurrent,
724 }
725 
726 impl FromStr for BatHealth {
727     type Err = BatControlResult;
728 
from_str(s: &str) -> StdResult<Self, Self::Err>729     fn from_str(s: &str) -> StdResult<Self, Self::Err> {
730         match s {
731             "unknown" => Ok(BatHealth::Unknown),
732             "good" => Ok(BatHealth::Good),
733             "overheat" => Ok(BatHealth::Overheat),
734             "dead" => Ok(BatHealth::Dead),
735             "overvoltage" => Ok(BatHealth::OverVoltage),
736             "unexpectedfailure" => Ok(BatHealth::UnexpectedFailure),
737             "cold" => Ok(BatHealth::Cold),
738             "watchdogtimerexpire" => Ok(BatHealth::WatchdogTimerExpire),
739             "safetytimerexpire" => Ok(BatHealth::SafetyTimerExpire),
740             "overcurrent" => Ok(BatHealth::OverCurrent),
741             _ => Err(BatControlResult::NoSuchHealth),
742         }
743     }
744 }
745 
746 impl From<BatHealth> for u32 {
from(status: BatHealth) -> Self747     fn from(status: BatHealth) -> Self {
748         status as u32
749     }
750 }
751 
752 #[derive(Serialize, Deserialize, Debug)]
753 pub enum BatControlCommand {
754     SetStatus(BatStatus),
755     SetHealth(BatHealth),
756     SetPresent(u32),
757     SetCapacity(u32),
758     SetACOnline(u32),
759 }
760 
761 impl BatControlCommand {
new(property: String, target: String) -> std::result::Result<Self, BatControlResult>762     pub fn new(property: String, target: String) -> std::result::Result<Self, BatControlResult> {
763         let cmd = property.parse::<BatProperty>()?;
764         match cmd {
765             BatProperty::Status => Ok(BatControlCommand::SetStatus(target.parse::<BatStatus>()?)),
766             BatProperty::Health => Ok(BatControlCommand::SetHealth(target.parse::<BatHealth>()?)),
767             BatProperty::Present => Ok(BatControlCommand::SetPresent(
768                 target
769                     .parse::<u32>()
770                     .map_err(|_| BatControlResult::StringParseIntErr)?,
771             )),
772             BatProperty::Capacity => Ok(BatControlCommand::SetCapacity(
773                 target
774                     .parse::<u32>()
775                     .map_err(|_| BatControlResult::StringParseIntErr)?,
776             )),
777             BatProperty::ACOnline => Ok(BatControlCommand::SetACOnline(
778                 target
779                     .parse::<u32>()
780                     .map_err(|_| BatControlResult::StringParseIntErr)?,
781             )),
782         }
783     }
784 }
785 
786 /// Used for VM to control battery properties.
787 pub struct BatControl {
788     pub type_: BatteryType,
789     pub control_tube: Tube,
790 }
791 
792 #[derive(Serialize, Deserialize, Debug)]
793 pub enum FsMappingRequest {
794     /// Create an anonymous memory mapping that spans the entire region described by `Alloc`.
795     AllocateSharedMemoryRegion(Alloc),
796     /// Create a memory mapping.
797     CreateMemoryMapping {
798         /// The slot for a MemoryMappingArena, previously returned by a response to an
799         /// `AllocateSharedMemoryRegion` request.
800         slot: u32,
801         /// The file descriptor that should be mapped.
802         fd: SafeDescriptor,
803         /// The size of the mapping.
804         size: usize,
805         /// The offset into the file from where the mapping should start.
806         file_offset: u64,
807         /// The memory protection to be used for the mapping.  Protections other than readable and
808         /// writable will be silently dropped.
809         prot: u32,
810         /// The offset into the shared memory region where the mapping should be placed.
811         mem_offset: usize,
812     },
813     /// Remove a memory mapping.
814     RemoveMemoryMapping {
815         /// The slot for a MemoryMappingArena.
816         slot: u32,
817         /// The offset into the shared memory region.
818         offset: usize,
819         /// The size of the mapping.
820         size: usize,
821     },
822 }
823 
824 impl FsMappingRequest {
execute(&self, vm: &mut dyn Vm, allocator: &mut SystemAllocator) -> VmResponse825     pub fn execute(&self, vm: &mut dyn Vm, allocator: &mut SystemAllocator) -> VmResponse {
826         use self::FsMappingRequest::*;
827         match *self {
828             AllocateSharedMemoryRegion(Alloc::PciBar {
829                 bus,
830                 dev,
831                 func,
832                 bar,
833             }) => {
834                 match allocator
835                     .mmio_allocator(MmioType::High)
836                     .get(&Alloc::PciBar {
837                         bus,
838                         dev,
839                         func,
840                         bar,
841                     }) {
842                     Some((addr, length, _)) => {
843                         let arena = match MemoryMappingArena::new(*length as usize) {
844                             Ok(a) => a,
845                             Err(MmapError::SystemCallFailed(e)) => return VmResponse::Err(e),
846                             _ => return VmResponse::Err(SysError::new(EINVAL)),
847                         };
848 
849                         match vm.add_memory_region(
850                             GuestAddress(*addr),
851                             Box::new(arena),
852                             false,
853                             false,
854                         ) {
855                             Ok(slot) => VmResponse::RegisterMemory {
856                                 pfn: addr >> 12,
857                                 slot,
858                             },
859                             Err(e) => VmResponse::Err(e),
860                         }
861                     }
862                     None => VmResponse::Err(SysError::new(EINVAL)),
863                 }
864             }
865             CreateMemoryMapping {
866                 slot,
867                 ref fd,
868                 size,
869                 file_offset,
870                 prot,
871                 mem_offset,
872             } => {
873                 let raw_fd: Fd = Fd(fd.as_raw_descriptor());
874 
875                 match vm.add_fd_mapping(
876                     slot,
877                     mem_offset,
878                     size,
879                     &raw_fd,
880                     file_offset,
881                     Protection::from(prot as c_int & (libc::PROT_READ | libc::PROT_WRITE)),
882                 ) {
883                     Ok(()) => VmResponse::Ok,
884                     Err(e) => VmResponse::Err(e),
885                 }
886             }
887             RemoveMemoryMapping { slot, offset, size } => {
888                 match vm.remove_mapping(slot, offset, size) {
889                     Ok(()) => VmResponse::Ok,
890                     Err(e) => VmResponse::Err(e),
891                 }
892             }
893             _ => VmResponse::Err(SysError::new(EINVAL)),
894         }
895     }
896 }
897 /// A request to the main process to perform some operation on the VM.
898 ///
899 /// Unless otherwise noted, each request should expect a `VmResponse::Ok` to be received on success.
900 #[derive(Serialize, Deserialize, Debug)]
901 pub enum VmRequest {
902     /// Break the VM's run loop and exit.
903     Exit,
904     /// Suspend the VM's VCPUs until resume.
905     Suspend,
906     /// Resume the VM's VCPUs that were previously suspended.
907     Resume,
908     /// Command for balloon driver.
909     BalloonCommand(BalloonControlCommand),
910     /// Send a command to a disk chosen by `disk_index`.
911     /// `disk_index` is a 0-based count of `--disk`, `--rwdisk`, and `-r` command-line options.
912     DiskCommand {
913         disk_index: usize,
914         command: DiskControlCommand,
915     },
916     /// Command to use controller.
917     UsbCommand(UsbControlCommand),
918     /// Command to set battery.
919     BatCommand(BatteryType, BatControlCommand),
920 }
921 
register_memory( vm: &mut impl Vm, allocator: &mut SystemAllocator, descriptor: &dyn AsRawDescriptor, size: usize, pci_allocation: Option<(Alloc, u64)>, ) -> Result<(u64, MemSlot)>922 fn register_memory(
923     vm: &mut impl Vm,
924     allocator: &mut SystemAllocator,
925     descriptor: &dyn AsRawDescriptor,
926     size: usize,
927     pci_allocation: Option<(Alloc, u64)>,
928 ) -> Result<(u64, MemSlot)> {
929     let mmap = match MemoryMappingBuilder::new(size)
930         .from_descriptor(descriptor)
931         .build()
932     {
933         Ok(v) => v,
934         Err(MmapError::SystemCallFailed(e)) => return Err(e),
935         _ => return Err(SysError::new(EINVAL)),
936     };
937 
938     let addr = match pci_allocation {
939         Some(pci_allocation) => allocator
940             .mmio_allocator_any()
941             .address_from_pci_offset(pci_allocation.0, pci_allocation.1, size as u64)
942             .map_err(|_e| SysError::new(EINVAL))?,
943         None => {
944             let alloc = allocator.get_anon_alloc();
945             allocator
946                 .mmio_allocator_any()
947                 .allocate(size as u64, alloc, "vmcontrol_register_memory".to_string())
948                 .map_err(|_e| SysError::new(EINVAL))?
949         }
950     };
951 
952     let slot = vm.add_memory_region(GuestAddress(addr), Box::new(mmap), false, false)?;
953 
954     Ok((addr >> 12, slot))
955 }
956 
register_host_pointer( vm: &mut impl Vm, allocator: &mut SystemAllocator, mem: Box<dyn MappedRegion>, pci_allocation: (Alloc, u64), ) -> Result<(u64, MemSlot)>957 fn register_host_pointer(
958     vm: &mut impl Vm,
959     allocator: &mut SystemAllocator,
960     mem: Box<dyn MappedRegion>,
961     pci_allocation: (Alloc, u64),
962 ) -> Result<(u64, MemSlot)> {
963     let addr = allocator
964         .mmio_allocator_any()
965         .address_from_pci_offset(pci_allocation.0, pci_allocation.1, mem.size() as u64)
966         .map_err(|_e| SysError::new(EINVAL))?;
967 
968     let slot = vm.add_memory_region(GuestAddress(addr), mem, false, false)?;
969     Ok((addr >> 12, slot))
970 }
971 
972 impl VmRequest {
973     /// Executes this request on the given Vm and other mutable state.
974     ///
975     /// This does not return a result, instead encapsulating the success or failure in a
976     /// `VmResponse` with the intended purpose of sending the response back over the  socket that
977     /// received this `VmRequest`.
execute( &self, run_mode: &mut Option<VmRunMode>, balloon_host_tube: &Tube, disk_host_tubes: &[Tube], usb_control_tube: &Tube, bat_control: &mut Option<BatControl>, ) -> VmResponse978     pub fn execute(
979         &self,
980         run_mode: &mut Option<VmRunMode>,
981         balloon_host_tube: &Tube,
982         disk_host_tubes: &[Tube],
983         usb_control_tube: &Tube,
984         bat_control: &mut Option<BatControl>,
985     ) -> VmResponse {
986         match *self {
987             VmRequest::Exit => {
988                 *run_mode = Some(VmRunMode::Exiting);
989                 VmResponse::Ok
990             }
991             VmRequest::Suspend => {
992                 *run_mode = Some(VmRunMode::Suspending);
993                 VmResponse::Ok
994             }
995             VmRequest::Resume => {
996                 *run_mode = Some(VmRunMode::Running);
997                 VmResponse::Ok
998             }
999             VmRequest::BalloonCommand(BalloonControlCommand::Adjust { num_bytes }) => {
1000                 match balloon_host_tube.send(&BalloonControlCommand::Adjust { num_bytes }) {
1001                     Ok(_) => VmResponse::Ok,
1002                     Err(_) => VmResponse::Err(SysError::last()),
1003                 }
1004             }
1005             VmRequest::BalloonCommand(BalloonControlCommand::Stats) => {
1006                 match balloon_host_tube.send(&BalloonControlCommand::Stats {}) {
1007                     Ok(_) => match balloon_host_tube.recv() {
1008                         Ok(BalloonControlResult::Stats {
1009                             stats,
1010                             balloon_actual,
1011                         }) => VmResponse::BalloonStats {
1012                             stats,
1013                             balloon_actual,
1014                         },
1015                         Err(e) => {
1016                             error!("balloon socket recv failed: {}", e);
1017                             VmResponse::Err(SysError::last())
1018                         }
1019                     },
1020                     Err(_) => VmResponse::Err(SysError::last()),
1021                 }
1022             }
1023             VmRequest::DiskCommand {
1024                 disk_index,
1025                 ref command,
1026             } => {
1027                 // Forward the request to the block device process via its control socket.
1028                 if let Some(sock) = disk_host_tubes.get(disk_index) {
1029                     if let Err(e) = sock.send(command) {
1030                         error!("disk socket send failed: {}", e);
1031                         VmResponse::Err(SysError::new(EINVAL))
1032                     } else {
1033                         match sock.recv() {
1034                             Ok(DiskControlResult::Ok) => VmResponse::Ok,
1035                             Ok(DiskControlResult::Err(e)) => VmResponse::Err(e),
1036                             Err(e) => {
1037                                 error!("disk socket recv failed: {}", e);
1038                                 VmResponse::Err(SysError::new(EINVAL))
1039                             }
1040                         }
1041                     }
1042                 } else {
1043                     VmResponse::Err(SysError::new(ENODEV))
1044                 }
1045             }
1046             VmRequest::UsbCommand(ref cmd) => {
1047                 let res = usb_control_tube.send(cmd);
1048                 if let Err(e) = res {
1049                     error!("fail to send command to usb control socket: {}", e);
1050                     return VmResponse::Err(SysError::new(EIO));
1051                 }
1052                 match usb_control_tube.recv() {
1053                     Ok(response) => VmResponse::UsbResponse(response),
1054                     Err(e) => {
1055                         error!("fail to recv command from usb control socket: {}", e);
1056                         VmResponse::Err(SysError::new(EIO))
1057                     }
1058                 }
1059             }
1060             VmRequest::BatCommand(type_, ref cmd) => {
1061                 match bat_control {
1062                     Some(battery) => {
1063                         if battery.type_ != type_ {
1064                             error!("ignored battery command due to battery type: expected {:?}, got {:?}", battery.type_, type_);
1065                             return VmResponse::Err(SysError::new(EINVAL));
1066                         }
1067 
1068                         let res = battery.control_tube.send(cmd);
1069                         if let Err(e) = res {
1070                             error!("fail to send command to bat control socket: {}", e);
1071                             return VmResponse::Err(SysError::new(EIO));
1072                         }
1073 
1074                         match battery.control_tube.recv() {
1075                             Ok(response) => VmResponse::BatResponse(response),
1076                             Err(e) => {
1077                                 error!("fail to recv command from bat control socket: {}", e);
1078                                 VmResponse::Err(SysError::new(EIO))
1079                             }
1080                         }
1081                     }
1082                     None => VmResponse::BatResponse(BatControlResult::NoBatDevice),
1083                 }
1084             }
1085         }
1086     }
1087 }
1088 
1089 /// Indication of success or failure of a `VmRequest`.
1090 ///
1091 /// Success is usually indicated `VmResponse::Ok` unless there is data associated with the response.
1092 #[derive(Serialize, Deserialize, Debug)]
1093 pub enum VmResponse {
1094     /// Indicates the request was executed successfully.
1095     Ok,
1096     /// Indicates the request encountered some error during execution.
1097     Err(SysError),
1098     /// The request to register memory into guest address space was successfully done at page frame
1099     /// number `pfn` and memory slot number `slot`.
1100     RegisterMemory { pfn: u64, slot: u32 },
1101     /// The request to allocate and register GPU memory into guest address space was successfully
1102     /// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`.
1103     AllocateAndRegisterGpuMemory {
1104         descriptor: SafeDescriptor,
1105         pfn: u64,
1106         slot: u32,
1107         desc: GpuMemoryDesc,
1108     },
1109     /// Results of balloon control commands.
1110     BalloonStats {
1111         stats: BalloonStats,
1112         balloon_actual: u64,
1113     },
1114     /// Results of usb control commands.
1115     UsbResponse(UsbControlResult),
1116     /// Results of battery control commands.
1117     BatResponse(BatControlResult),
1118 }
1119 
1120 impl Display for VmResponse {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1121     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1122         use self::VmResponse::*;
1123 
1124         match self {
1125             Ok => write!(f, "ok"),
1126             Err(e) => write!(f, "error: {}", e),
1127             RegisterMemory { pfn, slot } => write!(
1128                 f,
1129                 "memory registered to page frame number {:#x} and memory slot {}",
1130                 pfn, slot
1131             ),
1132             AllocateAndRegisterGpuMemory { pfn, slot, .. } => write!(
1133                 f,
1134                 "gpu memory allocated and registered to page frame number {:#x} and memory slot {}",
1135                 pfn, slot
1136             ),
1137             VmResponse::BalloonStats {
1138                 stats,
1139                 balloon_actual,
1140             } => write!(
1141                 f,
1142                 "balloon size: {}\nballoon stats: {}",
1143                 balloon_actual, stats
1144             ),
1145             UsbResponse(result) => write!(f, "usb control request get result {:?}", result),
1146             BatResponse(result) => write!(f, "{}", result),
1147         }
1148     }
1149 }
1150