xref: /aosp_15_r20/external/crosvm/devices/src/virtio/vhost/vsock.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 use std::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::prelude::OpenOptionsExt;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
10*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::open_file_or_duplicate;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
18*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le64;
19*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
20*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
21*bb4ee6a4SAndroid Build Coastguard Worker use vhost::Vhost;
22*bb4ee6a4SAndroid Build Coastguard Worker use vhost::Vsock as VhostVsockHandle;
23*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
24*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker use super::worker::VringBase;
27*bb4ee6a4SAndroid Build Coastguard Worker use super::worker::Worker;
28*bb4ee6a4SAndroid Build Coastguard Worker use super::Error;
29*bb4ee6a4SAndroid Build Coastguard Worker use super::Result;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::copy_config;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::device_constants::vsock::NUM_QUEUES;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::vsock::VsockConfig;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::DeviceType;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::Interrupt;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::Queue;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::VirtioDevice;
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZE: u16 = 256;
39*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE; NUM_QUEUES];
40*bb4ee6a4SAndroid Build Coastguard Worker 
41*bb4ee6a4SAndroid Build Coastguard Worker pub struct Vsock {
42*bb4ee6a4SAndroid Build Coastguard Worker     worker_thread: Option<WorkerThread<Worker<VhostVsockHandle>>>,
43*bb4ee6a4SAndroid Build Coastguard Worker     vhost_handle: Option<VhostVsockHandle>,
44*bb4ee6a4SAndroid Build Coastguard Worker     cid: u64,
45*bb4ee6a4SAndroid Build Coastguard Worker     interrupts: Option<Vec<Event>>,
46*bb4ee6a4SAndroid Build Coastguard Worker     avail_features: u64,
47*bb4ee6a4SAndroid Build Coastguard Worker     acked_features: u64,
48*bb4ee6a4SAndroid Build Coastguard Worker     // vrings_base states:
49*bb4ee6a4SAndroid Build Coastguard Worker     // None - device was just created or is running.
50*bb4ee6a4SAndroid Build Coastguard Worker     // Some - device was put to sleep after running or was restored.
51*bb4ee6a4SAndroid Build Coastguard Worker     vrings_base: Option<Vec<VringBase>>,
52*bb4ee6a4SAndroid Build Coastguard Worker     // Some iff the device is active and awake.
53*bb4ee6a4SAndroid Build Coastguard Worker     event_queue: Option<Queue>,
54*bb4ee6a4SAndroid Build Coastguard Worker     // If true, we should send a TRANSPORT_RESET event to the guest at the next opportunity.
55*bb4ee6a4SAndroid Build Coastguard Worker     needs_transport_reset: bool,
56*bb4ee6a4SAndroid Build Coastguard Worker }
57*bb4ee6a4SAndroid Build Coastguard Worker 
58*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
59*bb4ee6a4SAndroid Build Coastguard Worker struct VsockSnapshot {
60*bb4ee6a4SAndroid Build Coastguard Worker     cid: u64,
61*bb4ee6a4SAndroid Build Coastguard Worker     avail_features: u64,
62*bb4ee6a4SAndroid Build Coastguard Worker     acked_features: u64,
63*bb4ee6a4SAndroid Build Coastguard Worker     vrings_base: Vec<VringBase>,
64*bb4ee6a4SAndroid Build Coastguard Worker }
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker impl Vsock {
67*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new virtio-vsock device with the given VM cid.
new(base_features: u64, vsock_config: &VsockConfig) -> anyhow::Result<Vsock>68*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(base_features: u64, vsock_config: &VsockConfig) -> anyhow::Result<Vsock> {
69*bb4ee6a4SAndroid Build Coastguard Worker         let device_file = open_file_or_duplicate(
70*bb4ee6a4SAndroid Build Coastguard Worker             &vsock_config.vhost_device,
71*bb4ee6a4SAndroid Build Coastguard Worker             OpenOptions::new()
72*bb4ee6a4SAndroid Build Coastguard Worker                 .read(true)
73*bb4ee6a4SAndroid Build Coastguard Worker                 .write(true)
74*bb4ee6a4SAndroid Build Coastguard Worker                 .custom_flags(libc::O_CLOEXEC | libc::O_NONBLOCK),
75*bb4ee6a4SAndroid Build Coastguard Worker         )
76*bb4ee6a4SAndroid Build Coastguard Worker         .with_context(|| {
77*bb4ee6a4SAndroid Build Coastguard Worker             format!(
78*bb4ee6a4SAndroid Build Coastguard Worker                 "failed to open virtual socket device {}",
79*bb4ee6a4SAndroid Build Coastguard Worker                 vsock_config.vhost_device.display(),
80*bb4ee6a4SAndroid Build Coastguard Worker             )
81*bb4ee6a4SAndroid Build Coastguard Worker         })?;
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker         let handle = VhostVsockHandle::new(device_file);
84*bb4ee6a4SAndroid Build Coastguard Worker 
85*bb4ee6a4SAndroid Build Coastguard Worker         let avail_features = base_features;
86*bb4ee6a4SAndroid Build Coastguard Worker 
87*bb4ee6a4SAndroid Build Coastguard Worker         let mut interrupts = Vec::new();
88*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..NUM_QUEUES {
89*bb4ee6a4SAndroid Build Coastguard Worker             interrupts.push(Event::new().map_err(Error::VhostIrqCreate)?);
90*bb4ee6a4SAndroid Build Coastguard Worker         }
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Vsock {
93*bb4ee6a4SAndroid Build Coastguard Worker             worker_thread: None,
94*bb4ee6a4SAndroid Build Coastguard Worker             vhost_handle: Some(handle),
95*bb4ee6a4SAndroid Build Coastguard Worker             cid: vsock_config.cid,
96*bb4ee6a4SAndroid Build Coastguard Worker             interrupts: Some(interrupts),
97*bb4ee6a4SAndroid Build Coastguard Worker             avail_features,
98*bb4ee6a4SAndroid Build Coastguard Worker             acked_features: 0,
99*bb4ee6a4SAndroid Build Coastguard Worker             vrings_base: None,
100*bb4ee6a4SAndroid Build Coastguard Worker             event_queue: None,
101*bb4ee6a4SAndroid Build Coastguard Worker             needs_transport_reset: false,
102*bb4ee6a4SAndroid Build Coastguard Worker         })
103*bb4ee6a4SAndroid Build Coastguard Worker     }
104*bb4ee6a4SAndroid Build Coastguard Worker 
new_for_testing(cid: u64, features: u64) -> Vsock105*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_for_testing(cid: u64, features: u64) -> Vsock {
106*bb4ee6a4SAndroid Build Coastguard Worker         Vsock {
107*bb4ee6a4SAndroid Build Coastguard Worker             worker_thread: None,
108*bb4ee6a4SAndroid Build Coastguard Worker             vhost_handle: None,
109*bb4ee6a4SAndroid Build Coastguard Worker             cid,
110*bb4ee6a4SAndroid Build Coastguard Worker             interrupts: None,
111*bb4ee6a4SAndroid Build Coastguard Worker             avail_features: features,
112*bb4ee6a4SAndroid Build Coastguard Worker             acked_features: 0,
113*bb4ee6a4SAndroid Build Coastguard Worker             vrings_base: None,
114*bb4ee6a4SAndroid Build Coastguard Worker             event_queue: None,
115*bb4ee6a4SAndroid Build Coastguard Worker             needs_transport_reset: false,
116*bb4ee6a4SAndroid Build Coastguard Worker         }
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker 
acked_features(&self) -> u64119*bb4ee6a4SAndroid Build Coastguard Worker     pub fn acked_features(&self) -> u64 {
120*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features
121*bb4ee6a4SAndroid Build Coastguard Worker     }
122*bb4ee6a4SAndroid Build Coastguard Worker }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker impl VirtioDevice for Vsock {
keep_rds(&self) -> Vec<RawDescriptor>125*bb4ee6a4SAndroid Build Coastguard Worker     fn keep_rds(&self) -> Vec<RawDescriptor> {
126*bb4ee6a4SAndroid Build Coastguard Worker         let mut keep_rds = Vec::new();
127*bb4ee6a4SAndroid Build Coastguard Worker 
128*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(handle) = &self.vhost_handle {
129*bb4ee6a4SAndroid Build Coastguard Worker             keep_rds.push(handle.as_raw_descriptor());
130*bb4ee6a4SAndroid Build Coastguard Worker         }
131*bb4ee6a4SAndroid Build Coastguard Worker 
132*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(interrupt) = &self.interrupts {
133*bb4ee6a4SAndroid Build Coastguard Worker             for vhost_int in interrupt.iter() {
134*bb4ee6a4SAndroid Build Coastguard Worker                 keep_rds.push(vhost_int.as_raw_descriptor());
135*bb4ee6a4SAndroid Build Coastguard Worker             }
136*bb4ee6a4SAndroid Build Coastguard Worker         }
137*bb4ee6a4SAndroid Build Coastguard Worker 
138*bb4ee6a4SAndroid Build Coastguard Worker         keep_rds
139*bb4ee6a4SAndroid Build Coastguard Worker     }
140*bb4ee6a4SAndroid Build Coastguard Worker 
device_type(&self) -> DeviceType141*bb4ee6a4SAndroid Build Coastguard Worker     fn device_type(&self) -> DeviceType {
142*bb4ee6a4SAndroid Build Coastguard Worker         DeviceType::Vsock
143*bb4ee6a4SAndroid Build Coastguard Worker     }
144*bb4ee6a4SAndroid Build Coastguard Worker 
queue_max_sizes(&self) -> &[u16]145*bb4ee6a4SAndroid Build Coastguard Worker     fn queue_max_sizes(&self) -> &[u16] {
146*bb4ee6a4SAndroid Build Coastguard Worker         QUEUE_SIZES
147*bb4ee6a4SAndroid Build Coastguard Worker     }
148*bb4ee6a4SAndroid Build Coastguard Worker 
features(&self) -> u64149*bb4ee6a4SAndroid Build Coastguard Worker     fn features(&self) -> u64 {
150*bb4ee6a4SAndroid Build Coastguard Worker         self.avail_features
151*bb4ee6a4SAndroid Build Coastguard Worker     }
152*bb4ee6a4SAndroid Build Coastguard Worker 
read_config(&self, offset: u64, data: &mut [u8])153*bb4ee6a4SAndroid Build Coastguard Worker     fn read_config(&self, offset: u64, data: &mut [u8]) {
154*bb4ee6a4SAndroid Build Coastguard Worker         let cid = Le64::from(self.cid);
155*bb4ee6a4SAndroid Build Coastguard Worker         copy_config(data, 0, cid.as_bytes(), offset);
156*bb4ee6a4SAndroid Build Coastguard Worker     }
157*bb4ee6a4SAndroid Build Coastguard Worker 
ack_features(&mut self, value: u64)158*bb4ee6a4SAndroid Build Coastguard Worker     fn ack_features(&mut self, value: u64) {
159*bb4ee6a4SAndroid Build Coastguard Worker         let mut v = value;
160*bb4ee6a4SAndroid Build Coastguard Worker 
161*bb4ee6a4SAndroid Build Coastguard Worker         // Check if the guest is ACK'ing a feature that we didn't claim to have.
162*bb4ee6a4SAndroid Build Coastguard Worker         let unrequested_features = v & !self.avail_features;
163*bb4ee6a4SAndroid Build Coastguard Worker         if unrequested_features != 0 {
164*bb4ee6a4SAndroid Build Coastguard Worker             warn!("vsock: virtio-vsock got unknown feature ack: {:x}", v);
165*bb4ee6a4SAndroid Build Coastguard Worker 
166*bb4ee6a4SAndroid Build Coastguard Worker             // Don't count these features as acked.
167*bb4ee6a4SAndroid Build Coastguard Worker             v &= !unrequested_features;
168*bb4ee6a4SAndroid Build Coastguard Worker         }
169*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features |= v;
170*bb4ee6a4SAndroid Build Coastguard Worker     }
171*bb4ee6a4SAndroid Build Coastguard Worker 
activate( &mut self, mem: GuestMemory, interrupt: Interrupt, mut queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>172*bb4ee6a4SAndroid Build Coastguard Worker     fn activate(
173*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
174*bb4ee6a4SAndroid Build Coastguard Worker         mem: GuestMemory,
175*bb4ee6a4SAndroid Build Coastguard Worker         interrupt: Interrupt,
176*bb4ee6a4SAndroid Build Coastguard Worker         mut queues: BTreeMap<usize, Queue>,
177*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
178*bb4ee6a4SAndroid Build Coastguard Worker         if queues.len() != NUM_QUEUES {
179*bb4ee6a4SAndroid Build Coastguard Worker             return Err(anyhow!(
180*bb4ee6a4SAndroid Build Coastguard Worker                 "net: expected {} queues, got {}",
181*bb4ee6a4SAndroid Build Coastguard Worker                 NUM_QUEUES,
182*bb4ee6a4SAndroid Build Coastguard Worker                 queues.len()
183*bb4ee6a4SAndroid Build Coastguard Worker             ));
184*bb4ee6a4SAndroid Build Coastguard Worker         }
185*bb4ee6a4SAndroid Build Coastguard Worker 
186*bb4ee6a4SAndroid Build Coastguard Worker         let vhost_handle = self.vhost_handle.take().context("missing vhost_handle")?;
187*bb4ee6a4SAndroid Build Coastguard Worker         let interrupts = self.interrupts.take().context("missing interrupts")?;
188*bb4ee6a4SAndroid Build Coastguard Worker         let acked_features = self.acked_features;
189*bb4ee6a4SAndroid Build Coastguard Worker         let cid = self.cid;
190*bb4ee6a4SAndroid Build Coastguard Worker 
191*bb4ee6a4SAndroid Build Coastguard Worker         // The third vq is an event-only vq that is not handled by the vhost
192*bb4ee6a4SAndroid Build Coastguard Worker         // subsystem (but still needs to exist).  Split it off here.
193*bb4ee6a4SAndroid Build Coastguard Worker         let mut event_queue = queues.remove(&2).unwrap();
194*bb4ee6a4SAndroid Build Coastguard Worker         // Send TRANSPORT_RESET event if needed.
195*bb4ee6a4SAndroid Build Coastguard Worker         if self.needs_transport_reset {
196*bb4ee6a4SAndroid Build Coastguard Worker             self.needs_transport_reset = false;
197*bb4ee6a4SAndroid Build Coastguard Worker 
198*bb4ee6a4SAndroid Build Coastguard Worker             // We assume the event queue is non-empty. This should be OK for existing use cases
199*bb4ee6a4SAndroid Build Coastguard Worker             // because we expect the guest vsock driver to be initialized at the time of snapshot
200*bb4ee6a4SAndroid Build Coastguard Worker             // and this is only the event we ever write to the queue.
201*bb4ee6a4SAndroid Build Coastguard Worker             //
202*bb4ee6a4SAndroid Build Coastguard Worker             // If that assumption becomes invalid, we could integrate this logic into the worker
203*bb4ee6a4SAndroid Build Coastguard Worker             // thread's event loop so that it can wait for space in the queue.
204*bb4ee6a4SAndroid Build Coastguard Worker             let mut avail_desc = event_queue
205*bb4ee6a4SAndroid Build Coastguard Worker                 .pop()
206*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("event queue is empty, can't send transport reset event");
207*bb4ee6a4SAndroid Build Coastguard Worker             let transport_reset = virtio_sys::virtio_vsock::virtio_vsock_event{
208*bb4ee6a4SAndroid Build Coastguard Worker                 id: virtio_sys::virtio_vsock::virtio_vsock_event_id_VIRTIO_VSOCK_EVENT_TRANSPORT_RESET.into(),
209*bb4ee6a4SAndroid Build Coastguard Worker             };
210*bb4ee6a4SAndroid Build Coastguard Worker             avail_desc
211*bb4ee6a4SAndroid Build Coastguard Worker                 .writer
212*bb4ee6a4SAndroid Build Coastguard Worker                 .write_obj(transport_reset)
213*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to write transport reset event");
214*bb4ee6a4SAndroid Build Coastguard Worker             let len = avail_desc.writer.bytes_written() as u32;
215*bb4ee6a4SAndroid Build Coastguard Worker             event_queue.add_used(avail_desc, len);
216*bb4ee6a4SAndroid Build Coastguard Worker             event_queue.trigger_interrupt();
217*bb4ee6a4SAndroid Build Coastguard Worker         }
218*bb4ee6a4SAndroid Build Coastguard Worker         self.event_queue = Some(event_queue);
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker         let mut worker = Worker::new(
221*bb4ee6a4SAndroid Build Coastguard Worker             queues,
222*bb4ee6a4SAndroid Build Coastguard Worker             vhost_handle,
223*bb4ee6a4SAndroid Build Coastguard Worker             interrupts,
224*bb4ee6a4SAndroid Build Coastguard Worker             interrupt,
225*bb4ee6a4SAndroid Build Coastguard Worker             acked_features,
226*bb4ee6a4SAndroid Build Coastguard Worker             None,
227*bb4ee6a4SAndroid Build Coastguard Worker         );
228*bb4ee6a4SAndroid Build Coastguard Worker         let activate_vqs = |handle: &VhostVsockHandle| -> Result<()> {
229*bb4ee6a4SAndroid Build Coastguard Worker             handle.set_cid(cid).map_err(Error::VhostVsockSetCid)?;
230*bb4ee6a4SAndroid Build Coastguard Worker             handle.start().map_err(Error::VhostVsockStart)?;
231*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
232*bb4ee6a4SAndroid Build Coastguard Worker         };
233*bb4ee6a4SAndroid Build Coastguard Worker         worker
234*bb4ee6a4SAndroid Build Coastguard Worker             .init(mem, QUEUE_SIZES, activate_vqs, self.vrings_base.take())
235*bb4ee6a4SAndroid Build Coastguard Worker             .context("vsock worker init exited with error")?;
236*bb4ee6a4SAndroid Build Coastguard Worker 
237*bb4ee6a4SAndroid Build Coastguard Worker         self.worker_thread = Some(WorkerThread::start("vhost_vsock", move |kill_evt| {
238*bb4ee6a4SAndroid Build Coastguard Worker             let cleanup_vqs = |_handle: &VhostVsockHandle| -> Result<()> { Ok(()) };
239*bb4ee6a4SAndroid Build Coastguard Worker             let result = worker.run(cleanup_vqs, kill_evt);
240*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = result {
241*bb4ee6a4SAndroid Build Coastguard Worker                 error!("vsock worker thread exited with error: {:?}", e);
242*bb4ee6a4SAndroid Build Coastguard Worker             }
243*bb4ee6a4SAndroid Build Coastguard Worker             worker
244*bb4ee6a4SAndroid Build Coastguard Worker         }));
245*bb4ee6a4SAndroid Build Coastguard Worker 
246*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
247*bb4ee6a4SAndroid Build Coastguard Worker     }
248*bb4ee6a4SAndroid Build Coastguard Worker 
reset(&mut self) -> anyhow::Result<()>249*bb4ee6a4SAndroid Build Coastguard Worker     fn reset(&mut self) -> anyhow::Result<()> {
250*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(worker_thread) = self.worker_thread.take() {
251*bb4ee6a4SAndroid Build Coastguard Worker             let worker = worker_thread.stop();
252*bb4ee6a4SAndroid Build Coastguard Worker             worker
253*bb4ee6a4SAndroid Build Coastguard Worker                 .vhost_handle
254*bb4ee6a4SAndroid Build Coastguard Worker                 .stop()
255*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to stop vrings")?;
256*bb4ee6a4SAndroid Build Coastguard Worker             // Call get_vring_base to stop the queues.
257*bb4ee6a4SAndroid Build Coastguard Worker             for (pos, _) in worker.queues.iter() {
258*bb4ee6a4SAndroid Build Coastguard Worker                 worker
259*bb4ee6a4SAndroid Build Coastguard Worker                     .vhost_handle
260*bb4ee6a4SAndroid Build Coastguard Worker                     .get_vring_base(*pos)
261*bb4ee6a4SAndroid Build Coastguard Worker                     .context("get_vring_base failed")?;
262*bb4ee6a4SAndroid Build Coastguard Worker             }
263*bb4ee6a4SAndroid Build Coastguard Worker 
264*bb4ee6a4SAndroid Build Coastguard Worker             self.vhost_handle = Some(worker.vhost_handle);
265*bb4ee6a4SAndroid Build Coastguard Worker             self.interrupts = Some(worker.vhost_interrupt);
266*bb4ee6a4SAndroid Build Coastguard Worker         }
267*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features = 0;
268*bb4ee6a4SAndroid Build Coastguard Worker         self.vrings_base = None;
269*bb4ee6a4SAndroid Build Coastguard Worker         self.event_queue = None;
270*bb4ee6a4SAndroid Build Coastguard Worker         self.needs_transport_reset = false;
271*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
272*bb4ee6a4SAndroid Build Coastguard Worker     }
273*bb4ee6a4SAndroid Build Coastguard Worker 
on_device_sandboxed(&mut self)274*bb4ee6a4SAndroid Build Coastguard Worker     fn on_device_sandboxed(&mut self) {
275*bb4ee6a4SAndroid Build Coastguard Worker         // ignore the error but to log the error. We don't need to do
276*bb4ee6a4SAndroid Build Coastguard Worker         // anything here because when activate, the other vhost set up
277*bb4ee6a4SAndroid Build Coastguard Worker         // will be failed to stop the activate thread.
278*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(vhost_handle) = &self.vhost_handle {
279*bb4ee6a4SAndroid Build Coastguard Worker             match vhost_handle.set_owner() {
280*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(_) => {}
281*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => error!("{}: failed to set owner: {:?}", self.debug_label(), e),
282*bb4ee6a4SAndroid Build Coastguard Worker             }
283*bb4ee6a4SAndroid Build Coastguard Worker         }
284*bb4ee6a4SAndroid Build Coastguard Worker     }
285*bb4ee6a4SAndroid Build Coastguard Worker 
virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>>286*bb4ee6a4SAndroid Build Coastguard Worker     fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> {
287*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(worker_thread) = self.worker_thread.take() {
288*bb4ee6a4SAndroid Build Coastguard Worker             let worker = worker_thread.stop();
289*bb4ee6a4SAndroid Build Coastguard Worker             self.interrupts = Some(worker.vhost_interrupt);
290*bb4ee6a4SAndroid Build Coastguard Worker             worker
291*bb4ee6a4SAndroid Build Coastguard Worker                 .vhost_handle
292*bb4ee6a4SAndroid Build Coastguard Worker                 .stop()
293*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to stop vrings")?;
294*bb4ee6a4SAndroid Build Coastguard Worker             let mut queues: BTreeMap<usize, Queue> = worker.queues;
295*bb4ee6a4SAndroid Build Coastguard Worker             let mut vrings_base = Vec::new();
296*bb4ee6a4SAndroid Build Coastguard Worker             for (pos, _) in queues.iter() {
297*bb4ee6a4SAndroid Build Coastguard Worker                 let vring_base = VringBase {
298*bb4ee6a4SAndroid Build Coastguard Worker                     index: *pos,
299*bb4ee6a4SAndroid Build Coastguard Worker                     base: worker.vhost_handle.get_vring_base(*pos)?,
300*bb4ee6a4SAndroid Build Coastguard Worker                 };
301*bb4ee6a4SAndroid Build Coastguard Worker                 vrings_base.push(vring_base);
302*bb4ee6a4SAndroid Build Coastguard Worker             }
303*bb4ee6a4SAndroid Build Coastguard Worker             self.vrings_base = Some(vrings_base);
304*bb4ee6a4SAndroid Build Coastguard Worker             self.vhost_handle = Some(worker.vhost_handle);
305*bb4ee6a4SAndroid Build Coastguard Worker             queues.insert(
306*bb4ee6a4SAndroid Build Coastguard Worker                 2,
307*bb4ee6a4SAndroid Build Coastguard Worker                 self.event_queue.take().expect("Vsock event queue missing"),
308*bb4ee6a4SAndroid Build Coastguard Worker             );
309*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(Some(BTreeMap::from_iter(queues)));
310*bb4ee6a4SAndroid Build Coastguard Worker         }
311*bb4ee6a4SAndroid Build Coastguard Worker         Ok(None)
312*bb4ee6a4SAndroid Build Coastguard Worker     }
313*bb4ee6a4SAndroid Build Coastguard Worker 
virtio_wake( &mut self, device_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>, ) -> anyhow::Result<()>314*bb4ee6a4SAndroid Build Coastguard Worker     fn virtio_wake(
315*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
316*bb4ee6a4SAndroid Build Coastguard Worker         device_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>,
317*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
318*bb4ee6a4SAndroid Build Coastguard Worker         match device_state {
319*bb4ee6a4SAndroid Build Coastguard Worker             None => Ok(()),
320*bb4ee6a4SAndroid Build Coastguard Worker             Some((mem, interrupt, queues)) => {
321*bb4ee6a4SAndroid Build Coastguard Worker                 // TODO: activate is just what we want at the moment, but we should probably move
322*bb4ee6a4SAndroid Build Coastguard Worker                 // it into a "start workers" function to make it obvious that it isn't strictly
323*bb4ee6a4SAndroid Build Coastguard Worker                 // used for activate events.
324*bb4ee6a4SAndroid Build Coastguard Worker                 self.activate(mem, interrupt, queues)?;
325*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(())
326*bb4ee6a4SAndroid Build Coastguard Worker             }
327*bb4ee6a4SAndroid Build Coastguard Worker         }
328*bb4ee6a4SAndroid Build Coastguard Worker     }
329*bb4ee6a4SAndroid Build Coastguard Worker 
virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value>330*bb4ee6a4SAndroid Build Coastguard Worker     fn virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
331*bb4ee6a4SAndroid Build Coastguard Worker         let vrings_base = self.vrings_base.clone().unwrap_or_default();
332*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(VsockSnapshot {
333*bb4ee6a4SAndroid Build Coastguard Worker             // `cid` and `avail_features` are snapshot as a safeguard. Upon restore, validate
334*bb4ee6a4SAndroid Build Coastguard Worker             // cid and avail_features in the current vsock match the previously snapshot vsock.
335*bb4ee6a4SAndroid Build Coastguard Worker             cid: self.cid,
336*bb4ee6a4SAndroid Build Coastguard Worker             avail_features: self.avail_features,
337*bb4ee6a4SAndroid Build Coastguard Worker             acked_features: self.acked_features,
338*bb4ee6a4SAndroid Build Coastguard Worker             vrings_base,
339*bb4ee6a4SAndroid Build Coastguard Worker         })
340*bb4ee6a4SAndroid Build Coastguard Worker         .context("failed to snapshot virtio console")
341*bb4ee6a4SAndroid Build Coastguard Worker     }
342*bb4ee6a4SAndroid Build Coastguard Worker 
virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>343*bb4ee6a4SAndroid Build Coastguard Worker     fn virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
344*bb4ee6a4SAndroid Build Coastguard Worker         let deser: VsockSnapshot =
345*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_value(data).context("failed to deserialize virtio vsock")?;
346*bb4ee6a4SAndroid Build Coastguard Worker         anyhow::ensure!(
347*bb4ee6a4SAndroid Build Coastguard Worker             self.cid == deser.cid,
348*bb4ee6a4SAndroid Build Coastguard Worker             "Virtio vsock incorrect cid for restore:\n Expected: {}, Actual: {}",
349*bb4ee6a4SAndroid Build Coastguard Worker             self.cid,
350*bb4ee6a4SAndroid Build Coastguard Worker             deser.cid,
351*bb4ee6a4SAndroid Build Coastguard Worker         );
352*bb4ee6a4SAndroid Build Coastguard Worker         anyhow::ensure!(
353*bb4ee6a4SAndroid Build Coastguard Worker             self.avail_features == deser.avail_features,
354*bb4ee6a4SAndroid Build Coastguard Worker             "Virtio vsock incorrect avail features for restore:\n Expected: {}, Actual: {}",
355*bb4ee6a4SAndroid Build Coastguard Worker             self.avail_features,
356*bb4ee6a4SAndroid Build Coastguard Worker             deser.avail_features,
357*bb4ee6a4SAndroid Build Coastguard Worker         );
358*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features = deser.acked_features;
359*bb4ee6a4SAndroid Build Coastguard Worker         self.vrings_base = Some(deser.vrings_base);
360*bb4ee6a4SAndroid Build Coastguard Worker         // Send the TRANSPORT_RESET on next wake so that the guest knows that its existing vsock
361*bb4ee6a4SAndroid Build Coastguard Worker         // connections are broken.
362*bb4ee6a4SAndroid Build Coastguard Worker         self.needs_transport_reset = true;
363*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
364*bb4ee6a4SAndroid Build Coastguard Worker     }
365*bb4ee6a4SAndroid Build Coastguard Worker }
366*bb4ee6a4SAndroid Build Coastguard Worker 
367*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
368*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
369*bb4ee6a4SAndroid Build Coastguard Worker     use std::convert::TryInto;
370*bb4ee6a4SAndroid Build Coastguard Worker 
371*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
372*bb4ee6a4SAndroid Build Coastguard Worker 
373*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
ack_features()374*bb4ee6a4SAndroid Build Coastguard Worker     fn ack_features() {
375*bb4ee6a4SAndroid Build Coastguard Worker         let cid = 5;
376*bb4ee6a4SAndroid Build Coastguard Worker         let features: u64 = (1 << 20) | (1 << 49) | (1 << 2) | (1 << 19);
377*bb4ee6a4SAndroid Build Coastguard Worker         let mut acked_features: u64 = 0;
378*bb4ee6a4SAndroid Build Coastguard Worker         let mut unavailable_features: u64 = 0;
379*bb4ee6a4SAndroid Build Coastguard Worker 
380*bb4ee6a4SAndroid Build Coastguard Worker         let mut vsock = Vsock::new_for_testing(cid, features);
381*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(acked_features, vsock.acked_features());
382*bb4ee6a4SAndroid Build Coastguard Worker 
383*bb4ee6a4SAndroid Build Coastguard Worker         acked_features |= 1 << 2;
384*bb4ee6a4SAndroid Build Coastguard Worker         vsock.ack_features(acked_features);
385*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(acked_features, vsock.acked_features());
386*bb4ee6a4SAndroid Build Coastguard Worker 
387*bb4ee6a4SAndroid Build Coastguard Worker         acked_features |= 1 << 49;
388*bb4ee6a4SAndroid Build Coastguard Worker         vsock.ack_features(acked_features);
389*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(acked_features, vsock.acked_features());
390*bb4ee6a4SAndroid Build Coastguard Worker 
391*bb4ee6a4SAndroid Build Coastguard Worker         acked_features |= 1 << 60;
392*bb4ee6a4SAndroid Build Coastguard Worker         unavailable_features |= 1 << 60;
393*bb4ee6a4SAndroid Build Coastguard Worker         vsock.ack_features(acked_features);
394*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
395*bb4ee6a4SAndroid Build Coastguard Worker             acked_features & !unavailable_features,
396*bb4ee6a4SAndroid Build Coastguard Worker             vsock.acked_features()
397*bb4ee6a4SAndroid Build Coastguard Worker         );
398*bb4ee6a4SAndroid Build Coastguard Worker 
399*bb4ee6a4SAndroid Build Coastguard Worker         acked_features |= 1 << 1;
400*bb4ee6a4SAndroid Build Coastguard Worker         unavailable_features |= 1 << 1;
401*bb4ee6a4SAndroid Build Coastguard Worker         vsock.ack_features(acked_features);
402*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
403*bb4ee6a4SAndroid Build Coastguard Worker             acked_features & !unavailable_features,
404*bb4ee6a4SAndroid Build Coastguard Worker             vsock.acked_features()
405*bb4ee6a4SAndroid Build Coastguard Worker         );
406*bb4ee6a4SAndroid Build Coastguard Worker     }
407*bb4ee6a4SAndroid Build Coastguard Worker 
408*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_config()409*bb4ee6a4SAndroid Build Coastguard Worker     fn read_config() {
410*bb4ee6a4SAndroid Build Coastguard Worker         let cid = 0xfca9a559fdcb9756;
411*bb4ee6a4SAndroid Build Coastguard Worker         let vsock = Vsock::new_for_testing(cid, 0);
412*bb4ee6a4SAndroid Build Coastguard Worker 
413*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = [0u8; 8];
414*bb4ee6a4SAndroid Build Coastguard Worker         vsock.read_config(0, &mut buf);
415*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cid, u64::from_le_bytes(buf));
416*bb4ee6a4SAndroid Build Coastguard Worker 
417*bb4ee6a4SAndroid Build Coastguard Worker         vsock.read_config(0, &mut buf[..4]);
418*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
419*bb4ee6a4SAndroid Build Coastguard Worker             (cid & 0xffffffff) as u32,
420*bb4ee6a4SAndroid Build Coastguard Worker             u32::from_le_bytes(buf[..4].try_into().unwrap())
421*bb4ee6a4SAndroid Build Coastguard Worker         );
422*bb4ee6a4SAndroid Build Coastguard Worker 
423*bb4ee6a4SAndroid Build Coastguard Worker         vsock.read_config(4, &mut buf[..4]);
424*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
425*bb4ee6a4SAndroid Build Coastguard Worker             (cid >> 32) as u32,
426*bb4ee6a4SAndroid Build Coastguard Worker             u32::from_le_bytes(buf[..4].try_into().unwrap())
427*bb4ee6a4SAndroid Build Coastguard Worker         );
428*bb4ee6a4SAndroid Build Coastguard Worker 
429*bb4ee6a4SAndroid Build Coastguard Worker         let data: [u8; 8] = [8, 226, 5, 46, 159, 59, 89, 77];
430*bb4ee6a4SAndroid Build Coastguard Worker         buf.copy_from_slice(&data);
431*bb4ee6a4SAndroid Build Coastguard Worker 
432*bb4ee6a4SAndroid Build Coastguard Worker         vsock.read_config(12, &mut buf);
433*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&buf, &data);
434*bb4ee6a4SAndroid Build Coastguard Worker     }
435*bb4ee6a4SAndroid Build Coastguard Worker 
436*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
features()437*bb4ee6a4SAndroid Build Coastguard Worker     fn features() {
438*bb4ee6a4SAndroid Build Coastguard Worker         let cid = 5;
439*bb4ee6a4SAndroid Build Coastguard Worker         let features: u64 = 0xfc195ae8db88cff9;
440*bb4ee6a4SAndroid Build Coastguard Worker 
441*bb4ee6a4SAndroid Build Coastguard Worker         let vsock = Vsock::new_for_testing(cid, features);
442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(features, vsock.features());
443*bb4ee6a4SAndroid Build Coastguard Worker     }
444*bb4ee6a4SAndroid Build Coastguard Worker }
445