From 55a9e504beef368bd97e51ffd5a7fa6c034eb8ad Mon Sep 17 00:00:00 2001 From: Zach Reizner Date: Wed, 3 Oct 2018 10:22:32 -0700 Subject: cargo fmt all source code Now that cargo fmt has landed, run it over everything at once to bring rust source to the standard formatting. TEST=cargo test BUG=None Change-Id: Ic95a48725e5a40dcbd33ba6d5aef2bd01e91865b Reviewed-on: https://chromium-review.googlesource.com/1259287 Commit-Ready: ChromeOS CL Exonerator Bot Tested-by: Zach Reizner Reviewed-by: Zach Reizner --- devices/src/virtio/balloon.rs | 80 ++- devices/src/virtio/block.rs | 215 ++++---- devices/src/virtio/gpu/backend.rs | 685 ++++++++++++------------- devices/src/virtio/gpu/mod.rs | 399 +++++++------- devices/src/virtio/gpu/protocol.rs | 88 ++-- devices/src/virtio/mmio.rs | 63 ++- devices/src/virtio/mod.rs | 16 +- devices/src/virtio/net.rs | 116 +++-- devices/src/virtio/p9.rs | 49 +- devices/src/virtio/queue.rs | 148 +++--- devices/src/virtio/rng.rs | 99 ++-- devices/src/virtio/vhost/net.rs | 65 +-- devices/src/virtio/vhost/vsock.rs | 50 +- devices/src/virtio/vhost/worker.rs | 44 +- devices/src/virtio/virtio_device.rs | 16 +- devices/src/virtio/virtio_pci_common_config.rs | 25 +- devices/src/virtio/virtio_pci_device.rs | 19 +- devices/src/virtio/wl.rs | 615 ++++++++++++---------- 18 files changed, 1452 insertions(+), 1340 deletions(-) (limited to 'devices/src/virtio') diff --git a/devices/src/virtio/balloon.rs b/devices/src/virtio/balloon.rs index 2943359..76cbc33 100644 --- a/devices/src/virtio/balloon.rs +++ b/devices/src/virtio/balloon.rs @@ -8,15 +8,17 @@ use std::io::Write; use std::mem; use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::net::UnixDatagram; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread; use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; use sys_util::{self, EventFd, GuestAddress, GuestMemory, PollContext, PollToken}; -use super::{VirtioDevice, Queue, DescriptorChain, INTERRUPT_STATUS_CONFIG_CHANGED, - INTERRUPT_STATUS_USED_RING, TYPE_BALLOON}; +use super::{ + DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_CONFIG_CHANGED, + INTERRUPT_STATUS_USED_RING, TYPE_BALLOON, +}; #[derive(Debug)] pub enum BalloonError { @@ -85,7 +87,8 @@ impl Worker { let guest_address = GuestAddress((guest_input as u64) << VIRTIO_BALLOON_PFN_SHIFT); - if self.mem + if self + .mem .remove_range(guest_address, 1 << VIRTIO_BALLOON_PFN_SHIFT) .is_err() { @@ -107,19 +110,14 @@ impl Worker { } fn signal_used_queue(&self) { - self.interrupt_status.fetch_or( - INTERRUPT_STATUS_USED_RING as usize, - Ordering::SeqCst, - ); + self.interrupt_status + .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); self.interrupt_evt.write(1).unwrap(); } fn signal_config_changed(&self) { - self.interrupt_status.fetch_or( - INTERRUPT_STATUS_CONFIG_CHANGED as - usize, - Ordering::SeqCst, - ); + self.interrupt_status + .fetch_or(INTERRUPT_STATUS_CONFIG_CHANGED as usize, Ordering::SeqCst); self.interrupt_evt.write(1).unwrap(); } @@ -135,18 +133,20 @@ impl Worker { let inflate_queue_evt = queue_evts.remove(0); let deflate_queue_evt = queue_evts.remove(0); - let poll_ctx: PollContext = - match PollContext::new() - .and_then(|pc| pc.add(&inflate_queue_evt, Token::Inflate).and(Ok(pc))) - .and_then(|pc| pc.add(&deflate_queue_evt, Token::Deflate).and(Ok(pc))) - .and_then(|pc| pc.add(&self.command_socket, Token::CommandSocket).and(Ok(pc))) - .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) { - Ok(pc) => pc, - Err(e) => { - error!("failed creating PollContext: {:?}", e); - return; - } - }; + let poll_ctx: PollContext = match PollContext::new() + .and_then(|pc| pc.add(&inflate_queue_evt, Token::Inflate).and(Ok(pc))) + .and_then(|pc| pc.add(&deflate_queue_evt, Token::Deflate).and(Ok(pc))) + .and_then(|pc| { + pc.add(&self.command_socket, Token::CommandSocket) + .and(Ok(pc)) + }).and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) + { + Ok(pc) => pc, + Err(e) => { + error!("failed creating PollContext: {:?}", e); + return; + } + }; 'poll: loop { let events = match poll_ctx.wait() { @@ -279,10 +279,9 @@ impl VirtioDevice for Balloon { } // This read can't fail as it fits in the declared array so unwrap is fine. let new_actual: u32 = data.read_u32::().unwrap(); - self.config.actual_pages.store( - new_actual as usize, - Ordering::Relaxed, - ); + self.config + .actual_pages + .store(new_actual as usize, Ordering::Relaxed); } fn features(&self, page: u32) -> u32 { @@ -311,14 +310,13 @@ impl VirtioDevice for Balloon { return; } - let (self_kill_evt, kill_evt) = - match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { - Ok(v) => v, - Err(e) => { - error!("failed to create kill EventFd pair: {:?}", e); - return; - } - }; + let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { + Ok(v) => v, + Err(e) => { + error!("failed to create kill EventFd pair: {:?}", e); + return; + } + }; self.kill_evt = Some(self_kill_evt); let config = self.config.clone(); @@ -327,13 +325,13 @@ impl VirtioDevice for Balloon { .name("virtio_balloon".to_string()) .spawn(move || { let mut worker = Worker { - mem: mem, + mem, inflate_queue: queues.remove(0), deflate_queue: queues.remove(0), interrupt_status: status, - interrupt_evt: interrupt_evt, - command_socket: command_socket, - config: config, + interrupt_evt, + command_socket, + config, }; worker.run(queue_evts, kill_evt); }); diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs index 2502171..a6594ec 100644 --- a/devices/src/virtio/block.rs +++ b/devices/src/virtio/block.rs @@ -3,12 +3,12 @@ // found in the LICENSE file. use std::cmp; -use std::io::{self, Seek, SeekFrom, Read, Write}; +use std::io::{self, Read, Seek, SeekFrom, Write}; use std::mem::{size_of, size_of_val}; use std::os::unix::io::{AsRawFd, RawFd}; use std::result; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread; use std::time::Duration; use std::u32; @@ -22,7 +22,7 @@ use sys_util::{ use data_model::{DataInit, Le16, Le32, Le64}; -use super::{VirtioDevice, Queue, DescriptorChain, INTERRUPT_STATUS_USED_RING, TYPE_BLOCK}; +use super::{DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_BLOCK}; const QUEUE_SIZE: u16 = 256; const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE]; @@ -137,10 +137,12 @@ enum ParseError { DescriptorLengthTooSmall, } -fn request_type(mem: &GuestMemory, - desc_addr: GuestAddress) - -> result::Result { - let type_ = mem.read_obj_from_addr(desc_addr) +fn request_type( + mem: &GuestMemory, + desc_addr: GuestAddress, +) -> result::Result { + let type_ = mem + .read_obj_from_addr(desc_addr) .map_err(ParseError::GuestMemory)?; match type_ { VIRTIO_BLK_T_IN => Ok(RequestType::In), @@ -179,18 +181,18 @@ enum ExecuteError { addr: GuestAddress, length: u32, sector: u64, - guestmemerr: GuestMemoryError + guestmemerr: GuestMemoryError, }, Seek { ioerr: io::Error, - sector: u64 + sector: u64, }, TimerFd(SysError), Write { addr: GuestAddress, length: u32, sector: u64, - guestmemerr: GuestMemoryError + guestmemerr: GuestMemoryError, }, DiscardWriteZeroes { ioerr: Option, @@ -208,12 +210,12 @@ impl ExecuteError { fn status(&self) -> u8 { match self { &ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR, - &ExecuteError::Read{ .. } => VIRTIO_BLK_S_IOERR, - &ExecuteError::Seek{ .. } => VIRTIO_BLK_S_IOERR, + &ExecuteError::Read { .. } => VIRTIO_BLK_S_IOERR, + &ExecuteError::Seek { .. } => VIRTIO_BLK_S_IOERR, &ExecuteError::TimerFd(_) => VIRTIO_BLK_S_IOERR, - &ExecuteError::Write{ .. } => VIRTIO_BLK_S_IOERR, - &ExecuteError::DiscardWriteZeroes{ .. } => VIRTIO_BLK_S_IOERR, - &ExecuteError::ReadOnly{ .. } => VIRTIO_BLK_S_IOERR, + &ExecuteError::Write { .. } => VIRTIO_BLK_S_IOERR, + &ExecuteError::DiscardWriteZeroes { .. } => VIRTIO_BLK_S_IOERR, + &ExecuteError::ReadOnly { .. } => VIRTIO_BLK_S_IOERR, &ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP, } } @@ -229,9 +231,10 @@ struct Request { } impl Request { - fn parse(avail_desc: &DescriptorChain, - mem: &GuestMemory) - -> result::Result { + fn parse( + avail_desc: &DescriptorChain, + mem: &GuestMemory, + ) -> result::Result { // The head contains the request type which MUST be readable. if avail_desc.is_write_only() { return Err(ParseError::UnexpectedWriteOnlyDescriptor); @@ -247,10 +250,10 @@ impl Request { } } - fn parse_flush(avail_desc: &DescriptorChain, - mem: &GuestMemory) - -> result::Result - { + fn parse_flush( + avail_desc: &DescriptorChain, + mem: &GuestMemory, + ) -> result::Result { let sector = sector(&mem, avail_desc.addr)?; let status_desc = avail_desc .next_descriptor() @@ -266,13 +269,13 @@ impl Request { } Ok(Request { - request_type: RequestType::Flush, - sector: sector, - data_addr: GuestAddress(0), - data_len: 0, - status_addr: status_desc.addr, - discard_write_zeroes_seg: None, - }) + request_type: RequestType::Flush, + sector, + data_addr: GuestAddress(0), + data_len: 0, + status_addr: status_desc.addr, + discard_write_zeroes_seg: None, + }) } fn parse_discard_write_zeroes( @@ -319,11 +322,11 @@ impl Request { }) } - fn parse_read_write(avail_desc: &DescriptorChain, - mem: &GuestMemory, - req_type: RequestType) - -> result::Result - { + fn parse_read_write( + avail_desc: &DescriptorChain, + mem: &GuestMemory, + req_type: RequestType, + ) -> result::Result { let sector = sector(&mem, avail_desc.addr)?; let data_desc = avail_desc .next_descriptor() @@ -350,13 +353,13 @@ impl Request { } Ok(Request { - request_type: req_type, - sector: sector, - data_addr: data_desc.addr, - data_len: data_desc.len, - status_addr: status_desc.addr, - discard_write_zeroes_seg: None, - }) + request_type: req_type, + sector, + data_addr: data_desc.addr, + data_len: data_desc.len, + status_addr: status_desc.addr, + discard_write_zeroes_seg: None, + }) } fn execute( @@ -377,14 +380,19 @@ impl Request { } disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT)) - .map_err(|e| ExecuteError::Seek{ ioerr: e, sector: self.sector })?; + .map_err(|e| ExecuteError::Seek { + ioerr: e, + sector: self.sector, + })?; match self.request_type { RequestType::In => { mem.read_to_memory(self.data_addr, disk, self.data_len as usize) - .map_err(|e| ExecuteError::Read{ addr: self.data_addr, - length: self.data_len, - sector: self.sector, - guestmemerr: e })?; + .map_err(|e| ExecuteError::Read { + addr: self.data_addr, + length: self.data_len, + sector: self.sector, + guestmemerr: e, + })?; return Ok(self.data_len); } RequestType::Out => { @@ -415,22 +423,22 @@ impl Request { }; if (flags & !valid_flags) != 0 { - return Err(ExecuteError::DiscardWriteZeroes{ - ioerr: None, - sector, - num_sectors, - flags - }); + return Err(ExecuteError::DiscardWriteZeroes { + ioerr: None, + sector, + num_sectors, + flags, + }); } disk.seek(SeekFrom::Start(sector << SECTOR_SHIFT)) - .map_err(|e| ExecuteError::Seek{ ioerr: e, sector })?; + .map_err(|e| ExecuteError::Seek { ioerr: e, sector })?; disk.write_zeroes((num_sectors as usize) << SECTOR_SHIFT) .map_err(|e| ExecuteError::DiscardWriteZeroes { ioerr: Some(e), sector, num_sectors, - flags + flags, })?; } } @@ -530,17 +538,17 @@ impl Worker { }; let mut flush_timer_armed = false; - let poll_ctx: PollContext = - match PollContext::new() - .and_then(|pc| pc.add(&flush_timer, Token::FlushTimer).and(Ok(pc))) - .and_then(|pc| pc.add(&queue_evt, Token::QueueAvailable).and(Ok(pc))) - .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) { - Ok(pc) => pc, - Err(e) => { - error!("failed creating PollContext: {:?}", e); - return; - } - }; + let poll_ctx: PollContext = match PollContext::new() + .and_then(|pc| pc.add(&flush_timer, Token::FlushTimer).and(Ok(pc))) + .and_then(|pc| pc.add(&queue_evt, Token::QueueAvailable).and(Ok(pc))) + .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) + { + Ok(pc) => pc, + Err(e) => { + error!("failed creating PollContext: {:?}", e); + return; + } + }; 'poll: loop { let events = match poll_ctx.wait() { @@ -613,10 +621,11 @@ impl Block { pub fn new(mut disk_image: T, read_only: bool) -> SysResult> { let disk_size = disk_image.seek(SeekFrom::End(0))? as u64; if disk_size % SECTOR_SIZE != 0 { - warn!("Disk size {} is not a multiple of sector size {}; \ - the remainder will not be visible to the guest.", - disk_size, - SECTOR_SIZE); + warn!( + "Disk size {} is not a multiple of sector size {}; \ + the remainder will not be visible to the guest.", + disk_size, SECTOR_SIZE + ); } let mut avail_features: u64 = 1 << VIRTIO_BLK_F_FLUSH; @@ -628,12 +637,12 @@ impl Block { } Ok(Block { - kill_evt: None, - disk_image: Some(disk_image), - config_space: build_config_space(disk_size), - avail_features, - read_only, - }) + kill_evt: None, + disk_image: Some(disk_image), + config_space: build_config_space(disk_size), + avail_features, + read_only, + }) } } @@ -687,41 +696,43 @@ impl VirtioDevice for Block { } } - fn activate(&mut self, - mem: GuestMemory, - interrupt_evt: EventFd, - status: Arc, - queues: Vec, - mut queue_evts: Vec) { + fn activate( + &mut self, + mem: GuestMemory, + interrupt_evt: EventFd, + status: Arc, + queues: Vec, + mut queue_evts: Vec, + ) { if queues.len() != 1 || queue_evts.len() != 1 { return; } - let (self_kill_evt, kill_evt) = - match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { - Ok(v) => v, - Err(e) => { - error!("failed creating kill EventFd pair: {:?}", e); - return; - } - }; + let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { + Ok(v) => v, + Err(e) => { + error!("failed creating kill EventFd pair: {:?}", e); + return; + } + }; self.kill_evt = Some(self_kill_evt); let read_only = self.read_only; if let Some(disk_image) = self.disk_image.take() { - let worker_result = thread::Builder::new() - .name("virtio_blk".to_string()) - .spawn(move || { - let mut worker = Worker { - queues: queues, - mem: mem, - disk_image: disk_image, - read_only: read_only, - interrupt_status: status, - interrupt_evt: interrupt_evt, - }; - worker.run(queue_evts.remove(0), kill_evt); - }); + let worker_result = + thread::Builder::new() + .name("virtio_blk".to_string()) + .spawn(move || { + let mut worker = Worker { + queues, + mem, + disk_image, + read_only, + interrupt_status: status, + interrupt_evt, + }; + worker.run(queue_evts.remove(0), kill_evt); + }); if let Err(e) = worker_result { error!("failed to spawn virtio_blk worker: {}", e); diff --git a/devices/src/virtio/gpu/backend.rs b/devices/src/virtio/gpu/backend.rs index 62cceb2..9c27712 100644 --- a/devices/src/virtio/gpu/backend.rs +++ b/devices/src/virtio/gpu/backend.rs @@ -15,12 +15,12 @@ use data_model::*; use sys_util::{GuestAddress, GuestMemory}; -use super::gpu_buffer::{Device, Buffer, Format, Flags}; +use super::gpu_buffer::{Buffer, Device, Flags, Format}; use super::gpu_display::*; -use super::gpu_renderer::{Box3, Renderer, Context as RendererContext, - Image as RendererImage, - Resource as GpuRendererResource, ResourceCreateArgs, - format_fourcc as renderer_fourcc}; +use super::gpu_renderer::{ + format_fourcc as renderer_fourcc, Box3, Context as RendererContext, Image as RendererImage, + Renderer, Resource as GpuRendererResource, ResourceCreateArgs, +}; use super::protocol::GpuResponse; use super::protocol::{VIRTIO_GPU_CAPSET_VIRGL, VIRTIO_GPU_CAPSET_VIRGL2}; @@ -59,13 +59,15 @@ trait VirglResource { /// Copies the given rectangle of pixels from guest memory, using the backing specified from a /// call to `attach_guest_backing`. - fn write_from_guest_memory(&mut self, - x: u32, - y: u32, - width: u32, - height: u32, - src_offset: u64, - mem: &GuestMemory); + fn write_from_guest_memory( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + src_offset: u64, + mem: &GuestMemory, + ); /// Reads from the given rectangle of pixels in the resource to the `dst` slice of memory. fn read_to_volatile(&mut self, x: u32, y: u32, width: u32, height: u32, dst: VolatileSlice); @@ -99,53 +101,56 @@ impl VirglResource for GpuRendererResource { Some(self) } - fn write_from_guest_memory(&mut self, - x: u32, - y: u32, - width: u32, - height: u32, - src_offset: u64, - _mem: &GuestMemory) { - let res = self.transfer_write(None, - 0, - 0, - 0, - Box3 { - x, - y, - z: 0, - w: width, - h: height, - d: 0, - }, - src_offset); + fn write_from_guest_memory( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + src_offset: u64, + _mem: &GuestMemory, + ) { + let res = self.transfer_write( + None, + 0, + 0, + 0, + Box3 { + x, + y, + z: 0, + w: width, + h: height, + d: 0, + }, + src_offset, + ); if let Err(e) = res { - error!("failed to write to resource (x={} y={} w={} h={}, src_offset={}): {}", - x, - y, - width, - height, - src_offset, - e); + error!( + "failed to write to resource (x={} y={} w={} h={}, src_offset={}): {}", + x, y, width, height, src_offset, e + ); } } fn read_to_volatile(&mut self, x: u32, y: u32, width: u32, height: u32, dst: VolatileSlice) { - let res = GpuRendererResource::read_to_volatile(self, - None, - 0, - 0, - 0, - Box3 { - x, - y, - z: 0, - w: width, - h: height, - d: 0, - }, - 0, - dst); + let res = GpuRendererResource::read_to_volatile( + self, + None, + 0, + 0, + 0, + Box3 { + x, + y, + z: 0, + w: width, + h: height, + d: 0, + }, + 0, + dst, + ); if let Err(e) = res { error!("failed to read from resource: {}", e); } @@ -162,9 +167,11 @@ struct BackedBuffer { } impl BackedBuffer { - fn new_renderer_registered(buffer: Buffer, - gpu_renderer_resource: GpuRendererResource, - image: RendererImage) -> BackedBuffer { + fn new_renderer_registered( + buffer: Buffer, + gpu_renderer_resource: GpuRendererResource, + image: RendererImage, + ) -> BackedBuffer { BackedBuffer { display_import: None, backing: Vec::new(), @@ -226,15 +233,15 @@ impl VirglResource for BackedBuffer { } }; - match display - .borrow_mut() - .import_dmabuf(dmabuf.as_raw_fd(), - 0, /* offset */ - self.buffer.stride(), - self.buffer.format_modifier(), - self.buffer.width(), - self.buffer.height(), - self.buffer.format().into()) { + match display.borrow_mut().import_dmabuf( + dmabuf.as_raw_fd(), + 0, /* offset */ + self.buffer.stride(), + self.buffer.format_modifier(), + self.buffer.width(), + self.buffer.height(), + self.buffer.format().into(), + ) { Ok(import_id) => { self.display_import = Some((display.clone(), import_id)); Some(import_id) @@ -246,29 +253,33 @@ impl VirglResource for BackedBuffer { } } - fn write_from_guest_memory(&mut self, - x: u32, - y: u32, - width: u32, - height: u32, - src_offset: u64, - mem: &GuestMemory) { + fn write_from_guest_memory( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + src_offset: u64, + mem: &GuestMemory, + ) { if src_offset >= usize::MAX as u64 { - error!("failed to write to resource with given offset: {}", src_offset); - return - } - let res = self.buffer - .write_from_sg(x, - y, - width, - height, - 0, // plane - src_offset as usize, - self.backing - .iter() - .map(|&(addr, len)| { - mem.get_slice(addr.offset(), len as u64).unwrap_or_default() - })); + error!( + "failed to write to resource with given offset: {}", + src_offset + ); + return; + } + let res = self.buffer.write_from_sg( + x, + y, + width, + height, + 0, // plane + src_offset as usize, + self.backing + .iter() + .map(|&(addr, len)| mem.get_slice(addr.offset(), len as u64).unwrap_or_default()), + ); if let Err(e) = res { error!("failed to write to resource from guest memory: {:?}", e) } @@ -336,22 +347,24 @@ impl Backend { } /// Creates a 2D resource with the given properties and associated it with the given id. - pub fn create_resource_2d(&mut self, - id: u32, - width: u32, - height: u32, - fourcc: u32) - -> GpuResponse { + pub fn create_resource_2d( + &mut self, + id: u32, + width: u32, + height: u32, + fourcc: u32, + ) -> GpuResponse { if id == 0 { return GpuResponse::ErrInvalidResourceId; } match self.resources.entry(id) { Entry::Vacant(slot) => { - let res = self.device - .create_buffer(width, - height, - Format::from(fourcc), - Flags::empty().use_scanout(true).use_linear(true)); + let res = self.device.create_buffer( + width, + height, + Format::from(fourcc), + Flags::empty().use_scanout(true).use_linear(true), + ); match res { Ok(res) => { slot.insert(Box::from(BackedBuffer::from(res))); @@ -403,14 +416,15 @@ impl Backend { } } - fn flush_resource_to_surface(&mut self, - resource_id: u32, - surface_id: u32, - x: u32, - y: u32, - width: u32, - height: u32) - -> GpuResponse { + fn flush_resource_to_surface( + &mut self, + resource_id: u32, + surface_id: u32, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> GpuResponse { let resource = match self.resources.get_mut(&resource_id) { Some(r) => r, None => return GpuResponse::ErrInvalidResourceId, @@ -442,13 +456,14 @@ impl Backend { } /// Flushes the given rectangle of pixels of the given resource to the display. - pub fn flush_resource(&mut self, - id: u32, - x: u32, - y: u32, - width: u32, - height: u32) - -> GpuResponse { + pub fn flush_resource( + &mut self, + id: u32, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> GpuResponse { if id == 0 { return GpuResponse::OkNoData; } @@ -476,15 +491,16 @@ impl Backend { /// Copes the given rectangle of pixels of the given resource's backing memory to the host side /// resource. - pub fn transfer_to_resource_2d(&mut self, - id: u32, - x: u32, - y: u32, - width: u32, - height: u32, - src_offset: u64, - mem: &GuestMemory) - -> GpuResponse { + pub fn transfer_to_resource_2d( + &mut self, + id: u32, + x: u32, + y: u32, + width: u32, + height: u32, + src_offset: u64, + mem: &GuestMemory, + ) -> GpuResponse { match self.resources.get_mut(&id) { Some(res) => { res.write_from_guest_memory(x, y, width, height, src_offset, mem); @@ -496,11 +512,12 @@ impl Backend { /// Attaches backing memory to the given resource, represented by a `Vec` of `(address, size)` /// tuples in the guest's physical address space. - pub fn attach_backing(&mut self, - id: u32, - mem: &GuestMemory, - vecs: Vec<(GuestAddress, usize)>) - -> GpuResponse { + pub fn attach_backing( + &mut self, + id: u32, + mem: &GuestMemory, + vecs: Vec<(GuestAddress, usize)>, + ) -> GpuResponse { match self.resources.get_mut(&id) { Some(resource) => { resource.attach_guest_backing(mem, vecs); @@ -532,11 +549,11 @@ impl Backend { } else if let Some(resource) = self.resources.get_mut(&id) { self.cursor_resource = id; if self.cursor_surface.is_none() { - match self.display - .borrow_mut() - .create_surface(self.scanout_surface, - resource.width(), - resource.height()) { + match self.display.borrow_mut().create_surface( + self.scanout_surface, + resource.width(), + resource.height(), + ) { Ok(surface) => self.cursor_surface = Some(surface), Err(e) => { error!("failed to create cursor surface: {:?}", e); @@ -546,30 +563,21 @@ impl Backend { } let cursor_surface = self.cursor_surface.unwrap(); - self.display - .borrow_mut() - .set_position(cursor_surface, x, y); + self.display.borrow_mut().set_position(cursor_surface, x, y); // Gets the resource's pixels into the display by importing the buffer. if let Some(import_id) = resource.import_to_display(&self.display) { - self.display - .borrow_mut() - .flip_to(cursor_surface, import_id); + self.display.borrow_mut().flip_to(cursor_surface, import_id); return GpuResponse::OkNoData; } // Importing failed, so try copying the pixels into the surface's slower shared memory // framebuffer. if let Some(buffer) = resource.buffer() { - if let Some(fb) = self.display - .borrow_mut() - .framebuffer_memory(cursor_surface) { - if let Err(e) = buffer.read_to_volatile(0, - 0, - buffer.width(), - buffer.height(), - 0, - fb) { + if let Some(fb) = self.display.borrow_mut().framebuffer_memory(cursor_surface) { + if let Err(e) = + buffer.read_to_volatile(0, 0, buffer.width(), buffer.height(), 0, fb) + { error!("failed to copy resource to cursor: {:?}", e); return GpuResponse::ErrInvalidParameter; } @@ -617,18 +625,16 @@ impl Backend { } match self.contexts.entry(id) { Entry::Occupied(_) => GpuResponse::ErrInvalidContextId, - Entry::Vacant(slot) => { - match self.renderer.create_context(id) { - Ok(ctx) => { - slot.insert(ctx); - GpuResponse::OkNoData - } - Err(e) => { - error!("failed to create renderer ctx: {}", e); - GpuResponse::ErrUnspec - } + Entry::Vacant(slot) => match self.renderer.create_context(id) { + Ok(ctx) => { + slot.insert(ctx); + GpuResponse::OkNoData } - } + Err(e) => { + error!("failed to create renderer ctx: {}", e); + GpuResponse::ErrUnspec + } + }, } } @@ -642,10 +648,12 @@ impl Backend { /// Attaches the indicated resource to the given context. pub fn context_attach_resource(&mut self, ctx_id: u32, res_id: u32) -> GpuResponse { - match (self.contexts.get_mut(&ctx_id), - self.resources - .get_mut(&res_id) - .and_then(|res| res.gpu_renderer_resource())) { + match ( + self.contexts.get_mut(&ctx_id), + self.resources + .get_mut(&res_id) + .and_then(|res| res.gpu_renderer_resource()), + ) { (Some(ctx), Some(res)) => { ctx.attach(res); GpuResponse::OkNoData @@ -657,10 +665,12 @@ impl Backend { /// detaches the indicated resource to the given context. pub fn context_detach_resource(&mut self, ctx_id: u32, res_id: u32) -> GpuResponse { - match (self.contexts.get_mut(&ctx_id), - self.resources - .get_mut(&res_id) - .and_then(|res| res.gpu_renderer_resource())) { + match ( + self.contexts.get_mut(&ctx_id), + self.resources + .get_mut(&res_id) + .and_then(|res| res.gpu_renderer_resource()), + ) { (Some(ctx), Some(res)) => { ctx.detach(res); GpuResponse::OkNoData @@ -671,10 +681,7 @@ impl Backend { } pub fn validate_args_as_fourcc(args: ResourceCreateArgs) -> Option { - if args.depth == 1 && - args.array_size == 1 && - args.last_level == 0 && - args.nr_samples == 0 { + if args.depth == 1 && args.array_size == 1 && args.last_level == 0 && args.nr_samples == 0 { renderer_fourcc(args.format) } else { None @@ -682,19 +689,20 @@ impl Backend { } /// Creates a 3D resource with the given properties and associated it with the given id. - pub fn resource_create_3d(&mut self, - id: u32, - target: u32, - format: u32, - bind: u32, - width: u32, - height: u32, - depth: u32, - array_size: u32, - last_level: u32, - nr_samples: u32, - flags: u32) - -> GpuResponse { + pub fn resource_create_3d( + &mut self, + id: u32, + target: u32, + format: u32, + bind: u32, + width: u32, + height: u32, + depth: u32, + array_size: u32, + last_level: u32, + nr_samples: u32, + flags: u32, + ) -> GpuResponse { if id == 0 { return GpuResponse::ErrInvalidResourceId; } @@ -715,192 +723,173 @@ impl Backend { match self.resources.entry(id) { Entry::Occupied(_) => GpuResponse::ErrInvalidResourceId, - Entry::Vacant(slot) => { - match Backend::validate_args_as_fourcc(create_args) { - Some(fourcc) => { - let buffer = match self.device - .create_buffer(width, - height, - Format::from(fourcc), - Flags::empty().use_scanout(true).use_linear(true)) { - Ok(buffer) => buffer, - Err(e) => { - error!("failed to create buffer for 3d resource {}: {}", format, e); - return GpuResponse::ErrUnspec; - } - }; - - let dma_buf_fd = match buffer.export_plane_fd(0) { - Ok(dma_buf_fd) => dma_buf_fd, - Err(e) => { - error!("failed to export plane fd: {}", e); - return GpuResponse::ErrUnspec - } - }; - - let image = match self.renderer - .image_from_dmabuf(fourcc, - width, - height, - dma_buf_fd.as_raw_fd(), - buffer.plane_offset(0), - buffer.plane_stride(0)) { - Ok(image) => image, - Err(e) => { - error!("failed to create egl image: {}", e); - return GpuResponse::ErrUnspec - } - }; - - let res = self.renderer - .import_resource(create_args, &image); - match res { - Ok(res) => { - let mut backed = - BackedBuffer::new_renderer_registered(buffer, - res, - image); - slot.insert(Box::new(backed)); - GpuResponse::OkNoData - } - Err(e) => { - error!("failed to import renderer resource: {}", - e); - GpuResponse::ErrUnspec - } + Entry::Vacant(slot) => match Backend::validate_args_as_fourcc(create_args) { + Some(fourcc) => { + let buffer = match self.device.create_buffer( + width, + height, + Format::from(fourcc), + Flags::empty().use_scanout(true).use_linear(true), + ) { + Ok(buffer) => buffer, + Err(e) => { + error!("failed to create buffer for 3d resource {}: {}", format, e); + return GpuResponse::ErrUnspec; + } + }; + + let dma_buf_fd = match buffer.export_plane_fd(0) { + Ok(dma_buf_fd) => dma_buf_fd, + Err(e) => { + error!("failed to export plane fd: {}", e); + return GpuResponse::ErrUnspec; + } + }; + + let image = match self.renderer.image_from_dmabuf( + fourcc, + width, + height, + dma_buf_fd.as_raw_fd(), + buffer.plane_offset(0), + buffer.plane_stride(0), + ) { + Ok(image) => image, + Err(e) => { + error!("failed to create egl image: {}", e); + return GpuResponse::ErrUnspec; } - }, - None => { - let res = self.renderer.create_resource(create_args); - match res { - Ok(res) => { - slot.insert(Box::new(res)); - GpuResponse::OkNoData - } - Err(e) => { - error!("failed to create renderer resource: {}", - e); - GpuResponse::ErrUnspec - } + }; + + let res = self.renderer.import_resource(create_args, &image); + match res { + Ok(res) => { + let mut backed = + BackedBuffer::new_renderer_registered(buffer, res, image); + slot.insert(Box::new(backed)); + GpuResponse::OkNoData + } + Err(e) => { + error!("failed to import renderer resource: {}", e); + GpuResponse::ErrUnspec } } } - } + None => { + let res = self.renderer.create_resource(create_args); + match res { + Ok(res) => { + slot.insert(Box::new(res)); + GpuResponse::OkNoData + } + Err(e) => { + error!("failed to create renderer resource: {}", e); + GpuResponse::ErrUnspec + } + } + } + }, } } /// Copes the given 3D rectangle of pixels of the given resource's backing memory to the host /// side resource. - pub fn transfer_to_resource_3d(&mut self, - ctx_id: u32, - res_id: u32, - x: u32, - y: u32, - z: u32, - width: u32, - height: u32, - depth: u32, - level: u32, - stride: u32, - layer_stride: u32, - offset: u64) - -> GpuResponse { + pub fn transfer_to_resource_3d( + &mut self, + ctx_id: u32, + res_id: u32, + x: u32, + y: u32, + z: u32, + width: u32, + height: u32, + depth: u32, + level: u32, + stride: u32, + layer_stride: u32, + offset: u64, + ) -> GpuResponse { let ctx = match ctx_id { 0 => None, - id => { - match self.contexts.get(&id) { - None => return GpuResponse::ErrInvalidContextId, - ctx => ctx, - } - } + id => match self.contexts.get(&id) { + None => return GpuResponse::ErrInvalidContextId, + ctx => ctx, + }, }; match self.resources.get_mut(&res_id) { - Some(res) => { - match res.gpu_renderer_resource() { - Some(res) => { - let transfer_box = Box3 { - x, - y, - z, - w: width, - h: height, - d: depth, - }; - let res = res.transfer_write(ctx, - level, - stride, - layer_stride, - transfer_box, - offset); - match res { - Ok(_) => GpuResponse::OkNoData, - Err(e) => { - error!("failed to transfer to host: {}", e); - GpuResponse::ErrUnspec - } + Some(res) => match res.gpu_renderer_resource() { + Some(res) => { + let transfer_box = Box3 { + x, + y, + z, + w: width, + h: height, + d: depth, + }; + let res = + res.transfer_write(ctx, level, stride, layer_stride, transfer_box, offset); + match res { + Ok(_) => GpuResponse::OkNoData, + Err(e) => { + error!("failed to transfer to host: {}", e); + GpuResponse::ErrUnspec } } - None => GpuResponse::ErrInvalidResourceId, } - } + None => GpuResponse::ErrInvalidResourceId, + }, None => GpuResponse::ErrInvalidResourceId, } } /// Copes the given rectangle of pixels from the resource to the given resource's backing /// memory. - pub fn transfer_from_resource_3d(&mut self, - ctx_id: u32, - res_id: u32, - x: u32, - y: u32, - z: u32, - width: u32, - height: u32, - depth: u32, - level: u32, - stride: u32, - layer_stride: u32, - offset: u64) - -> GpuResponse { + pub fn transfer_from_resource_3d( + &mut self, + ctx_id: u32, + res_id: u32, + x: u32, + y: u32, + z: u32, + width: u32, + height: u32, + depth: u32, + level: u32, + stride: u32, + layer_stride: u32, + offset: u64, + ) -> GpuResponse { let ctx = match ctx_id { 0 => None, - id => { - match self.contexts.get(&id) { - None => return GpuResponse::ErrInvalidContextId, - ctx => ctx, - } - } + id => match self.contexts.get(&id) { + None => return GpuResponse::ErrInvalidContextId, + ctx => ctx, + }, }; match self.resources.get_mut(&res_id) { - Some(res) => { - match res.gpu_renderer_resource() { - Some(res) => { - let transfer_box = Box3 { - x, - y, - z, - w: width, - h: height, - d: depth, - }; - let res = res.transfer_read(ctx, - level, - stride, - layer_stride, - transfer_box, - offset); - match res { - Ok(_) => GpuResponse::OkNoData, - Err(e) => { - error!("failed to transfer from host: {}", e); - GpuResponse::ErrUnspec - } + Some(res) => match res.gpu_renderer_resource() { + Some(res) => { + let transfer_box = Box3 { + x, + y, + z, + w: width, + h: height, + d: depth, + }; + let res = + res.transfer_read(ctx, level, stride, layer_stride, transfer_box, offset); + match res { + Ok(_) => GpuResponse::OkNoData, + Err(e) => { + error!("failed to transfer from host: {}", e); + GpuResponse::ErrUnspec } } - None => GpuResponse::ErrInvalidResourceId, } - } + None => GpuResponse::ErrInvalidResourceId, + }, None => GpuResponse::ErrInvalidResourceId, } } @@ -908,15 +897,13 @@ impl Backend { /// Submits a command buffer to the given rendering context. pub fn submit_command(&mut self, ctx_id: u32, commands: &mut [u8]) -> GpuResponse { match self.contexts.get_mut(&ctx_id) { - Some(ctx) => { - match ctx.submit(&mut commands[..]) { - Ok(_) => GpuResponse::OkNoData, - Err(e) => { - error!("failed to submit command buffer: {}", e); - GpuResponse::ErrUnspec - } + Some(ctx) => match ctx.submit(&mut commands[..]) { + Ok(_) => GpuResponse::OkNoData, + Err(e) => { + error!("failed to submit command buffer: {}", e); + GpuResponse::ErrUnspec } - } + }, None => GpuResponse::ErrInvalidContextId, } } diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index 0b6f05e..ec60634 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -6,8 +6,8 @@ extern crate gpu_buffer; extern crate gpu_display; extern crate gpu_renderer; -mod protocol; mod backend; +mod protocol; use std::cell::RefCell; use std::collections::VecDeque; @@ -16,24 +16,25 @@ use std::mem::size_of; use std::os::unix::io::{AsRawFd, RawFd}; use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread::spawn; use std::time::Duration; use data_model::*; -use sys_util::{EventFd, PollContext, PollToken, GuestAddress, GuestMemory}; +use sys_util::{EventFd, GuestAddress, GuestMemory, PollContext, PollToken}; use self::gpu_buffer::Device; use self::gpu_display::*; -use self::gpu_renderer::{Renderer, format_fourcc}; +use self::gpu_renderer::{format_fourcc, Renderer}; -use super::{VirtioDevice, Queue, AvailIter, VIRTIO_F_VERSION_1, INTERRUPT_STATUS_USED_RING, - TYPE_GPU}; +use super::{ + AvailIter, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_GPU, VIRTIO_F_VERSION_1, +}; -use self::protocol::*; use self::backend::Backend; +use self::protocol::*; // First queue is for virtio gpu commands. Second queue is for cursor commands, which we expect // there to be fewer of. @@ -88,11 +89,12 @@ impl Frontend { self.backend.process_display() } - fn process_gpu_command(&mut self, - mem: &GuestMemory, - cmd: GpuCommand, - data: Option) - -> GpuResponse { + fn process_gpu_command( + &mut self, + mem: &GuestMemory, + cmd: GpuCommand, + data: Option, + ) -> GpuResponse { self.backend.force_ctx_0(); match cmd { @@ -102,50 +104,49 @@ impl Frontend { GpuCommand::ResourceCreate2d(info) => { let format = info.format.to_native(); match format_fourcc(format) { - Some(fourcc) => { - self.backend - .create_resource_2d(info.resource_id.to_native(), - info.width.to_native(), - info.height.to_native(), - fourcc) - } + Some(fourcc) => self.backend.create_resource_2d( + info.resource_id.to_native(), + info.width.to_native(), + info.height.to_native(), + fourcc, + ), None => { - warn!("failed to create resource with unrecognized pipe format {}", - format); + warn!( + "failed to create resource with unrecognized pipe format {}", + format + ); GpuResponse::ErrInvalidParameter } } - } GpuCommand::ResourceUnref(info) => { self.backend.unref_resource(info.resource_id.to_native()) } GpuCommand::SetScanout(info) => self.backend.set_scanout(info.resource_id.to_native()), - GpuCommand::ResourceFlush(info) => { - self.backend - .flush_resource(info.resource_id.to_native(), - info.r.x.to_native(), - info.r.y.to_native(), - info.r.width.to_native(), - info.r.height.to_native()) - } - GpuCommand::TransferToHost2d(info) => { - self.backend - .transfer_to_resource_2d(info.resource_id.to_native(), - info.r.x.to_native(), - info.r.y.to_native(), - info.r.width.to_native(), - info.r.height.to_native(), - info.offset.to_native(), - mem) - } + GpuCommand::ResourceFlush(info) => self.backend.flush_resource( + info.resource_id.to_native(), + info.r.x.to_native(), + info.r.y.to_native(), + info.r.width.to_native(), + info.r.height.to_native(), + ), + GpuCommand::TransferToHost2d(info) => self.backend.transfer_to_resource_2d( + info.resource_id.to_native(), + info.r.x.to_native(), + info.r.y.to_native(), + info.r.width.to_native(), + info.r.height.to_native(), + info.offset.to_native(), + mem, + ), GpuCommand::ResourceAttachBacking(info) if data.is_some() => { let data = data.unwrap(); let entry_count = info.nr_entries.to_native() as usize; let mut iovecs = Vec::with_capacity(entry_count); for i in 0..entry_count { - if let Ok(entry_ref) = data.get_ref((i * size_of::()) as - u64) { + if let Ok(entry_ref) = + data.get_ref((i * size_of::()) as u64) + { let entry: virtio_gpu_mem_entry = entry_ref.load(); let addr = GuestAddress(entry.addr.to_native()); let len = entry.length.to_native() as usize; @@ -160,42 +161,32 @@ impl Frontend { GpuCommand::ResourceDetachBacking(info) => { self.backend.detach_backing(info.resource_id.to_native()) } - GpuCommand::UpdateCursor(info) => { - self.backend - .update_cursor(info.resource_id.to_native(), - info.pos.x.into(), - info.pos.y.into()) - } - GpuCommand::MoveCursor(info) => { - self.backend - .move_cursor(info.pos.x.into(), info.pos.y.into()) - } + GpuCommand::UpdateCursor(info) => self.backend.update_cursor( + info.resource_id.to_native(), + info.pos.x.into(), + info.pos.y.into(), + ), + GpuCommand::MoveCursor(info) => self + .backend + .move_cursor(info.pos.x.into(), info.pos.y.into()), GpuCommand::GetCapsetInfo(info) => { - self.backend - .get_capset_info(info.capset_index.to_native()) - } - GpuCommand::GetCapset(info) => { - self.backend - .get_capset(info.capset_id.to_native(), info.capset_version.to_native()) - } - GpuCommand::CtxCreate(info) => { - self.backend - .create_renderer_context(info.hdr.ctx_id.to_native()) - } - GpuCommand::CtxDestroy(info) => { - self.backend - .destroy_renderer_context(info.hdr.ctx_id.to_native()) - } - GpuCommand::CtxAttachResource(info) => { - self.backend - .context_attach_resource(info.hdr.ctx_id.to_native(), - info.resource_id.to_native()) - } - GpuCommand::CtxDetachResource(info) => { - self.backend - .context_detach_resource(info.hdr.ctx_id.to_native(), - info.resource_id.to_native()) + self.backend.get_capset_info(info.capset_index.to_native()) } + GpuCommand::GetCapset(info) => self + .backend + .get_capset(info.capset_id.to_native(), info.capset_version.to_native()), + GpuCommand::CtxCreate(info) => self + .backend + .create_renderer_context(info.hdr.ctx_id.to_native()), + GpuCommand::CtxDestroy(info) => self + .backend + .destroy_renderer_context(info.hdr.ctx_id.to_native()), + GpuCommand::CtxAttachResource(info) => self + .backend + .context_attach_resource(info.hdr.ctx_id.to_native(), info.resource_id.to_native()), + GpuCommand::CtxDetachResource(info) => self + .backend + .context_detach_resource(info.hdr.ctx_id.to_native(), info.resource_id.to_native()), GpuCommand::ResourceCreate3d(info) => { let id = info.resource_id.to_native(); let target = info.target.to_native(); @@ -208,18 +199,10 @@ impl Frontend { let last_level = info.last_level.to_native(); let nr_samples = info.nr_samples.to_native(); let flags = info.flags.to_native(); - self.backend - .resource_create_3d(id, - target, - format, - bind, - width, - height, - depth, - array_size, - last_level, - nr_samples, - flags) + self.backend.resource_create_3d( + id, target, format, bind, width, height, depth, array_size, last_level, + nr_samples, flags, + ) } GpuCommand::TransferToHost3d(info) => { let ctx_id = info.hdr.ctx_id.to_native(); @@ -234,20 +217,20 @@ impl Frontend { let stride = info.stride.to_native(); let layer_stride = info.layer_stride.to_native(); let offset = info.offset.to_native(); - self.backend - .transfer_to_resource_3d(ctx_id, - res_id, - x, - y, - z, - width, - height, - depth, - level, - stride, - layer_stride, - offset) - + self.backend.transfer_to_resource_3d( + ctx_id, + res_id, + x, + y, + z, + width, + height, + depth, + level, + stride, + layer_stride, + offset, + ) } GpuCommand::TransferFromHost3d(info) => { let ctx_id = info.hdr.ctx_id.to_native(); @@ -262,19 +245,20 @@ impl Frontend { let stride = info.stride.to_native(); let layer_stride = info.layer_stride.to_native(); let offset = info.offset.to_native(); - self.backend - .transfer_from_resource_3d(ctx_id, - res_id, - x, - y, - z, - width, - height, - depth, - level, - stride, - layer_stride, - offset) + self.backend.transfer_from_resource_3d( + ctx_id, + res_id, + x, + y, + z, + width, + height, + depth, + level, + stride, + layer_stride, + offset, + ) } GpuCommand::CmdSubmit3d(info) if data.is_some() => { let data = data.unwrap(); // guarded by this match arm @@ -296,10 +280,12 @@ impl Frontend { } } - fn take_descriptors(mem: &GuestMemory, - desc_iter: AvailIter, - descriptors: &mut VecDeque, - return_descriptors: &mut VecDeque) { + fn take_descriptors( + mem: &GuestMemory, + desc_iter: AvailIter, + descriptors: &mut VecDeque, + return_descriptors: &mut VecDeque, + ) { for desc in desc_iter { if desc.len as usize >= size_of::() && !desc.is_write_only() { let mut q_desc = QueueDescriptor { @@ -323,38 +309,45 @@ impl Frontend { } descriptors.push_back(q_desc); } else { - let likely_type = mem.read_obj_from_addr(desc.addr) - .unwrap_or(Le32::from(0)); - debug!("ctrl queue bad descriptor index = {} len = {} write = {} type = {}", - desc.index, - desc.len, - desc.is_write_only(), - virtio_gpu_cmd_str(likely_type.to_native())); + let likely_type = mem.read_obj_from_addr(desc.addr).unwrap_or(Le32::from(0)); + debug!( + "ctrl queue bad descriptor index = {} len = {} write = {} type = {}", + desc.index, + desc.len, + desc.is_write_only(), + virtio_gpu_cmd_str(likely_type.to_native()) + ); return_descriptors.push_back(ReturnDescriptor { - index: desc.index, - len: 0, - }); + index: desc.index, + len: 0, + }); } } } fn take_ctrl_descriptors(&mut self, mem: &GuestMemory, desc_iter: AvailIter) { - Frontend::take_descriptors(mem, - desc_iter, - &mut self.ctrl_descriptors, - &mut self.return_ctrl_descriptors); + Frontend::take_descriptors( + mem, + desc_iter, + &mut self.ctrl_descriptors, + &mut self.return_ctrl_descriptors, + ); } fn take_cursor_descriptors(&mut self, mem: &GuestMemory, desc_iter: AvailIter) { - Frontend::take_descriptors(mem, - desc_iter, - &mut self.cursor_descriptors, - &mut self.return_cursor_descriptors); + Frontend::take_descriptors( + mem, + desc_iter, + &mut self.cursor_descriptors, + &mut self.return_cursor_descriptors, + ); } - fn process_descriptor(&mut self, - mem: &GuestMemory, - desc: QueueDescriptor) -> Option { + fn process_descriptor( + &mut self, + mem: &GuestMemory, + desc: QueueDescriptor, + ) -> Option { let mut resp = GpuResponse::ErrUnspec; let mut gpu_cmd = None; let mut len = 0; @@ -392,17 +385,14 @@ impl Frontend { ctx_id = ctrl_hdr.ctx_id.to_native(); flags = VIRTIO_GPU_FLAG_FENCE; - let fence_resp = self.backend - .create_fence(ctx_id, fence_id as u32); + let fence_resp = self.backend.create_fence(ctx_id, fence_id as u32); if fence_resp.is_err() { - warn!("create_fence {} -> {:?}", - fence_id, fence_resp); + warn!("create_fence {} -> {:?}", fence_id, fence_resp); resp = fence_resp; } } } - // Prepare the response now, even if it is going to wait until // fence is complete. match resp.encode(flags, fence_id, ctx_id, ret_desc_mem) { @@ -417,7 +407,7 @@ impl Frontend { desc, }); - return None + return None; } // No fence, respond now. @@ -430,23 +420,19 @@ impl Frontend { } fn process_ctrl(&mut self, mem: &GuestMemory) -> Option { - self.return_ctrl_descriptors - .pop_front() - .or_else(|| { - self.ctrl_descriptors - .pop_front() - .and_then(|desc| self.process_descriptor(mem, desc)) - }) + self.return_ctrl_descriptors.pop_front().or_else(|| { + self.ctrl_descriptors + .pop_front() + .and_then(|desc| self.process_descriptor(mem, desc)) + }) } fn process_cursor(&mut self, mem: &GuestMemory) -> Option { - self.return_cursor_descriptors - .pop_front() - .or_else(|| { - self.cursor_descriptors - .pop_front() - .and_then(|desc| self.process_descriptor(mem, desc)) - }) + self.return_cursor_descriptors.pop_front().or_else(|| { + self.cursor_descriptors + .pop_front() + .and_then(|desc| self.process_descriptor(mem, desc)) + }) } fn fence_poll(&mut self) { @@ -457,9 +443,9 @@ impl Frontend { true } else { return_descs.push_back(ReturnDescriptor { - index: f_desc.desc.index, - len: f_desc.len - }); + index: f_desc.desc.index, + len: f_desc.len, + }); false } }) @@ -486,7 +472,6 @@ impl Worker { let _ = self.interrupt_evt.write(1); } - fn run(&mut self) { #[derive(PollToken)] enum Token { @@ -496,23 +481,20 @@ impl Worker { Kill, } - let poll_ctx: PollContext = - match PollContext::new() - .and_then(|pc| pc.add(&self.ctrl_evt, Token::CtrlQueue).and(Ok(pc))) - .and_then(|pc| { - pc.add(&self.cursor_evt, Token::CursorQueue).and(Ok(pc)) - }) - .and_then(|pc| { - pc.add(&*self.state.display().borrow(), Token::Display) - .and(Ok(pc)) - }) - .and_then(|pc| pc.add(&self.kill_evt, Token::Kill).and(Ok(pc))) { - Ok(pc) => pc, - Err(e) => { - error!("failed creating PollContext: {:?}", e); - return; - } - }; + let poll_ctx: PollContext = match PollContext::new() + .and_then(|pc| pc.add(&self.ctrl_evt, Token::CtrlQueue).and(Ok(pc))) + .and_then(|pc| pc.add(&self.cursor_evt, Token::CursorQueue).and(Ok(pc))) + .and_then(|pc| { + pc.add(&*self.state.display().borrow(), Token::Display) + .and(Ok(pc)) + }).and_then(|pc| pc.add(&self.kill_evt, Token::Kill).and(Ok(pc))) + { + Ok(pc) => pc, + Err(e) => { + error!("failed creating PollContext: {:?}", e); + return; + } + }; 'poll: loop { // If there are outstanding fences, wake up early to poll them. @@ -653,7 +635,6 @@ impl VirtioDevice for Gpu { let _ = value; } - fn read_config(&self, offset: u64, data: &mut [u8]) { let offset = offset as usize; let len = data.len(); @@ -679,12 +660,14 @@ impl VirtioDevice for Gpu { } } - fn activate(&mut self, - mem: GuestMemory, - interrupt_evt: EventFd, - interrupt_status: Arc, - mut queues: Vec, - mut queue_evts: Vec) { + fn activate( + &mut self, + mem: GuestMemory, + interrupt_evt: EventFd, + interrupt_status: Arc, + mut queues: Vec, + mut queue_evts: Vec, + ) { if queues.len() != QUEUE_SIZES.len() || queue_evts.len() != QUEUE_SIZES.len() { return; } @@ -697,14 +680,13 @@ impl VirtioDevice for Gpu { } }; - let (self_kill_evt, kill_evt) = - match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { - Ok(v) => v, - Err(e) => { - error!("error creating kill EventFd pair: {:?}", e); - return; - } - }; + let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { + Ok(v) => v, + Err(e) => { + error!("error creating kill EventFd pair: {:?}", e); + return; + } + }; self.kill_evt = Some(self_kill_evt); let ctrl_queue = queues.remove(0); @@ -726,7 +708,7 @@ impl VirtioDevice for Gpu { Ok(d) => d, Err(()) => { error!("failed to open device"); - return + return; } }; @@ -747,18 +729,17 @@ impl VirtioDevice for Gpu { }; Worker { - exit_evt, - mem, - interrupt_evt, - interrupt_status, - ctrl_queue, - ctrl_evt, - cursor_queue, - cursor_evt, - kill_evt, - state: Frontend::new(Backend::new(device, display, renderer)), - } - .run() + exit_evt, + mem, + interrupt_evt, + interrupt_status, + ctrl_queue, + ctrl_evt, + cursor_queue, + cursor_evt, + kill_evt, + state: Frontend::new(Backend::new(device, display, renderer)), + }.run() }); } } diff --git a/devices/src/virtio/gpu/protocol.rs b/devices/src/virtio/gpu/protocol.rs index 1c9b1c3..2001cd7 100644 --- a/devices/src/virtio/gpu/protocol.rs +++ b/devices/src/virtio/gpu/protocol.rs @@ -7,7 +7,7 @@ use std::marker::PhantomData; use std::mem::{size_of, size_of_val}; use std::str::from_utf8; -use data_model::{DataInit, Le32, Le64, VolatileMemory, VolatileSlice, VolatileMemoryError}; +use data_model::{DataInit, Le32, Le64, VolatileMemory, VolatileMemoryError, VolatileSlice}; pub const VIRTIO_GPU_F_VIRGL: u32 = 0; @@ -122,9 +122,9 @@ unsafe impl DataInit for virtio_gpu_cursor_pos {} pub struct virtio_gpu_update_cursor { pub hdr: virtio_gpu_ctrl_hdr, pub pos: virtio_gpu_cursor_pos, /* update & move */ - pub resource_id: Le32, /* update only */ - pub hot_x: Le32, /* update only */ - pub hot_y: Le32, /* update only */ + pub resource_id: Le32, /* update only */ + pub hot_x: Le32, /* update only */ + pub hot_y: Le32, /* update only */ pub padding: Le32, } @@ -417,7 +417,6 @@ pub struct virtio_gpu_resp_capset { unsafe impl DataInit for virtio_gpu_resp_capset {} - pub const VIRTIO_GPU_EVENT_DISPLAY: u32 = 1 << 0; #[derive(Copy, Clone, Debug)] @@ -516,32 +515,28 @@ impl GpuCommand { use self::GpuCommand::*; let hdr: virtio_gpu_ctrl_hdr = cmd.get_ref(0)?.load(); Ok(match hdr.type_.into() { - VIRTIO_GPU_CMD_GET_DISPLAY_INFO => GetDisplayInfo(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_RESOURCE_CREATE_2D => ResourceCreate2d(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_RESOURCE_UNREF => ResourceUnref(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_SET_SCANOUT => SetScanout(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_RESOURCE_FLUSH => ResourceFlush(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D => TransferToHost2d(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING => { - ResourceAttachBacking(cmd.get_ref(0)?.load()) - } - VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING => { - ResourceDetachBacking(cmd.get_ref(0)?.load()) - } - VIRTIO_GPU_CMD_GET_CAPSET_INFO => GetCapsetInfo(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_GET_CAPSET => GetCapset(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_CTX_CREATE => CtxCreate(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_CTX_DESTROY => CtxDestroy(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE => CtxAttachResource(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE => CtxDetachResource(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_RESOURCE_CREATE_3D => ResourceCreate3d(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D => TransferToHost3d(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D => TransferFromHost3d(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_SUBMIT_3D => CmdSubmit3d(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_UPDATE_CURSOR => UpdateCursor(cmd.get_ref(0)?.load()), - VIRTIO_GPU_CMD_MOVE_CURSOR => MoveCursor(cmd.get_ref(0)?.load()), - _ => return Err(GpuCommandDecodeError::InvalidType(hdr.type_.into())), - }) + VIRTIO_GPU_CMD_GET_DISPLAY_INFO => GetDisplayInfo(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_RESOURCE_CREATE_2D => ResourceCreate2d(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_RESOURCE_UNREF => ResourceUnref(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_SET_SCANOUT => SetScanout(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_RESOURCE_FLUSH => ResourceFlush(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D => TransferToHost2d(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING => ResourceAttachBacking(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING => ResourceDetachBacking(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_GET_CAPSET_INFO => GetCapsetInfo(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_GET_CAPSET => GetCapset(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_CTX_CREATE => CtxCreate(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_CTX_DESTROY => CtxDestroy(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE => CtxAttachResource(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE => CtxDetachResource(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_RESOURCE_CREATE_3D => ResourceCreate3d(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D => TransferToHost3d(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D => TransferFromHost3d(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_SUBMIT_3D => CmdSubmit3d(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_UPDATE_CURSOR => UpdateCursor(cmd.get_ref(0)?.load()), + VIRTIO_GPU_CMD_MOVE_CURSOR => MoveCursor(cmd.get_ref(0)?.load()), + _ => return Err(GpuCommandDecodeError::InvalidType(hdr.type_.into())), + }) } /// Gets the generic `virtio_gpu_ctrl_hdr` from this command. @@ -604,12 +599,13 @@ impl From for GpuResponseEncodeError { impl GpuResponse { /// Encodes a this `GpuResponse` into `resp` and the given set of metadata. - pub fn encode(&self, - flags: u32, - fence_id: u64, - ctx_id: u32, - resp: VolatileSlice) - -> Result { + pub fn encode( + &self, + flags: u32, + fence_id: u64, + ctx_id: u32, + resp: VolatileSlice, + ) -> Result { let hdr = virtio_gpu_ctrl_hdr { type_: Le32::from(self.get_type()), flags: Le32::from(flags), @@ -635,19 +631,19 @@ impl GpuResponse { size_of_val(&disp_info) } &GpuResponse::OkCapsetInfo { id, version, size } => { - resp.get_ref(0)? - .store(virtio_gpu_resp_capset_info { - hdr, - capset_id: Le32::from(id), - capset_max_version: Le32::from(version), - capset_max_size: Le32::from(size), - padding: Le32::from(0), - }); + resp.get_ref(0)?.store(virtio_gpu_resp_capset_info { + hdr, + capset_id: Le32::from(id), + capset_max_version: Le32::from(version), + capset_max_size: Le32::from(size), + padding: Le32::from(0), + }); size_of::() } &GpuResponse::OkCapset(ref data) => { resp.get_ref(0)?.store(hdr); - let resp_data_slice = resp.get_slice(size_of_val(&hdr) as u64, data.len() as u64)?; + let resp_data_slice = + resp.get_slice(size_of_val(&hdr) as u64, data.len() as u64)?; resp_data_slice.copy_from(data); size_of_val(&hdr) + data.len() } diff --git a/devices/src/virtio/mmio.rs b/devices/src/virtio/mmio.rs index 5e7226f..400afd9 100644 --- a/devices/src/virtio/mmio.rs +++ b/devices/src/virtio/mmio.rs @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use byteorder::{ByteOrder, LittleEndian}; use super::*; +use sys_util::{EventFd, GuestAddress, GuestMemory, Result}; use BusDevice; -use sys_util::{Result, EventFd, GuestAddress, GuestMemory}; const VENDOR_ID: u32 = 0; @@ -59,19 +59,19 @@ impl MmioDevice { .map(|&s| Queue::new(s)) .collect(); Ok(MmioDevice { - device: device, - device_activated: false, - features_select: 0, - acked_features_select: 0, - queue_select: 0, - interrupt_status: Arc::new(AtomicUsize::new(0)), - interrupt_evt: Some(EventFd::new()?), - driver_status: 0, - config_generation: 0, - queues: queues, - queue_evts: queue_evts, - mem: Some(mem), - }) + device, + device_activated: false, + features_select: 0, + acked_features_select: 0, + queue_select: 0, + interrupt_status: Arc::new(AtomicUsize::new(0)), + interrupt_evt: Some(EventFd::new()?), + driver_status: 0, + config_generation: 0, + queues, + queue_evts, + mem: Some(mem), + }) } /// Gets the list of queue events that must be triggered whenever the VM writes to @@ -100,7 +100,8 @@ impl MmioDevice { } fn with_queue(&self, d: U, f: F) -> U - where F: FnOnce(&Queue) -> U + where + F: FnOnce(&Queue) -> U, { match self.queues.get(self.queue_select as usize) { Some(queue) => f(queue), @@ -128,8 +129,8 @@ impl BusDevice for MmioDevice { 0x08 => self.device.device_type(), 0x0c => VENDOR_ID, // vendor id 0x10 => { - self.device.features(self.features_select) | - if self.features_select == 1 { 0x1 } else { 0x0 } + self.device.features(self.features_select) + | if self.features_select == 1 { 0x1 } else { 0x0 } } 0x34 => self.with_queue(0, |q| q.max_size as u32), 0x44 => self.with_queue(0, |q| q.ready as u32), @@ -145,10 +146,13 @@ impl BusDevice for MmioDevice { } 0x100...0xfff => self.device.read_config(offset - 0x100, data), _ => { - warn!("invalid virtio mmio read: 0x{:x}:0x{:x}", offset, data.len()); + warn!( + "invalid virtio mmio read: 0x{:x}:0x{:x}", + offset, + data.len() + ); } }; - } fn write(&mut self, offset: u64, data: &[u8]) { @@ -190,7 +194,11 @@ impl BusDevice for MmioDevice { } 0x100...0xfff => return self.device.write_config(offset - 0x100, data), _ => { - warn!("invalid virtio mmio write: 0x{:x}:0x{:x}", offset, data.len()); + warn!( + "invalid virtio mmio write: 0x{:x}:0x{:x}", + offset, + data.len() + ); return; } } @@ -202,12 +210,13 @@ impl BusDevice for MmioDevice { if !self.device_activated && self.is_driver_ready() && self.are_queues_valid() { if let Some(interrupt_evt) = self.interrupt_evt.take() { if let Some(mem) = self.mem.take() { - self.device - .activate(mem, - interrupt_evt, - self.interrupt_status.clone(), - self.queues.clone(), - self.queue_evts.split_off(0)); + self.device.activate( + mem, + interrupt_evt, + self.interrupt_status.clone(), + self.queues.clone(), + self.queue_evts.split_off(0), + ); self.device_activated = true; } } diff --git a/devices/src/virtio/mod.rs b/devices/src/virtio/mod.rs index a85b04b..c23c56d 100644 --- a/devices/src/virtio/mod.rs +++ b/devices/src/virtio/mod.rs @@ -5,14 +5,14 @@ //! Implements virtio devices, queues, and transport mechanisms. mod balloon; -mod queue; -mod mmio; mod block; -mod rng; -mod net; #[cfg(feature = "gpu")] mod gpu; +mod mmio; +mod net; mod p9; +mod queue; +mod rng; mod virtio_device; mod virtio_pci_common_config; mod virtio_pci_device; @@ -21,14 +21,14 @@ mod wl; pub mod vhost; pub use self::balloon::*; -pub use self::queue::*; -pub use self::mmio::*; pub use self::block::*; -pub use self::rng::*; -pub use self::net::*; #[cfg(feature = "gpu")] pub use self::gpu::*; +pub use self::mmio::*; +pub use self::net::*; pub use self::p9::*; +pub use self::queue::*; +pub use self::rng::*; pub use self::virtio_device::*; pub use self::virtio_pci_device::*; pub use self::wl::*; diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs index 96f7199..e5b9650 100644 --- a/devices/src/virtio/net.rs +++ b/devices/src/virtio/net.rs @@ -6,8 +6,8 @@ use std::cmp; use std::mem; use std::net::Ipv4Addr; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread; use libc::EAGAIN; @@ -15,10 +15,10 @@ use net_sys; use net_util::{Error as TapError, MacAddress, TapT}; use sys_util::Error as SysError; use sys_util::{EventFd, GuestMemory, PollContext, PollToken}; -use virtio_sys::{vhost, virtio_net}; use virtio_sys::virtio_net::virtio_net_hdr_v1; +use virtio_sys::{vhost, virtio_net}; -use super::{VirtioDevice, Queue, INTERRUPT_STATUS_USED_RING, TYPE_NET}; +use super::{Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_NET}; /// The maximum buffer size when segmentation offload is enabled. This /// includes the 12-byte virtio net header. @@ -120,14 +120,17 @@ where next_desc = desc.next_descriptor(); } None => { - warn!("net: rx: buffer is too small to hold frame of size {}", - self.rx_count); + warn!( + "net: rx: buffer is too small to hold frame of size {}", + self.rx_count + ); break; } } } - self.rx_queue.add_used(&self.mem, head_index, write_count as u32); + self.rx_queue + .add_used(&self.mem, head_index, write_count as u32); // Interrupt the guest immediately for received frames to // reduce latency. @@ -178,7 +181,8 @@ where break; } let limit = cmp::min(read_count + desc.len as usize, frame.len()); - let read_result = self.mem + let read_result = self + .mem .read_slice_at_addr(&mut frame[read_count..limit as usize], desc.addr); match read_result { Ok(sz) => { @@ -199,7 +203,7 @@ where let write_result = self.tap.write(&frame[..read_count as usize]); match write_result { - Ok(_) => {}, + Ok(_) => {} Err(e) => { warn!("net: tx: error failed to write to tap: {:?}", e); } @@ -216,11 +220,12 @@ where self.signal_used_queue(); } - fn run(&mut self, - rx_queue_evt: EventFd, - tx_queue_evt: EventFd, - kill_evt: EventFd) - -> Result<(), NetError> { + fn run( + &mut self, + rx_queue_evt: EventFd, + tx_queue_evt: EventFd, + kill_evt: EventFd, + ) -> Result<(), NetError> { #[derive(PollToken)] enum Token { // A frame is available for reading from the tap device to receive in the guest. @@ -234,11 +239,11 @@ where } let poll_ctx: PollContext = PollContext::new() - .and_then(|pc| pc.add(&self.tap, Token::RxTap).and(Ok(pc))) - .and_then(|pc| pc.add(&rx_queue_evt, Token::RxQueue).and(Ok(pc))) - .and_then(|pc| pc.add(&tx_queue_evt, Token::TxQueue).and(Ok(pc))) - .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) - .map_err(NetError::CreatePollContext)?; + .and_then(|pc| pc.add(&self.tap, Token::RxTap).and(Ok(pc))) + .and_then(|pc| pc.add(&rx_queue_evt, Token::RxQueue).and(Ok(pc))) + .and_then(|pc| pc.add(&tx_queue_evt, Token::TxQueue).and(Ok(pc))) + .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) + .map_err(NetError::CreatePollContext)?; 'poll: loop { let events = poll_ctx.wait().map_err(NetError::PollError)?; @@ -335,9 +340,9 @@ where let kill_evt = EventFd::new().map_err(NetError::CreateKillEventFd)?; Ok(Net { workers_kill_evt: Some(kill_evt.try_clone().map_err(NetError::CloneKillEventFd)?), - kill_evt: kill_evt, + kill_evt, tap: Some(tap), - avail_features: avail_features, + avail_features, acked_features: 0u64, }) } @@ -398,8 +403,10 @@ where 0 => value as u64, 1 => (value as u64) << 32, _ => { - warn!("net: virtio net device cannot ack unknown feature page: {}", - page); + warn!( + "net: virtio net device cannot ack unknown feature page: {}", + page + ); 0u64 } }; @@ -415,12 +422,14 @@ where self.acked_features |= v; } - fn activate(&mut self, - mem: GuestMemory, - interrupt_evt: EventFd, - status: Arc, - mut queues: Vec, - mut queue_evts: Vec) { + fn activate( + &mut self, + mem: GuestMemory, + interrupt_evt: EventFd, + status: Arc, + mut queues: Vec, + mut queue_evts: Vec, + ) { if queues.len() != 2 || queue_evts.len() != 2 { error!("net: expected 2 queues, got {}", queues.len()); return; @@ -429,31 +438,32 @@ where if let Some(tap) = self.tap.take() { if let Some(kill_evt) = self.workers_kill_evt.take() { let acked_features = self.acked_features; - let worker_result = thread::Builder::new() - .name("virtio_net".to_string()) - .spawn(move || { - // First queue is rx, second is tx. - let rx_queue = queues.remove(0); - let tx_queue = queues.remove(0); - let mut worker = Worker { - mem: mem, - rx_queue: rx_queue, - tx_queue: tx_queue, - tap: tap, - interrupt_status: status, - interrupt_evt: interrupt_evt, - rx_buf: [0u8; MAX_BUFFER_SIZE], - rx_count: 0, - deferred_rx: false, - acked_features: acked_features, - }; - let rx_queue_evt = queue_evts.remove(0); - let tx_queue_evt = queue_evts.remove(0); - let result = worker.run(rx_queue_evt, tx_queue_evt, kill_evt); - if let Err(e) = result { - error!("net worker thread exited with error: {:?}", e); - } - }); + let worker_result = + thread::Builder::new() + .name("virtio_net".to_string()) + .spawn(move || { + // First queue is rx, second is tx. + let rx_queue = queues.remove(0); + let tx_queue = queues.remove(0); + let mut worker = Worker { + mem, + rx_queue, + tx_queue, + tap, + interrupt_status: status, + interrupt_evt, + rx_buf: [0u8; MAX_BUFFER_SIZE], + rx_count: 0, + deferred_rx: false, + acked_features, + }; + let rx_queue_evt = queue_evts.remove(0); + let tx_queue_evt = queue_evts.remove(0); + let result = worker.run(rx_queue_evt, tx_queue_evt, kill_evt); + if let Err(e) = result { + error!("net worker thread exited with error: {:?}", e); + } + }); if let Err(e) = worker_result { error!("failed to spawn virtio_net worker: {}", e); diff --git a/devices/src/virtio/p9.rs b/devices/src/virtio/p9.rs index 0ff4de1..12e4911 100644 --- a/devices/src/virtio/p9.rs +++ b/devices/src/virtio/p9.rs @@ -11,15 +11,15 @@ use std::mem; use std::os::unix::io::RawFd; use std::path::{Path, PathBuf}; use std::result; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread; use p9; use sys_util::{Error as SysError, EventFd, GuestAddress, GuestMemory, PollContext, PollToken}; use virtio_sys::vhost::VIRTIO_F_VERSION_1; -use super::{DescriptorChain, Queue, TYPE_9P, VirtioDevice, INTERRUPT_STATUS_USED_RING}; +use super::{DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_9P}; const QUEUE_SIZE: u16 = 128; const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE]; @@ -137,7 +137,8 @@ where ) })?; let len = min(buf.len(), (current.len - self.offset) as usize); - let count = self.mem + let count = self + .mem .read_slice_at_addr(&mut buf[..len], addr) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; @@ -192,7 +193,8 @@ where })?; let len = min(buf.len(), (current.len - self.offset) as usize); - let count = self.mem + let count = self + .mem .write_slice_at_addr(&buf[..len], addr) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; @@ -237,21 +239,13 @@ impl Worker { let mut reader = Reader { mem: &self.mem, offset: 0, - iter: avail_desc - .clone() - .into_iter() - .readable() - .peekable(), + iter: avail_desc.clone().into_iter().readable().peekable(), }; let mut writer = Writer { mem: &self.mem, bytes_written: 0, offset: 0, - iter: avail_desc - .clone() - .into_iter() - .writable() - .peekable(), + iter: avail_desc.clone().into_iter().writable().peekable(), }; self.server @@ -422,19 +416,20 @@ impl VirtioDevice for P9 { self.kill_evt = Some(self_kill_evt); if let Some(server) = self.server.take() { - let worker_result = thread::Builder::new().name("virtio_9p".to_string()).spawn( - move || { - let mut worker = Worker { - mem: guest_mem, - queue: queues.remove(0), - server: server, - irq_status: status, - irq_evt: interrupt_evt, - }; - - worker.run(queue_evts.remove(0), kill_evt) - }, - ); + let worker_result = + thread::Builder::new() + .name("virtio_9p".to_string()) + .spawn(move || { + let mut worker = Worker { + mem: guest_mem, + queue: queues.remove(0), + server, + irq_status: status, + irq_evt: interrupt_evt, + }; + + worker.run(queue_evts.remove(0), kill_evt) + }); match worker_result { Ok(worker) => self.worker = Some(worker), diff --git a/devices/src/virtio/queue.rs b/devices/src/virtio/queue.rs index 41a745f..0f596ba 100644 --- a/devices/src/virtio/queue.rs +++ b/devices/src/virtio/queue.rs @@ -21,12 +21,12 @@ pub struct DescIter<'a> { impl<'a> DescIter<'a> { /// Returns an iterator that only yields the readable descriptors in the chain. - pub fn readable(self) -> impl Iterator> { + pub fn readable(self) -> impl Iterator> { self.take_while(DescriptorChain::is_read_only) } /// Returns an iterator that only yields the writable descriptors in the chain. - pub fn writable(self) -> impl Iterator> { + pub fn writable(self) -> impl Iterator> { self.skip_while(DescriptorChain::is_read_only) } } @@ -70,11 +70,12 @@ pub struct DescriptorChain<'a> { } impl<'a> DescriptorChain<'a> { - fn checked_new(mem: &GuestMemory, - desc_table: GuestAddress, - queue_size: u16, - index: u16) - -> Option { + fn checked_new( + mem: &GuestMemory, + desc_table: GuestAddress, + queue_size: u16, + index: u16, + ) -> Option { if index >= queue_size { return None; } @@ -88,31 +89,34 @@ impl<'a> DescriptorChain<'a> { if mem.checked_offset(desc_head, 16).is_none() { return None; } - let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8)) - .unwrap(); - let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12)) - .unwrap(); - let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14)) - .unwrap(); + let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8)).unwrap(); + let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12)).unwrap(); + let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14)).unwrap(); let chain = DescriptorChain { - mem: mem, - desc_table: desc_table, - queue_size: queue_size, + mem, + desc_table, + queue_size, ttl: queue_size, - index: index, - addr: addr, - len: len, - flags: flags, - next: next, + index, + addr, + len, + flags, + next, }; - if chain.is_valid() { Some(chain) } else { None } + if chain.is_valid() { + Some(chain) + } else { + None + } } fn is_valid(&self) -> bool { - if self.mem - .checked_offset(self.addr, self.len as u64) - .is_none() { + if self + .mem + .checked_offset(self.addr, self.len as u64) + .is_none() + { false } else if self.has_next() && self.next >= self.queue_size { false @@ -148,11 +152,12 @@ impl<'a> DescriptorChain<'a> { /// the head of the next _available_ descriptor chain. pub fn next_descriptor(&self) -> Option> { if self.has_next() { - DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next) - .map(|mut c| { - c.ttl = self.ttl - 1; - c - }) + DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next).map( + |mut c| { + c.ttl = self.ttl - 1; + c + }, + ) } else { None } @@ -160,9 +165,7 @@ impl<'a> DescriptorChain<'a> { /// Produces an iterator over all the descriptors in this chain. pub fn into_iter(self) -> DescIter<'a> { - DescIter { - next: Some(self), - } + DescIter { next: Some(self) } } } @@ -233,7 +236,7 @@ impl Queue { /// Constructs an empty virtio queue with the given `max_size`. pub fn new(max_size: u16) -> Queue { Queue { - max_size: max_size, + max_size, size: max_size, ready: false, desc_table: GuestAddress(0), @@ -261,49 +264,57 @@ impl Queue { if !self.ready { error!("attempt to use virtio queue that is not marked ready"); false - } else if self.size > self.max_size || self.size == 0 || - (self.size & (self.size - 1)) != 0 { + } else if self.size > self.max_size || self.size == 0 || (self.size & (self.size - 1)) != 0 + { error!("virtio queue with invalid size: {}", self.size); false } else if desc_table - .checked_add(desc_table_size as u64) - .map_or(true, |v| !mem.address_in_range(v)) { - error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}", - desc_table.offset(), - desc_table_size); + .checked_add(desc_table_size as u64) + .map_or(true, |v| !mem.address_in_range(v)) + { + error!( + "virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}", + desc_table.offset(), + desc_table_size + ); false } else if avail_ring - .checked_add(avail_ring_size as u64) - .map_or(true, |v| !mem.address_in_range(v)) { - error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}", - avail_ring.offset(), - avail_ring_size); + .checked_add(avail_ring_size as u64) + .map_or(true, |v| !mem.address_in_range(v)) + { + error!( + "virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}", + avail_ring.offset(), + avail_ring_size + ); false } else if used_ring - .checked_add(used_ring_size as u64) - .map_or(true, |v| !mem.address_in_range(v)) { - error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}", - used_ring.offset(), - used_ring_size); + .checked_add(used_ring_size as u64) + .map_or(true, |v| !mem.address_in_range(v)) + { + error!( + "virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}", + used_ring.offset(), + used_ring_size + ); false } else { true } - } /// A consuming iterator over all available descriptor chain heads offered by the driver. pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> { if !self.is_valid(mem) { return AvailIter { - mem: mem, - desc_table: GuestAddress(0), - avail_ring: GuestAddress(0), - next_index: Wrapping(0), - last_index: Wrapping(0), - queue_size: 0, - next_avail: &mut self.next_avail, - }; + mem, + desc_table: GuestAddress(0), + avail_ring: GuestAddress(0), + next_index: Wrapping(0), + last_index: Wrapping(0), + queue_size: 0, + next_avail: &mut self.next_avail, + }; } let queue_size = self.actual_size(); let avail_ring = self.avail_ring; @@ -315,7 +326,7 @@ impl Queue { if queue_len.0 > queue_size { return AvailIter { - mem: mem, + mem, desc_table: GuestAddress(0), avail_ring: GuestAddress(0), next_index: Wrapping(0), @@ -326,12 +337,12 @@ impl Queue { } AvailIter { - mem: mem, + mem, desc_table: self.desc_table, - avail_ring: avail_ring, + avail_ring, next_index: self.next_avail, last_index: Wrapping(last_index), - queue_size: queue_size, + queue_size, next_avail: &mut self.next_avail, } } @@ -339,8 +350,10 @@ impl Queue { /// Puts an available descriptor head into the used ring for use by the guest. pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) { if desc_index >= self.actual_size() { - error!("attempted to add out of bounds descriptor to used ring: {}", - desc_index); + error!( + "attempted to add out of bounds descriptor to used ring: {}", + desc_index + ); return; } @@ -349,8 +362,7 @@ impl Queue { let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64); // These writes can't fail as we are guaranteed to be within the descriptor ring. - mem.write_obj_at_addr(desc_index as u32, used_elem) - .unwrap(); + mem.write_obj_at_addr(desc_index as u32, used_elem).unwrap(); mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4)) .unwrap(); diff --git a/devices/src/virtio/rng.rs b/devices/src/virtio/rng.rs index f1cfe0a..0c0dd13 100644 --- a/devices/src/virtio/rng.rs +++ b/devices/src/virtio/rng.rs @@ -6,13 +6,13 @@ use std; use std::fs::File; use std::io; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread; use sys_util::{EventFd, GuestMemory, PollContext, PollToken}; -use super::{VirtioDevice, Queue, INTERRUPT_STATUS_USED_RING, TYPE_RNG}; +use super::{Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_RNG}; const QUEUE_SIZE: u16 = 256; const QUEUE_SIZES: &'static [u16] = &[QUEUE_SIZE]; @@ -44,10 +44,14 @@ impl Worker { // Drivers can only read from the random device. if avail_desc.is_write_only() { // Fill the read with data from the random device on the host. - if self.mem.read_to_memory(avail_desc.addr, - &mut self.random_file, - avail_desc.len as usize) - .is_ok() { + if self + .mem + .read_to_memory( + avail_desc.addr, + &mut self.random_file, + avail_desc.len as usize, + ).is_ok() + { len = avail_desc.len; } } @@ -75,16 +79,16 @@ impl Worker { Kill, } - let poll_ctx: PollContext = - match PollContext::new() - .and_then(|pc| pc.add(&queue_evt, Token::QueueAvailable).and(Ok(pc))) - .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) { - Ok(pc) => pc, - Err(e) => { - error!("failed creating PollContext: {:?}", e); - return; - } - }; + let poll_ctx: PollContext = match PollContext::new() + .and_then(|pc| pc.add(&queue_evt, Token::QueueAvailable).and(Ok(pc))) + .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) + { + Ok(pc) => pc, + Err(e) => { + error!("failed creating PollContext: {:?}", e); + return; + } + }; 'poll: loop { let events = match poll_ctx.wait() { @@ -124,12 +128,11 @@ pub struct Rng { impl Rng { /// Create a new virtio rng device that gets random data from /dev/urandom. pub fn new() -> Result { - let random_file = File::open("/dev/urandom") - .map_err(RngError::AccessingRandomDev)?; + let random_file = File::open("/dev/urandom").map_err(RngError::AccessingRandomDev)?; Ok(Rng { - kill_evt: None, - random_file: Some(random_file), - }) + kill_evt: None, + random_file: Some(random_file), + }) } } @@ -161,41 +164,43 @@ impl VirtioDevice for Rng { QUEUE_SIZES } - fn activate(&mut self, - mem: GuestMemory, - interrupt_evt: EventFd, - status: Arc, - mut queues: Vec, - mut queue_evts: Vec) { + fn activate( + &mut self, + mem: GuestMemory, + interrupt_evt: EventFd, + status: Arc, + mut queues: Vec, + mut queue_evts: Vec, + ) { if queues.len() != 1 || queue_evts.len() != 1 { return; } - let (self_kill_evt, kill_evt) = - match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { - Ok(v) => v, - Err(e) => { - error!("failed to create kill EventFd pair: {:?}", e); - return; - } - }; + let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { + Ok(v) => v, + Err(e) => { + error!("failed to create kill EventFd pair: {:?}", e); + return; + } + }; self.kill_evt = Some(self_kill_evt); let queue = queues.remove(0); if let Some(random_file) = self.random_file.take() { - let worker_result = thread::Builder::new() - .name("virtio_rng".to_string()) - .spawn(move || { - let mut worker = Worker { - queue: queue, - mem: mem, - random_file: random_file, - interrupt_status: status, - interrupt_evt: interrupt_evt, - }; - worker.run(queue_evts.remove(0), kill_evt); - }); + let worker_result = + thread::Builder::new() + .name("virtio_rng".to_string()) + .spawn(move || { + let mut worker = Worker { + queue, + mem, + random_file, + interrupt_status: status, + interrupt_evt, + }; + worker.run(queue_evts.remove(0), kill_evt); + }); if let Err(e) = worker_result { error!("failed to spawn virtio_rng worker: {}", e); diff --git a/devices/src/virtio/vhost/net.rs b/devices/src/virtio/vhost/net.rs index 694dc6a..1f73863 100644 --- a/devices/src/virtio/vhost/net.rs +++ b/devices/src/virtio/vhost/net.rs @@ -5,8 +5,8 @@ use std::mem; use std::net::Ipv4Addr; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::Arc; use std::sync::atomic::AtomicUsize; +use std::sync::Arc; use std::thread; use net_sys; @@ -16,9 +16,9 @@ use sys_util::{EventFd, GuestMemory}; use vhost::NetT as VhostNetT; use virtio_sys::{vhost, virtio_net}; -use super::{Error, Result}; use super::super::{Queue, VirtioDevice, TYPE_NET}; use super::worker::Worker; +use super::{Error, Result}; const QUEUE_SIZE: u16 = 256; const NUM_QUEUES: usize = 2; @@ -41,16 +41,19 @@ where { /// Create a new virtio network device with the given IP address and /// netmask. - pub fn new(ip_addr: Ipv4Addr, - netmask: Ipv4Addr, - mac_addr: MacAddress, - mem: &GuestMemory) -> Result> { + pub fn new( + ip_addr: Ipv4Addr, + netmask: Ipv4Addr, + mac_addr: MacAddress, + mem: &GuestMemory, + ) -> Result> { let kill_evt = EventFd::new().map_err(Error::CreateKillEventFd)?; let tap: T = T::new(true).map_err(Error::TapOpen)?; tap.set_ip_addr(ip_addr).map_err(Error::TapSetIp)?; tap.set_netmask(netmask).map_err(Error::TapSetNetmask)?; - tap.set_mac_address(mac_addr).map_err(Error::TapSetMacAddress)?; + tap.set_mac_address(mac_addr) + .map_err(Error::TapSetMacAddress)?; // Set offload flags to match the virtio features below. tap.set_offload( @@ -59,29 +62,31 @@ where // We declare VIRTIO_NET_F_MRG_RXBUF, so set the vnet hdr size to match. let vnet_hdr_size = mem::size_of::() as i32; - tap.set_vnet_hdr_size(vnet_hdr_size).map_err(Error::TapSetVnetHdrSize)?; + tap.set_vnet_hdr_size(vnet_hdr_size) + .map_err(Error::TapSetVnetHdrSize)?; tap.enable().map_err(Error::TapEnable)?; let vhost_net_handle = U::new(mem).map_err(Error::VhostOpen)?; - let avail_features = - 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM | 1 << virtio_net::VIRTIO_NET_F_CSUM | - 1 << virtio_net::VIRTIO_NET_F_GUEST_TSO4 | - 1 << virtio_net::VIRTIO_NET_F_GUEST_UFO | - 1 << virtio_net::VIRTIO_NET_F_HOST_TSO4 | - 1 << virtio_net::VIRTIO_NET_F_HOST_UFO | - 1 << virtio_net::VIRTIO_NET_F_MRG_RXBUF | - 1 << vhost::VIRTIO_RING_F_INDIRECT_DESC | - 1 << vhost::VIRTIO_RING_F_EVENT_IDX | - 1 << vhost::VIRTIO_F_NOTIFY_ON_EMPTY | 1 << vhost::VIRTIO_F_VERSION_1; + let avail_features = 1 << virtio_net::VIRTIO_NET_F_GUEST_CSUM + | 1 << virtio_net::VIRTIO_NET_F_CSUM + | 1 << virtio_net::VIRTIO_NET_F_GUEST_TSO4 + | 1 << virtio_net::VIRTIO_NET_F_GUEST_UFO + | 1 << virtio_net::VIRTIO_NET_F_HOST_TSO4 + | 1 << virtio_net::VIRTIO_NET_F_HOST_UFO + | 1 << virtio_net::VIRTIO_NET_F_MRG_RXBUF + | 1 << vhost::VIRTIO_RING_F_INDIRECT_DESC + | 1 << vhost::VIRTIO_RING_F_EVENT_IDX + | 1 << vhost::VIRTIO_F_NOTIFY_ON_EMPTY + | 1 << vhost::VIRTIO_F_VERSION_1; Ok(Net { workers_kill_evt: Some(kill_evt.try_clone().map_err(Error::CloneKillEventFd)?), - kill_evt: kill_evt, + kill_evt, tap: Some(tap), vhost_net_handle: Some(vhost_net_handle), vhost_interrupt: Some(EventFd::new().map_err(Error::VhostIrqCreate)?), - avail_features: avail_features, + avail_features, acked_features: 0u64, }) } @@ -143,7 +148,7 @@ where _ => { warn!("net: virtio net got request for features page: {}", page); 0u32 - }, + } } } @@ -157,7 +162,7 @@ where page ); 0u64 - }, + } }; // Check if the guest is ACK'ing a feature that we didn't claim to have. @@ -192,12 +197,14 @@ where let worker_result = thread::Builder::new() .name("vhost_net".to_string()) .spawn(move || { - let mut worker = Worker::new(queues, - vhost_net_handle, - vhost_interrupt, - status, - interrupt_evt, - acked_features); + let mut worker = Worker::new( + queues, + vhost_net_handle, + vhost_interrupt, + status, + interrupt_evt, + acked_features, + ); let activate_vqs = |handle: &U| -> Result<()> { for idx in 0..NUM_QUEUES { handle @@ -227,8 +234,8 @@ where #[cfg(test)] pub mod tests { use super::*; - use std::result; use net_util::fakes::FakeTap; + use std::result; use sys_util::{GuestAddress, GuestMemory, GuestMemoryError}; use vhost::net::fakes::FakeNet; diff --git a/devices/src/virtio/vhost/vsock.rs b/devices/src/virtio/vhost/vsock.rs index b55b6a0..694ea25 100644 --- a/devices/src/virtio/vhost/vsock.rs +++ b/devices/src/virtio/vhost/vsock.rs @@ -3,8 +3,8 @@ // found in the LICENSE file. use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::Arc; use std::sync::atomic::AtomicUsize; +use std::sync::Arc; use std::thread; use byteorder::{ByteOrder, LittleEndian}; @@ -13,9 +13,9 @@ use sys_util::{EventFd, GuestMemory}; use vhost::Vsock as VhostVsockHandle; use virtio_sys::vhost; -use super::{Error, Result}; use super::super::{Queue, VirtioDevice, TYPE_VSOCK}; use super::worker::Worker; +use super::{Error, Result}; const QUEUE_SIZE: u16 = 256; const NUM_QUEUES: usize = 3; @@ -37,18 +37,20 @@ impl Vsock { let kill_evt = EventFd::new().map_err(Error::CreateKillEventFd)?; let handle = VhostVsockHandle::new(mem).map_err(Error::VhostOpen)?; - let avail_features = - 1 << vhost::VIRTIO_F_NOTIFY_ON_EMPTY | 1 << vhost::VIRTIO_RING_F_INDIRECT_DESC | - 1 << vhost::VIRTIO_RING_F_EVENT_IDX | 1 << vhost::VHOST_F_LOG_ALL | - 1 << vhost::VIRTIO_F_ANY_LAYOUT | 1 << vhost::VIRTIO_F_VERSION_1; + let avail_features = 1 << vhost::VIRTIO_F_NOTIFY_ON_EMPTY + | 1 << vhost::VIRTIO_RING_F_INDIRECT_DESC + | 1 << vhost::VIRTIO_RING_F_EVENT_IDX + | 1 << vhost::VHOST_F_LOG_ALL + | 1 << vhost::VIRTIO_F_ANY_LAYOUT + | 1 << vhost::VIRTIO_F_VERSION_1; Ok(Vsock { worker_kill_evt: Some(kill_evt.try_clone().map_err(Error::CloneKillEventFd)?), kill_evt: Some(kill_evt), vhost_handle: Some(handle), - cid: cid, + cid, interrupt: Some(EventFd::new().map_err(Error::VhostIrqCreate)?), - avail_features: avail_features, + avail_features, acked_features: 0, }) } @@ -58,7 +60,7 @@ impl Vsock { worker_kill_evt: None, kill_evt: None, vhost_handle: None, - cid: cid, + cid, interrupt: None, avail_features: features, acked_features: 0, @@ -121,7 +123,7 @@ impl VirtioDevice for Vsock { page ); 0u32 - }, + } } } @@ -131,7 +133,7 @@ impl VirtioDevice for Vsock { 0 if data.len() == 4 => LittleEndian::write_u32(data, (self.cid & 0xffffffff) as u32), 4 if data.len() == 4 => { LittleEndian::write_u32(data, ((self.cid >> 32) & 0xffffffff) as u32) - }, + } _ => warn!( "vsock: virtio-vsock received invalid read request of {} bytes at offset {}", data.len(), @@ -150,7 +152,7 @@ impl VirtioDevice for Vsock { page ); 0u64 - }, + } }; // Check if the guest is ACK'ing a feature that we didn't claim to have. @@ -188,12 +190,14 @@ impl VirtioDevice for Vsock { // The third vq is an event-only vq that is not handled by the vhost // subsystem (but still needs to exist). Split it off here. let vhost_queues = queues[..2].to_vec(); - let mut worker = Worker::new(vhost_queues, - vhost_handle, - interrupt, - status, - interrupt_evt, - acked_features); + let mut worker = Worker::new( + vhost_queues, + vhost_handle, + interrupt, + status, + interrupt_evt, + acked_features, + ); let activate_vqs = |handle: &VhostVsockHandle| -> Result<()> { handle.set_cid(cid).map_err(Error::VhostVsockSetCid)?; handle.start().map_err(Error::VhostVsockStart)?; @@ -242,12 +246,18 @@ mod tests { acked_features |= 1 << 60; unavailable_features |= 1 << 60; vsock.ack_features(1, (acked_features >> 32) as u32); - assert_eq!(acked_features & !unavailable_features, vsock.acked_features()); + assert_eq!( + acked_features & !unavailable_features, + vsock.acked_features() + ); acked_features |= 1 << 1; unavailable_features |= 1 << 1; vsock.ack_features(0, (acked_features & 0xffffffff) as u32); - assert_eq!(acked_features & !unavailable_features, vsock.acked_features()); + assert_eq!( + acked_features & !unavailable_features, + vsock.acked_features() + ); } #[test] diff --git a/devices/src/virtio/vhost/worker.rs b/devices/src/virtio/vhost/worker.rs index 6d4cab7..529ebc0 100644 --- a/devices/src/virtio/vhost/worker.rs +++ b/devices/src/virtio/vhost/worker.rs @@ -3,14 +3,14 @@ // found in the LICENSE file. use std::os::raw::c_ulonglong; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use sys_util::{EventFd, PollContext, PollToken}; use vhost::Vhost; -use super::{Error, Result}; use super::super::{Queue, INTERRUPT_STATUS_USED_RING}; +use super::{Error, Result}; /// Worker that takes care of running the vhost device. This mainly involves forwarding interrupts /// from the vhost driver to the guest VM because crosvm only supports the virtio-mmio transport, @@ -35,12 +35,12 @@ impl Worker { acked_features: u64, ) -> Worker { Worker { - queues: queues, - vhost_handle: vhost_handle, - vhost_interrupt: vhost_interrupt, - interrupt_status: interrupt_status, - interrupt_evt: interrupt_evt, - acked_features: acked_features, + queues, + vhost_handle, + vhost_interrupt, + interrupt_status, + interrupt_evt, + acked_features, } } @@ -61,14 +61,23 @@ impl Worker { F: FnOnce(&T) -> Result<()>, { // Preliminary setup for vhost net. - self.vhost_handle.set_owner().map_err(Error::VhostSetOwner)?; + self.vhost_handle + .set_owner() + .map_err(Error::VhostSetOwner)?; - let avail_features = self.vhost_handle.get_features().map_err(Error::VhostGetFeatures)?; + let avail_features = self + .vhost_handle + .get_features() + .map_err(Error::VhostGetFeatures)?; let features: c_ulonglong = self.acked_features & avail_features; - self.vhost_handle.set_features(features).map_err(Error::VhostSetFeatures)?; + self.vhost_handle + .set_features(features) + .map_err(Error::VhostSetFeatures)?; - self.vhost_handle.set_mem_table().map_err(Error::VhostSetMemTable)?; + self.vhost_handle + .set_mem_table() + .map_err(Error::VhostSetMemTable)?; for (queue_index, ref queue) in self.queues.iter().enumerate() { self.vhost_handle @@ -85,8 +94,7 @@ impl Worker { queue.used_ring, queue.avail_ring, None, - ) - .map_err(Error::VhostSetVringAddr)?; + ).map_err(Error::VhostSetVringAddr)?; self.vhost_handle .set_vring_base(queue_index, 0) .map_err(Error::VhostSetVringBase)?; @@ -107,9 +115,9 @@ impl Worker { } let poll_ctx: PollContext = PollContext::new() - .and_then(|pc| pc.add(&self.vhost_interrupt, Token::VhostIrq).and(Ok(pc))) - .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) - .map_err(Error::CreatePollContext)?; + .and_then(|pc| pc.add(&self.vhost_interrupt, Token::VhostIrq).and(Ok(pc))) + .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) + .map_err(Error::CreatePollContext)?; 'poll: loop { let events = poll_ctx.wait().map_err(Error::PollError)?; @@ -120,7 +128,7 @@ impl Worker { Token::VhostIrq => { needs_interrupt = true; self.vhost_interrupt.read().map_err(Error::VhostIrqRead)?; - }, + } Token::Kill => break 'poll, } } diff --git a/devices/src/virtio/virtio_device.rs b/devices/src/virtio/virtio_device.rs index 7458be8..3c6d868 100644 --- a/devices/src/virtio/virtio_device.rs +++ b/devices/src/virtio/virtio_device.rs @@ -3,8 +3,8 @@ // found in the LICENSE file. use std::os::unix::io::RawFd; -use std::sync::Arc; use std::sync::atomic::AtomicUsize; +use std::sync::Arc; use super::*; use sys_util::{EventFd, GuestMemory}; @@ -52,12 +52,14 @@ pub trait VirtioDevice: Send { } /// Activates this device for real usage. - fn activate(&mut self, - mem: GuestMemory, - interrupt_evt: EventFd, - status: Arc, - queues: Vec, - queue_evts: Vec); + fn activate( + &mut self, + mem: GuestMemory, + interrupt_evt: EventFd, + status: Arc, + queues: Vec, + queue_evts: Vec, + ); /// Optionally deactivates this device and returns ownership of the guest memory map, interrupt /// event, and queue events. diff --git a/devices/src/virtio/virtio_pci_common_config.rs b/devices/src/virtio/virtio_pci_common_config.rs index 8a50b35..2793052 100644 --- a/devices/src/virtio/virtio_pci_common_config.rs +++ b/devices/src/virtio/virtio_pci_common_config.rs @@ -138,9 +138,12 @@ impl VirtioPciCommonConfig { // TODO(dverkamp): This hack (copied from MmioDevice) unconditionally // reports support for VIRTIO_F_VERSION_1; once all devices have been // fixed to report VIRTIO_F_VERSION_1, remove this workaround. - device.features(self.device_feature_select) | - if self.device_feature_select == 1 { 0x1 } else { 0x0 } - }, + device.features(self.device_feature_select) | if self.device_feature_select == 1 { + 0x1 + } else { + 0x0 + } + } 0x08 => self.driver_feature_select, _ => 0, } @@ -211,8 +214,8 @@ mod tests { use super::*; use std::os::unix::io::RawFd; - use std::sync::Arc; use std::sync::atomic::AtomicUsize; + use std::sync::Arc; use sys_util::{EventFd, GuestMemory}; struct DummyDevice(u32); @@ -229,12 +232,14 @@ mod tests { fn queue_max_sizes(&self) -> &[u16] { QUEUE_SIZES } - fn activate(&mut self, - _mem: GuestMemory, - _interrupt_evt: EventFd, - _status: Arc, - _queues: Vec, - _queue_evts: Vec) { + fn activate( + &mut self, + _mem: GuestMemory, + _interrupt_evt: EventFd, + _status: Arc, + _queues: Vec, + _queue_evts: Vec, + ) { } fn features(&self, _page: u32) -> u32 { DUMMY_FEATURES diff --git a/devices/src/virtio/virtio_pci_device.rs b/devices/src/virtio/virtio_pci_device.rs index e9b57ac..10cbd32 100644 --- a/devices/src/virtio/virtio_pci_device.rs +++ b/devices/src/virtio/virtio_pci_device.rs @@ -266,8 +266,7 @@ impl VirtioPciDevice { //TODO(dgreid) - How will the configuration_cap work? let configuration_cap = VirtioPciCap::new(PciCapabilityType::PciConfig, 0, 0, 0); - self.config_regs - .add_capability(&configuration_cap); + self.config_regs.add_capability(&configuration_cap); self.settings_bar = settings_bar; } @@ -335,8 +334,12 @@ impl PciDevice for VirtioPciDevice { o if COMMON_CONFIG_BAR_OFFSET <= o && o < COMMON_CONFIG_BAR_OFFSET + COMMON_CONFIG_SIZE => { - self.common_config - .read(o - COMMON_CONFIG_BAR_OFFSET, data, &mut self.queues, &mut self.device) + self.common_config.read( + o - COMMON_CONFIG_BAR_OFFSET, + data, + &mut self.queues, + &mut self.device, + ) } o if ISR_CONFIG_BAR_OFFSET <= o && o < ISR_CONFIG_BAR_OFFSET + ISR_CONFIG_SIZE => { if let Some(v) = data.get_mut(0) { @@ -364,8 +367,12 @@ impl PciDevice for VirtioPciDevice { o if COMMON_CONFIG_BAR_OFFSET <= o && o < COMMON_CONFIG_BAR_OFFSET + COMMON_CONFIG_SIZE => { - self.common_config - .write(o - COMMON_CONFIG_BAR_OFFSET, data, &mut self.queues, &mut self.device) + self.common_config.write( + o - COMMON_CONFIG_BAR_OFFSET, + data, + &mut self.queues, + &mut self.device, + ) } o if ISR_CONFIG_BAR_OFFSET <= o && o < ISR_CONFIG_BAR_OFFSET + ISR_CONFIG_SIZE => { if let Some(v) = data.get(0) { diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index 7c6ae58..e1a9025 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -30,41 +30,43 @@ use std::cell::RefCell; use std::collections::btree_map::Entry; -use std::collections::{BTreeSet as Set, BTreeMap as Map, VecDeque}; +use std::collections::{BTreeMap as Map, BTreeSet as Set, VecDeque}; use std::convert::From; -use std::ffi::CStr; use std::error::{self, Error as StdError}; +use std::ffi::CStr; use std::fmt; use std::fs::File; -use std::io::{self, Seek, SeekFrom, Read}; +use std::io::{self, Read, Seek, SeekFrom}; use std::mem::{size_of, size_of_val}; #[cfg(feature = "wl-dmabuf")] use std::os::raw::{c_uint, c_ulonglong}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::os::unix::net::{UnixDatagram, UnixStream}; -use std::path::{PathBuf, Path}; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::result; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::thread; use std::time::Duration; #[cfg(feature = "wl-dmabuf")] use libc::{dup, EBADF, EINVAL}; -use data_model::*; use data_model::VolatileMemoryError; +use data_model::*; use resources::GpuMemoryDesc; -use sys_util::{Error, Result, EventFd, ScmSocket, SharedMemory, GuestAddress, GuestMemory, - GuestMemoryError, PollContext, PollToken, FileFlags, pipe, round_up_to_page_size}; +use sys_util::{ + pipe, round_up_to_page_size, Error, EventFd, FileFlags, GuestAddress, GuestMemory, + GuestMemoryError, PollContext, PollToken, Result, ScmSocket, SharedMemory, +}; #[cfg(feature = "wl-dmabuf")] use sys_util::ioctl_with_ref; -use vm_control::{VmControlError, VmRequest, VmResponse, MaybeOwnedFd}; -use super::{VirtioDevice, Queue, DescriptorChain, INTERRUPT_STATUS_USED_RING, TYPE_WL}; +use super::{DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_WL}; +use vm_control::{MaybeOwnedFd, VmControlError, VmRequest, VmResponse}; const VIRTWL_SEND_MAX_ALLOCS: usize = 28; const VIRTIO_WL_CMD_VFD_NEW: u32 = 256; @@ -122,33 +124,41 @@ fn parse_new(addr: GuestAddress, mem: &GuestMemory) -> WlResult { const FLAGS_OFFSET: u64 = 12; const SIZE_OFFSET: u64 = 24; - let id: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, ID_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let flags: Le32 = - mem.read_obj_from_addr(mem.checked_offset(addr, FLAGS_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let size: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, SIZE_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; + let id: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, ID_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let flags: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, FLAGS_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let size: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, SIZE_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; Ok(WlOp::NewAlloc { - id: id.into(), - flags: flags.into(), - size: size.into(), - }) + id: id.into(), + flags: flags.into(), + size: size.into(), + }) } fn parse_new_pipe(addr: GuestAddress, mem: &GuestMemory) -> WlResult { const ID_OFFSET: u64 = 8; const FLAGS_OFFSET: u64 = 12; - let id: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, ID_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let flags: Le32 = - mem.read_obj_from_addr(mem.checked_offset(addr, FLAGS_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; + let id: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, ID_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let flags: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, FLAGS_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; Ok(WlOp::NewPipe { - id: id.into(), - flags: flags.into(), - }) + id: id.into(), + flags: flags.into(), + }) } #[cfg(feature = "wl-dmabuf")] @@ -158,35 +168,46 @@ fn parse_new_dmabuf(addr: GuestAddress, mem: &GuestMemory) -> WlResult { const HEIGHT_OFFSET: u64 = 32; const FORMAT_OFFSET: u64 = 36; - let id: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, ID_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let width: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, WIDTH_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let height: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, HEIGHT_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let format: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, FORMAT_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; + let id: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, ID_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let width: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, WIDTH_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let height: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, HEIGHT_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let format: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, FORMAT_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; Ok(WlOp::NewDmabuf { - id: id.into(), - width: width.into(), - height: height.into(), - format: format.into(), - }) + id: id.into(), + width: width.into(), + height: height.into(), + format: format.into(), + }) } #[cfg(feature = "wl-dmabuf")] fn parse_dmabuf_sync(addr: GuestAddress, mem: &GuestMemory) -> WlResult { const ID_OFFSET: u64 = 8; const FLAGS_OFFSET: u64 = 12; - let id: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, ID_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let flags: Le32 = - mem.read_obj_from_addr(mem.checked_offset(addr, FLAGS_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; + let id: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, ID_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let flags: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, FLAGS_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; Ok(WlOp::DmabufSync { - id: id.into(), - flags: flags.into(), - }) + id: id.into(), + flags: flags.into(), + }) } fn parse_send(addr: GuestAddress, len: u32, mem: &GuestMemory) -> WlResult { @@ -194,29 +215,36 @@ fn parse_send(addr: GuestAddress, len: u32, mem: &GuestMemory) -> WlResult const VFD_COUNT_OFFSET: u64 = 12; const VFDS_OFFSET: u64 = 16; - let id: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, ID_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; - let vfd_count: Le32 = - mem.read_obj_from_addr(mem.checked_offset(addr, VFD_COUNT_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; + let id: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, ID_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; + let vfd_count: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, VFD_COUNT_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; let vfd_count: u32 = vfd_count.into(); - let vfds_addr = mem.checked_offset(addr, VFDS_OFFSET) + let vfds_addr = mem + .checked_offset(addr, VFDS_OFFSET) .ok_or(WlError::CheckedOffset)?; - let data_addr = mem.checked_offset(vfds_addr, (vfd_count * 4) as u64) + let data_addr = mem + .checked_offset(vfds_addr, (vfd_count * 4) as u64) .ok_or(WlError::CheckedOffset)?; Ok(WlOp::Send { - id: id.into(), - vfds_addr: vfds_addr, - vfd_count: vfd_count, - data_addr: data_addr, - data_len: len - (VFDS_OFFSET as u32) - vfd_count * 4, - }) + id: id.into(), + vfds_addr, + vfd_count, + data_addr, + data_len: len - (VFDS_OFFSET as u32) - vfd_count * 4, + }) } fn parse_id(addr: GuestAddress, mem: &GuestMemory) -> WlResult { const ID_OFFSET: u64 = 8; - let id: Le32 = mem.read_obj_from_addr(mem.checked_offset(addr, ID_OFFSET) - .ok_or(WlError::CheckedOffset)?)?; + let id: Le32 = mem.read_obj_from_addr( + mem.checked_offset(addr, ID_OFFSET) + .ok_or(WlError::CheckedOffset)?, + )?; Ok(id.into()) } @@ -224,9 +252,13 @@ fn parse_desc(desc: &DescriptorChain, mem: &GuestMemory) -> WlResult { let type_: Le32 = mem.read_obj_from_addr(desc.addr)?; match type_.into() { VIRTIO_WL_CMD_VFD_NEW => parse_new(desc.addr, mem), - VIRTIO_WL_CMD_VFD_CLOSE => Ok(WlOp::Close { id: parse_id(desc.addr, mem)? }), + VIRTIO_WL_CMD_VFD_CLOSE => Ok(WlOp::Close { + id: parse_id(desc.addr, mem)?, + }), VIRTIO_WL_CMD_VFD_SEND => parse_send(desc.addr, desc.len, mem), - VIRTIO_WL_CMD_VFD_NEW_CTX => Ok(WlOp::NewCtx { id: parse_id(desc.addr, mem)? }), + VIRTIO_WL_CMD_VFD_NEW_CTX => Ok(WlOp::NewCtx { + id: parse_id(desc.addr, mem)?, + }), VIRTIO_WL_CMD_VFD_NEW_PIPE => parse_new_pipe(desc.addr, mem), #[cfg(feature = "wl-dmabuf")] VIRTIO_WL_CMD_VFD_NEW_DMABUF => parse_new_dmabuf(desc.addr, mem), @@ -236,20 +268,21 @@ fn parse_desc(desc: &DescriptorChain, mem: &GuestMemory) -> WlResult { } } -fn encode_vfd_new(desc_mem: VolatileSlice, - resp: bool, - vfd_id: u32, - flags: u32, - pfn: u64, - size: u32) - -> WlResult { +fn encode_vfd_new( + desc_mem: VolatileSlice, + resp: bool, + vfd_id: u32, + flags: u32, + pfn: u64, + size: u32, +) -> WlResult { let ctrl_vfd_new = CtrlVfdNew { hdr: CtrlHeader { type_: Le32::from(if resp { - VIRTIO_WL_RESP_VFD_NEW - } else { - VIRTIO_WL_CMD_VFD_NEW - }), + VIRTIO_WL_RESP_VFD_NEW + } else { + VIRTIO_WL_CMD_VFD_NEW + }), flags: Le32::from(0), }, id: Le32::from(vfd_id), @@ -263,13 +296,14 @@ fn encode_vfd_new(desc_mem: VolatileSlice, } #[cfg(feature = "wl-dmabuf")] -fn encode_vfd_new_dmabuf(desc_mem: VolatileSlice, - vfd_id: u32, - flags: u32, - pfn: u64, - size: u32, - desc: GpuMemoryDesc) - -> WlResult { +fn encode_vfd_new_dmabuf( + desc_mem: VolatileSlice, + vfd_id: u32, + flags: u32, + pfn: u64, + size: u32, + desc: GpuMemoryDesc, +) -> WlResult { let ctrl_vfd_new_dmabuf = CtrlVfdNewDmabuf { hdr: CtrlHeader { type_: Le32::from(VIRTIO_WL_RESP_VFD_NEW_DMABUF), @@ -294,11 +328,12 @@ fn encode_vfd_new_dmabuf(desc_mem: VolatileSlice, Ok(size_of::() as u32) } -fn encode_vfd_recv(desc_mem: VolatileSlice, - vfd_id: u32, - data: &[u8], - vfd_ids: &[u32]) - -> WlResult { +fn encode_vfd_recv( + desc_mem: VolatileSlice, + vfd_id: u32, + data: &[u8], + vfd_ids: &[u32], +) -> WlResult { let ctrl_vfd_recv = CtrlVfdRecv { hdr: CtrlHeader { type_: Le32::from(VIRTIO_WL_CMD_VFD_RECV), @@ -309,18 +344,20 @@ fn encode_vfd_recv(desc_mem: VolatileSlice, }; desc_mem.get_ref(0)?.store(ctrl_vfd_recv); - let vfd_slice = desc_mem - .get_slice(size_of::() as u64, - (vfd_ids.len() * size_of::()) as u64)?; + let vfd_slice = desc_mem.get_slice( + size_of::() as u64, + (vfd_ids.len() * size_of::()) as u64, + )?; for (i, &recv_vfd_id) in vfd_ids.iter().enumerate() { vfd_slice .get_ref((size_of::() * i) as u64)? .store(recv_vfd_id); } - let data_slice = desc_mem - .get_slice((size_of::() + vfd_ids.len() * size_of::()) as u64, - data.len() as u64)?; + let data_slice = desc_mem.get_slice( + (size_of::() + vfd_ids.len() * size_of::()) as u64, + data.len() as u64, + )?; data_slice.copy_from(data); Ok((size_of::() + vfd_ids.len() * size_of::() + data.len()) as u32) @@ -435,7 +472,9 @@ struct VmRequester { impl VmRequester { fn new(vm_socket: UnixDatagram) -> VmRequester { - VmRequester { inner: Rc::new(RefCell::new(vm_socket)) } + VmRequester { + inner: Rc::new(RefCell::new(vm_socket)), + } } fn request(&self, request: VmRequest) -> WlResult { @@ -509,8 +548,14 @@ unsafe impl DataInit for CtrlVfd {} #[derive(Debug)] enum WlOp { - NewAlloc { id: u32, flags: u32, size: u32 }, - Close { id: u32 }, + NewAlloc { + id: u32, + flags: u32, + size: u32, + }, + Close { + id: u32, + }, Send { id: u32, vfds_addr: GuestAddress, @@ -518,13 +563,28 @@ enum WlOp { data_addr: GuestAddress, data_len: u32, }, - NewCtx { id: u32 }, - NewPipe { id: u32, flags: u32 }, + NewCtx { + id: u32, + }, + NewPipe { + id: u32, + flags: u32, + }, #[cfg(feature = "wl-dmabuf")] - NewDmabuf { id: u32, width: u32, height: u32, format: u32 }, + NewDmabuf { + id: u32, + width: u32, + height: u32, + format: u32, + }, #[cfg(feature = "wl-dmabuf")] - DmabufSync { id: u32, flags: u32 }, - InvalidCommand { op_type: u32 }, + DmabufSync { + id: u32, + flags: u32, + }, + InvalidCommand { + op_type: u32, + }, } #[derive(Debug)] @@ -553,7 +613,9 @@ enum WlResp<'a> { data: &'a [u8], vfds: &'a [u32], }, - VfdHup { id: u32 }, + VfdHup { + id: u32, + }, Err(Box), OutOfMemory, InvalidId, @@ -619,8 +681,7 @@ impl fmt::Debug for WlVfd { impl WlVfd { fn connect>(path: P) -> WlResult { - let socket = UnixStream::connect(path) - .map_err(WlError::SocketConnect)?; + let socket = UnixStream::connect(path).map_err(WlError::SocketConnect)?; socket .set_nonblocking(true) .map_err(WlError::SocketNonBlock)?; @@ -631,15 +692,16 @@ impl WlVfd { fn allocate(vm: VmRequester, size: u64) -> WlResult { let size_page_aligned = round_up_to_page_size(size as usize) as u64; - let mut vfd_shm = SharedMemory::new(Some(CStr::from_bytes_with_nul(b"virtwl_alloc\0") - .unwrap())) + let mut vfd_shm = + SharedMemory::new(Some(CStr::from_bytes_with_nul(b"virtwl_alloc\0").unwrap())) .map_err(WlError::NewAlloc)?; vfd_shm .set_size(size_page_aligned) .map_err(WlError::AllocSetSize)?; - let register_response = - vm.request(VmRequest::RegisterMemory(MaybeOwnedFd::Borrowed(vfd_shm.as_raw_fd()), - vfd_shm.size() as usize))?; + let register_response = vm.request(VmRequest::RegisterMemory( + MaybeOwnedFd::Borrowed(vfd_shm.as_raw_fd()), + vfd_shm.size() as usize, + ))?; match register_response { VmResponse::RegisterMemory { pfn, slot } => { let mut vfd = WlVfd::default(); @@ -652,14 +714,25 @@ impl WlVfd { } #[cfg(feature = "wl-dmabuf")] - fn dmabuf(vm: VmRequester, width: u32, height: u32, format: u32) -> - WlResult<(WlVfd, GpuMemoryDesc)> { + fn dmabuf( + vm: VmRequester, + width: u32, + height: u32, + format: u32, + ) -> WlResult<(WlVfd, GpuMemoryDesc)> { let allocate_and_register_gpu_memory_response = - vm.request(VmRequest::AllocateAndRegisterGpuMemory { width: width, - height: height, - format: format })?; + vm.request(VmRequest::AllocateAndRegisterGpuMemory { + width, + height, + format, + })?; match allocate_and_register_gpu_memory_response { - VmResponse::AllocateAndRegisterGpuMemory { fd, pfn, slot, desc } => { + VmResponse::AllocateAndRegisterGpuMemory { + fd, + pfn, + slot, + desc, + } => { let mut vfd = WlVfd::default(); // Duplicate FD for shared memory instance. let raw_fd = unsafe { File::from_raw_fd(dup(fd.as_raw_fd())) }; @@ -691,7 +764,7 @@ impl WlVfd { Ok(()) } } - None => Err(WlError::DmabufSync(io::Error::from_raw_os_error(EBADF))) + None => Err(WlError::DmabufSync(io::Error::from_raw_os_error(EBADF))), } } @@ -720,9 +793,10 @@ impl WlVfd { match fd.seek(SeekFrom::End(0)) { Ok(fd_size) => { let size = round_up_to_page_size(fd_size as usize) as u64; - let register_response = - vm.request(VmRequest::RegisterMemory(MaybeOwnedFd::Borrowed(fd.as_raw_fd()), - size as usize))?; + let register_response = vm.request(VmRequest::RegisterMemory( + MaybeOwnedFd::Borrowed(fd.as_raw_fd()), + size as usize, + ))?; match register_response { VmResponse::RegisterMemory { pfn, slot } => { @@ -792,26 +866,20 @@ impl WlVfd { self.socket .as_ref() .map(|s| s as &AsRawFd) - .or(self.local_pipe - .as_ref() - .map(|&(_, ref p)| p as &AsRawFd)) - + .or(self.local_pipe.as_ref().map(|&(_, ref p)| p as &AsRawFd)) } // Sends data/files from the guest to the host over this VFD. fn send(&mut self, fds: &[RawFd], data: VolatileSlice) -> WlResult { if let Some(ref socket) = self.socket { - socket - .send_with_fds(data, fds) - .map_err(WlError::SendVfd)?; + socket.send_with_fds(data, fds).map_err(WlError::SendVfd)?; Ok(WlResp::Ok) } else if let Some((_, ref mut local_pipe)) = self.local_pipe { // Impossible to send fds over a simple pipe. if !fds.is_empty() { return Ok(WlResp::InvalidType); } - data.write_all_to(local_pipe) - .map_err(WlError::WritePipe)?; + data.write_all_to(local_pipe).map_err(WlError::WritePipe)?; Ok(WlResp::Ok) } else { Ok(WlResp::InvalidType) @@ -834,18 +902,18 @@ impl WlVfd { self.socket = Some(socket); // Safe because the first file_counts fds from recv_with_fds are owned by us and // valid. - in_file_queue.extend(fd_buf[..file_count] - .iter() - .map(|&fd| unsafe { File::from_raw_fd(fd) })); + in_file_queue.extend( + fd_buf[..file_count] + .iter() + .map(|&fd| unsafe { File::from_raw_fd(fd) }), + ); return Ok(buf); } Ok(Vec::new()) } else if let Some((flags, mut local_pipe)) = self.local_pipe.take() { let mut buf = Vec::new(); buf.resize(IN_BUFFER_LEN, 0); - let len = local_pipe - .read(&mut buf[..]) - .map_err(WlError::ReadPipe)?; + let len = local_pipe.read(&mut buf[..]).map_err(WlError::ReadPipe)?; if len != 0 { buf.truncate(len); buf.shrink_to_fit(); @@ -904,7 +972,7 @@ struct WlState { impl WlState { fn new(wayland_path: PathBuf, vm_socket: UnixDatagram, use_transition_flags: bool) -> WlState { WlState { - wayland_path: wayland_path, + wayland_path, vm: VmRequester::new(vm_socket), poll_ctx: PollContext::new().expect("failed to create PollContext"), use_transition_flags, @@ -943,7 +1011,7 @@ impl WlState { .add(vfd.poll_fd().unwrap(), id) .map_err(WlError::PollContextAdd)?; let resp = WlResp::VfdNew { - id: id, + id, flags: 0, pfn: 0, size: 0, @@ -973,7 +1041,7 @@ impl WlState { Entry::Vacant(entry) => { let vfd = WlVfd::allocate(self.vm.clone(), size as u64)?; let resp = WlResp::VfdNew { - id: id, + id, flags, pfn: vfd.pfn().unwrap_or_default(), size: vfd.size().unwrap_or_default() as u32, @@ -994,12 +1062,9 @@ impl WlState { match self.vfds.entry(id) { Entry::Vacant(entry) => { - let (vfd, desc) = WlVfd::dmabuf(self.vm.clone(), - width, - height, - format)?; + let (vfd, desc) = WlVfd::dmabuf(self.vm.clone(), width, height, format)?; let resp = WlResp::VfdNewDmabuf { - id: id, + id, flags: 0, pfn: vfd.pfn().unwrap_or_default(), size: vfd.size().unwrap_or_default() as u32, @@ -1019,7 +1084,7 @@ impl WlState { } match self.vfds.get_mut(&vfd_id) { - Some(vfd) => { + Some(vfd) => { vfd.dmabuf_sync(flags)?; Ok(WlResp::Ok) } @@ -1045,12 +1110,12 @@ impl WlState { .add(vfd.poll_fd().unwrap(), id) .map_err(WlError::PollContextAdd)?; Ok(WlResp::VfdNew { - id: id, - flags, - pfn: 0, - size: 0, - resp: true, - }) + id, + flags, + pfn: 0, + size: 0, + resp: true, + }) } Entry::Occupied(_) => Ok(WlResp::InvalidId), } @@ -1114,23 +1179,19 @@ impl WlState { let mut fds = [0; VIRTWL_SEND_MAX_ALLOCS]; for (&id, fd) in vfd_ids[..vfd_count].iter().zip(fds.iter_mut()) { match self.vfds.get(&id.into()) { - Some(vfd) => { - match vfd.send_fd() { - Some(vfd_fd) => *fd = vfd_fd, - None => return Ok(WlResp::InvalidType), - } - } + Some(vfd) => match vfd.send_fd() { + Some(vfd_fd) => *fd = vfd_fd, + None => return Ok(WlResp::InvalidType), + }, None => return Ok(WlResp::InvalidId), } } match self.vfds.get_mut(&vfd_id) { - Some(vfd) => { - match vfd.send(&fds[..vfd_count], data)? { - WlResp::Ok => {} - _ => return Ok(WlResp::InvalidType), - } - } + Some(vfd) => match vfd.send(&fds[..vfd_count], data)? { + WlResp::Ok => {} + _ => return Ok(WlResp::InvalidType), + }, None => return Ok(WlResp::InvalidId), } // The vfds with remote FDs need to be closed so that the local side can receive @@ -1160,12 +1221,15 @@ impl WlState { .map_err(WlError::PollContextAdd)?; } self.vfds.insert(self.next_vfd_id, vfd); - self.in_queue - .push_back((vfd_id, WlRecv::Vfd { id: self.next_vfd_id })); + self.in_queue.push_back(( + vfd_id, + WlRecv::Vfd { + id: self.next_vfd_id, + }, + )); self.next_vfd_id += 1; } - self.in_queue - .push_back((vfd_id, WlRecv::Data { buf: buf })); + self.in_queue.push_back((vfd_id, WlRecv::Data { buf })); Ok(()) } @@ -1189,7 +1253,12 @@ impl WlState { WlOp::NewCtx { id } => self.new_context(id), WlOp::NewPipe { id, flags } => self.new_pipe(id, flags), #[cfg(feature = "wl-dmabuf")] - WlOp::NewDmabuf { id, width, height, format } => self.new_dmabuf(id, width, height, format), + WlOp::NewDmabuf { + id, + width, + height, + format, + } => self.new_dmabuf(id, width, height, format), #[cfg(feature = "wl-dmabuf")] WlOp::DmabufSync { id, flags } => self.dmabuf_sync(id, flags), WlOp::InvalidCommand { op_type } => { @@ -1205,53 +1274,48 @@ impl WlState { &(vfd_id, WlRecv::Vfd { id }) => { if self.current_recv_vfd.is_none() || self.current_recv_vfd == Some(vfd_id) { match self.vfds.get(&id) { - Some(vfd) => { - Some(WlResp::VfdNew { - id: id, - flags: vfd.flags(self.use_transition_flags), - pfn: vfd.pfn().unwrap_or_default(), - size: vfd.size().unwrap_or_default() as u32, - resp: false, - }) - } - _ => { - Some(WlResp::VfdNew { - id: id, - flags: 0, - pfn: 0, - size: 0, - resp: false, - }) - } + Some(vfd) => Some(WlResp::VfdNew { + id, + flags: vfd.flags(self.use_transition_flags), + pfn: vfd.pfn().unwrap_or_default(), + size: vfd.size().unwrap_or_default() as u32, + resp: false, + }), + _ => Some(WlResp::VfdNew { + id, + flags: 0, + pfn: 0, + size: 0, + resp: false, + }), } } else { Some(WlResp::VfdRecv { - id: self.current_recv_vfd.unwrap(), - data: &[], - vfds: &self.recv_vfds[..], - }) + id: self.current_recv_vfd.unwrap(), + data: &[], + vfds: &self.recv_vfds[..], + }) } } &(vfd_id, WlRecv::Data { ref buf }) => { if self.current_recv_vfd.is_none() || self.current_recv_vfd == Some(vfd_id) { Some(WlResp::VfdRecv { - id: vfd_id, - data: &buf[..], - vfds: &self.recv_vfds[..], - }) + id: vfd_id, + data: &buf[..], + vfds: &self.recv_vfds[..], + }) } else { Some(WlResp::VfdRecv { - id: self.current_recv_vfd.unwrap(), - data: &[], - vfds: &self.recv_vfds[..], - }) + id: self.current_recv_vfd.unwrap(), + data: &[], + vfds: &self.recv_vfds[..], + }) } } &(vfd_id, WlRecv::Hup) => Some(WlResp::VfdHup { id: vfd_id }), } } else { None - } } @@ -1296,21 +1360,22 @@ struct Worker { } impl Worker { - fn new(mem: GuestMemory, - interrupt_evt: EventFd, - interrupt_status: Arc, - in_queue: Queue, - out_queue: Queue, - wayland_path: PathBuf, - vm_socket: UnixDatagram, - use_transition_flags: bool) - -> Worker { + fn new( + mem: GuestMemory, + interrupt_evt: EventFd, + interrupt_status: Arc, + in_queue: Queue, + out_queue: Queue, + wayland_path: PathBuf, + vm_socket: UnixDatagram, + use_transition_flags: bool, + ) -> Worker { Worker { - mem: mem, - interrupt_evt: interrupt_evt, - interrupt_status: interrupt_status, - in_queue: in_queue, - out_queue: out_queue, + mem, + interrupt_evt, + interrupt_status, + in_queue, + out_queue, state: WlState::new(wayland_path, vm_socket, use_transition_flags), in_desc_chains: VecDeque::with_capacity(QUEUE_SIZE as usize), } @@ -1333,18 +1398,18 @@ impl Worker { State, } - let poll_ctx: PollContext = - match PollContext::new() - .and_then(|pc| pc.add(&in_queue_evt, Token::InQueue).and(Ok(pc))) - .and_then(|pc| pc.add(&out_queue_evt, Token::OutQueue).and(Ok(pc))) - .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) - .and_then(|pc| pc.add(&self.state.poll_ctx, Token::State).and(Ok(pc))) { - Ok(pc) => pc, - Err(e) => { - error!("failed creating PollContext: {:?}", e); - return; - } - }; + let poll_ctx: PollContext = match PollContext::new() + .and_then(|pc| pc.add(&in_queue_evt, Token::InQueue).and(Ok(pc))) + .and_then(|pc| pc.add(&out_queue_evt, Token::OutQueue).and(Ok(pc))) + .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc))) + .and_then(|pc| pc.add(&self.state.poll_ctx, Token::State).and(Ok(pc))) + { + Ok(pc) => pc, + Err(e) => { + error!("failed creating PollContext: {:?}", e); + return; + } + }; 'poll: loop { let mut signal_used = false; @@ -1363,10 +1428,11 @@ impl Worker { // Used to buffer descriptor indexes that are invalid for our uses. let mut rejects = [0u16; QUEUE_SIZE as usize]; let mut rejects_len = 0; - let min_in_desc_len = (size_of::() + - size_of::() * VIRTWL_SEND_MAX_ALLOCS) as - u32; - self.in_desc_chains.extend(self.in_queue.iter(&self.mem).filter_map(|d| { + let min_in_desc_len = (size_of::() + + size_of::() * VIRTWL_SEND_MAX_ALLOCS) + as u32; + self.in_desc_chains + .extend(self.in_queue.iter(&self.mem).filter_map(|d| { if d.len >= min_in_desc_len && d.is_write_only() { Some((d.index, d.addr, d.len)) } else { @@ -1395,23 +1461,23 @@ impl Worker { // one "out" descriptor. if !desc.is_write_only() { if let Some(resp_desc) = desc.next_descriptor() { - if resp_desc.is_write_only() && - resp_desc.len >= min_resp_desc_len { + if resp_desc.is_write_only() + && resp_desc.len >= min_resp_desc_len + { let resp = match parse_desc(&desc, &self.mem) { - Ok(op) => { - match self.state.execute(&self.mem, op) { - Ok(r) => r, - Err(e) => WlResp::Err(Box::new(e)), - } - } + Ok(op) => match self.state.execute(&self.mem, op) { + Ok(r) => r, + Err(e) => WlResp::Err(Box::new(e)), + }, Err(e) => WlResp::Err(Box::new(e)), }; - let resp_mem = self.mem + let resp_mem = self + .mem .get_slice(resp_desc.addr.0, resp_desc.len as u64) .unwrap(); - let used_len = encode_resp(resp_mem, resp) - .unwrap_or_default(); + let used_len = + encode_resp(resp_mem, resp).unwrap_or_default(); used_descs[used_descs_len] = (desc.index, used_len); } @@ -1483,11 +1549,11 @@ impl Wl { // let kill_evt = EventFd::new()?; // workers_kill_evt: Some(kill_evt.try_clone()?), Ok(Wl { - kill_evt: None, - wayland_path: wayland_path.as_ref().to_owned(), - vm_socket: Some(vm_socket), - use_transition_flags: false, - }) + kill_evt: None, + wayland_path: wayland_path.as_ref().to_owned(), + vm_socket: Some(vm_socket), + use_transition_flags: false, + }) } } @@ -1532,42 +1598,45 @@ impl VirtioDevice for Wl { } } - fn activate(&mut self, - mem: GuestMemory, - interrupt_evt: EventFd, - status: Arc, - mut queues: Vec, - queue_evts: Vec) { + fn activate( + &mut self, + mem: GuestMemory, + interrupt_evt: EventFd, + status: Arc, + mut queues: Vec, + queue_evts: Vec, + ) { if queues.len() != QUEUE_SIZES.len() || queue_evts.len() != QUEUE_SIZES.len() { return; } - let (self_kill_evt, kill_evt) = - match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { - Ok(v) => v, - Err(e) => { - error!("failed creating kill EventFd pair: {:?}", e); - return; - } - }; + let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { + Ok(v) => v, + Err(e) => { + error!("failed creating kill EventFd pair: {:?}", e); + return; + } + }; self.kill_evt = Some(self_kill_evt); if let Some(vm_socket) = self.vm_socket.take() { let wayland_path = self.wayland_path.clone(); let use_transition_flags = self.use_transition_flags; - let worker_result = thread::Builder::new() - .name("virtio_wl".to_string()) - .spawn(move || { - Worker::new(mem, - interrupt_evt, - status, - queues.remove(0), - queues.remove(0), - wayland_path, - vm_socket, - use_transition_flags) - .run(queue_evts, kill_evt); - }); + let worker_result = + thread::Builder::new() + .name("virtio_wl".to_string()) + .spawn(move || { + Worker::new( + mem, + interrupt_evt, + status, + queues.remove(0), + queues.remove(0), + wayland_path, + vm_socket, + use_transition_flags, + ).run(queue_evts, kill_evt); + }); if let Err(e) = worker_result { error!("failed to spawn virtio_wl worker: {}", e); -- cgit 1.4.1