summary refs log tree commit diff
path: root/devices/src/virtio/controller.rs
diff options
context:
space:
mode:
Diffstat (limited to 'devices/src/virtio/controller.rs')
-rw-r--r--devices/src/virtio/controller.rs47
1 files changed, 46 insertions, 1 deletions
diff --git a/devices/src/virtio/controller.rs b/devices/src/virtio/controller.rs
index 33dbdd4..c5d2ef4 100644
--- a/devices/src/virtio/controller.rs
+++ b/devices/src/virtio/controller.rs
@@ -37,7 +37,7 @@ use std::thread;
 use super::resource_bridge::*;
 use super::{Interrupt, InterruptProxyEvent, Queue, VirtioDevice, TYPE_WL, VIRTIO_F_VERSION_1};
 use crate::{
-    pci::{PciAddress, PciBarConfiguration},
+    pci::{PciAddress, PciBarConfiguration, PciCapability, PciCapabilityID},
     MemoryParams,
 };
 use vm_control::{MaybeOwnedFd, VmMemoryControlRequestSocket};
@@ -47,6 +47,33 @@ use serde::{Deserialize, Serialize};
 use sys_util::net::UnixSeqpacket;
 use sys_util::{error, EventFd, GuestMemory, PollContext, PollToken, SharedMemory};
 
+// 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, MsgOnSocket)]
 pub enum MsgOnSocketRequest {
     Create {
@@ -79,6 +106,7 @@ pub enum BincodeRequest {
     WriteConfig { offset: u64, data: Vec<u8> },
 
     GetDeviceBars(PciAddress),
+    GetDeviceCaps,
 }
 
 pub type Request = poly_msg_socket::Value<MsgOnSocketRequest, BincodeRequest>;
@@ -106,6 +134,7 @@ pub enum BincodeResponse {
     ReadConfig(Vec<u8>),
 
     GetDeviceBars(Vec<PciBarConfiguration>),
+    GetDeviceCaps(Vec<RemotePciCapability>),
 }
 
 pub type Response = poly_msg_socket::Value<MsgOnSocketResponse, BincodeResponse>;
@@ -406,4 +435,20 @@ impl VirtioDevice for Controller {
             }
         }
     }
+
+    fn get_device_caps(&self) -> Vec<Box<dyn PciCapability>> {
+        if let Err(e) = self.socket.send(BincodeRequest::GetDeviceCaps) {
+            panic!("failed to send GetDeviceCaps: {}", e);
+        }
+
+        match self.socket.recv_bincode() {
+            Ok(BincodeResponse::GetDeviceCaps(caps)) => caps
+                .into_iter()
+                .map(|cap| Box::new(cap) as Box<dyn PciCapability>)
+                .collect(),
+            response => {
+                panic!("bad response to GetDeviceCaps: {:?}", response);
+            }
+        }
+    }
 }