xref: /aosp_15_r20/external/crosvm/devices/src/proxy.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 //! 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