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