From e2225bb4b0cd9a4bb50f908bafceacdd86e39d88 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Wed, 26 Jan 2022 17:15:50 +0100 Subject: [PATCH] virtio-devices: vsock: Handle descriptor address translation Since we're trying to move away from the translation happening in the virtio-queue crate, the device itself is performing the address translation when needed. Signed-off-by: Sebastien Boeuf --- virtio-devices/src/vsock/csm/connection.rs | 1 + virtio-devices/src/vsock/device.rs | 18 +++++-- virtio-devices/src/vsock/mod.rs | 1 + virtio-devices/src/vsock/packet.rs | 58 +++++++++++++++++++--- virtio-devices/src/vsock/unix/muxer.rs | 1 + 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/virtio-devices/src/vsock/csm/connection.rs b/virtio-devices/src/vsock/csm/connection.rs index 9b8741ba8..b349895c4 100644 --- a/virtio-devices/src/vsock/csm/connection.rs +++ b/virtio-devices/src/vsock/csm/connection.rs @@ -823,6 +823,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); let conn = match conn_state { diff --git a/virtio-devices/src/vsock/device.rs b/virtio-devices/src/vsock/device.rs index 4a53a81f9..205146c22 100644 --- a/virtio-devices/src/vsock/device.rs +++ b/virtio-devices/src/vsock/device.rs @@ -47,7 +47,7 @@ use std::sync::atomic::AtomicBool; use std::sync::{Arc, Barrier, RwLock}; use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize_derive::Versionize; -use virtio_queue::Queue; +use virtio_queue::{AccessPlatform, Queue}; use vm_memory::GuestMemoryAtomic; use vm_migration::{ Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, @@ -93,6 +93,7 @@ pub struct VsockEpollHandler { pub pause_evt: EventFd, pub interrupt_cb: Arc, pub backend: Arc>, + pub access_platform: Option>, } impl VsockEpollHandler @@ -124,7 +125,10 @@ where let mut avail_iter = self.queues[0].iter().map_err(DeviceError::QueueIterator)?; for mut desc_chain in &mut avail_iter { - let used_len = match VsockPacket::from_rx_virtq_head(&mut desc_chain) { + let used_len = match VsockPacket::from_rx_virtq_head( + &mut desc_chain, + self.access_platform.as_ref(), + ) { Ok(mut pkt) => { if self.backend.write().unwrap().recv_pkt(&mut pkt).is_ok() { pkt.hdr().len() as u32 + pkt.len() @@ -169,7 +173,10 @@ where let mut avail_iter = self.queues[1].iter().map_err(DeviceError::QueueIterator)?; for mut desc_chain in &mut avail_iter { - let pkt = match VsockPacket::from_tx_virtq_head(&mut desc_chain) { + let pkt = match VsockPacket::from_tx_virtq_head( + &mut desc_chain, + self.access_platform.as_ref(), + ) { Ok(pkt) => pkt, Err(e) => { error!("vsock: error reading TX packet: {:?}", e); @@ -438,6 +445,7 @@ where pause_evt, interrupt_cb, backend: self.backend.clone(), + access_platform: self.common.access_platform.clone(), }; let paused = self.common.paused.clone(); @@ -472,6 +480,10 @@ where fn shutdown(&mut self) { std::fs::remove_file(&self.path).ok(); } + + fn set_access_platform(&mut self, access_platform: Arc) { + self.common.set_access_platform(access_platform) + } } impl Pausable for Vsock diff --git a/virtio-devices/src/vsock/mod.rs b/virtio-devices/src/vsock/mod.rs index 1baecb5e5..a54ad6bba 100644 --- a/virtio-devices/src/vsock/mod.rs +++ b/virtio-devices/src/vsock/mod.rs @@ -328,6 +328,7 @@ mod tests { pause_evt: EventFd::new(EFD_NONBLOCK).unwrap(), interrupt_cb, backend: Arc::new(RwLock::new(TestBackend::new())), + access_platform: None, }, } } diff --git a/virtio-devices/src/vsock/packet.rs b/virtio-devices/src/vsock/packet.rs index 6f6b97647..cdd2a30f9 100644 --- a/virtio-devices/src/vsock/packet.rs +++ b/virtio-devices/src/vsock/packet.rs @@ -16,12 +16,13 @@ /// to temporary buffers, before passing it on to the vsock backend. /// use byteorder::{ByteOrder, LittleEndian}; +use std::sync::Arc; use super::defs; use super::{Result, VsockError}; use crate::{get_host_address_range, GuestMemoryMmap}; -use virtio_queue::DescriptorChain; -use vm_memory::GuestMemoryLoadGuard; +use virtio_queue::{AccessPlatform, DescriptorChain}; +use vm_memory::{GuestAddress, GuestMemoryLoadGuard}; // The vsock packet header is defined by the C struct: // @@ -107,6 +108,7 @@ impl VsockPacket { /// pub fn from_tx_virtq_head( desc_chain: &mut DescriptorChain>, + access_platform: Option<&Arc>, ) -> Result { let head = desc_chain.next().ok_or(VsockError::HdrDescMissing)?; @@ -121,8 +123,18 @@ impl VsockPacket { return Err(VsockError::HdrDescTooSmall(head.len())); } + let head_addr = if let Some(access_platform) = access_platform { + GuestAddress( + access_platform + .translate(head.addr().0, u64::from(head.len())) + .unwrap(), + ) + } else { + head.addr() + }; + let mut pkt = Self { - hdr: get_host_address_range(desc_chain.memory(), head.addr(), VSOCK_PKT_HDR_SIZE) + hdr: get_host_address_range(desc_chain.memory(), head_addr, VSOCK_PKT_HDR_SIZE) .ok_or(VsockError::GuestMemory)? as *mut u8, buf: None, buf_size: 0, @@ -153,9 +165,19 @@ impl VsockPacket { return Err(VsockError::BufDescTooSmall); } + let buf_desc_addr = if let Some(access_platform) = access_platform { + GuestAddress( + access_platform + .translate(buf_desc.addr().0, u64::from(buf_desc.len())) + .unwrap(), + ) + } else { + buf_desc.addr() + }; + pkt.buf_size = buf_desc.len() as usize; pkt.buf = Some( - get_host_address_range(desc_chain.memory(), buf_desc.addr(), pkt.buf_size) + get_host_address_range(desc_chain.memory(), buf_desc_addr, pkt.buf_size) .ok_or(VsockError::GuestMemory)? as *mut u8, ); @@ -169,6 +191,7 @@ impl VsockPacket { /// pub fn from_rx_virtq_head( desc_chain: &mut DescriptorChain>, + access_platform: Option<&Arc>, ) -> Result { let head = desc_chain.next().ok_or(VsockError::HdrDescMissing)?; @@ -190,11 +213,28 @@ impl VsockPacket { let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?; let buf_size = buf_desc.len() as usize; + let (head_addr, buf_desc_addr) = if let Some(access_platform) = access_platform { + ( + GuestAddress( + access_platform + .translate(head.addr().0, u64::from(head.len())) + .unwrap(), + ), + GuestAddress( + access_platform + .translate(buf_desc.addr().0, u64::from(buf_desc.len())) + .unwrap(), + ), + ) + } else { + (head.addr(), buf_desc.addr()) + }; + Ok(Self { - hdr: get_host_address_range(desc_chain.memory(), head.addr(), VSOCK_PKT_HDR_SIZE) + hdr: get_host_address_range(desc_chain.memory(), head_addr, VSOCK_PKT_HDR_SIZE) .ok_or(VsockError::GuestMemory)? as *mut u8, buf: Some( - get_host_address_range(desc_chain.memory(), buf_desc.addr(), buf_size) + get_host_address_range(desc_chain.memory(), buf_desc_addr, buf_size) .ok_or(VsockError::GuestMemory)? as *mut u8, ), buf_size, @@ -380,6 +420,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) { Err($err) => (), Ok(_) => panic!("Packet assembly should've failed!"), @@ -410,6 +451,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); assert_eq!(pkt.hdr().len(), VSOCK_PKT_HDR_SIZE); @@ -447,6 +489,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); assert!(pkt.buf().is_none()); @@ -504,6 +547,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); assert_eq!(pkt.hdr().len(), VSOCK_PKT_HDR_SIZE); @@ -560,6 +604,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); @@ -650,6 +695,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); diff --git a/virtio-devices/src/vsock/unix/muxer.rs b/virtio-devices/src/vsock/unix/muxer.rs index a95a4e322..0664298b8 100644 --- a/virtio-devices/src/vsock/unix/muxer.rs +++ b/virtio-devices/src/vsock/unix/muxer.rs @@ -846,6 +846,7 @@ mod tests { .unwrap() .next() .unwrap(), + None, ) .unwrap(); let uds_path = format!("test_vsock_{}.sock", name);