mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vfio_user: Split the function for getting device regions
To prepare the support of region capabilities, this commit factorizes the `VFIO_USER_DEVICE_GET_REGION_INFO` operation in its own function. In this process, it also removes the need of the hard-coded arbitrary value for `vfio_region_info.argsz` (the maximum size of the reply payload). Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
+50
-36
@@ -4,6 +4,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use std::fs::File;
|
||||||
use std::io::{IoSlice, Read, Write};
|
use std::io::{IoSlice, Read, Write};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::num::Wrapping;
|
use std::num::Wrapping;
|
||||||
@@ -475,52 +476,65 @@ impl Client {
|
|||||||
let num_regions = reply.num_regions;
|
let num_regions = reply.num_regions;
|
||||||
let mut regions = Vec::new();
|
let mut regions = Vec::new();
|
||||||
for index in 0..num_regions {
|
for index in 0..num_regions {
|
||||||
let get_region_info = DeviceGetRegionInfo {
|
let (region_info, fd) = self.get_region_info(index, None)?;
|
||||||
header: Header {
|
|
||||||
message_id: self.next_message_id.0,
|
|
||||||
command: Command::DeviceGetRegionInfo,
|
|
||||||
flags: HeaderFlags::Command as u32,
|
|
||||||
message_size: std::mem::size_of::<DeviceGetRegionInfo>() as u32,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
region_info: vfio_region_info {
|
|
||||||
argsz: 1024, // Arbitrary max size
|
|
||||||
index,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
debug!("Command: {:?}", get_region_info);
|
|
||||||
self.next_message_id += Wrapping(1);
|
|
||||||
|
|
||||||
self.stream
|
|
||||||
.write_all(get_region_info.as_slice())
|
|
||||||
.map_err(Error::StreamWrite)?;
|
|
||||||
|
|
||||||
let mut reply = DeviceGetRegionInfo::default();
|
|
||||||
let (_, fd) = self
|
|
||||||
.stream
|
|
||||||
.recv_with_fd(reply.as_mut_slice())
|
|
||||||
.map_err(Error::ReceiveWithFd)?;
|
|
||||||
debug!("Reply: {:?}", reply);
|
|
||||||
|
|
||||||
regions.push(Region {
|
regions.push(Region {
|
||||||
flags: reply.region_info.flags,
|
flags: region_info.flags,
|
||||||
index: reply.region_info.index,
|
index: region_info.index,
|
||||||
size: reply.region_info.size,
|
size: region_info.size,
|
||||||
file_offset: fd.map(|fd| FileOffset::new(fd, reply.region_info.offset)),
|
file_offset: fd.map(|fd| FileOffset::new(fd, region_info.offset)),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Handle region with capabilities
|
Ok(regions)
|
||||||
let mut _cap_data = Vec::with_capacity(
|
}
|
||||||
reply.header.message_size as usize - std::mem::size_of::<DeviceGetRegionInfo>(),
|
|
||||||
|
fn get_region_info(
|
||||||
|
&mut self,
|
||||||
|
index: u32,
|
||||||
|
cap_size: Option<u32>,
|
||||||
|
) -> Result<(vfio_region_info, Option<File>), Error> {
|
||||||
|
let get_region_info = DeviceGetRegionInfo {
|
||||||
|
header: Header {
|
||||||
|
message_id: self.next_message_id.0,
|
||||||
|
command: Command::DeviceGetRegionInfo,
|
||||||
|
flags: HeaderFlags::Command as u32,
|
||||||
|
message_size: std::mem::size_of::<DeviceGetRegionInfo>() as u32,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
region_info: vfio_region_info {
|
||||||
|
argsz: size_of::<vfio_region_info>() as u32 + cap_size.unwrap_or_default(),
|
||||||
|
index,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
debug!("Command: {:?}", get_region_info);
|
||||||
|
self.next_message_id += Wrapping(1);
|
||||||
|
|
||||||
|
self.stream
|
||||||
|
.write_all(get_region_info.as_slice())
|
||||||
|
.map_err(Error::StreamWrite)?;
|
||||||
|
|
||||||
|
let mut reply = DeviceGetRegionInfo::default();
|
||||||
|
let (_, fd) = self
|
||||||
|
.stream
|
||||||
|
.recv_with_fd(reply.as_mut_slice())
|
||||||
|
.map_err(Error::ReceiveWithFd)?;
|
||||||
|
debug!("Reply: {:?}", reply);
|
||||||
|
|
||||||
|
// TODO: Handle region with capabilities
|
||||||
|
if let Some(cap_size) = cap_size {
|
||||||
|
assert_eq!(
|
||||||
|
cap_size,
|
||||||
|
reply.header.message_size - size_of::<DeviceGetRegionInfo>() as u32
|
||||||
);
|
);
|
||||||
|
let mut _cap_data = Vec::with_capacity(cap_size as usize);
|
||||||
_cap_data.resize(_cap_data.capacity(), 0u8);
|
_cap_data.resize(_cap_data.capacity(), 0u8);
|
||||||
self.stream
|
self.stream
|
||||||
.read_exact(_cap_data.as_mut_slice())
|
.read_exact(_cap_data.as_mut_slice())
|
||||||
.map_err(Error::StreamRead)?;
|
.map_err(Error::StreamRead)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(regions)
|
Ok((reply.region_info, fd))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn region_read(&mut self, region: u32, offset: u64, data: &mut [u8]) -> Result<(), Error> {
|
pub fn region_read(&mut self, region: u32, offset: u64, data: &mut [u8]) -> Result<(), Error> {
|
||||||
|
|||||||
Reference in New Issue
Block a user