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 //! Runs hardware devices in child processes.
6*bb4ee6a4SAndroid Build Coastguard Worker
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fs;
8*bb4ee6a4SAndroid Build Coastguard Worker
9*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
13*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
14*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptors;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::TubeError;
19*bb4ee6a4SAndroid Build Coastguard Worker use jail::fork::fork_process;
20*bb4ee6a4SAndroid Build Coastguard Worker use libc::pid_t;
21*bb4ee6a4SAndroid Build Coastguard Worker use minijail::Minijail;
22*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
23*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
24*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
25*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
26*bb4ee6a4SAndroid Build Coastguard Worker
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::ConfigWriteResult;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddress;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusRange;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusType;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
36*bb4ee6a4SAndroid Build Coastguard Worker
37*bb4ee6a4SAndroid Build Coastguard Worker /// Errors for proxy devices.
38*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
39*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
40*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
41*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failed to activate ProxyDevice")]
42*bb4ee6a4SAndroid Build Coastguard Worker ActivatingProxyDevice,
43*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failed to fork jail process: {0}")]
44*bb4ee6a4SAndroid Build Coastguard Worker ForkingJail(#[from] minijail::Error),
45*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failed to configure swap: {0}")]
46*bb4ee6a4SAndroid Build Coastguard Worker Swap(anyhow::Error),
47*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failed to configure tube: {0}")]
48*bb4ee6a4SAndroid Build Coastguard Worker Tube(#[from] TubeError),
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker
51*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
52*bb4ee6a4SAndroid Build Coastguard Worker
53*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Serialize, Deserialize)]
54*bb4ee6a4SAndroid Build Coastguard Worker enum Command {
55*bb4ee6a4SAndroid Build Coastguard Worker Activate,
56*bb4ee6a4SAndroid Build Coastguard Worker Read {
57*bb4ee6a4SAndroid Build Coastguard Worker len: u32,
58*bb4ee6a4SAndroid Build Coastguard Worker info: BusAccessInfo,
59*bb4ee6a4SAndroid Build Coastguard Worker },
60*bb4ee6a4SAndroid Build Coastguard Worker Write {
61*bb4ee6a4SAndroid Build Coastguard Worker len: u32,
62*bb4ee6a4SAndroid Build Coastguard Worker info: BusAccessInfo,
63*bb4ee6a4SAndroid Build Coastguard Worker data: [u8; 8],
64*bb4ee6a4SAndroid Build Coastguard Worker },
65*bb4ee6a4SAndroid Build Coastguard Worker ReadConfig(u32),
66*bb4ee6a4SAndroid Build Coastguard Worker WriteConfig {
67*bb4ee6a4SAndroid Build Coastguard Worker reg_idx: u32,
68*bb4ee6a4SAndroid Build Coastguard Worker offset: u32,
69*bb4ee6a4SAndroid Build Coastguard Worker len: u32,
70*bb4ee6a4SAndroid Build Coastguard Worker data: [u8; 4],
71*bb4ee6a4SAndroid Build Coastguard Worker },
72*bb4ee6a4SAndroid Build Coastguard Worker InitPciConfigMapping {
73*bb4ee6a4SAndroid Build Coastguard Worker shmem: SharedMemory,
74*bb4ee6a4SAndroid Build Coastguard Worker base: usize,
75*bb4ee6a4SAndroid Build Coastguard Worker len: usize,
76*bb4ee6a4SAndroid Build Coastguard Worker },
77*bb4ee6a4SAndroid Build Coastguard Worker ReadVirtualConfig(u32),
78*bb4ee6a4SAndroid Build Coastguard Worker WriteVirtualConfig {
79*bb4ee6a4SAndroid Build Coastguard Worker reg_idx: u32,
80*bb4ee6a4SAndroid Build Coastguard Worker value: u32,
81*bb4ee6a4SAndroid Build Coastguard Worker },
82*bb4ee6a4SAndroid Build Coastguard Worker DestroyDevice,
83*bb4ee6a4SAndroid Build Coastguard Worker Shutdown,
84*bb4ee6a4SAndroid Build Coastguard Worker GetRanges,
85*bb4ee6a4SAndroid Build Coastguard Worker Snapshot,
86*bb4ee6a4SAndroid Build Coastguard Worker Restore {
87*bb4ee6a4SAndroid Build Coastguard Worker data: serde_json::Value,
88*bb4ee6a4SAndroid Build Coastguard Worker },
89*bb4ee6a4SAndroid Build Coastguard Worker Sleep,
90*bb4ee6a4SAndroid Build Coastguard Worker Wake,
91*bb4ee6a4SAndroid Build Coastguard Worker }
92*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Serialize, Deserialize)]
93*bb4ee6a4SAndroid Build Coastguard Worker enum CommandResult {
94*bb4ee6a4SAndroid Build Coastguard Worker Ok,
95*bb4ee6a4SAndroid Build Coastguard Worker ReadResult([u8; 8]),
96*bb4ee6a4SAndroid Build Coastguard Worker ReadConfigResult(u32),
97*bb4ee6a4SAndroid Build Coastguard Worker WriteConfigResult {
98*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: Vec<BusRange>,
99*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: Vec<BusRange>,
100*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec<BusRange>,
101*bb4ee6a4SAndroid Build Coastguard Worker io_add: Vec<BusRange>,
102*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec<PciAddress>,
103*bb4ee6a4SAndroid Build Coastguard Worker },
104*bb4ee6a4SAndroid Build Coastguard Worker InitPciConfigMappingResult(bool),
105*bb4ee6a4SAndroid Build Coastguard Worker ReadVirtualConfigResult(u32),
106*bb4ee6a4SAndroid Build Coastguard Worker GetRangesResult(Vec<(BusRange, BusType)>),
107*bb4ee6a4SAndroid Build Coastguard Worker SnapshotResult(std::result::Result<serde_json::Value, String>),
108*bb4ee6a4SAndroid Build Coastguard Worker RestoreResult(std::result::Result<(), String>),
109*bb4ee6a4SAndroid Build Coastguard Worker SleepResult(std::result::Result<(), String>),
110*bb4ee6a4SAndroid Build Coastguard Worker WakeResult(std::result::Result<(), String>),
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker
child_proc<D: BusDevice>(tube: Tube, mut device: D)113*bb4ee6a4SAndroid Build Coastguard Worker fn child_proc<D: BusDevice>(tube: Tube, mut device: D) {
114*bb4ee6a4SAndroid Build Coastguard Worker // Wait for activation signal to function as BusDevice.
115*bb4ee6a4SAndroid Build Coastguard Worker match tube.recv() {
116*bb4ee6a4SAndroid Build Coastguard Worker Ok(Command::Activate) => {
117*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = tube.send(&CommandResult::Ok) {
118*bb4ee6a4SAndroid Build Coastguard Worker error!(
119*bb4ee6a4SAndroid Build Coastguard Worker "sending {} activation result failed: {}",
120*bb4ee6a4SAndroid Build Coastguard Worker device.debug_label(),
121*bb4ee6a4SAndroid Build Coastguard Worker e,
122*bb4ee6a4SAndroid Build Coastguard Worker );
123*bb4ee6a4SAndroid Build Coastguard Worker return;
124*bb4ee6a4SAndroid Build Coastguard Worker }
125*bb4ee6a4SAndroid Build Coastguard Worker }
126*bb4ee6a4SAndroid Build Coastguard Worker // Commands other than activate is unexpected, close device.
127*bb4ee6a4SAndroid Build Coastguard Worker Ok(cmd) => {
128*bb4ee6a4SAndroid Build Coastguard Worker panic!("Receiving Command {:?} before device is activated", &cmd);
129*bb4ee6a4SAndroid Build Coastguard Worker }
130*bb4ee6a4SAndroid Build Coastguard Worker // Most likely tube error is caused by other end is dropped, release resource.
131*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
132*bb4ee6a4SAndroid Build Coastguard Worker error!(
133*bb4ee6a4SAndroid Build Coastguard Worker "{} device failed before activation: {}. Dropping device",
134*bb4ee6a4SAndroid Build Coastguard Worker device.debug_label(),
135*bb4ee6a4SAndroid Build Coastguard Worker e,
136*bb4ee6a4SAndroid Build Coastguard Worker );
137*bb4ee6a4SAndroid Build Coastguard Worker drop(device);
138*bb4ee6a4SAndroid Build Coastguard Worker return;
139*bb4ee6a4SAndroid Build Coastguard Worker }
140*bb4ee6a4SAndroid Build Coastguard Worker };
141*bb4ee6a4SAndroid Build Coastguard Worker loop {
142*bb4ee6a4SAndroid Build Coastguard Worker let cmd = match tube.recv() {
143*bb4ee6a4SAndroid Build Coastguard Worker Ok(cmd) => cmd,
144*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
145*bb4ee6a4SAndroid Build Coastguard Worker error!(
146*bb4ee6a4SAndroid Build Coastguard Worker "recv from {} child device process failed: {}",
147*bb4ee6a4SAndroid Build Coastguard Worker device.debug_label(),
148*bb4ee6a4SAndroid Build Coastguard Worker e,
149*bb4ee6a4SAndroid Build Coastguard Worker );
150*bb4ee6a4SAndroid Build Coastguard Worker break;
151*bb4ee6a4SAndroid Build Coastguard Worker }
152*bb4ee6a4SAndroid Build Coastguard Worker };
153*bb4ee6a4SAndroid Build Coastguard Worker
154*bb4ee6a4SAndroid Build Coastguard Worker let res = match cmd {
155*bb4ee6a4SAndroid Build Coastguard Worker Command::Activate => {
156*bb4ee6a4SAndroid Build Coastguard Worker panic!("Device shall only be activated once, duplicated ProxyDevice likely");
157*bb4ee6a4SAndroid Build Coastguard Worker }
158*bb4ee6a4SAndroid Build Coastguard Worker Command::Read { len, info } => {
159*bb4ee6a4SAndroid Build Coastguard Worker let mut buffer = [0u8; 8];
160*bb4ee6a4SAndroid Build Coastguard Worker device.read(info, &mut buffer[0..len as usize]);
161*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::ReadResult(buffer))
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker Command::Write { len, info, data } => {
164*bb4ee6a4SAndroid Build Coastguard Worker let len = len as usize;
165*bb4ee6a4SAndroid Build Coastguard Worker device.write(info, &data[0..len]);
166*bb4ee6a4SAndroid Build Coastguard Worker // Command::Write does not have a result.
167*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker Command::ReadConfig(idx) => {
170*bb4ee6a4SAndroid Build Coastguard Worker let val = device.config_register_read(idx as usize);
171*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::ReadConfigResult(val))
172*bb4ee6a4SAndroid Build Coastguard Worker }
173*bb4ee6a4SAndroid Build Coastguard Worker Command::WriteConfig {
174*bb4ee6a4SAndroid Build Coastguard Worker reg_idx,
175*bb4ee6a4SAndroid Build Coastguard Worker offset,
176*bb4ee6a4SAndroid Build Coastguard Worker len,
177*bb4ee6a4SAndroid Build Coastguard Worker data,
178*bb4ee6a4SAndroid Build Coastguard Worker } => {
179*bb4ee6a4SAndroid Build Coastguard Worker let len = len as usize;
180*bb4ee6a4SAndroid Build Coastguard Worker let res =
181*bb4ee6a4SAndroid Build Coastguard Worker device.config_register_write(reg_idx as usize, offset as u64, &data[0..len]);
182*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::WriteConfigResult {
183*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: res.mmio_remove,
184*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: res.mmio_add,
185*bb4ee6a4SAndroid Build Coastguard Worker io_remove: res.io_remove,
186*bb4ee6a4SAndroid Build Coastguard Worker io_add: res.io_add,
187*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: res.removed_pci_devices,
188*bb4ee6a4SAndroid Build Coastguard Worker })
189*bb4ee6a4SAndroid Build Coastguard Worker }
190*bb4ee6a4SAndroid Build Coastguard Worker Command::InitPciConfigMapping { shmem, base, len } => {
191*bb4ee6a4SAndroid Build Coastguard Worker let success = device.init_pci_config_mapping(&shmem, base, len);
192*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::InitPciConfigMappingResult(success))
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker Command::ReadVirtualConfig(idx) => {
195*bb4ee6a4SAndroid Build Coastguard Worker let val = device.virtual_config_register_read(idx as usize);
196*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::ReadVirtualConfigResult(val))
197*bb4ee6a4SAndroid Build Coastguard Worker }
198*bb4ee6a4SAndroid Build Coastguard Worker Command::WriteVirtualConfig { reg_idx, value } => {
199*bb4ee6a4SAndroid Build Coastguard Worker device.virtual_config_register_write(reg_idx as usize, value);
200*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::Ok)
201*bb4ee6a4SAndroid Build Coastguard Worker }
202*bb4ee6a4SAndroid Build Coastguard Worker Command::DestroyDevice => {
203*bb4ee6a4SAndroid Build Coastguard Worker device.destroy_device();
204*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker Command::Shutdown => {
207*bb4ee6a4SAndroid Build Coastguard Worker // Explicitly drop the device so that its Drop implementation has a chance to run
208*bb4ee6a4SAndroid Build Coastguard Worker // before sending the `Command::Shutdown` response.
209*bb4ee6a4SAndroid Build Coastguard Worker drop(device);
210*bb4ee6a4SAndroid Build Coastguard Worker
211*bb4ee6a4SAndroid Build Coastguard Worker let _ = tube.send(&CommandResult::Ok);
212*bb4ee6a4SAndroid Build Coastguard Worker return;
213*bb4ee6a4SAndroid Build Coastguard Worker }
214*bb4ee6a4SAndroid Build Coastguard Worker Command::GetRanges => {
215*bb4ee6a4SAndroid Build Coastguard Worker let ranges = device.get_ranges();
216*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::GetRangesResult(ranges))
217*bb4ee6a4SAndroid Build Coastguard Worker }
218*bb4ee6a4SAndroid Build Coastguard Worker Command::Snapshot => {
219*bb4ee6a4SAndroid Build Coastguard Worker let res = device.snapshot();
220*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::SnapshotResult(
221*bb4ee6a4SAndroid Build Coastguard Worker res.map_err(|e| e.to_string()),
222*bb4ee6a4SAndroid Build Coastguard Worker ))
223*bb4ee6a4SAndroid Build Coastguard Worker }
224*bb4ee6a4SAndroid Build Coastguard Worker Command::Restore { data } => {
225*bb4ee6a4SAndroid Build Coastguard Worker let res = device.restore(data);
226*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::RestoreResult(
227*bb4ee6a4SAndroid Build Coastguard Worker res.map_err(|e| e.to_string()),
228*bb4ee6a4SAndroid Build Coastguard Worker ))
229*bb4ee6a4SAndroid Build Coastguard Worker }
230*bb4ee6a4SAndroid Build Coastguard Worker Command::Sleep => {
231*bb4ee6a4SAndroid Build Coastguard Worker let res = device.sleep();
232*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::SleepResult(res.map_err(|e| e.to_string())))
233*bb4ee6a4SAndroid Build Coastguard Worker }
234*bb4ee6a4SAndroid Build Coastguard Worker Command::Wake => {
235*bb4ee6a4SAndroid Build Coastguard Worker let res = device.wake();
236*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&CommandResult::WakeResult(res.map_err(|e| e.to_string())))
237*bb4ee6a4SAndroid Build Coastguard Worker }
238*bb4ee6a4SAndroid Build Coastguard Worker };
239*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = res {
240*bb4ee6a4SAndroid Build Coastguard Worker error!(
241*bb4ee6a4SAndroid Build Coastguard Worker "send to {} child device process failed: {}",
242*bb4ee6a4SAndroid Build Coastguard Worker device.debug_label(),
243*bb4ee6a4SAndroid Build Coastguard Worker e,
244*bb4ee6a4SAndroid Build Coastguard Worker );
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker }
248*bb4ee6a4SAndroid Build Coastguard Worker
249*bb4ee6a4SAndroid Build Coastguard Worker /// ChildProcIntf is the interface to the device child process.
250*bb4ee6a4SAndroid Build Coastguard Worker ///
251*bb4ee6a4SAndroid Build Coastguard Worker /// ChildProcIntf implements Serialize, and can be sent across process before it functions as a
252*bb4ee6a4SAndroid Build Coastguard Worker /// ProxyDevice. However, a child process shall only correspond to one ProxyDevice. The uniqueness
253*bb4ee6a4SAndroid Build Coastguard Worker /// is checked when ChildProcIntf is casted into ProxyDevice.
254*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
255*bb4ee6a4SAndroid Build Coastguard Worker pub struct ChildProcIntf {
256*bb4ee6a4SAndroid Build Coastguard Worker tube: Tube,
257*bb4ee6a4SAndroid Build Coastguard Worker pid: pid_t,
258*bb4ee6a4SAndroid Build Coastguard Worker debug_label: String,
259*bb4ee6a4SAndroid Build Coastguard Worker }
260*bb4ee6a4SAndroid Build Coastguard Worker
261*bb4ee6a4SAndroid Build Coastguard Worker impl ChildProcIntf {
262*bb4ee6a4SAndroid Build Coastguard Worker /// Creates ChildProcIntf that shall be turned into exactly one ProxyDevice.
263*bb4ee6a4SAndroid Build Coastguard Worker ///
264*bb4ee6a4SAndroid Build Coastguard Worker /// The ChildProcIntf struct holds the interface to the device process. It shall be turned into
265*bb4ee6a4SAndroid Build Coastguard Worker /// a ProxyDevice exactly once (at an arbitrary process). Since ChildProcIntf may be duplicated
266*bb4ee6a4SAndroid Build Coastguard Worker /// by serde, the uniqueness of the interface is checked when ChildProcIntf is converted into
267*bb4ee6a4SAndroid Build Coastguard Worker /// ProxyDevice.
268*bb4ee6a4SAndroid Build Coastguard Worker ///
269*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
270*bb4ee6a4SAndroid Build Coastguard Worker /// * `device` - The device to isolate to another process.
271*bb4ee6a4SAndroid Build Coastguard Worker /// * `jail` - The jail to use for isolating the given device.
272*bb4ee6a4SAndroid Build Coastguard Worker /// * `keep_rds` - File descriptors that will be kept open in the child.
new<D: BusDevice, #[cfg(feature = "swap")] P: swap::PrepareFork>( mut device: D, jail: Minijail, mut keep_rds: Vec<RawDescriptor>, #[cfg(feature = "swap")] swap_prepare_fork: &mut Option<P>, ) -> Result<ChildProcIntf>273*bb4ee6a4SAndroid Build Coastguard Worker pub fn new<D: BusDevice, #[cfg(feature = "swap")] P: swap::PrepareFork>(
274*bb4ee6a4SAndroid Build Coastguard Worker mut device: D,
275*bb4ee6a4SAndroid Build Coastguard Worker jail: Minijail,
276*bb4ee6a4SAndroid Build Coastguard Worker mut keep_rds: Vec<RawDescriptor>,
277*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_prepare_fork: &mut Option<P>,
278*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ChildProcIntf> {
279*bb4ee6a4SAndroid Build Coastguard Worker let debug_label = device.debug_label();
280*bb4ee6a4SAndroid Build Coastguard Worker let (child_tube, parent_tube) = Tube::pair()?;
281*bb4ee6a4SAndroid Build Coastguard Worker
282*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(child_tube.as_raw_descriptor());
283*bb4ee6a4SAndroid Build Coastguard Worker
284*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
285*bb4ee6a4SAndroid Build Coastguard Worker let swap_device_uffd_sender = if let Some(prepare_fork) = swap_prepare_fork {
286*bb4ee6a4SAndroid Build Coastguard Worker let sender = prepare_fork.prepare_fork().map_err(Error::Swap)?;
287*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.extend(sender.as_raw_descriptors());
288*bb4ee6a4SAndroid Build Coastguard Worker Some(sender)
289*bb4ee6a4SAndroid Build Coastguard Worker } else {
290*bb4ee6a4SAndroid Build Coastguard Worker None
291*bb4ee6a4SAndroid Build Coastguard Worker };
292*bb4ee6a4SAndroid Build Coastguard Worker
293*bb4ee6a4SAndroid Build Coastguard Worker // This will be removed after b/183540186 gets fixed.
294*bb4ee6a4SAndroid Build Coastguard Worker // Only enabled it for x86_64 since the original bug mostly happens on x86 boards.
295*bb4ee6a4SAndroid Build Coastguard Worker if cfg!(target_arch = "x86_64") && debug_label == "pcivirtio-gpu" {
296*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(cmd) = fs::read_to_string("/proc/self/cmdline") {
297*bb4ee6a4SAndroid Build Coastguard Worker if cmd.contains("arcvm") {
298*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(share) = fs::read_to_string("/sys/fs/cgroup/cpu/arcvm/cpu.shares") {
299*bb4ee6a4SAndroid Build Coastguard Worker info!("arcvm cpu share when booting gpu is {:}", share.trim());
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker }
302*bb4ee6a4SAndroid Build Coastguard Worker }
303*bb4ee6a4SAndroid Build Coastguard Worker }
304*bb4ee6a4SAndroid Build Coastguard Worker
305*bb4ee6a4SAndroid Build Coastguard Worker let child_process = fork_process(jail, keep_rds, Some(debug_label.clone()), || {
306*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
307*bb4ee6a4SAndroid Build Coastguard Worker if let Some(swap_device_uffd_sender) = swap_device_uffd_sender {
308*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = swap_device_uffd_sender.on_process_forked() {
309*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to SwapController::on_process_forked: {:?}", e);
310*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
311*bb4ee6a4SAndroid Build Coastguard Worker // exit() is trivially safe.
312*bb4ee6a4SAndroid Build Coastguard Worker unsafe { libc::exit(1) };
313*bb4ee6a4SAndroid Build Coastguard Worker }
314*bb4ee6a4SAndroid Build Coastguard Worker }
315*bb4ee6a4SAndroid Build Coastguard Worker
316*bb4ee6a4SAndroid Build Coastguard Worker device.on_sandboxed();
317*bb4ee6a4SAndroid Build Coastguard Worker child_proc(child_tube, device);
318*bb4ee6a4SAndroid Build Coastguard Worker
319*bb4ee6a4SAndroid Build Coastguard Worker // We're explicitly not using std::process::exit here to avoid the cleanup of
320*bb4ee6a4SAndroid Build Coastguard Worker // stdout/stderr globals. This can cause cascading panics and SIGILL if a worker
321*bb4ee6a4SAndroid Build Coastguard Worker // thread attempts to log to stderr after at_exit handlers have been run.
322*bb4ee6a4SAndroid Build Coastguard Worker // TODO(crbug.com/992494): Remove this once device shutdown ordering is clearly
323*bb4ee6a4SAndroid Build Coastguard Worker // defined.
324*bb4ee6a4SAndroid Build Coastguard Worker //
325*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
326*bb4ee6a4SAndroid Build Coastguard Worker // exit() is trivially safe.
327*bb4ee6a4SAndroid Build Coastguard Worker // ! Never returns
328*bb4ee6a4SAndroid Build Coastguard Worker unsafe { libc::exit(0) };
329*bb4ee6a4SAndroid Build Coastguard Worker })?;
330*bb4ee6a4SAndroid Build Coastguard Worker
331*bb4ee6a4SAndroid Build Coastguard Worker // Suppress the no waiting warning from `base::sys::linux::process::Child` because crosvm
332*bb4ee6a4SAndroid Build Coastguard Worker // does not wait for the processes from ProxyDevice explicitly. Instead it reaps all the
333*bb4ee6a4SAndroid Build Coastguard Worker // child processes on its exit by `crosvm::sys::linux::main::wait_all_children()`.
334*bb4ee6a4SAndroid Build Coastguard Worker let pid = child_process.into_pid();
335*bb4ee6a4SAndroid Build Coastguard Worker
336*bb4ee6a4SAndroid Build Coastguard Worker Ok(ChildProcIntf {
337*bb4ee6a4SAndroid Build Coastguard Worker tube: parent_tube,
338*bb4ee6a4SAndroid Build Coastguard Worker pid,
339*bb4ee6a4SAndroid Build Coastguard Worker debug_label,
340*bb4ee6a4SAndroid Build Coastguard Worker })
341*bb4ee6a4SAndroid Build Coastguard Worker }
342*bb4ee6a4SAndroid Build Coastguard Worker }
343*bb4ee6a4SAndroid Build Coastguard Worker
344*bb4ee6a4SAndroid Build Coastguard Worker /// Wraps an inner `BusDevice` that is run inside a child process via fork.
345*bb4ee6a4SAndroid Build Coastguard Worker ///
346*bb4ee6a4SAndroid Build Coastguard Worker /// The forked device process will automatically be terminated when this is dropped.
347*bb4ee6a4SAndroid Build Coastguard Worker pub struct ProxyDevice {
348*bb4ee6a4SAndroid Build Coastguard Worker child_proc_intf: ChildProcIntf,
349*bb4ee6a4SAndroid Build Coastguard Worker }
350*bb4ee6a4SAndroid Build Coastguard Worker
351*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<ChildProcIntf> for ProxyDevice {
352*bb4ee6a4SAndroid Build Coastguard Worker type Error = Error;
try_from(child_proc_intf: ChildProcIntf) -> Result<Self>353*bb4ee6a4SAndroid Build Coastguard Worker fn try_from(child_proc_intf: ChildProcIntf) -> Result<Self> {
354*bb4ee6a4SAndroid Build Coastguard Worker // Notify child process to be activated as a BusDevice.
355*bb4ee6a4SAndroid Build Coastguard Worker child_proc_intf.tube.send(&Command::Activate)?;
356*bb4ee6a4SAndroid Build Coastguard Worker // Device returns Ok if it is activated only once.
357*bb4ee6a4SAndroid Build Coastguard Worker match child_proc_intf.tube.recv()? {
358*bb4ee6a4SAndroid Build Coastguard Worker CommandResult::Ok => Ok(Self { child_proc_intf }),
359*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(Error::ActivatingProxyDevice),
360*bb4ee6a4SAndroid Build Coastguard Worker }
361*bb4ee6a4SAndroid Build Coastguard Worker }
362*bb4ee6a4SAndroid Build Coastguard Worker }
363*bb4ee6a4SAndroid Build Coastguard Worker
364*bb4ee6a4SAndroid Build Coastguard Worker impl ProxyDevice {
365*bb4ee6a4SAndroid Build Coastguard Worker /// Takes the given device and isolates it into another process via fork before returning.
366*bb4ee6a4SAndroid Build Coastguard Worker ///
367*bb4ee6a4SAndroid Build Coastguard Worker /// Because forks are very unfriendly to destructors and all memory mappings and file
368*bb4ee6a4SAndroid Build Coastguard Worker /// descriptors are inherited, this should be used as early as possible in the main process.
369*bb4ee6a4SAndroid Build Coastguard Worker /// ProxyDevice::new shall not be used for hotplugging. Call ChildProcIntf::new on jail warden
370*bb4ee6a4SAndroid Build Coastguard Worker /// process, send using serde, then cast into ProxyDevice instead.
371*bb4ee6a4SAndroid Build Coastguard Worker ///
372*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
373*bb4ee6a4SAndroid Build Coastguard Worker /// * `device` - The device to isolate to another process.
374*bb4ee6a4SAndroid Build Coastguard Worker /// * `jail` - The jail to use for isolating the given device.
375*bb4ee6a4SAndroid Build Coastguard Worker /// * `keep_rds` - File descriptors that will be kept open in the child.
new<D: BusDevice, #[cfg(feature = "swap")] P: swap::PrepareFork>( device: D, jail: Minijail, keep_rds: Vec<RawDescriptor>, #[cfg(feature = "swap")] swap_prepare_fork: &mut Option<P>, ) -> Result<ProxyDevice>376*bb4ee6a4SAndroid Build Coastguard Worker pub fn new<D: BusDevice, #[cfg(feature = "swap")] P: swap::PrepareFork>(
377*bb4ee6a4SAndroid Build Coastguard Worker device: D,
378*bb4ee6a4SAndroid Build Coastguard Worker jail: Minijail,
379*bb4ee6a4SAndroid Build Coastguard Worker keep_rds: Vec<RawDescriptor>,
380*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_prepare_fork: &mut Option<P>,
381*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ProxyDevice> {
382*bb4ee6a4SAndroid Build Coastguard Worker ChildProcIntf::new(
383*bb4ee6a4SAndroid Build Coastguard Worker device,
384*bb4ee6a4SAndroid Build Coastguard Worker jail,
385*bb4ee6a4SAndroid Build Coastguard Worker keep_rds,
386*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
387*bb4ee6a4SAndroid Build Coastguard Worker swap_prepare_fork,
388*bb4ee6a4SAndroid Build Coastguard Worker )?
389*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
390*bb4ee6a4SAndroid Build Coastguard Worker }
391*bb4ee6a4SAndroid Build Coastguard Worker
pid(&self) -> pid_t392*bb4ee6a4SAndroid Build Coastguard Worker pub fn pid(&self) -> pid_t {
393*bb4ee6a4SAndroid Build Coastguard Worker self.child_proc_intf.pid
394*bb4ee6a4SAndroid Build Coastguard Worker }
395*bb4ee6a4SAndroid Build Coastguard Worker
396*bb4ee6a4SAndroid Build Coastguard Worker /// Send a command that does not expect a response from the child device process.
send_no_result(&self, cmd: &Command)397*bb4ee6a4SAndroid Build Coastguard Worker fn send_no_result(&self, cmd: &Command) {
398*bb4ee6a4SAndroid Build Coastguard Worker let res = self.child_proc_intf.tube.send(cmd);
399*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = res {
400*bb4ee6a4SAndroid Build Coastguard Worker error!(
401*bb4ee6a4SAndroid Build Coastguard Worker "failed write to child device process {}: {}",
402*bb4ee6a4SAndroid Build Coastguard Worker self.child_proc_intf.debug_label, e,
403*bb4ee6a4SAndroid Build Coastguard Worker );
404*bb4ee6a4SAndroid Build Coastguard Worker }
405*bb4ee6a4SAndroid Build Coastguard Worker }
406*bb4ee6a4SAndroid Build Coastguard Worker
407*bb4ee6a4SAndroid Build Coastguard Worker /// Send a command and read its response from the child device process.
sync_send(&self, cmd: &Command) -> Option<CommandResult>408*bb4ee6a4SAndroid Build Coastguard Worker fn sync_send(&self, cmd: &Command) -> Option<CommandResult> {
409*bb4ee6a4SAndroid Build Coastguard Worker self.send_no_result(cmd);
410*bb4ee6a4SAndroid Build Coastguard Worker match self.child_proc_intf.tube.recv() {
411*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
412*bb4ee6a4SAndroid Build Coastguard Worker error!(
413*bb4ee6a4SAndroid Build Coastguard Worker "failed to read result of {:?} from child device process {}: {}",
414*bb4ee6a4SAndroid Build Coastguard Worker cmd, self.child_proc_intf.debug_label, e,
415*bb4ee6a4SAndroid Build Coastguard Worker );
416*bb4ee6a4SAndroid Build Coastguard Worker None
417*bb4ee6a4SAndroid Build Coastguard Worker }
418*bb4ee6a4SAndroid Build Coastguard Worker Ok(r) => Some(r),
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker }
421*bb4ee6a4SAndroid Build Coastguard Worker }
422*bb4ee6a4SAndroid Build Coastguard Worker
423*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for ProxyDevice {
device_id(&self) -> DeviceId424*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId {
425*bb4ee6a4SAndroid Build Coastguard Worker CrosvmDeviceId::ProxyDevice.into()
426*bb4ee6a4SAndroid Build Coastguard Worker }
427*bb4ee6a4SAndroid Build Coastguard Worker
debug_label(&self) -> String428*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String {
429*bb4ee6a4SAndroid Build Coastguard Worker self.child_proc_intf.debug_label.clone()
430*bb4ee6a4SAndroid Build Coastguard Worker }
431*bb4ee6a4SAndroid Build Coastguard Worker
config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult432*bb4ee6a4SAndroid Build Coastguard Worker fn config_register_write(
433*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
434*bb4ee6a4SAndroid Build Coastguard Worker reg_idx: usize,
435*bb4ee6a4SAndroid Build Coastguard Worker offset: u64,
436*bb4ee6a4SAndroid Build Coastguard Worker data: &[u8],
437*bb4ee6a4SAndroid Build Coastguard Worker ) -> ConfigWriteResult {
438*bb4ee6a4SAndroid Build Coastguard Worker let len = data.len() as u32;
439*bb4ee6a4SAndroid Build Coastguard Worker let mut buffer = [0u8; 4];
440*bb4ee6a4SAndroid Build Coastguard Worker buffer[0..data.len()].clone_from_slice(data);
441*bb4ee6a4SAndroid Build Coastguard Worker let reg_idx = reg_idx as u32;
442*bb4ee6a4SAndroid Build Coastguard Worker let offset = offset as u32;
443*bb4ee6a4SAndroid Build Coastguard Worker if let Some(CommandResult::WriteConfigResult {
444*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove,
445*bb4ee6a4SAndroid Build Coastguard Worker mmio_add,
446*bb4ee6a4SAndroid Build Coastguard Worker io_remove,
447*bb4ee6a4SAndroid Build Coastguard Worker io_add,
448*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices,
449*bb4ee6a4SAndroid Build Coastguard Worker }) = self.sync_send(&Command::WriteConfig {
450*bb4ee6a4SAndroid Build Coastguard Worker reg_idx,
451*bb4ee6a4SAndroid Build Coastguard Worker offset,
452*bb4ee6a4SAndroid Build Coastguard Worker len,
453*bb4ee6a4SAndroid Build Coastguard Worker data: buffer,
454*bb4ee6a4SAndroid Build Coastguard Worker }) {
455*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
456*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove,
457*bb4ee6a4SAndroid Build Coastguard Worker mmio_add,
458*bb4ee6a4SAndroid Build Coastguard Worker io_remove,
459*bb4ee6a4SAndroid Build Coastguard Worker io_add,
460*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices,
461*bb4ee6a4SAndroid Build Coastguard Worker }
462*bb4ee6a4SAndroid Build Coastguard Worker } else {
463*bb4ee6a4SAndroid Build Coastguard Worker Default::default()
464*bb4ee6a4SAndroid Build Coastguard Worker }
465*bb4ee6a4SAndroid Build Coastguard Worker }
466*bb4ee6a4SAndroid Build Coastguard Worker
config_register_read(&self, reg_idx: usize) -> u32467*bb4ee6a4SAndroid Build Coastguard Worker fn config_register_read(&self, reg_idx: usize) -> u32 {
468*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::ReadConfig(reg_idx as u32));
469*bb4ee6a4SAndroid Build Coastguard Worker if let Some(CommandResult::ReadConfigResult(val)) = res {
470*bb4ee6a4SAndroid Build Coastguard Worker val
471*bb4ee6a4SAndroid Build Coastguard Worker } else {
472*bb4ee6a4SAndroid Build Coastguard Worker 0
473*bb4ee6a4SAndroid Build Coastguard Worker }
474*bb4ee6a4SAndroid Build Coastguard Worker }
475*bb4ee6a4SAndroid Build Coastguard Worker
init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool476*bb4ee6a4SAndroid Build Coastguard Worker fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool {
477*bb4ee6a4SAndroid Build Coastguard Worker let Ok(shmem) = shmem.try_clone() else {
478*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to clone pci config mapping shmem");
479*bb4ee6a4SAndroid Build Coastguard Worker return false;
480*bb4ee6a4SAndroid Build Coastguard Worker };
481*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::InitPciConfigMapping { shmem, base, len });
482*bb4ee6a4SAndroid Build Coastguard Worker matches!(res, Some(CommandResult::InitPciConfigMappingResult(true)))
483*bb4ee6a4SAndroid Build Coastguard Worker }
484*bb4ee6a4SAndroid Build Coastguard Worker
virtual_config_register_write(&mut self, reg_idx: usize, value: u32)485*bb4ee6a4SAndroid Build Coastguard Worker fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {
486*bb4ee6a4SAndroid Build Coastguard Worker let reg_idx = reg_idx as u32;
487*bb4ee6a4SAndroid Build Coastguard Worker self.sync_send(&Command::WriteVirtualConfig { reg_idx, value });
488*bb4ee6a4SAndroid Build Coastguard Worker }
489*bb4ee6a4SAndroid Build Coastguard Worker
virtual_config_register_read(&self, reg_idx: usize) -> u32490*bb4ee6a4SAndroid Build Coastguard Worker fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
491*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::ReadVirtualConfig(reg_idx as u32));
492*bb4ee6a4SAndroid Build Coastguard Worker if let Some(CommandResult::ReadVirtualConfigResult(val)) = res {
493*bb4ee6a4SAndroid Build Coastguard Worker val
494*bb4ee6a4SAndroid Build Coastguard Worker } else {
495*bb4ee6a4SAndroid Build Coastguard Worker 0
496*bb4ee6a4SAndroid Build Coastguard Worker }
497*bb4ee6a4SAndroid Build Coastguard Worker }
498*bb4ee6a4SAndroid Build Coastguard Worker
read(&mut self, info: BusAccessInfo, data: &mut [u8])499*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
500*bb4ee6a4SAndroid Build Coastguard Worker let len = data.len() as u32;
501*bb4ee6a4SAndroid Build Coastguard Worker if let Some(CommandResult::ReadResult(buffer)) =
502*bb4ee6a4SAndroid Build Coastguard Worker self.sync_send(&Command::Read { len, info })
503*bb4ee6a4SAndroid Build Coastguard Worker {
504*bb4ee6a4SAndroid Build Coastguard Worker let len = data.len();
505*bb4ee6a4SAndroid Build Coastguard Worker data.clone_from_slice(&buffer[0..len]);
506*bb4ee6a4SAndroid Build Coastguard Worker }
507*bb4ee6a4SAndroid Build Coastguard Worker }
508*bb4ee6a4SAndroid Build Coastguard Worker
write(&mut self, info: BusAccessInfo, data: &[u8])509*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
510*bb4ee6a4SAndroid Build Coastguard Worker let mut buffer = [0u8; 8];
511*bb4ee6a4SAndroid Build Coastguard Worker let len = data.len() as u32;
512*bb4ee6a4SAndroid Build Coastguard Worker buffer[0..data.len()].clone_from_slice(data);
513*bb4ee6a4SAndroid Build Coastguard Worker self.send_no_result(&Command::Write {
514*bb4ee6a4SAndroid Build Coastguard Worker len,
515*bb4ee6a4SAndroid Build Coastguard Worker info,
516*bb4ee6a4SAndroid Build Coastguard Worker data: buffer,
517*bb4ee6a4SAndroid Build Coastguard Worker });
518*bb4ee6a4SAndroid Build Coastguard Worker }
519*bb4ee6a4SAndroid Build Coastguard Worker
get_ranges(&self) -> Vec<(BusRange, BusType)>520*bb4ee6a4SAndroid Build Coastguard Worker fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
521*bb4ee6a4SAndroid Build Coastguard Worker if let Some(CommandResult::GetRangesResult(ranges)) = self.sync_send(&Command::GetRanges) {
522*bb4ee6a4SAndroid Build Coastguard Worker ranges
523*bb4ee6a4SAndroid Build Coastguard Worker } else {
524*bb4ee6a4SAndroid Build Coastguard Worker Default::default()
525*bb4ee6a4SAndroid Build Coastguard Worker }
526*bb4ee6a4SAndroid Build Coastguard Worker }
527*bb4ee6a4SAndroid Build Coastguard Worker
destroy_device(&mut self)528*bb4ee6a4SAndroid Build Coastguard Worker fn destroy_device(&mut self) {
529*bb4ee6a4SAndroid Build Coastguard Worker self.send_no_result(&Command::DestroyDevice);
530*bb4ee6a4SAndroid Build Coastguard Worker }
531*bb4ee6a4SAndroid Build Coastguard Worker }
532*bb4ee6a4SAndroid Build Coastguard Worker
533*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for ProxyDevice {
snapshot(&mut self) -> anyhow::Result<serde_json::Value>534*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
535*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::Snapshot);
536*bb4ee6a4SAndroid Build Coastguard Worker match res {
537*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::SnapshotResult(Ok(snap))) => Ok(snap),
538*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::SnapshotResult(Err(e))) => Err(anyhow!(
539*bb4ee6a4SAndroid Build Coastguard Worker "failed to snapshot {}: {:#}",
540*bb4ee6a4SAndroid Build Coastguard Worker self.debug_label(),
541*bb4ee6a4SAndroid Build Coastguard Worker e
542*bb4ee6a4SAndroid Build Coastguard Worker )),
543*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(anyhow!("unexpected snapshot result {:?}", res)),
544*bb4ee6a4SAndroid Build Coastguard Worker }
545*bb4ee6a4SAndroid Build Coastguard Worker }
546*bb4ee6a4SAndroid Build Coastguard Worker
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>547*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
548*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::Restore { data });
549*bb4ee6a4SAndroid Build Coastguard Worker match res {
550*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::RestoreResult(Ok(()))) => Ok(()),
551*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::RestoreResult(Err(e))) => {
552*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow!("failed to restore {}: {:#}", self.debug_label(), e))
553*bb4ee6a4SAndroid Build Coastguard Worker }
554*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(anyhow!("unexpected restore result {:?}", res)),
555*bb4ee6a4SAndroid Build Coastguard Worker }
556*bb4ee6a4SAndroid Build Coastguard Worker }
557*bb4ee6a4SAndroid Build Coastguard Worker
sleep(&mut self) -> anyhow::Result<()>558*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> {
559*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::Sleep);
560*bb4ee6a4SAndroid Build Coastguard Worker match res {
561*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::SleepResult(Ok(()))) => Ok(()),
562*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::SleepResult(Err(e))) => {
563*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow!("failed to sleep {}: {:#}", self.debug_label(), e))
564*bb4ee6a4SAndroid Build Coastguard Worker }
565*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(anyhow!("unexpected sleep result {:?}", res)),
566*bb4ee6a4SAndroid Build Coastguard Worker }
567*bb4ee6a4SAndroid Build Coastguard Worker }
568*bb4ee6a4SAndroid Build Coastguard Worker
wake(&mut self) -> anyhow::Result<()>569*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> {
570*bb4ee6a4SAndroid Build Coastguard Worker let res = self.sync_send(&Command::Wake);
571*bb4ee6a4SAndroid Build Coastguard Worker match res {
572*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::WakeResult(Ok(()))) => Ok(()),
573*bb4ee6a4SAndroid Build Coastguard Worker Some(CommandResult::WakeResult(Err(e))) => {
574*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow!("failed to wake {}: {:#}", self.debug_label(), e))
575*bb4ee6a4SAndroid Build Coastguard Worker }
576*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(anyhow!("unexpected wake result {:?}", res)),
577*bb4ee6a4SAndroid Build Coastguard Worker }
578*bb4ee6a4SAndroid Build Coastguard Worker }
579*bb4ee6a4SAndroid Build Coastguard Worker }
580*bb4ee6a4SAndroid Build Coastguard Worker
581*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for ProxyDevice {
drop(&mut self)582*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
583*bb4ee6a4SAndroid Build Coastguard Worker self.sync_send(&Command::Shutdown);
584*bb4ee6a4SAndroid Build Coastguard Worker }
585*bb4ee6a4SAndroid Build Coastguard Worker }
586*bb4ee6a4SAndroid Build Coastguard Worker
587*bb4ee6a4SAndroid Build Coastguard Worker /// Note: These tests must be run with --test-threads=1 to allow minijail to fork
588*bb4ee6a4SAndroid Build Coastguard Worker /// the process.
589*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
590*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
591*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
592*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciId;
593*bb4ee6a4SAndroid Build Coastguard Worker
594*bb4ee6a4SAndroid Build Coastguard Worker /// A simple test echo device that outputs the same u8 that was written to it.
595*bb4ee6a4SAndroid Build Coastguard Worker struct EchoDevice {
596*bb4ee6a4SAndroid Build Coastguard Worker data: u8,
597*bb4ee6a4SAndroid Build Coastguard Worker config: u8,
598*bb4ee6a4SAndroid Build Coastguard Worker }
599*bb4ee6a4SAndroid Build Coastguard Worker impl EchoDevice {
new() -> EchoDevice600*bb4ee6a4SAndroid Build Coastguard Worker fn new() -> EchoDevice {
601*bb4ee6a4SAndroid Build Coastguard Worker EchoDevice { data: 0, config: 0 }
602*bb4ee6a4SAndroid Build Coastguard Worker }
603*bb4ee6a4SAndroid Build Coastguard Worker }
604*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for EchoDevice {
device_id(&self) -> DeviceId605*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId {
606*bb4ee6a4SAndroid Build Coastguard Worker PciId::new(0, 0).into()
607*bb4ee6a4SAndroid Build Coastguard Worker }
608*bb4ee6a4SAndroid Build Coastguard Worker
debug_label(&self) -> String609*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String {
610*bb4ee6a4SAndroid Build Coastguard Worker "EchoDevice".to_owned()
611*bb4ee6a4SAndroid Build Coastguard Worker }
612*bb4ee6a4SAndroid Build Coastguard Worker
write(&mut self, _info: BusAccessInfo, data: &[u8])613*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, _info: BusAccessInfo, data: &[u8]) {
614*bb4ee6a4SAndroid Build Coastguard Worker assert!(data.len() == 1);
615*bb4ee6a4SAndroid Build Coastguard Worker self.data = data[0];
616*bb4ee6a4SAndroid Build Coastguard Worker }
617*bb4ee6a4SAndroid Build Coastguard Worker
read(&mut self, _info: BusAccessInfo, data: &mut [u8])618*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, _info: BusAccessInfo, data: &mut [u8]) {
619*bb4ee6a4SAndroid Build Coastguard Worker assert!(data.len() == 1);
620*bb4ee6a4SAndroid Build Coastguard Worker data[0] = self.data;
621*bb4ee6a4SAndroid Build Coastguard Worker }
622*bb4ee6a4SAndroid Build Coastguard Worker
config_register_write( &mut self, _reg_idx: usize, _offset: u64, data: &[u8], ) -> ConfigWriteResult623*bb4ee6a4SAndroid Build Coastguard Worker fn config_register_write(
624*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
625*bb4ee6a4SAndroid Build Coastguard Worker _reg_idx: usize,
626*bb4ee6a4SAndroid Build Coastguard Worker _offset: u64,
627*bb4ee6a4SAndroid Build Coastguard Worker data: &[u8],
628*bb4ee6a4SAndroid Build Coastguard Worker ) -> ConfigWriteResult {
629*bb4ee6a4SAndroid Build Coastguard Worker let result = ConfigWriteResult {
630*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
631*bb4ee6a4SAndroid Build Coastguard Worker };
632*bb4ee6a4SAndroid Build Coastguard Worker assert!(data.len() == 1);
633*bb4ee6a4SAndroid Build Coastguard Worker self.config = data[0];
634*bb4ee6a4SAndroid Build Coastguard Worker result
635*bb4ee6a4SAndroid Build Coastguard Worker }
636*bb4ee6a4SAndroid Build Coastguard Worker
config_register_read(&self, _reg_idx: usize) -> u32637*bb4ee6a4SAndroid Build Coastguard Worker fn config_register_read(&self, _reg_idx: usize) -> u32 {
638*bb4ee6a4SAndroid Build Coastguard Worker self.config as u32
639*bb4ee6a4SAndroid Build Coastguard Worker }
640*bb4ee6a4SAndroid Build Coastguard Worker }
641*bb4ee6a4SAndroid Build Coastguard Worker
642*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for EchoDevice {}
643*bb4ee6a4SAndroid Build Coastguard Worker
new_proxied_echo_device() -> ProxyDevice644*bb4ee6a4SAndroid Build Coastguard Worker fn new_proxied_echo_device() -> ProxyDevice {
645*bb4ee6a4SAndroid Build Coastguard Worker let device = EchoDevice::new();
646*bb4ee6a4SAndroid Build Coastguard Worker let keep_fds: Vec<RawDescriptor> = Vec::new();
647*bb4ee6a4SAndroid Build Coastguard Worker let minijail = Minijail::new().unwrap();
648*bb4ee6a4SAndroid Build Coastguard Worker ProxyDevice::new(
649*bb4ee6a4SAndroid Build Coastguard Worker device,
650*bb4ee6a4SAndroid Build Coastguard Worker minijail,
651*bb4ee6a4SAndroid Build Coastguard Worker keep_fds,
652*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
653*bb4ee6a4SAndroid Build Coastguard Worker &mut None::<swap::SwapController>,
654*bb4ee6a4SAndroid Build Coastguard Worker )
655*bb4ee6a4SAndroid Build Coastguard Worker .unwrap()
656*bb4ee6a4SAndroid Build Coastguard Worker }
657*bb4ee6a4SAndroid Build Coastguard Worker
658*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/173833661): Find a way to ensure these tests are run single-threaded.
659*bb4ee6a4SAndroid Build Coastguard Worker #[test]
660*bb4ee6a4SAndroid Build Coastguard Worker #[ignore]
test_debug_label()661*bb4ee6a4SAndroid Build Coastguard Worker fn test_debug_label() {
662*bb4ee6a4SAndroid Build Coastguard Worker let proxy_device = new_proxied_echo_device();
663*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(proxy_device.debug_label(), "EchoDevice");
664*bb4ee6a4SAndroid Build Coastguard Worker }
665*bb4ee6a4SAndroid Build Coastguard Worker
666*bb4ee6a4SAndroid Build Coastguard Worker #[test]
667*bb4ee6a4SAndroid Build Coastguard Worker #[ignore]
test_proxied_read_write()668*bb4ee6a4SAndroid Build Coastguard Worker fn test_proxied_read_write() {
669*bb4ee6a4SAndroid Build Coastguard Worker let mut proxy_device = new_proxied_echo_device();
670*bb4ee6a4SAndroid Build Coastguard Worker let address = BusAccessInfo {
671*bb4ee6a4SAndroid Build Coastguard Worker offset: 0,
672*bb4ee6a4SAndroid Build Coastguard Worker address: 0,
673*bb4ee6a4SAndroid Build Coastguard Worker id: 0,
674*bb4ee6a4SAndroid Build Coastguard Worker };
675*bb4ee6a4SAndroid Build Coastguard Worker proxy_device.write(address, &[42]);
676*bb4ee6a4SAndroid Build Coastguard Worker let mut read_buffer = [0];
677*bb4ee6a4SAndroid Build Coastguard Worker proxy_device.read(address, &mut read_buffer);
678*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(read_buffer, [42]);
679*bb4ee6a4SAndroid Build Coastguard Worker }
680*bb4ee6a4SAndroid Build Coastguard Worker
681*bb4ee6a4SAndroid Build Coastguard Worker #[test]
682*bb4ee6a4SAndroid Build Coastguard Worker #[ignore]
test_proxied_config()683*bb4ee6a4SAndroid Build Coastguard Worker fn test_proxied_config() {
684*bb4ee6a4SAndroid Build Coastguard Worker let mut proxy_device = new_proxied_echo_device();
685*bb4ee6a4SAndroid Build Coastguard Worker proxy_device.config_register_write(0, 0, &[42]);
686*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(proxy_device.config_register_read(0), 42);
687*bb4ee6a4SAndroid Build Coastguard Worker }
688*bb4ee6a4SAndroid Build Coastguard Worker }
689