summary refs log tree commit diff
path: root/devices
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-04-10 13:19:04 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 09:37:29 +0000
commiteb90518961ca5f00bd832429be840600ce305fb4 (patch)
tree8415abc6314ac439b47d90305194cc88eca76146 /devices
parentaa9ee49fdf908aef32d4363704099a0584834d4c (diff)
downloadcrosvm-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
Diffstat (limited to 'devices')
-rw-r--r--devices/src/virtio/controller.rs534
-rw-r--r--devices/src/virtio/mod.rs2
-rw-r--r--devices/src/virtio/remote.rs536
-rw-r--r--devices/src/virtio/virtualized.rs505
4 files changed, 1052 insertions, 525 deletions
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,
+}