From 90309b5106b57967efbe51ee2107818ea4fe4ffa Mon Sep 17 00:00:00 2001 From: Sergio Lopez Date: Thu, 5 Mar 2020 14:30:36 +0100 Subject: [PATCH] vm-virtio: queue: Add methods to switch a descriptor context "DescriptorChain"s are tied to the lifetime of the referenced GuestMemoryMmap object (for good reasons), but sometimes (i.e., when processing descriptors from different contexts) we may need to switch them to point a different GuestMemoryMmap. Here we introduce the structure DescriptorHead, which holds the data needed to rebuild a DescriptorChain, the method "get_head" which returns the DescriptorHead for a DescriptorChain, and the method "new_from_head", which allows to create a new DescriptorChain with a DescriptorHead and a new reference to a GuestMemoryMmap. Signed-off-by: Sergio Lopez --- vm-virtio/src/queue.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/vm-virtio/src/queue.rs b/vm-virtio/src/queue.rs index 5c6532a16..ed28b6384 100644 --- a/vm-virtio/src/queue.rs +++ b/vm-virtio/src/queue.rs @@ -94,6 +94,14 @@ pub struct Descriptor { unsafe impl ByteValued for Descriptor {} +/// A virtio descriptor head, not tied to a GuestMemoryMmap. +pub struct DescriptorHead { + desc_table: GuestAddress, + table_size: u16, + index: u16, + iommu_mapping_cb: Option>, +} + /// A virtio descriptor chain. #[derive(Clone)] pub struct DescriptorChain<'a> { @@ -224,6 +232,34 @@ impl<'a> DescriptorChain<'a> { Ok(chain) } + /// Returns a copy of a descriptor referencing a different GuestMemoryMmap object. + pub fn new_from_head( + mem: &'a GuestMemoryMmap, + head: DescriptorHead, + ) -> Result, Error> { + match DescriptorChain::checked_new( + mem, + head.desc_table, + head.table_size, + head.index, + head.iommu_mapping_cb, + ) { + Some(d) => Ok(d), + None => Err(Error::InvalidChain), + } + } + + /// Returns a DescriptorHead that can be used to build a copy of a descriptor + /// referencing a different GuestMemoryMmap. + pub fn get_head(&self) -> DescriptorHead { + DescriptorHead { + desc_table: self.desc_table, + table_size: self.table_size, + index: self.index, + iommu_mapping_cb: self.iommu_mapping_cb.clone(), + } + } + fn is_valid(&self) -> bool { !(self .mem