1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 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::io; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::mem; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::result; 10*bb4ee6a4SAndroid Build Coastguard Worker 11*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow; 12*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context; 13*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 14*bb4ee6a4SAndroid Build Coastguard Worker use base::warn; 15*bb4ee6a4SAndroid Build Coastguard Worker use base::Error as SysError; 16*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 17*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken; 18*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 19*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext; 20*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread; 21*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted; 22*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error; 23*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory; 24*bb4ee6a4SAndroid Build Coastguard Worker 25*bb4ee6a4SAndroid Build Coastguard Worker use super::copy_config; 26*bb4ee6a4SAndroid Build Coastguard Worker use super::queue::Queue; 27*bb4ee6a4SAndroid Build Coastguard Worker use super::DeviceType; 28*bb4ee6a4SAndroid Build Coastguard Worker use super::Interrupt; 29*bb4ee6a4SAndroid Build Coastguard Worker use super::VirtioDevice; 30*bb4ee6a4SAndroid Build Coastguard Worker 31*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZE: u16 = 128; 32*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE]; 33*bb4ee6a4SAndroid Build Coastguard Worker 34*bb4ee6a4SAndroid Build Coastguard Worker // The only virtio_9p feature. 35*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_9P_MOUNT_TAG: u8 = 0; 36*bb4ee6a4SAndroid Build Coastguard Worker 37*bb4ee6a4SAndroid Build Coastguard Worker /// Errors that occur during operation of a virtio 9P device. 38*bb4ee6a4SAndroid Build Coastguard Worker #[sorted] 39*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)] 40*bb4ee6a4SAndroid Build Coastguard Worker pub enum P9Error { 41*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to create a 9p server. 42*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create 9p server: {0}")] 43*bb4ee6a4SAndroid Build Coastguard Worker CreateServer(io::Error), 44*bb4ee6a4SAndroid Build Coastguard Worker /// Creating WaitContext failed. 45*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create WaitContext: {0}")] 46*bb4ee6a4SAndroid Build Coastguard Worker CreateWaitContext(SysError), 47*bb4ee6a4SAndroid Build Coastguard Worker /// An internal I/O error occurred. 48*bb4ee6a4SAndroid Build Coastguard Worker #[error("P9 internal server error: {0}")] 49*bb4ee6a4SAndroid Build Coastguard Worker Internal(io::Error), 50*bb4ee6a4SAndroid Build Coastguard Worker /// A request is missing readable descriptors. 51*bb4ee6a4SAndroid Build Coastguard Worker #[error("request does not have any readable descriptors")] 52*bb4ee6a4SAndroid Build Coastguard Worker NoReadableDescriptors, 53*bb4ee6a4SAndroid Build Coastguard Worker /// A request is missing writable descriptors. 54*bb4ee6a4SAndroid Build Coastguard Worker #[error("request does not have any writable descriptors")] 55*bb4ee6a4SAndroid Build Coastguard Worker NoWritableDescriptors, 56*bb4ee6a4SAndroid Build Coastguard Worker /// Error while reading from the virtio queue's Event. 57*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to read from virtio queue Event: {0}")] 58*bb4ee6a4SAndroid Build Coastguard Worker ReadQueueEvent(SysError), 59*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to signal the virio used queue. 60*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to signal used queue: {0}")] 61*bb4ee6a4SAndroid Build Coastguard Worker SignalUsedQueue(SysError), 62*bb4ee6a4SAndroid Build Coastguard Worker /// The tag for the 9P device was too large to fit in the config space. 63*bb4ee6a4SAndroid Build Coastguard Worker #[error("P9 device tag is too long: len = {0}, max = {}", u16::MAX)] 64*bb4ee6a4SAndroid Build Coastguard Worker TagTooLong(usize), 65*bb4ee6a4SAndroid Build Coastguard Worker /// Error while polling for events. 66*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to wait for events: {0}")] 67*bb4ee6a4SAndroid Build Coastguard Worker WaitError(SysError), 68*bb4ee6a4SAndroid Build Coastguard Worker } 69*bb4ee6a4SAndroid Build Coastguard Worker 70*bb4ee6a4SAndroid Build Coastguard Worker pub type P9Result<T> = result::Result<T, P9Error>; 71*bb4ee6a4SAndroid Build Coastguard Worker 72*bb4ee6a4SAndroid Build Coastguard Worker struct Worker { 73*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt, 74*bb4ee6a4SAndroid Build Coastguard Worker queue: Queue, 75*bb4ee6a4SAndroid Build Coastguard Worker server: p9::Server, 76*bb4ee6a4SAndroid Build Coastguard Worker } 77*bb4ee6a4SAndroid Build Coastguard Worker 78*bb4ee6a4SAndroid Build Coastguard Worker impl Worker { process_queue(&mut self) -> P9Result<()>79*bb4ee6a4SAndroid Build Coastguard Worker fn process_queue(&mut self) -> P9Result<()> { 80*bb4ee6a4SAndroid Build Coastguard Worker while let Some(mut avail_desc) = self.queue.pop() { 81*bb4ee6a4SAndroid Build Coastguard Worker self.server 82*bb4ee6a4SAndroid Build Coastguard Worker .handle_message(&mut avail_desc.reader, &mut avail_desc.writer) 83*bb4ee6a4SAndroid Build Coastguard Worker .map_err(P9Error::Internal)?; 84*bb4ee6a4SAndroid Build Coastguard Worker 85*bb4ee6a4SAndroid Build Coastguard Worker let len = avail_desc.writer.bytes_written() as u32; 86*bb4ee6a4SAndroid Build Coastguard Worker 87*bb4ee6a4SAndroid Build Coastguard Worker self.queue.add_used(avail_desc, len); 88*bb4ee6a4SAndroid Build Coastguard Worker } 89*bb4ee6a4SAndroid Build Coastguard Worker self.queue.trigger_interrupt(); 90*bb4ee6a4SAndroid Build Coastguard Worker 91*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 92*bb4ee6a4SAndroid Build Coastguard Worker } 93*bb4ee6a4SAndroid Build Coastguard Worker run(&mut self, kill_evt: Event) -> P9Result<()>94*bb4ee6a4SAndroid Build Coastguard Worker fn run(&mut self, kill_evt: Event) -> P9Result<()> { 95*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken)] 96*bb4ee6a4SAndroid Build Coastguard Worker enum Token { 97*bb4ee6a4SAndroid Build Coastguard Worker // A request is ready on the queue. 98*bb4ee6a4SAndroid Build Coastguard Worker QueueReady, 99*bb4ee6a4SAndroid Build Coastguard Worker // Check if any interrupts need to be re-asserted. 100*bb4ee6a4SAndroid Build Coastguard Worker InterruptResample, 101*bb4ee6a4SAndroid Build Coastguard Worker // The parent thread requested an exit. 102*bb4ee6a4SAndroid Build Coastguard Worker Kill, 103*bb4ee6a4SAndroid Build Coastguard Worker } 104*bb4ee6a4SAndroid Build Coastguard Worker 105*bb4ee6a4SAndroid Build Coastguard Worker let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[ 106*bb4ee6a4SAndroid Build Coastguard Worker (self.queue.event(), Token::QueueReady), 107*bb4ee6a4SAndroid Build Coastguard Worker (&kill_evt, Token::Kill), 108*bb4ee6a4SAndroid Build Coastguard Worker ]) 109*bb4ee6a4SAndroid Build Coastguard Worker .map_err(P9Error::CreateWaitContext)?; 110*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resample_evt) = self.interrupt.get_resample_evt() { 111*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 112*bb4ee6a4SAndroid Build Coastguard Worker .add(resample_evt, Token::InterruptResample) 113*bb4ee6a4SAndroid Build Coastguard Worker .map_err(P9Error::CreateWaitContext)?; 114*bb4ee6a4SAndroid Build Coastguard Worker } 115*bb4ee6a4SAndroid Build Coastguard Worker 116*bb4ee6a4SAndroid Build Coastguard Worker loop { 117*bb4ee6a4SAndroid Build Coastguard Worker let events = wait_ctx.wait().map_err(P9Error::WaitError)?; 118*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) { 119*bb4ee6a4SAndroid Build Coastguard Worker match event.token { 120*bb4ee6a4SAndroid Build Coastguard Worker Token::QueueReady => { 121*bb4ee6a4SAndroid Build Coastguard Worker self.queue.event().wait().map_err(P9Error::ReadQueueEvent)?; 122*bb4ee6a4SAndroid Build Coastguard Worker self.process_queue()?; 123*bb4ee6a4SAndroid Build Coastguard Worker } 124*bb4ee6a4SAndroid Build Coastguard Worker Token::InterruptResample => { 125*bb4ee6a4SAndroid Build Coastguard Worker self.interrupt.interrupt_resample(); 126*bb4ee6a4SAndroid Build Coastguard Worker } 127*bb4ee6a4SAndroid Build Coastguard Worker Token::Kill => return Ok(()), 128*bb4ee6a4SAndroid Build Coastguard Worker } 129*bb4ee6a4SAndroid Build Coastguard Worker } 130*bb4ee6a4SAndroid Build Coastguard Worker } 131*bb4ee6a4SAndroid Build Coastguard Worker } 132*bb4ee6a4SAndroid Build Coastguard Worker } 133*bb4ee6a4SAndroid Build Coastguard Worker 134*bb4ee6a4SAndroid Build Coastguard Worker /// Virtio device for sharing specific directories on the host system with the guest VM. 135*bb4ee6a4SAndroid Build Coastguard Worker pub struct P9 { 136*bb4ee6a4SAndroid Build Coastguard Worker config: Vec<u8>, 137*bb4ee6a4SAndroid Build Coastguard Worker server: Option<p9::Server>, 138*bb4ee6a4SAndroid Build Coastguard Worker avail_features: u64, 139*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64, 140*bb4ee6a4SAndroid Build Coastguard Worker worker: Option<WorkerThread<P9Result<()>>>, 141*bb4ee6a4SAndroid Build Coastguard Worker } 142*bb4ee6a4SAndroid Build Coastguard Worker 143*bb4ee6a4SAndroid Build Coastguard Worker impl P9 { new(base_features: u64, tag: &str, p9_cfg: p9::Config) -> P9Result<P9>144*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(base_features: u64, tag: &str, p9_cfg: p9::Config) -> P9Result<P9> { 145*bb4ee6a4SAndroid Build Coastguard Worker if tag.len() > u16::MAX as usize { 146*bb4ee6a4SAndroid Build Coastguard Worker return Err(P9Error::TagTooLong(tag.len())); 147*bb4ee6a4SAndroid Build Coastguard Worker } 148*bb4ee6a4SAndroid Build Coastguard Worker 149*bb4ee6a4SAndroid Build Coastguard Worker let len = tag.len() as u16; 150*bb4ee6a4SAndroid Build Coastguard Worker let mut cfg = Vec::with_capacity(tag.len() + mem::size_of::<u16>()); 151*bb4ee6a4SAndroid Build Coastguard Worker cfg.push(len as u8); 152*bb4ee6a4SAndroid Build Coastguard Worker cfg.push((len >> 8) as u8); 153*bb4ee6a4SAndroid Build Coastguard Worker 154*bb4ee6a4SAndroid Build Coastguard Worker cfg.write_all(tag.as_bytes()).map_err(P9Error::Internal)?; 155*bb4ee6a4SAndroid Build Coastguard Worker 156*bb4ee6a4SAndroid Build Coastguard Worker let server = p9::Server::with_config(p9_cfg).map_err(P9Error::CreateServer)?; 157*bb4ee6a4SAndroid Build Coastguard Worker Ok(P9 { 158*bb4ee6a4SAndroid Build Coastguard Worker config: cfg, 159*bb4ee6a4SAndroid Build Coastguard Worker server: Some(server), 160*bb4ee6a4SAndroid Build Coastguard Worker avail_features: base_features | 1 << VIRTIO_9P_MOUNT_TAG, 161*bb4ee6a4SAndroid Build Coastguard Worker acked_features: 0, 162*bb4ee6a4SAndroid Build Coastguard Worker worker: None, 163*bb4ee6a4SAndroid Build Coastguard Worker }) 164*bb4ee6a4SAndroid Build Coastguard Worker } 165*bb4ee6a4SAndroid Build Coastguard Worker } 166*bb4ee6a4SAndroid Build Coastguard Worker 167*bb4ee6a4SAndroid Build Coastguard Worker impl VirtioDevice for P9 { keep_rds(&self) -> Vec<RawDescriptor>168*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> { 169*bb4ee6a4SAndroid Build Coastguard Worker self.server 170*bb4ee6a4SAndroid Build Coastguard Worker .as_ref() 171*bb4ee6a4SAndroid Build Coastguard Worker .map(p9::Server::keep_fds) 172*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_default() 173*bb4ee6a4SAndroid Build Coastguard Worker } 174*bb4ee6a4SAndroid Build Coastguard Worker device_type(&self) -> DeviceType175*bb4ee6a4SAndroid Build Coastguard Worker fn device_type(&self) -> DeviceType { 176*bb4ee6a4SAndroid Build Coastguard Worker DeviceType::P9 177*bb4ee6a4SAndroid Build Coastguard Worker } 178*bb4ee6a4SAndroid Build Coastguard Worker queue_max_sizes(&self) -> &[u16]179*bb4ee6a4SAndroid Build Coastguard Worker fn queue_max_sizes(&self) -> &[u16] { 180*bb4ee6a4SAndroid Build Coastguard Worker QUEUE_SIZES 181*bb4ee6a4SAndroid Build Coastguard Worker } 182*bb4ee6a4SAndroid Build Coastguard Worker features(&self) -> u64183*bb4ee6a4SAndroid Build Coastguard Worker fn features(&self) -> u64 { 184*bb4ee6a4SAndroid Build Coastguard Worker self.avail_features 185*bb4ee6a4SAndroid Build Coastguard Worker } 186*bb4ee6a4SAndroid Build Coastguard Worker ack_features(&mut self, value: u64)187*bb4ee6a4SAndroid Build Coastguard Worker fn ack_features(&mut self, value: u64) { 188*bb4ee6a4SAndroid Build Coastguard Worker let mut v = value; 189*bb4ee6a4SAndroid Build Coastguard Worker 190*bb4ee6a4SAndroid Build Coastguard Worker // Check if the guest is ACK'ing a feature that we didn't claim to have. 191*bb4ee6a4SAndroid Build Coastguard Worker let unrequested_features = v & !self.avail_features; 192*bb4ee6a4SAndroid Build Coastguard Worker if unrequested_features != 0 { 193*bb4ee6a4SAndroid Build Coastguard Worker warn!("virtio_9p got unknown feature ack: {:x}", v); 194*bb4ee6a4SAndroid Build Coastguard Worker 195*bb4ee6a4SAndroid Build Coastguard Worker // Don't count these features as acked. 196*bb4ee6a4SAndroid Build Coastguard Worker v &= !unrequested_features; 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker self.acked_features |= v; 199*bb4ee6a4SAndroid Build Coastguard Worker } 200*bb4ee6a4SAndroid Build Coastguard Worker read_config(&self, offset: u64, data: &mut [u8])201*bb4ee6a4SAndroid Build Coastguard Worker fn read_config(&self, offset: u64, data: &mut [u8]) { 202*bb4ee6a4SAndroid Build Coastguard Worker copy_config(data, 0, self.config.as_slice(), offset); 203*bb4ee6a4SAndroid Build Coastguard Worker } 204*bb4ee6a4SAndroid Build Coastguard Worker activate( &mut self, _guest_mem: GuestMemory, interrupt: Interrupt, mut queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>205*bb4ee6a4SAndroid Build Coastguard Worker fn activate( 206*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 207*bb4ee6a4SAndroid Build Coastguard Worker _guest_mem: GuestMemory, 208*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt, 209*bb4ee6a4SAndroid Build Coastguard Worker mut queues: BTreeMap<usize, Queue>, 210*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> { 211*bb4ee6a4SAndroid Build Coastguard Worker if queues.len() != 1 { 212*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!("expected 1 queue, got {}", queues.len())); 213*bb4ee6a4SAndroid Build Coastguard Worker } 214*bb4ee6a4SAndroid Build Coastguard Worker 215*bb4ee6a4SAndroid Build Coastguard Worker let queue = queues.remove(&0).unwrap(); 216*bb4ee6a4SAndroid Build Coastguard Worker 217*bb4ee6a4SAndroid Build Coastguard Worker let server = self.server.take().context("missing server")?; 218*bb4ee6a4SAndroid Build Coastguard Worker 219*bb4ee6a4SAndroid Build Coastguard Worker self.worker = Some(WorkerThread::start("v_9p", move |kill_evt| { 220*bb4ee6a4SAndroid Build Coastguard Worker let mut worker = Worker { 221*bb4ee6a4SAndroid Build Coastguard Worker interrupt, 222*bb4ee6a4SAndroid Build Coastguard Worker queue, 223*bb4ee6a4SAndroid Build Coastguard Worker server, 224*bb4ee6a4SAndroid Build Coastguard Worker }; 225*bb4ee6a4SAndroid Build Coastguard Worker 226*bb4ee6a4SAndroid Build Coastguard Worker worker.run(kill_evt) 227*bb4ee6a4SAndroid Build Coastguard Worker })); 228*bb4ee6a4SAndroid Build Coastguard Worker 229*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 230*bb4ee6a4SAndroid Build Coastguard Worker } 231*bb4ee6a4SAndroid Build Coastguard Worker } 232