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