xref: /aosp_15_r20/external/crosvm/devices/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker #![cfg_attr(windows, allow(unused))]
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker //! Emulates virtual and hardware devices.
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker pub mod ac_adapter;
10*bb4ee6a4SAndroid Build Coastguard Worker pub mod acpi;
11*bb4ee6a4SAndroid Build Coastguard Worker pub mod bat;
12*bb4ee6a4SAndroid Build Coastguard Worker mod bus;
13*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
14*bb4ee6a4SAndroid Build Coastguard Worker mod bus_stats;
15*bb4ee6a4SAndroid Build Coastguard Worker pub mod cmos;
16*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
17*bb4ee6a4SAndroid Build Coastguard Worker mod debugcon;
18*bb4ee6a4SAndroid Build Coastguard Worker mod fw_cfg;
19*bb4ee6a4SAndroid Build Coastguard Worker mod i8042;
20*bb4ee6a4SAndroid Build Coastguard Worker mod irq_event;
21*bb4ee6a4SAndroid Build Coastguard Worker pub mod irqchip;
22*bb4ee6a4SAndroid Build Coastguard Worker mod pci;
23*bb4ee6a4SAndroid Build Coastguard Worker mod pflash;
24*bb4ee6a4SAndroid Build Coastguard Worker pub mod pl030;
25*bb4ee6a4SAndroid Build Coastguard Worker pub mod pmc_virt;
26*bb4ee6a4SAndroid Build Coastguard Worker mod serial;
27*bb4ee6a4SAndroid Build Coastguard Worker pub mod serial_device;
28*bb4ee6a4SAndroid Build Coastguard Worker mod suspendable;
29*bb4ee6a4SAndroid Build Coastguard Worker mod sys;
30*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
31*bb4ee6a4SAndroid Build Coastguard Worker mod virtcpufreq;
32*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
33*bb4ee6a4SAndroid Build Coastguard Worker mod virtcpufreq_v2;
34*bb4ee6a4SAndroid Build Coastguard Worker pub mod virtio;
35*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "vtpm")]
36*bb4ee6a4SAndroid Build Coastguard Worker mod vtpm_proxy;
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker cfg_if::cfg_if! {
39*bb4ee6a4SAndroid Build Coastguard Worker     if #[cfg(target_arch = "x86_64")] {
40*bb4ee6a4SAndroid Build Coastguard Worker         mod pit;
41*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::pit::{Pit, PitError};
42*bb4ee6a4SAndroid Build Coastguard Worker         pub mod tsc;
43*bb4ee6a4SAndroid Build Coastguard Worker     }
44*bb4ee6a4SAndroid Build Coastguard Worker }
45*bb4ee6a4SAndroid Build Coastguard Worker 
46*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
49*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
50*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
51*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
52*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
53*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
54*bb4ee6a4SAndroid Build Coastguard Worker use base::TubeError;
55*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::AsyncTube;
56*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::Executor;
57*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
58*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
59*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::DeviceControlCommand;
60*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::DevicesState;
61*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmResponse;
62*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
63*bb4ee6a4SAndroid Build Coastguard Worker 
64*bb4ee6a4SAndroid Build Coastguard Worker pub use self::acpi::ACPIPMFixedEvent;
65*bb4ee6a4SAndroid Build Coastguard Worker pub use self::acpi::ACPIPMResource;
66*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bat::BatteryError;
67*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bat::GoldfishBattery;
68*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::Bus;
69*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusAccessInfo;
70*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusDevice;
71*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusDeviceObj;
72*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusDeviceSync;
73*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusRange;
74*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusResumeDevice;
75*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::BusType;
76*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::Error as BusError;
77*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::HotPlugBus;
78*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus::HotPlugKey;
79*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
80*bb4ee6a4SAndroid Build Coastguard Worker pub use self::bus_stats::BusStatistics;
81*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
82*bb4ee6a4SAndroid Build Coastguard Worker pub use self::debugcon::Debugcon;
83*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::Error as FwCfgError;
84*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::FwCfgDevice;
85*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::FwCfgItemType;
86*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::FwCfgParameters;
87*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::FW_CFG_BASE_PORT;
88*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::FW_CFG_MAX_FILE_SLOTS;
89*bb4ee6a4SAndroid Build Coastguard Worker pub use self::fw_cfg::FW_CFG_WIDTH;
90*bb4ee6a4SAndroid Build Coastguard Worker pub use self::i8042::I8042Device;
91*bb4ee6a4SAndroid Build Coastguard Worker pub use self::irq_event::IrqEdgeEvent;
92*bb4ee6a4SAndroid Build Coastguard Worker pub use self::irq_event::IrqLevelEvent;
93*bb4ee6a4SAndroid Build Coastguard Worker pub use self::irqchip::*;
94*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::BarRange;
95*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::CrosvmDeviceId;
96*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::GpeScope;
97*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
98*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::HotPluggable;
99*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
100*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::IntxParameter;
101*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
102*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::NetResourceCarrier;
103*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciAddress;
104*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciAddressError;
105*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciBarConfiguration;
106*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciBarIndex;
107*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciBus;
108*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciClassCode;
109*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciConfigIo;
110*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciConfigMmio;
111*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciDevice;
112*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciDeviceError;
113*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciInterruptPin;
114*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciMmioMapper;
115*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciRoot;
116*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciRootCommand;
117*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PciVirtualConfigMmio;
118*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::PreferredIrq;
119*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
120*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::ResourceCarrier;
121*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::StubPciDevice;
122*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pci::StubPciParameters;
123*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pflash::Pflash;
124*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pflash::PflashParameters;
125*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pl030::Pl030;
126*bb4ee6a4SAndroid Build Coastguard Worker pub use self::pmc_virt::VirtualPmc;
127*bb4ee6a4SAndroid Build Coastguard Worker pub use self::serial::Serial;
128*bb4ee6a4SAndroid Build Coastguard Worker pub use self::serial_device::Error as SerialError;
129*bb4ee6a4SAndroid Build Coastguard Worker pub use self::serial_device::SerialDevice;
130*bb4ee6a4SAndroid Build Coastguard Worker pub use self::serial_device::SerialHardware;
131*bb4ee6a4SAndroid Build Coastguard Worker pub use self::serial_device::SerialParameters;
132*bb4ee6a4SAndroid Build Coastguard Worker pub use self::serial_device::SerialType;
133*bb4ee6a4SAndroid Build Coastguard Worker pub use self::suspendable::DeviceState;
134*bb4ee6a4SAndroid Build Coastguard Worker pub use self::suspendable::Suspendable;
135*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
136*bb4ee6a4SAndroid Build Coastguard Worker pub use self::virtcpufreq::VirtCpufreq;
137*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
138*bb4ee6a4SAndroid Build Coastguard Worker pub use self::virtcpufreq_v2::VirtCpufreqV2;
139*bb4ee6a4SAndroid Build Coastguard Worker pub use self::virtio::VirtioMmioDevice;
140*bb4ee6a4SAndroid Build Coastguard Worker pub use self::virtio::VirtioPciDevice;
141*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "vtpm")]
142*bb4ee6a4SAndroid Build Coastguard Worker pub use self::vtpm_proxy::VtpmProxy;
143*bb4ee6a4SAndroid Build Coastguard Worker 
144*bb4ee6a4SAndroid Build Coastguard Worker cfg_if::cfg_if! {
145*bb4ee6a4SAndroid Build Coastguard Worker     if #[cfg(any(target_os = "android", target_os = "linux"))] {
146*bb4ee6a4SAndroid Build Coastguard Worker         mod platform;
147*bb4ee6a4SAndroid Build Coastguard Worker         mod proxy;
148*bb4ee6a4SAndroid Build Coastguard Worker         pub mod vmwdt;
149*bb4ee6a4SAndroid Build Coastguard Worker         pub mod vfio;
150*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "usb")]
151*bb4ee6a4SAndroid Build Coastguard Worker         #[macro_use]
152*bb4ee6a4SAndroid Build Coastguard Worker         mod register_space;
153*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "usb")]
154*bb4ee6a4SAndroid Build Coastguard Worker         pub mod usb;
155*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "usb")]
156*bb4ee6a4SAndroid Build Coastguard Worker         mod utils;
157*bb4ee6a4SAndroid Build Coastguard Worker 
158*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::pci::{
159*bb4ee6a4SAndroid Build Coastguard Worker             CoIommuDev, CoIommuParameters, CoIommuUnpinPolicy, PciBridge, PcieDownstreamPort,
160*bb4ee6a4SAndroid Build Coastguard Worker             PcieHostPort, PcieRootPort, PcieUpstreamPort, PvPanicCode, PvPanicPciDevice,
161*bb4ee6a4SAndroid Build Coastguard Worker             VfioPciDevice,
162*bb4ee6a4SAndroid Build Coastguard Worker         };
163*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::platform::VfioPlatformDevice;
164*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::ac_adapter::AcAdapter;
165*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::proxy::ChildProcIntf;
166*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::proxy::Error as ProxyError;
167*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::proxy::ProxyDevice;
168*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "usb")]
169*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::usb::backend::device_provider::DeviceProvider;
170*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "usb")]
171*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::usb::xhci::xhci_controller::XhciController;
172*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::vfio::VfioContainer;
173*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::vfio::VfioDevice;
174*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::vfio::VfioDeviceType;
175*bb4ee6a4SAndroid Build Coastguard Worker         pub use self::virtio::vfio_wrapper;
176*bb4ee6a4SAndroid Build Coastguard Worker 
177*bb4ee6a4SAndroid Build Coastguard Worker     } else if #[cfg(windows)] {
178*bb4ee6a4SAndroid Build Coastguard Worker     } else {
179*bb4ee6a4SAndroid Build Coastguard Worker         compile_error!("Unsupported platform");
180*bb4ee6a4SAndroid Build Coastguard Worker     }
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker 
183*bb4ee6a4SAndroid Build Coastguard Worker /// Request CoIOMMU to unpin a specific range.
184*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
185*bb4ee6a4SAndroid Build Coastguard Worker pub struct UnpinRequest {
186*bb4ee6a4SAndroid Build Coastguard Worker     /// The ranges presents (start gfn, count).
187*bb4ee6a4SAndroid Build Coastguard Worker     ranges: Vec<(u64, u64)>,
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker 
190*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
191*bb4ee6a4SAndroid Build Coastguard Worker pub enum UnpinResponse {
192*bb4ee6a4SAndroid Build Coastguard Worker     Success,
193*bb4ee6a4SAndroid Build Coastguard Worker     Failed,
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker 
196*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
197*bb4ee6a4SAndroid Build Coastguard Worker pub enum IommuDevType {
198*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(rename = "off")]
199*bb4ee6a4SAndroid Build Coastguard Worker     #[default]
200*bb4ee6a4SAndroid Build Coastguard Worker     NoIommu,
201*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(rename = "viommu")]
202*bb4ee6a4SAndroid Build Coastguard Worker     VirtioIommu,
203*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(rename = "coiommu")]
204*bb4ee6a4SAndroid Build Coastguard Worker     CoIommu,
205*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(rename = "pkvm-iommu")]
206*bb4ee6a4SAndroid Build Coastguard Worker     PkvmPviommu,
207*bb4ee6a4SAndroid Build Coastguard Worker }
208*bb4ee6a4SAndroid Build Coastguard Worker 
209*bb4ee6a4SAndroid Build Coastguard Worker // Thread that handles commands sent to devices - such as snapshot, sleep, suspend
210*bb4ee6a4SAndroid Build Coastguard Worker // Created when the VM is first created, and re-created on resumption of the VM.
create_devices_worker_thread( guest_memory: GuestMemory, io_bus: Arc<Bus>, mmio_bus: Arc<Bus>, device_ctrl_resp: Tube, ) -> std::io::Result<std::thread::JoinHandle<()>>211*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_devices_worker_thread(
212*bb4ee6a4SAndroid Build Coastguard Worker     guest_memory: GuestMemory,
213*bb4ee6a4SAndroid Build Coastguard Worker     io_bus: Arc<Bus>,
214*bb4ee6a4SAndroid Build Coastguard Worker     mmio_bus: Arc<Bus>,
215*bb4ee6a4SAndroid Build Coastguard Worker     device_ctrl_resp: Tube,
216*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::io::Result<std::thread::JoinHandle<()>> {
217*bb4ee6a4SAndroid Build Coastguard Worker     std::thread::Builder::new()
218*bb4ee6a4SAndroid Build Coastguard Worker         .name("device_control".to_string())
219*bb4ee6a4SAndroid Build Coastguard Worker         .spawn(move || {
220*bb4ee6a4SAndroid Build Coastguard Worker             let ex = Executor::new().expect("Failed to create an executor");
221*bb4ee6a4SAndroid Build Coastguard Worker 
222*bb4ee6a4SAndroid Build Coastguard Worker             let async_control = AsyncTube::new(&ex, device_ctrl_resp).unwrap();
223*bb4ee6a4SAndroid Build Coastguard Worker             match ex.run_until(async move {
224*bb4ee6a4SAndroid Build Coastguard Worker                 handle_command_tube(async_control, guest_memory, io_bus, mmio_bus).await
225*bb4ee6a4SAndroid Build Coastguard Worker             }) {
226*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(_) => {}
227*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
228*bb4ee6a4SAndroid Build Coastguard Worker                     error!("Device control thread exited with error: {}", e);
229*bb4ee6a4SAndroid Build Coastguard Worker                 }
230*bb4ee6a4SAndroid Build Coastguard Worker             };
231*bb4ee6a4SAndroid Build Coastguard Worker         })
232*bb4ee6a4SAndroid Build Coastguard Worker }
233*bb4ee6a4SAndroid Build Coastguard Worker 
sleep_buses(buses: &[&Bus]) -> anyhow::Result<()>234*bb4ee6a4SAndroid Build Coastguard Worker fn sleep_buses(buses: &[&Bus]) -> anyhow::Result<()> {
235*bb4ee6a4SAndroid Build Coastguard Worker     for bus in buses {
236*bb4ee6a4SAndroid Build Coastguard Worker         bus.sleep_devices()
237*bb4ee6a4SAndroid Build Coastguard Worker             .with_context(|| format!("failed to sleep devices on {:?} bus", bus.get_bus_type()))?;
238*bb4ee6a4SAndroid Build Coastguard Worker         debug!("Devices slept successfully on {:?} bus", bus.get_bus_type());
239*bb4ee6a4SAndroid Build Coastguard Worker     }
240*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker 
wake_buses(buses: &[&Bus])243*bb4ee6a4SAndroid Build Coastguard Worker fn wake_buses(buses: &[&Bus]) {
244*bb4ee6a4SAndroid Build Coastguard Worker     for bus in buses {
245*bb4ee6a4SAndroid Build Coastguard Worker         bus.wake_devices()
246*bb4ee6a4SAndroid Build Coastguard Worker             .with_context(|| format!("failed to wake devices on {:?} bus", bus.get_bus_type()))
247*bb4ee6a4SAndroid Build Coastguard Worker             // Some devices may have slept. Eternally.
248*bb4ee6a4SAndroid Build Coastguard Worker             // Recovery - impossible.
249*bb4ee6a4SAndroid Build Coastguard Worker             // Shut down VM.
250*bb4ee6a4SAndroid Build Coastguard Worker             .expect("VM panicked to avoid unexpected behavior");
251*bb4ee6a4SAndroid Build Coastguard Worker         debug!(
252*bb4ee6a4SAndroid Build Coastguard Worker             "Devices awoken successfully on {:?} Bus",
253*bb4ee6a4SAndroid Build Coastguard Worker             bus.get_bus_type()
254*bb4ee6a4SAndroid Build Coastguard Worker         );
255*bb4ee6a4SAndroid Build Coastguard Worker     }
256*bb4ee6a4SAndroid Build Coastguard Worker }
257*bb4ee6a4SAndroid Build Coastguard Worker 
258*bb4ee6a4SAndroid Build Coastguard Worker // Use 64MB chunks when writing the memory snapshot (if encryption is used).
259*bb4ee6a4SAndroid Build Coastguard Worker const MEMORY_SNAP_ENCRYPTED_CHUNK_SIZE_BYTES: usize = 1024 * 1024 * 64;
260*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot_handler( snapshot_writer: vm_control::SnapshotWriter, guest_memory: &GuestMemory, buses: &[&Bus], compress_memory: bool, ) -> anyhow::Result<()>261*bb4ee6a4SAndroid Build Coastguard Worker async fn snapshot_handler(
262*bb4ee6a4SAndroid Build Coastguard Worker     snapshot_writer: vm_control::SnapshotWriter,
263*bb4ee6a4SAndroid Build Coastguard Worker     guest_memory: &GuestMemory,
264*bb4ee6a4SAndroid Build Coastguard Worker     buses: &[&Bus],
265*bb4ee6a4SAndroid Build Coastguard Worker     compress_memory: bool,
266*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
267*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
268*bb4ee6a4SAndroid Build Coastguard Worker     // VM & devices are stopped.
269*bb4ee6a4SAndroid Build Coastguard Worker     let guest_memory_metadata = unsafe {
270*bb4ee6a4SAndroid Build Coastguard Worker         guest_memory
271*bb4ee6a4SAndroid Build Coastguard Worker             .snapshot(
272*bb4ee6a4SAndroid Build Coastguard Worker                 &mut snapshot_writer
273*bb4ee6a4SAndroid Build Coastguard Worker                     .raw_fragment_with_chunk_size("mem", MEMORY_SNAP_ENCRYPTED_CHUNK_SIZE_BYTES)?,
274*bb4ee6a4SAndroid Build Coastguard Worker                 compress_memory,
275*bb4ee6a4SAndroid Build Coastguard Worker             )
276*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to snapshot memory")?
277*bb4ee6a4SAndroid Build Coastguard Worker     };
278*bb4ee6a4SAndroid Build Coastguard Worker     snapshot_writer.write_fragment("mem_metadata", &guest_memory_metadata)?;
279*bb4ee6a4SAndroid Build Coastguard Worker     for (i, bus) in buses.iter().enumerate() {
280*bb4ee6a4SAndroid Build Coastguard Worker         bus.snapshot_devices(&snapshot_writer.add_namespace(&format!("bus{i}"))?)
281*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to snapshot bus devices")?;
282*bb4ee6a4SAndroid Build Coastguard Worker         debug!(
283*bb4ee6a4SAndroid Build Coastguard Worker             "Devices snapshot successfully for {:?} Bus",
284*bb4ee6a4SAndroid Build Coastguard Worker             bus.get_bus_type()
285*bb4ee6a4SAndroid Build Coastguard Worker         );
286*bb4ee6a4SAndroid Build Coastguard Worker     }
287*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
288*bb4ee6a4SAndroid Build Coastguard Worker }
289*bb4ee6a4SAndroid Build Coastguard Worker 
restore_handler( snapshot_reader: vm_control::SnapshotReader, guest_memory: &GuestMemory, buses: &[&Bus], ) -> anyhow::Result<()>290*bb4ee6a4SAndroid Build Coastguard Worker async fn restore_handler(
291*bb4ee6a4SAndroid Build Coastguard Worker     snapshot_reader: vm_control::SnapshotReader,
292*bb4ee6a4SAndroid Build Coastguard Worker     guest_memory: &GuestMemory,
293*bb4ee6a4SAndroid Build Coastguard Worker     buses: &[&Bus],
294*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
295*bb4ee6a4SAndroid Build Coastguard Worker     let guest_memory_metadata = snapshot_reader.read_fragment("mem_metadata")?;
296*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
297*bb4ee6a4SAndroid Build Coastguard Worker     // VM & devices are stopped.
298*bb4ee6a4SAndroid Build Coastguard Worker     unsafe {
299*bb4ee6a4SAndroid Build Coastguard Worker         guest_memory.restore(
300*bb4ee6a4SAndroid Build Coastguard Worker             guest_memory_metadata,
301*bb4ee6a4SAndroid Build Coastguard Worker             &mut snapshot_reader.raw_fragment("mem")?,
302*bb4ee6a4SAndroid Build Coastguard Worker         )?
303*bb4ee6a4SAndroid Build Coastguard Worker     };
304*bb4ee6a4SAndroid Build Coastguard Worker     for (i, bus) in buses.iter().enumerate() {
305*bb4ee6a4SAndroid Build Coastguard Worker         bus.restore_devices(&snapshot_reader.namespace(&format!("bus{i}"))?)
306*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore bus devices")?;
307*bb4ee6a4SAndroid Build Coastguard Worker         debug!(
308*bb4ee6a4SAndroid Build Coastguard Worker             "Devices restore successfully for {:?} Bus",
309*bb4ee6a4SAndroid Build Coastguard Worker             bus.get_bus_type()
310*bb4ee6a4SAndroid Build Coastguard Worker         );
311*bb4ee6a4SAndroid Build Coastguard Worker     }
312*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
313*bb4ee6a4SAndroid Build Coastguard Worker }
314*bb4ee6a4SAndroid Build Coastguard Worker 
handle_command_tube( command_tube: AsyncTube, guest_memory: GuestMemory, io_bus: Arc<Bus>, mmio_bus: Arc<Bus>, ) -> anyhow::Result<()>315*bb4ee6a4SAndroid Build Coastguard Worker async fn handle_command_tube(
316*bb4ee6a4SAndroid Build Coastguard Worker     command_tube: AsyncTube,
317*bb4ee6a4SAndroid Build Coastguard Worker     guest_memory: GuestMemory,
318*bb4ee6a4SAndroid Build Coastguard Worker     io_bus: Arc<Bus>,
319*bb4ee6a4SAndroid Build Coastguard Worker     mmio_bus: Arc<Bus>,
320*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
321*bb4ee6a4SAndroid Build Coastguard Worker     let buses = &[&*io_bus, &*mmio_bus];
322*bb4ee6a4SAndroid Build Coastguard Worker 
323*bb4ee6a4SAndroid Build Coastguard Worker     // We assume devices are awake. This is safe because if the VM starts the
324*bb4ee6a4SAndroid Build Coastguard Worker     // sleeping state, run_control will ask us to sleep devices.
325*bb4ee6a4SAndroid Build Coastguard Worker     let mut devices_state = DevicesState::Wake;
326*bb4ee6a4SAndroid Build Coastguard Worker 
327*bb4ee6a4SAndroid Build Coastguard Worker     loop {
328*bb4ee6a4SAndroid Build Coastguard Worker         match command_tube.next().await {
329*bb4ee6a4SAndroid Build Coastguard Worker             Ok(command) => {
330*bb4ee6a4SAndroid Build Coastguard Worker                 match command {
331*bb4ee6a4SAndroid Build Coastguard Worker                     DeviceControlCommand::SleepDevices => {
332*bb4ee6a4SAndroid Build Coastguard Worker                         if let DevicesState::Wake = devices_state {
333*bb4ee6a4SAndroid Build Coastguard Worker                             match sleep_buses(buses) {
334*bb4ee6a4SAndroid Build Coastguard Worker                                 Ok(()) => {
335*bb4ee6a4SAndroid Build Coastguard Worker                                     devices_state = DevicesState::Sleep;
336*bb4ee6a4SAndroid Build Coastguard Worker                                 }
337*bb4ee6a4SAndroid Build Coastguard Worker                                 Err(e) => {
338*bb4ee6a4SAndroid Build Coastguard Worker                                     error!("failed to sleep: {:#}", e);
339*bb4ee6a4SAndroid Build Coastguard Worker 
340*bb4ee6a4SAndroid Build Coastguard Worker                                     // Failing to sleep could mean a single device failing to sleep.
341*bb4ee6a4SAndroid Build Coastguard Worker                                     // Wake up devices to resume functionality of the VM.
342*bb4ee6a4SAndroid Build Coastguard Worker                                     info!("Attempting to wake devices after failed sleep");
343*bb4ee6a4SAndroid Build Coastguard Worker                                     wake_buses(buses);
344*bb4ee6a4SAndroid Build Coastguard Worker 
345*bb4ee6a4SAndroid Build Coastguard Worker                                     command_tube
346*bb4ee6a4SAndroid Build Coastguard Worker                                         .send(VmResponse::ErrString(e.to_string()))
347*bb4ee6a4SAndroid Build Coastguard Worker                                         .await
348*bb4ee6a4SAndroid Build Coastguard Worker                                         .context("failed to send response.")?;
349*bb4ee6a4SAndroid Build Coastguard Worker                                     continue;
350*bb4ee6a4SAndroid Build Coastguard Worker                                 }
351*bb4ee6a4SAndroid Build Coastguard Worker                             }
352*bb4ee6a4SAndroid Build Coastguard Worker                         }
353*bb4ee6a4SAndroid Build Coastguard Worker                         command_tube
354*bb4ee6a4SAndroid Build Coastguard Worker                             .send(VmResponse::Ok)
355*bb4ee6a4SAndroid Build Coastguard Worker                             .await
356*bb4ee6a4SAndroid Build Coastguard Worker                             .context("failed to reply to sleep command")?;
357*bb4ee6a4SAndroid Build Coastguard Worker                     }
358*bb4ee6a4SAndroid Build Coastguard Worker                     DeviceControlCommand::WakeDevices => {
359*bb4ee6a4SAndroid Build Coastguard Worker                         if let DevicesState::Sleep = devices_state {
360*bb4ee6a4SAndroid Build Coastguard Worker                             wake_buses(buses);
361*bb4ee6a4SAndroid Build Coastguard Worker                             devices_state = DevicesState::Wake;
362*bb4ee6a4SAndroid Build Coastguard Worker                         }
363*bb4ee6a4SAndroid Build Coastguard Worker                         command_tube
364*bb4ee6a4SAndroid Build Coastguard Worker                             .send(VmResponse::Ok)
365*bb4ee6a4SAndroid Build Coastguard Worker                             .await
366*bb4ee6a4SAndroid Build Coastguard Worker                             .context("failed to reply to wake devices request")?;
367*bb4ee6a4SAndroid Build Coastguard Worker                     }
368*bb4ee6a4SAndroid Build Coastguard Worker                     DeviceControlCommand::SnapshotDevices {
369*bb4ee6a4SAndroid Build Coastguard Worker                         snapshot_writer,
370*bb4ee6a4SAndroid Build Coastguard Worker                         compress_memory,
371*bb4ee6a4SAndroid Build Coastguard Worker                     } => {
372*bb4ee6a4SAndroid Build Coastguard Worker                         assert!(
373*bb4ee6a4SAndroid Build Coastguard Worker                             matches!(devices_state, DevicesState::Sleep),
374*bb4ee6a4SAndroid Build Coastguard Worker                             "devices must be sleeping to snapshot"
375*bb4ee6a4SAndroid Build Coastguard Worker                         );
376*bb4ee6a4SAndroid Build Coastguard Worker                         if let Err(e) =
377*bb4ee6a4SAndroid Build Coastguard Worker                             snapshot_handler(snapshot_writer, &guest_memory, buses, compress_memory)
378*bb4ee6a4SAndroid Build Coastguard Worker                                 .await
379*bb4ee6a4SAndroid Build Coastguard Worker                         {
380*bb4ee6a4SAndroid Build Coastguard Worker                             error!("failed to snapshot: {:#}", e);
381*bb4ee6a4SAndroid Build Coastguard Worker                             command_tube
382*bb4ee6a4SAndroid Build Coastguard Worker                                 .send(VmResponse::ErrString(e.to_string()))
383*bb4ee6a4SAndroid Build Coastguard Worker                                 .await
384*bb4ee6a4SAndroid Build Coastguard Worker                                 .context("Failed to send response")?;
385*bb4ee6a4SAndroid Build Coastguard Worker                             continue;
386*bb4ee6a4SAndroid Build Coastguard Worker                         }
387*bb4ee6a4SAndroid Build Coastguard Worker                         command_tube
388*bb4ee6a4SAndroid Build Coastguard Worker                             .send(VmResponse::Ok)
389*bb4ee6a4SAndroid Build Coastguard Worker                             .await
390*bb4ee6a4SAndroid Build Coastguard Worker                             .context("Failed to send response")?;
391*bb4ee6a4SAndroid Build Coastguard Worker                     }
392*bb4ee6a4SAndroid Build Coastguard Worker                     DeviceControlCommand::RestoreDevices { snapshot_reader } => {
393*bb4ee6a4SAndroid Build Coastguard Worker                         assert!(
394*bb4ee6a4SAndroid Build Coastguard Worker                             matches!(devices_state, DevicesState::Sleep),
395*bb4ee6a4SAndroid Build Coastguard Worker                             "devices must be sleeping to restore"
396*bb4ee6a4SAndroid Build Coastguard Worker                         );
397*bb4ee6a4SAndroid Build Coastguard Worker                         if let Err(e) =
398*bb4ee6a4SAndroid Build Coastguard Worker                             restore_handler(snapshot_reader, &guest_memory, &[&*io_bus, &*mmio_bus])
399*bb4ee6a4SAndroid Build Coastguard Worker                                 .await
400*bb4ee6a4SAndroid Build Coastguard Worker                         {
401*bb4ee6a4SAndroid Build Coastguard Worker                             error!("failed to restore: {:#}", e);
402*bb4ee6a4SAndroid Build Coastguard Worker                             command_tube
403*bb4ee6a4SAndroid Build Coastguard Worker                                 .send(VmResponse::ErrString(e.to_string()))
404*bb4ee6a4SAndroid Build Coastguard Worker                                 .await
405*bb4ee6a4SAndroid Build Coastguard Worker                                 .context("Failed to send response")?;
406*bb4ee6a4SAndroid Build Coastguard Worker                             continue;
407*bb4ee6a4SAndroid Build Coastguard Worker                         }
408*bb4ee6a4SAndroid Build Coastguard Worker                         command_tube
409*bb4ee6a4SAndroid Build Coastguard Worker                             .send(VmResponse::Ok)
410*bb4ee6a4SAndroid Build Coastguard Worker                             .await
411*bb4ee6a4SAndroid Build Coastguard Worker                             .context("Failed to send response")?;
412*bb4ee6a4SAndroid Build Coastguard Worker                     }
413*bb4ee6a4SAndroid Build Coastguard Worker                     DeviceControlCommand::GetDevicesState => {
414*bb4ee6a4SAndroid Build Coastguard Worker                         command_tube
415*bb4ee6a4SAndroid Build Coastguard Worker                             .send(VmResponse::DevicesState(devices_state.clone()))
416*bb4ee6a4SAndroid Build Coastguard Worker                             .await
417*bb4ee6a4SAndroid Build Coastguard Worker                             .context("failed to send response")?;
418*bb4ee6a4SAndroid Build Coastguard Worker                     }
419*bb4ee6a4SAndroid Build Coastguard Worker                     DeviceControlCommand::Exit => {
420*bb4ee6a4SAndroid Build Coastguard Worker                         return Ok(());
421*bb4ee6a4SAndroid Build Coastguard Worker                     }
422*bb4ee6a4SAndroid Build Coastguard Worker                 };
423*bb4ee6a4SAndroid Build Coastguard Worker             }
424*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
425*bb4ee6a4SAndroid Build Coastguard Worker                 if matches!(e, TubeError::Disconnected) {
426*bb4ee6a4SAndroid Build Coastguard Worker                     // Tube disconnected - shut down thread.
427*bb4ee6a4SAndroid Build Coastguard Worker                     return Ok(());
428*bb4ee6a4SAndroid Build Coastguard Worker                 }
429*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(anyhow!("Failed to receive: {}", e));
430*bb4ee6a4SAndroid Build Coastguard Worker             }
431*bb4ee6a4SAndroid Build Coastguard Worker         }
432*bb4ee6a4SAndroid Build Coastguard Worker     }
433*bb4ee6a4SAndroid Build Coastguard Worker }
434