diff options
author | Alyssa Ross <hi@alyssa.is> | 2020-04-10 13:19:04 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2020-06-15 09:37:29 +0000 |
commit | eb90518961ca5f00bd832429be840600ce305fb4 (patch) | |
tree | 8415abc6314ac439b47d90305194cc88eca76146 | |
parent | aa9ee49fdf908aef32d4363704099a0584834d4c (diff) | |
download | crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.gz crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.bz2 crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.lz crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.xz crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.zst crosvm-eb90518961ca5f00bd832429be840600ce305fb4.zip |
three parts
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | Cargo.toml | 16 | ||||
-rw-r--r-- | devices/src/virtio/controller.rs | 534 | ||||
-rw-r--r-- | devices/src/virtio/mod.rs | 2 | ||||
-rw-r--r-- | devices/src/virtio/remote.rs | 536 | ||||
-rw-r--r-- | devices/src/virtio/virtualized.rs | 505 | ||||
-rw-r--r-- | src/ext/wl_main.rs | 187 | ||||
-rw-r--r-- | src/guest/wl.rs (renamed from src/wl.rs) | 32 | ||||
-rw-r--r-- | src/linux.rs | 17 | ||||
-rw-r--r-- | vm_control/src/lib.rs | 1 |
10 files changed, 1280 insertions, 551 deletions
diff --git a/Cargo.lock b/Cargo.lock index ba5218a..a72324e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,6 +154,7 @@ dependencies = [ "rand_ish 0.1.0", "remain 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "resources 0.1.0", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "sync 0.1.0", "sys_util 0.1.0", "vhost 0.1.0", diff --git a/Cargo.toml b/Cargo.toml index baf401b..2615178 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,20 +12,19 @@ name = "crosvm" path = "src/main.rs" [[bin]] -name = "crosvm_wl" -path = "src/wl.rs" +name = "crosvm_ext_wl" +path = "src/ext/wl_main.rs" + +[[bin]] +name = "crosvm_guest_wl" +path = "src/guest/wl.rs" [profile.release] panic = 'abort' overflow-checks = true [workspace] -members = ["qcow_utils", - -# TEMP -# "data_socket", - -] +members = ["qcow_utils"] exclude = [ "assertions", "async_core", @@ -81,6 +80,7 @@ protos = { path = "protos", optional = true } rand_ish = { path = "rand_ish" } remain = "*" resources = { path = "resources" } +serde = "*" sync = { path = "sync" } sys_util = "*" vhost = { path = "vhost" } diff --git a/devices/src/virtio/controller.rs b/devices/src/virtio/controller.rs index 7500164..dbb14e6 100644 --- a/devices/src/virtio/controller.rs +++ b/devices/src/virtio/controller.rs @@ -28,539 +28,23 @@ //! the virtio queue, and routing messages in and out of `WlState`. Possible events include the kill //! event, available descriptors on the `in` or `out` queue, and incoming data on any vfd's socket. -use std::fmt::{self, Formatter}; use std::os::unix::io::{AsRawFd, RawFd}; use std::sync::Arc; use std::thread; use msg_socket::{MsgReceiver, MsgSocket}; -use msg_socket2::de::{EnumAccessWithFds, SeqAccessWithFds, VariantAccessWithFds, VisitorWithFds}; -use msg_socket2::ser::{SerializeAdapter, SerializeStructVariantFds, SerializeTupleVariantFds}; -use msg_socket2::{DeserializeWithFds, DeserializerWithFds, FdSerializer, SerializeWithFds}; -use serde::ser::{SerializeStructVariant, SerializeTupleVariant, Serializer}; -use serde::{Deserialize, Serialize}; use sys_util::net::UnixSeqpacket; -use sys_util::{error, EventFd, GuestMemory, PollContext, PollToken, SharedMemory}; +use sys_util::{error, EventFd, GuestMemory, PollContext, PollToken}; +use vm_control::{MaybeOwnedFd, VmMemoryControlRequestSocket}; -use super::{Interrupt, InterruptProxyEvent, Params, Queue, VirtioDevice}; +use super::{ + remote::{Request, Response}, + Interrupt, InterruptProxyEvent, Queue, VirtioDevice, +}; use crate::{ - pci::{PciAddress, PciBarConfiguration, PciCapability, PciCapabilityID}, + pci::{PciAddress, PciBarConfiguration, PciCapability}, MemoryParams, }; -use vm_control::MaybeOwnedFd; - -// As far as I can tell, these never change on the other side, so it's -// fine to just copy them over. -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct RemotePciCapability { - bytes: Vec<u8>, - id: PciCapabilityID, -} - -impl RemotePciCapability { - pub fn from(capability: &dyn PciCapability) -> Self { - Self { - bytes: capability.bytes().to_vec(), - id: capability.id(), - } - } -} - -impl PciCapability for RemotePciCapability { - fn bytes(&self) -> &[u8] { - &self.bytes - } - - fn id(&self) -> PciCapabilityID { - self.id - } -} - -#[derive(Debug)] -pub enum Request { - Create { - device_params: Params, - memory_params: MemoryParams, - }, - - DebugLabel, - - DeviceType, - - QueueMaxSizes, - - Features, - AckFeatures(u64), - - ReadConfig { - offset: u64, - len: usize, - }, - WriteConfig { - offset: u64, - data: Vec<u8>, - }, - - Activate { - shm: MaybeOwnedFd<SharedMemory>, - interrupt: MaybeOwnedFd<UnixSeqpacket>, - interrupt_resample_evt: MaybeOwnedFd<EventFd>, - queues: Vec<Queue>, - queue_evts: Vec<MaybeOwnedFd<EventFd>>, - }, - - Reset, - - GetDeviceBars(PciAddress), - GetDeviceCaps, - - Kill, -} - -impl SerializeWithFds for Request { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - use Request::*; - - match self { - Create { - device_params, - memory_params, - } => { - let mut sv = serializer.serialize_struct_variant("Request", 0, "Create", 2)?; - sv.serialize_field("device_params", &SerializeAdapter::new(device_params))?; - sv.serialize_field("memory_params", memory_params)?; - sv.end() - } - - DebugLabel => serializer.serialize_unit_variant("Request", 1, "DebugLabel"), - - DeviceType => serializer.serialize_unit_variant("Request", 2, "DeviceType"), - QueueMaxSizes => serializer.serialize_unit_variant("Request", 3, "QueueMaxSizes"), - - Features => serializer.serialize_unit_variant("Request", 4, "Features"), - - AckFeatures(features) => { - let mut tv = serializer.serialize_tuple_variant("Request", 5, "AckFeatures", 1)?; - tv.serialize_field(features)?; - tv.end() - } - - ReadConfig { offset, len } => { - let mut sv = serializer.serialize_struct_variant("Request", 6, "ReadConfig", 2)?; - sv.serialize_field("offset", offset)?; - sv.serialize_field("len", len)?; - sv.end() - } - - WriteConfig { offset, data } => { - let mut sv = serializer.serialize_struct_variant("Request", 7, "WriteConfig", 2)?; - sv.serialize_field("offset", offset)?; - sv.serialize_field("data", data)?; - sv.end() - } - - Activate { - shm, - interrupt, - interrupt_resample_evt, - queues, - queue_evts, - } => { - let mut sv = serializer.serialize_struct_variant("Request", 8, "Activate", 7)?; - sv.serialize_field("shm", &SerializeAdapter::new(shm))?; - sv.serialize_field("interrupt", &SerializeAdapter::new(interrupt))?; - sv.serialize_field( - "interrupt_resample_evt", - &SerializeAdapter::new(interrupt_resample_evt), - )?; - sv.serialize_field("queues", queues)?; - sv.serialize_field("queue_evts", &SerializeAdapter::new(queue_evts))?; - sv.end() - } - - Reset => serializer.serialize_unit_variant("Request", 9, "Reset"), - - GetDeviceBars(address) => { - let mut sv = - serializer.serialize_struct_variant("Request", 10, "GetDeviceBars", 1)?; - sv.serialize_field("address", address)?; - sv.end() - } - - GetDeviceCaps => serializer.serialize_unit_variant("Request", 11, "GetDeviceCaps"), - - Kill => serializer.serialize_unit_variant("Request", 12, "Kill"), - } - } - - fn serialize_fds<'fds, S>(&'fds self, serializer: S) -> Result<S::Ok, S::Error> - where - S: FdSerializer<'fds>, - { - use Request::*; - - match self { - Create { - device_params, - memory_params, - } => { - let mut sv = serializer.serialize_struct_variant("Request", 0, "Create", 2)?; - sv.serialize_field("device_params", device_params)?; - sv.serialize_field("memory_params", memory_params)?; - sv.end() - } - - DebugLabel => serializer.serialize_unit_variant("Request", 1, "DebugLabel"), - DeviceType => serializer.serialize_unit_variant("Request", 2, "DeviceType"), - QueueMaxSizes => serializer.serialize_unit_variant("Request", 3, "QueueMaxSizes"), - Features => serializer.serialize_unit_variant("Request", 4, "Features"), - - AckFeatures(features) => { - let mut tv = serializer.serialize_tuple_variant("Request", 5, "AckFeatures", 1)?; - tv.serialize_field(features)?; - tv.end() - } - - ReadConfig { offset, len } => { - let mut sv = serializer.serialize_struct_variant("Request", 6, "ReadConfig", 2)?; - sv.serialize_field("offset", offset)?; - sv.serialize_field("len", len)?; - sv.end() - } - - WriteConfig { offset, data } => { - let mut sv = serializer.serialize_struct_variant("Request", 7, "WriteConfig", 2)?; - sv.serialize_field("offset", offset)?; - sv.serialize_field("data", data)?; - sv.end() - } - - Activate { - shm, - interrupt, - interrupt_resample_evt, - queues, - queue_evts, - } => { - let mut sv = serializer.serialize_struct_variant("Request", 8, "Activate", 2)?; - sv.serialize_field("shm", shm)?; - sv.serialize_field("interrupt", interrupt)?; - sv.serialize_field("interrupt_resample_evt", interrupt_resample_evt)?; - sv.serialize_field("queues", queues)?; - sv.serialize_field("queue_evts", queue_evts)?; - sv.end() - } - - Reset => serializer.serialize_unit_variant("Request", 9, "Reset"), - - GetDeviceBars(address) => { - let mut tv = - serializer.serialize_tuple_variant("Request", 10, "GetDeviceBars", 1)?; - tv.serialize_field(address)?; - tv.end() - } - - GetDeviceCaps => serializer.serialize_unit_variant("Request", 11, "GetDeviceCaps"), - - Kill => serializer.serialize_unit_variant("Request", 12, "Kill"), - } - } -} - -impl<'de> DeserializeWithFds<'de> for Request { - fn deserialize<D: DeserializerWithFds<'de>>(deserializer: D) -> Result<Self, D::Error> { - struct Visitor; - - impl<'de> VisitorWithFds<'de> for Visitor { - type Value = Request; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "enum Request") - } - - fn visit_enum<A: EnumAccessWithFds<'de>>( - self, - data: A, - ) -> Result<Self::Value, A::Error> { - #[derive(Debug, Deserialize)] - enum Variant { - Create, - DebugLabel, - DeviceType, - QueueMaxSizes, - Features, - AckFeatures, - ReadConfig, - WriteConfig, - Activate, - Reset, - GetDeviceBars, - GetDeviceCaps, - Kill, - } - - match data.variant()? { - (Variant::Create, variant) => { - struct Visitor; - - impl<'de> VisitorWithFds<'de> for Visitor { - type Value = Request; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "struct variant Request::Create") - } - - fn visit_seq<A: SeqAccessWithFds<'de>>( - self, - mut seq: A, - ) -> Result<Request, A::Error> { - use serde::de::Error; - - fn too_short<E: Error>(len: usize) -> E { - E::invalid_length( - len, - &"struct variant Request::Create with 2 elements", - ) - } - - Ok(Request::Create { - device_params: seq - .next_element()? - .ok_or_else(|| too_short(0))?, - memory_params: seq - .next_element()? - .ok_or_else(|| too_short(1))?, - }) - } - } - - variant.struct_variant(&["vm_socket", "memory_params"], Visitor) - } - - (Variant::DebugLabel, variant) => { - variant.unit_variant()?; - Ok(Request::DebugLabel) - } - - (Variant::DeviceType, variant) => { - variant.unit_variant()?; - Ok(Request::DeviceType) - } - - (Variant::QueueMaxSizes, variant) => { - variant.unit_variant()?; - Ok(Request::QueueMaxSizes) - } - - (Variant::Features, variant) => { - variant.unit_variant()?; - Ok(Request::Features) - } - - (Variant::AckFeatures, variant) => { - Ok(Request::AckFeatures(variant.newtype_variant()?)) - } - - (Variant::ReadConfig, variant) => { - struct Visitor; - - impl<'de> VisitorWithFds<'de> for Visitor { - type Value = Request; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "struct variant Request::ReadConfig") - } - - fn visit_seq<A: SeqAccessWithFds<'de>>( - self, - mut seq: A, - ) -> Result<Request, A::Error> { - use serde::de::Error; - - fn too_short<E: Error>(len: usize) -> E { - E::invalid_length( - len, - &"struct variant Request::ReadConfig with 2 elements", - ) - } - - Ok(Request::ReadConfig { - offset: seq.next_element()?.ok_or_else(|| too_short(0))?, - len: seq.next_element()?.ok_or_else(|| too_short(1))?, - }) - } - } - - variant.struct_variant(&["offset", "len"], Visitor) - } - - (Variant::WriteConfig, variant) => { - struct Visitor; - - impl<'de> VisitorWithFds<'de> for Visitor { - type Value = Request; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "struct variant Request::WriteConfig") - } - - fn visit_seq<A: SeqAccessWithFds<'de>>( - self, - mut seq: A, - ) -> Result<Request, A::Error> { - use serde::de::Error; - - fn too_short<E: Error>(len: usize) -> E { - E::invalid_length( - len, - &"struct variant Request::WriteConfig with 2 elements", - ) - } - - Ok(Request::WriteConfig { - offset: seq.next_element()?.ok_or_else(|| too_short(0))?, - data: seq.next_element()?.ok_or_else(|| too_short(1))?, - }) - } - } - - variant.struct_variant(&["offset", "data"], Visitor) - } - - (Variant::Activate, variant) => { - struct Visitor; - - impl<'de> VisitorWithFds<'de> for Visitor { - type Value = Request; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "struct variant Request::Activate") - } - - fn visit_seq<A: SeqAccessWithFds<'de>>( - self, - mut seq: A, - ) -> Result<Request, A::Error> { - use serde::de::Error; - - fn too_short<E: Error>(len: usize) -> E { - E::invalid_length( - len, - &"struct variant Request::Activate with 7 elements", - ) - } - - Ok(Request::Activate { - shm: seq.next_element()?.ok_or_else(|| too_short(0))?, - interrupt: seq.next_element()?.ok_or_else(|| too_short(1))?, - interrupt_resample_evt: seq - .next_element()? - .ok_or_else(|| too_short(2))?, - queues: seq.next_element()?.ok_or_else(|| too_short(3))?, - queue_evts: seq.next_element()?.ok_or_else(|| too_short(4))?, - }) - } - } - - variant.struct_variant( - &[ - "shm", - "interrupt", - "interrupt_resample_evt", - "in_queue", - "out_queue", - "in_queue_evt", - "out_queue_evt", - ], - Visitor, - ) - } - - (Variant::Reset, variant) => { - variant.unit_variant()?; - Ok(Request::Reset) - } - - (Variant::GetDeviceBars, variant) => { - struct Visitor; - - impl<'de> VisitorWithFds<'de> for Visitor { - type Value = Request; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "struct variant Request::GetDeviceBars") - } - - fn visit_seq<A: SeqAccessWithFds<'de>>( - self, - mut seq: A, - ) -> Result<Request, A::Error> { - use serde::de::Error; - - fn too_short<E: Error>(len: usize) -> E { - E::invalid_length( - len, - &"struct variant Request::GetDeviceBars with 2 elements", - ) - } - - Ok(Request::GetDeviceBars( - seq.next_element()?.ok_or_else(|| too_short(0))?, - )) - } - } - - variant.struct_variant(&["bus", "dev"], Visitor) - } - - (Variant::GetDeviceCaps, variant) => { - variant.unit_variant()?; - Ok(Request::GetDeviceCaps) - } - - (Variant::Kill, variant) => { - variant.unit_variant()?; - Ok(Request::Kill) - } - } - } - } - - deserializer.deserialize_enum( - "Request", - &[ - "Create", - "DebugLabel", - "DeviceType", - "QueueMaxSizes", - "Features", - "AckFeatures", - "ReadConfig", - "WriteConfig", - "Activate", - "Reset", - "GetDeviceBars", - "GetDeviceCaps", - "Kill", - ], - Visitor, - ) - } -} - -#[derive(Debug, Deserialize, DeserializeWithFds, Serialize, SerializeWithFds)] -#[msg_socket2(strategy = "serde")] -pub enum Response { - DebugLabel(String), - DeviceType(u32), - QueueMaxSizes(Vec<u16>), - Features(u64), - ReadConfig(Vec<u8>), - Reset(bool), - GetDeviceBars(Vec<PciBarConfiguration>), - GetDeviceCaps(Vec<RemotePciCapability>), - Kill, -} type Socket = msg_socket2::Socket<Request, Response>; @@ -671,13 +155,13 @@ impl Controller { /// Construct a controller, and initialize (but don't activate) /// the remote device. pub fn create( - device_params: Params, memory_params: MemoryParams, + vm_control_socket: VmMemoryControlRequestSocket, socket: Socket, ) -> Result<Controller, msg_socket2::Error> { socket.send(Request::Create { - device_params, memory_params, + vm_control_socket: MaybeOwnedFd::Borrowed(vm_control_socket.as_raw_fd()), })?; Ok(Controller { diff --git a/devices/src/virtio/mod.rs b/devices/src/virtio/mod.rs index acae318..9bc222e 100644 --- a/devices/src/virtio/mod.rs +++ b/devices/src/virtio/mod.rs @@ -32,8 +32,10 @@ use std::fmt::Debug; pub mod fs; #[cfg(feature = "gpu")] pub mod gpu; +pub mod remote; pub mod resource_bridge; pub mod vhost; +pub mod virtualized; pub use self::balloon::*; pub use self::block::*; diff --git a/devices/src/virtio/remote.rs b/devices/src/virtio/remote.rs new file mode 100644 index 0000000..e7f7967 --- /dev/null +++ b/devices/src/virtio/remote.rs @@ -0,0 +1,536 @@ +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use msg_socket2::de::{EnumAccessWithFds, SeqAccessWithFds, VariantAccessWithFds, VisitorWithFds}; +use msg_socket2::ser::{ + SerializeAdapter, SerializeStructVariant, SerializeStructVariantFds, SerializeTupleVariant, + SerializeTupleVariantFds, Serializer, +}; +use msg_socket2::{ + Deserialize, DeserializeWithFds, DeserializerWithFds, FdSerializer, Serialize, SerializeWithFds, +}; +use std::fmt::{self, Formatter}; +use sys_util::net::UnixSeqpacket; +use sys_util::{EventFd, SharedMemory}; +use vm_control::MaybeOwnedFd; + +use crate::pci::{PciAddress, PciBarConfiguration, PciCapability, PciCapabilityID}; +use crate::virtio::Queue; +use crate::MemoryParams; + +// As far as I can tell, these never change on the other side, so it's +// fine to just copy them over. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct RemotePciCapability { + bytes: Vec<u8>, + id: PciCapabilityID, +} + +impl RemotePciCapability { + pub fn from(capability: &dyn PciCapability) -> Self { + Self { + bytes: capability.bytes().to_vec(), + id: capability.id(), + } + } +} + +impl PciCapability for RemotePciCapability { + fn bytes(&self) -> &[u8] { + &self.bytes + } + + fn id(&self) -> PciCapabilityID { + self.id + } +} + +#[derive(Debug)] +pub enum Request { + Create { + memory_params: MemoryParams, + vm_control_socket: MaybeOwnedFd<UnixSeqpacket>, + }, + + DebugLabel, + + DeviceType, + + QueueMaxSizes, + + Features, + AckFeatures(u64), + + ReadConfig { + offset: u64, + len: usize, + }, + WriteConfig { + offset: u64, + data: Vec<u8>, + }, + + Activate { + shm: MaybeOwnedFd<SharedMemory>, + interrupt: MaybeOwnedFd<UnixSeqpacket>, + interrupt_resample_evt: MaybeOwnedFd<EventFd>, + queues: Vec<Queue>, + queue_evts: Vec<MaybeOwnedFd<EventFd>>, + }, + + Reset, + + GetDeviceBars(PciAddress), + GetDeviceCaps, + + Kill, +} + +impl SerializeWithFds for Request { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + use Request::*; + + match self { + Create { + memory_params, + vm_control_socket, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 0, "Create", 2)?; + sv.serialize_field("memory_params", memory_params)?; + sv.serialize_field( + "vm_control_socket", + &SerializeAdapter::new(vm_control_socket), + )?; + sv.end() + } + + DebugLabel => serializer.serialize_unit_variant("Request", 1, "DebugLabel"), + + DeviceType => serializer.serialize_unit_variant("Request", 2, "DeviceType"), + QueueMaxSizes => serializer.serialize_unit_variant("Request", 3, "QueueMaxSizes"), + + Features => serializer.serialize_unit_variant("Request", 4, "Features"), + + AckFeatures(features) => { + let mut tv = serializer.serialize_tuple_variant("Request", 5, "AckFeatures", 1)?; + tv.serialize_field(features)?; + tv.end() + } + + ReadConfig { offset, len } => { + let mut sv = serializer.serialize_struct_variant("Request", 6, "ReadConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("len", len)?; + sv.end() + } + + WriteConfig { offset, data } => { + let mut sv = serializer.serialize_struct_variant("Request", 7, "WriteConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("data", data)?; + sv.end() + } + + Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 8, "Activate", 7)?; + sv.serialize_field("shm", &SerializeAdapter::new(shm))?; + sv.serialize_field("interrupt", &SerializeAdapter::new(interrupt))?; + sv.serialize_field( + "interrupt_resample_evt", + &SerializeAdapter::new(interrupt_resample_evt), + )?; + sv.serialize_field("queues", queues)?; + sv.serialize_field("queue_evts", &SerializeAdapter::new(queue_evts))?; + sv.end() + } + + Reset => serializer.serialize_unit_variant("Request", 9, "Reset"), + + GetDeviceBars(address) => { + let mut tv = + serializer.serialize_tuple_variant("Request", 10, "GetDeviceBars", 1)?; + tv.serialize_field(address)?; + tv.end() + } + + GetDeviceCaps => serializer.serialize_unit_variant("Request", 11, "GetDeviceCaps"), + + Kill => serializer.serialize_unit_variant("Request", 12, "Kill"), + } + } + + fn serialize_fds<'fds, S>(&'fds self, serializer: S) -> Result<S::Ok, S::Error> + where + S: FdSerializer<'fds>, + { + use Request::*; + + match self { + Create { + memory_params, + vm_control_socket, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 0, "Create", 2)?; + sv.serialize_field("memory_params", memory_params)?; + sv.serialize_field("vm_control_socket", vm_control_socket)?; + sv.end() + } + + DebugLabel => serializer.serialize_unit_variant("Request", 1, "DebugLabel"), + DeviceType => serializer.serialize_unit_variant("Request", 2, "DeviceType"), + QueueMaxSizes => serializer.serialize_unit_variant("Request", 3, "QueueMaxSizes"), + Features => serializer.serialize_unit_variant("Request", 4, "Features"), + + AckFeatures(features) => { + let mut tv = serializer.serialize_tuple_variant("Request", 5, "AckFeatures", 1)?; + tv.serialize_field(features)?; + tv.end() + } + + ReadConfig { offset, len } => { + let mut sv = serializer.serialize_struct_variant("Request", 6, "ReadConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("len", len)?; + sv.end() + } + + WriteConfig { offset, data } => { + let mut sv = serializer.serialize_struct_variant("Request", 7, "WriteConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("data", data)?; + sv.end() + } + + Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 8, "Activate", 2)?; + sv.serialize_field("shm", shm)?; + sv.serialize_field("interrupt", interrupt)?; + sv.serialize_field("interrupt_resample_evt", interrupt_resample_evt)?; + sv.serialize_field("queues", queues)?; + sv.serialize_field("queue_evts", queue_evts)?; + sv.end() + } + + Reset => serializer.serialize_unit_variant("Request", 9, "Reset"), + + GetDeviceBars(address) => { + let mut tv = + serializer.serialize_tuple_variant("Request", 10, "GetDeviceBars", 1)?; + tv.serialize_field(address)?; + tv.end() + } + + GetDeviceCaps => serializer.serialize_unit_variant("Request", 11, "GetDeviceCaps"), + + Kill => serializer.serialize_unit_variant("Request", 12, "Kill"), + } + } +} + +impl<'de> DeserializeWithFds<'de> for Request { + fn deserialize<D: DeserializerWithFds<'de>>(deserializer: D) -> Result<Self, D::Error> { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "enum Request") + } + + fn visit_enum<A: EnumAccessWithFds<'de>>( + self, + data: A, + ) -> Result<Self::Value, A::Error> { + #[derive(Debug, Deserialize)] + enum Variant { + Create, + DebugLabel, + DeviceType, + QueueMaxSizes, + Features, + AckFeatures, + ReadConfig, + WriteConfig, + Activate, + Reset, + GetDeviceBars, + GetDeviceCaps, + Kill, + } + + match data.variant()? { + (Variant::Create, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::Create") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::Create with 2 elements", + ) + } + + Ok(Request::Create { + memory_params: seq + .next_element()? + .ok_or_else(|| too_short(0))?, + vm_control_socket: seq + .next_element()? + .ok_or_else(|| too_short(1))?, + }) + } + } + + variant.struct_variant(&["memory_params", "vm_control_socket"], Visitor) + } + + (Variant::DebugLabel, variant) => { + variant.unit_variant()?; + Ok(Request::DebugLabel) + } + + (Variant::DeviceType, variant) => { + variant.unit_variant()?; + Ok(Request::DeviceType) + } + + (Variant::QueueMaxSizes, variant) => { + variant.unit_variant()?; + Ok(Request::QueueMaxSizes) + } + + (Variant::Features, variant) => { + variant.unit_variant()?; + Ok(Request::Features) + } + + (Variant::AckFeatures, variant) => { + Ok(Request::AckFeatures(variant.newtype_variant()?)) + } + + (Variant::ReadConfig, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::ReadConfig") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::ReadConfig with 2 elements", + ) + } + + Ok(Request::ReadConfig { + offset: seq.next_element()?.ok_or_else(|| too_short(0))?, + len: seq.next_element()?.ok_or_else(|| too_short(1))?, + }) + } + } + + variant.struct_variant(&["offset", "len"], Visitor) + } + + (Variant::WriteConfig, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::WriteConfig") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::WriteConfig with 2 elements", + ) + } + + Ok(Request::WriteConfig { + offset: seq.next_element()?.ok_or_else(|| too_short(0))?, + data: seq.next_element()?.ok_or_else(|| too_short(1))?, + }) + } + } + + variant.struct_variant(&["offset", "data"], Visitor) + } + + (Variant::Activate, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::Activate") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::Activate with 7 elements", + ) + } + + Ok(Request::Activate { + shm: seq.next_element()?.ok_or_else(|| too_short(0))?, + interrupt: seq.next_element()?.ok_or_else(|| too_short(1))?, + interrupt_resample_evt: seq + .next_element()? + .ok_or_else(|| too_short(2))?, + queues: seq.next_element()?.ok_or_else(|| too_short(3))?, + queue_evts: seq.next_element()?.ok_or_else(|| too_short(4))?, + }) + } + } + + variant.struct_variant( + &[ + "shm", + "interrupt", + "interrupt_resample_evt", + "in_queue", + "out_queue", + "in_queue_evt", + "out_queue_evt", + ], + Visitor, + ) + } + + (Variant::Reset, variant) => { + variant.unit_variant()?; + Ok(Request::Reset) + } + + (Variant::GetDeviceBars, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "tuple variant Request::GetDeviceBars") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"tuple variant Request::GetDeviceBars with 1 elements", + ) + } + + Ok(Request::GetDeviceBars( + seq.next_element()?.ok_or_else(|| too_short(0))?, + )) + } + } + + variant.struct_variant(&["bus", "dev"], Visitor) + } + + (Variant::GetDeviceCaps, variant) => { + variant.unit_variant()?; + Ok(Request::GetDeviceCaps) + } + + (Variant::Kill, variant) => { + variant.unit_variant()?; + Ok(Request::Kill) + } + } + } + } + + deserializer.deserialize_enum( + "Request", + &[ + "Create", + "DebugLabel", + "DeviceType", + "QueueMaxSizes", + "Features", + "AckFeatures", + "ReadConfig", + "WriteConfig", + "Activate", + "Reset", + "GetDeviceBars", + "GetDeviceCaps", + "Kill", + ], + Visitor, + ) + } +} + +#[derive(Debug, Deserialize, DeserializeWithFds, Serialize, SerializeWithFds)] +#[msg_socket2(strategy = "serde")] +pub enum Response { + DebugLabel(String), + DeviceType(u32), + QueueMaxSizes(Vec<u16>), + Features(u64), + ReadConfig(Vec<u8>), + Reset(bool), + GetDeviceBars(Vec<PciBarConfiguration>), + GetDeviceCaps(Vec<RemotePciCapability>), + Kill, +} diff --git a/devices/src/virtio/virtualized.rs b/devices/src/virtio/virtualized.rs new file mode 100644 index 0000000..fd11f8a --- /dev/null +++ b/devices/src/virtio/virtualized.rs @@ -0,0 +1,505 @@ +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use msg_socket2::de::{EnumAccessWithFds, SeqAccessWithFds, VariantAccessWithFds, VisitorWithFds}; +use msg_socket2::ser::{ + SerializeAdapter, SerializeStructVariant, SerializeStructVariantFds, SerializeTupleVariant, + SerializeTupleVariantFds, Serializer, +}; +use msg_socket2::{ + Deserialize, DeserializeWithFds, DeserializerWithFds, FdSerializer, Serialize, SerializeWithFds, +}; +use std::fmt::{self, Formatter}; +use sys_util::net::UnixSeqpacket; +use sys_util::{EventFd, SharedMemory}; +use vm_control::MaybeOwnedFd; + +use crate::pci::{PciAddress, PciBarConfiguration}; +use crate::virtio::remote::RemotePciCapability; +use crate::virtio::Queue; +use crate::MemoryParams; + +#[derive(Debug)] +pub enum Request { + Create { + memory_params: MemoryParams, + ext_socket: UnixSeqpacket, + }, + + DebugLabel, + + DeviceType, + + QueueMaxSizes, + + Features, + AckFeatures(u64), + + ReadConfig { + offset: u64, + len: usize, + }, + WriteConfig { + offset: u64, + data: Vec<u8>, + }, + + Activate { + shm: MaybeOwnedFd<SharedMemory>, + interrupt: MaybeOwnedFd<UnixSeqpacket>, + interrupt_resample_evt: MaybeOwnedFd<EventFd>, + queues: Vec<Queue>, + queue_evts: Vec<MaybeOwnedFd<EventFd>>, + }, + + Reset, + + GetDeviceBars(PciAddress), + GetDeviceCaps, + + Kill, +} + +impl SerializeWithFds for Request { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + use Request::*; + + match self { + Create { + memory_params, + ext_socket, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 0, "Create", 2)?; + sv.serialize_field("memory_params", memory_params)?; + sv.serialize_field("ext_socket", &SerializeAdapter::new(ext_socket))?; + sv.end() + } + + DebugLabel => serializer.serialize_unit_variant("Request", 1, "DebugLabel"), + + DeviceType => serializer.serialize_unit_variant("Request", 2, "DeviceType"), + QueueMaxSizes => serializer.serialize_unit_variant("Request", 3, "QueueMaxSizes"), + + Features => serializer.serialize_unit_variant("Request", 4, "Features"), + + AckFeatures(features) => { + let mut tv = serializer.serialize_tuple_variant("Request", 5, "AckFeatures", 1)?; + tv.serialize_field(features)?; + tv.end() + } + + ReadConfig { offset, len } => { + let mut sv = serializer.serialize_struct_variant("Request", 6, "ReadConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("len", len)?; + sv.end() + } + + WriteConfig { offset, data } => { + let mut sv = serializer.serialize_struct_variant("Request", 7, "WriteConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("data", data)?; + sv.end() + } + + Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 8, "Activate", 7)?; + sv.serialize_field("shm", &SerializeAdapter::new(shm))?; + sv.serialize_field("interrupt", &SerializeAdapter::new(interrupt))?; + sv.serialize_field( + "interrupt_resample_evt", + &SerializeAdapter::new(interrupt_resample_evt), + )?; + sv.serialize_field("queues", queues)?; + sv.serialize_field("queue_evts", &SerializeAdapter::new(queue_evts))?; + sv.end() + } + + Reset => serializer.serialize_unit_variant("Request", 9, "Reset"), + + GetDeviceBars(address) => { + let mut tv = + serializer.serialize_tuple_variant("Request", 10, "GetDeviceBars", 1)?; + tv.serialize_field(address)?; + tv.end() + } + + GetDeviceCaps => serializer.serialize_unit_variant("Request", 11, "GetDeviceCaps"), + + Kill => serializer.serialize_unit_variant("Request", 12, "Kill"), + } + } + + fn serialize_fds<'fds, S>(&'fds self, serializer: S) -> Result<S::Ok, S::Error> + where + S: FdSerializer<'fds>, + { + use Request::*; + + match self { + Create { + memory_params, + ext_socket, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 0, "Create", 2)?; + sv.serialize_field("memory_params", memory_params)?; + sv.serialize_field("ext_socket", ext_socket)?; + sv.end() + } + + DebugLabel => serializer.serialize_unit_variant("Request", 1, "DebugLabel"), + DeviceType => serializer.serialize_unit_variant("Request", 2, "DeviceType"), + QueueMaxSizes => serializer.serialize_unit_variant("Request", 3, "QueueMaxSizes"), + Features => serializer.serialize_unit_variant("Request", 4, "Features"), + + AckFeatures(features) => { + let mut tv = serializer.serialize_tuple_variant("Request", 5, "AckFeatures", 1)?; + tv.serialize_field(features)?; + tv.end() + } + + ReadConfig { offset, len } => { + let mut sv = serializer.serialize_struct_variant("Request", 6, "ReadConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("len", len)?; + sv.end() + } + + WriteConfig { offset, data } => { + let mut sv = serializer.serialize_struct_variant("Request", 7, "WriteConfig", 2)?; + sv.serialize_field("offset", offset)?; + sv.serialize_field("data", data)?; + sv.end() + } + + Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + } => { + let mut sv = serializer.serialize_struct_variant("Request", 8, "Activate", 2)?; + sv.serialize_field("shm", shm)?; + sv.serialize_field("interrupt", interrupt)?; + sv.serialize_field("interrupt_resample_evt", interrupt_resample_evt)?; + sv.serialize_field("queues", queues)?; + sv.serialize_field("queue_evts", queue_evts)?; + sv.end() + } + + Reset => serializer.serialize_unit_variant("Request", 9, "Reset"), + + GetDeviceBars(address) => { + let mut tv = + serializer.serialize_tuple_variant("Request", 10, "GetDeviceBars", 1)?; + tv.serialize_field(address)?; + tv.end() + } + + GetDeviceCaps => serializer.serialize_unit_variant("Request", 11, "GetDeviceCaps"), + + Kill => serializer.serialize_unit_variant("Request", 12, "Kill"), + } + } +} + +impl<'de> DeserializeWithFds<'de> for Request { + fn deserialize<D: DeserializerWithFds<'de>>(deserializer: D) -> Result<Self, D::Error> { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "enum Request") + } + + fn visit_enum<A: EnumAccessWithFds<'de>>( + self, + data: A, + ) -> Result<Self::Value, A::Error> { + #[derive(Debug, Deserialize)] + enum Variant { + Create, + DebugLabel, + DeviceType, + QueueMaxSizes, + Features, + AckFeatures, + ReadConfig, + WriteConfig, + Activate, + Reset, + GetDeviceBars, + GetDeviceCaps, + Kill, + } + + match data.variant()? { + (Variant::Create, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::Create") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::Create with 2 elements", + ) + } + + Ok(Request::Create { + memory_params: seq + .next_element()? + .ok_or_else(|| too_short(0))?, + ext_socket: seq.next_element()?.ok_or_else(|| too_short(1))?, + }) + } + } + + variant.struct_variant(&["memory_params", "ext_socket"], Visitor) + } + + (Variant::DebugLabel, variant) => { + variant.unit_variant()?; + Ok(Request::DebugLabel) + } + + (Variant::DeviceType, variant) => { + variant.unit_variant()?; + Ok(Request::DeviceType) + } + + (Variant::QueueMaxSizes, variant) => { + variant.unit_variant()?; + Ok(Request::QueueMaxSizes) + } + + (Variant::Features, variant) => { + variant.unit_variant()?; + Ok(Request::Features) + } + + (Variant::AckFeatures, variant) => { + Ok(Request::AckFeatures(variant.newtype_variant()?)) + } + + (Variant::ReadConfig, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::ReadConfig") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::ReadConfig with 2 elements", + ) + } + + Ok(Request::ReadConfig { + offset: seq.next_element()?.ok_or_else(|| too_short(0))?, + len: seq.next_element()?.ok_or_else(|| too_short(1))?, + }) + } + } + + variant.struct_variant(&["offset", "len"], Visitor) + } + + (Variant::WriteConfig, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::WriteConfig") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::WriteConfig with 2 elements", + ) + } + + Ok(Request::WriteConfig { + offset: seq.next_element()?.ok_or_else(|| too_short(0))?, + data: seq.next_element()?.ok_or_else(|| too_short(1))?, + }) + } + } + + variant.struct_variant(&["offset", "data"], Visitor) + } + + (Variant::Activate, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "struct variant Request::Activate") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"struct variant Request::Activate with 7 elements", + ) + } + + Ok(Request::Activate { + shm: seq.next_element()?.ok_or_else(|| too_short(0))?, + interrupt: seq.next_element()?.ok_or_else(|| too_short(1))?, + interrupt_resample_evt: seq + .next_element()? + .ok_or_else(|| too_short(2))?, + queues: seq.next_element()?.ok_or_else(|| too_short(3))?, + queue_evts: seq.next_element()?.ok_or_else(|| too_short(4))?, + }) + } + } + + variant.struct_variant( + &[ + "shm", + "interrupt", + "interrupt_resample_evt", + "in_queue", + "out_queue", + "in_queue_evt", + "out_queue_evt", + ], + Visitor, + ) + } + + (Variant::Reset, variant) => { + variant.unit_variant()?; + Ok(Request::Reset) + } + + (Variant::GetDeviceBars, variant) => { + struct Visitor; + + impl<'de> VisitorWithFds<'de> for Visitor { + type Value = Request; + + fn expecting(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "tuple variant Request::GetDeviceBars") + } + + fn visit_seq<A: SeqAccessWithFds<'de>>( + self, + mut seq: A, + ) -> Result<Request, A::Error> { + use serde::de::Error; + + fn too_short<E: Error>(len: usize) -> E { + E::invalid_length( + len, + &"tuple variant Request::GetDeviceBars with 1 elements", + ) + } + + Ok(Request::GetDeviceBars( + seq.next_element()?.ok_or_else(|| too_short(0))?, + )) + } + } + + variant.struct_variant(&["bus", "dev"], Visitor) + } + + (Variant::GetDeviceCaps, variant) => { + variant.unit_variant()?; + Ok(Request::GetDeviceCaps) + } + + (Variant::Kill, variant) => { + variant.unit_variant()?; + Ok(Request::Kill) + } + } + } + } + + deserializer.deserialize_enum( + "Request", + &[ + "Create", + "DebugLabel", + "DeviceType", + "QueueMaxSizes", + "Features", + "AckFeatures", + "ReadConfig", + "WriteConfig", + "Activate", + "Reset", + "GetDeviceBars", + "GetDeviceCaps", + "Kill", + ], + Visitor, + ) + } +} + +#[derive(Debug, Deserialize, DeserializeWithFds, Serialize, SerializeWithFds)] +#[msg_socket2(strategy = "serde")] +pub enum Response { + DebugLabel(String), + DeviceType(u32), + QueueMaxSizes(Vec<u16>), + Features(u64), + ReadConfig(Vec<u8>), + Reset(bool), + GetDeviceBars(Vec<PciBarConfiguration>), + GetDeviceCaps(Vec<RemotePciCapability>), + Kill, +} diff --git a/src/ext/wl_main.rs b/src/ext/wl_main.rs new file mode 100644 index 0000000..0b8d6a3 --- /dev/null +++ b/src/ext/wl_main.rs @@ -0,0 +1,187 @@ +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use std::env::args_os; +use std::fs::remove_file; +use std::io::{stdout, IoSlice, Write}; +use std::os::unix::prelude::*; +use std::process; + +use devices::virtio::{remote, virtualized}; +use sys_util::net::{UnixSeqpacket, UnixSeqpacketListener}; +use sys_util::{PollContext, PollToken, ScmSocket}; + +fn main() { + // Create and display the incoming socket. + let mut path = std::env::var_os("XDG_RUNTIME_DIR").expect("XDG_RUNTIME_DIR missing"); + path.push("/crosvm_wl-"); + path.push(process::id().to_string()); + path.push(".sock"); + let _ = remove_file(&path); + let server = UnixSeqpacketListener::bind(&path).expect("failed to create socket"); + match stdout().write_all(path.as_bytes()) { + Ok(()) => println!(), + Err(e) => eprintln!("{}", e), + } + + // Receive connection from crosvm. + let conn = server.accept().expect("accept failed"); + let client_virtio_device_msg_socket: msg_socket2::Socket<remote::Response, remote::Request> = + msg_socket2::Socket::new(conn); + + let (memory_params, client_vm_control_socket) = match client_virtio_device_msg_socket.recv() { + Ok(remote::Request::Create { + memory_params, + vm_control_socket, + }) => (memory_params, vm_control_socket.owned()), + + Ok(msg) => panic!("unexpected message: {:?}", msg), + Err(e) => panic!("recv error: {}", e), + }; + + let server_virtio_device_socket_path = args_os().nth(1).expect("missing server socket path"); + let server_virtio_device_socket = + UnixSeqpacket::connect(server_virtio_device_socket_path).expect("connect failed"); + let server_virtio_device_msg_socket: msg_socket2::Socket< + virtualized::Request, + virtualized::Response, + > = msg_socket2::Socket::new(server_virtio_device_socket); + + let (server_vm_control_socket, ext_vm_control_socket) = + UnixSeqpacket::pair().expect("pair failed"); + + server_virtio_device_msg_socket + .send(virtualized::Request::Create { + memory_params, + ext_socket: ext_vm_control_socket, // TODO: proxy rather than passing through + }) + .expect("send failed"); + + #[derive(Debug, PollToken)] + enum Token { + ClientVirtioDevice, + ClientVmControl, + ServerVirtioDevice, + ServerVmControl, + } + + let poll_ctx = match PollContext::build_with(&[ + (&client_virtio_device_msg_socket, Token::ClientVirtioDevice), + (&client_vm_control_socket, Token::ClientVmControl), + (&server_virtio_device_msg_socket, Token::ServerVirtioDevice), + (&server_vm_control_socket, Token::ServerVmControl), + ]) { + Ok(pc) => pc, + Err(e) => panic!("failed creating PollContext: {}", e), + }; + + loop { + let events = match poll_ctx.wait() { + Ok(v) => v, + Err(e) => panic!("failed polling for events: {}", e), + }; + + for event in &events { + match event.token() { + Token::ClientVirtioDevice => { + let msg = match dbg!(client_virtio_device_msg_socket.recv()) { + Ok(remote::Request::DebugLabel) => virtualized::Request::DebugLabel, + Ok(remote::Request::DeviceType) => virtualized::Request::DeviceType, + Ok(remote::Request::QueueMaxSizes) => virtualized::Request::QueueMaxSizes, + Ok(remote::Request::Features) => virtualized::Request::Features, + Ok(remote::Request::AckFeatures(value)) => { + virtualized::Request::AckFeatures(value) + } + Ok(remote::Request::ReadConfig { offset, len }) => { + virtualized::Request::ReadConfig { offset, len } + } + Ok(remote::Request::WriteConfig { offset, data }) => { + virtualized::Request::WriteConfig { offset, data } + } + Ok(remote::Request::Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + }) => virtualized::Request::Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + }, + Ok(remote::Request::Reset) => virtualized::Request::Reset, + Ok(remote::Request::GetDeviceBars(address)) => { + virtualized::Request::GetDeviceBars(address) + } + Ok(remote::Request::GetDeviceCaps) => virtualized::Request::GetDeviceCaps, + Ok(remote::Request::Kill) => virtualized::Request::Kill, + + Ok(req @ remote::Request::Create { .. }) => { + panic!("unexpected message: {:?}", req) + } + + Err(e) => panic!("recv failed: {}", e), + }; + + if let Err(e) = server_virtio_device_msg_socket.send(msg) { + panic!("send failed: {}", e); + } + } + + Token::ClientVmControl => { + let (buf, fds) = client_vm_control_socket + .recv_as_vec_with_fds() + .expect("recv failed"); + server_vm_control_socket + .send_with_fds(&[IoSlice::new(&buf)], &fds[..]) + .expect("send failed"); + } + + Token::ServerVirtioDevice => { + let msg = match server_virtio_device_msg_socket.recv() { + Ok(virtualized::Response::DebugLabel(label)) => { + remote::Response::DebugLabel(label) + } + Ok(virtualized::Response::DeviceType(typ)) => { + remote::Response::DeviceType(typ) + } + Ok(virtualized::Response::Features(value)) => { + remote::Response::Features(value) + } + Ok(virtualized::Response::GetDeviceBars(bars)) => { + remote::Response::GetDeviceBars(bars) + } + Ok(virtualized::Response::GetDeviceCaps(caps)) => { + remote::Response::GetDeviceCaps(caps) + } + Ok(virtualized::Response::Kill) => remote::Response::Kill, + Ok(virtualized::Response::QueueMaxSizes(sizes)) => { + remote::Response::QueueMaxSizes(sizes) + } + Ok(virtualized::Response::ReadConfig(config)) => { + remote::Response::ReadConfig(config) + } + Ok(virtualized::Response::Reset(result)) => remote::Response::Reset(result), + Err(e) => panic!("recv failed: {}", e), + }; + + if let Err(e) = client_virtio_device_msg_socket.send(dbg!(msg)) { + panic!("send failed: {}", e); + } + } + + Token::ServerVmControl => { + let (buf, fds) = server_vm_control_socket + .recv_as_vec_with_fds() + .expect("recv failed"); + client_vm_control_socket + .send_with_fds(&[IoSlice::new(&buf)], &fds[..]) + .expect("send failed"); + } + } + } + } +} diff --git a/src/wl.rs b/src/guest/wl.rs index 1581b2c..e273246 100644 --- a/src/wl.rs +++ b/src/guest/wl.rs @@ -1,10 +1,14 @@ -// SPDX-License-Identifier: BSD-3-Clause +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +use devices::virtio::remote::RemotePciCapability; +use devices::virtio::virtualized::{Request, Response}; use devices::virtio::{ - InterruptProxy, InterruptProxyEvent, RemotePciCapability, Request, Response, VirtioDevice, - VirtioDeviceNew, Wl, + InterruptProxy, InterruptProxyEvent, Params, VirtioDevice, VirtioDeviceNew, Wl, }; use msg_socket::MsgSocket; +use std::collections::BTreeMap; use std::fs::remove_file; use std::io::prelude::*; use std::io::stdout; @@ -39,11 +43,11 @@ fn main() { let conn = server.accept().expect("accept failed"); let msg_socket: Socket = msg_socket2::Socket::new(conn); - let (device_params, memory_params) = match msg_socket.recv() { + let (memory_params, ext_socket) = match msg_socket.recv() { Ok(Request::Create { - device_params, memory_params, - }) => (device_params, memory_params), + ext_socket, + }) => (memory_params, ext_socket), Ok(msg) => { panic!("received unexpected message: {:?}", msg); @@ -54,10 +58,18 @@ fn main() { } }; - let mut wl = Wl::new(device_params).unwrap(); + let mut wayland_paths = BTreeMap::new(); + wayland_paths.insert("".into(), "/run/user/1000/wayland-0".into()); + + let mut wl = Wl::new(Params { + wayland_paths, + vm_socket: MsgSocket::new(ext_socket), + resource_bridge: None, + }) + .unwrap(); loop { - match msg_socket.recv() { + match dbg!(msg_socket.recv()) { Ok(Request::DebugLabel) => { let result = wl.debug_label(); if let Err(e) = msg_socket.send(Response::DebugLabel(result)) { @@ -74,7 +86,7 @@ fn main() { Ok(Request::QueueMaxSizes) => { let result = wl.queue_max_sizes(); - if let Err(e) = msg_socket.send(Response::QueueMaxSizes(result)) { + if let Err(e) = msg_socket.send(dbg!(Response::QueueMaxSizes(result))) { panic!("responding to QueueMaxSizes failed: {}", e); } } @@ -129,7 +141,7 @@ fn main() { Ok(Request::Reset) => { let result = wl.reset(); - if let Err(e) = msg_socket.send(Response::Reset(result)) { + if let Err(e) = msg_socket.send(dbg!(Response::Reset(result))) { panic!("responding to Reset failed: {}", e); } } diff --git a/src/linux.rs b/src/linux.rs index ce177e0..ee248a4 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -767,22 +767,23 @@ fn create_wayland_device( .collect::<Option<Vec<_>>>() .ok_or(Error::InvalidWaylandPath)?; - let params = Params { - wayland_paths: cfg.wayland_socket_paths.clone(), - vm_socket, - resource_bridge, - }; - let dev: Box<dyn VirtioDevice> = match cfg.remote_wayland_device_socket_path { Some(ref socket_path) => { let socket = UnixSeqpacket::connect(socket_path).map_err(Error::ConnectRemoteDevice)?; let msg_socket = msg_socket2::Socket::new(socket); - let controller = virtio::Controller::create(params, memory_params, msg_socket) + let controller = virtio::Controller::create(memory_params, vm_socket, msg_socket) .map_err(Error::CreateController)?; Box::new(controller) } - None => Box::new(virtio::Wl::new(params).unwrap()), + None => Box::new( + virtio::Wl::new(Params { + wayland_paths: cfg.wayland_socket_paths.clone(), + vm_socket, + resource_bridge, + }) + .unwrap(), + ), }; let jail = match simple_jail(&cfg, "wl_device")? { diff --git a/vm_control/src/lib.rs b/vm_control/src/lib.rs index 99fae7e..a9784b1 100644 --- a/vm_control/src/lib.rs +++ b/vm_control/src/lib.rs @@ -26,6 +26,7 @@ use sys_util::net::UnixSeqpacket; use sys_util::{error, Error as SysError, EventFd, GuestAddress, MemoryMapping, MmapError, Result}; /// A data structure that either owns or borrows a file descriptor. +// TODO: "Borrowed" should not be holding a raw file descriptor, it should be borrowing. #[derive(Debug, DeserializeWithFds, SerializeWithFds)] #[msg_socket2(strategy = "AsRawFd")] pub enum MaybeOwnedFd<Owned: AsRawFd + FromRawFd> { |