diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | data_model/src/flexible_array.rs | 39 | ||||
-rw-r--r-- | data_model/src/lib.rs | 3 | ||||
-rw-r--r-- | devices/src/vfio.rs | 5 | ||||
-rw-r--r-- | kvm/Cargo.toml | 1 | ||||
-rw-r--r-- | kvm/src/lib.rs | 6 | ||||
-rw-r--r-- | sys_util/src/struct_util.rs | 31 | ||||
-rw-r--r-- | usb_util/src/device.rs | 3 |
8 files changed, 53 insertions, 36 deletions
diff --git a/Cargo.lock b/Cargo.lock index e525db3..9536949 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,6 +257,7 @@ dependencies = [ name = "kvm" version = "0.1.0" dependencies = [ + "data_model 0.1.0", "kvm_sys 0.1.0", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "msg_socket 0.1.0", diff --git a/data_model/src/flexible_array.rs b/data_model/src/flexible_array.rs new file mode 100644 index 0000000..35ac15a --- /dev/null +++ b/data_model/src/flexible_array.rs @@ -0,0 +1,39 @@ +// Copyright 2019 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. + +//! A wrapper for structures that contain flexible arrays. + +use std::mem::size_of; + +// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`. +fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> { + let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>(); + let mut v = Vec::with_capacity(rounded_size); + for _ in 0..rounded_size { + v.push(T::default()) + } + v +} + +/// The kernel API has many structs that resemble the following `Foo` structure: +/// +/// ```ignore +/// #[repr(C)] +/// struct Foo { +/// some_data: u32, +/// entries: __IncompleteArrayField<__u32>, +/// } +/// ``` +/// +/// In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would +/// not include any space for `entries`. To make the allocation large enough while still being +/// aligned for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually +/// be used as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be +/// contiguous with `Foo`. This function is used to make the `Vec<Foo>` with enough space for +/// `count` entries. +pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> { + let element_space = count * size_of::<F>(); + let vec_size_bytes = size_of::<T>() + element_space; + vec_with_size_in_bytes(vec_size_bytes) +} diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index dcca108..3f75377 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -180,3 +180,6 @@ pub use crate::endian::*; pub mod volatile_memory; pub use crate::volatile_memory::*; + +mod flexible_array; +pub use flexible_array::vec_with_array_field; diff --git a/devices/src/vfio.rs b/devices/src/vfio.rs index c42c622..f8c15c8 100644 --- a/devices/src/vfio.rs +++ b/devices/src/vfio.rs @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +use data_model::vec_with_array_field; use std::ffi::CString; use std::fmt; use std::fs::{File, OpenOptions}; @@ -14,8 +15,8 @@ use std::u32; use kvm::Vm; use sys_util::{ - ioctl, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref, ioctl_with_val, - vec_with_array_field, warn, Error, EventFd, GuestMemory, + ioctl, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref, ioctl_with_val, warn, Error, + EventFd, GuestMemory, }; use vfio_sys::*; diff --git a/kvm/Cargo.toml b/kvm/Cargo.toml index d12aa76..f784ae7 100644 --- a/kvm/Cargo.toml +++ b/kvm/Cargo.toml @@ -5,6 +5,7 @@ authors = ["The Chromium OS Authors"] edition = "2018" [dependencies] +data_model = { path = "../data_model" } kvm_sys = { path = "../kvm_sys" } libc = "*" msg_socket = { path = "../msg_socket" } diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs index 06f5915..bc1abad 100644 --- a/kvm/src/lib.rs +++ b/kvm/src/lib.rs @@ -16,6 +16,8 @@ use std::os::raw::*; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::ptr::copy_nonoverlapping; +use data_model::vec_with_array_field; + use libc::sigset_t; use libc::{open, EBUSY, EINVAL, ENOENT, ENOSPC, EOVERFLOW, O_CLOEXEC, O_RDWR}; @@ -25,8 +27,8 @@ use msg_socket::MsgOnSocket; #[allow(unused_imports)] use sys_util::{ block_signal, ioctl, ioctl_with_mut_ptr, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref, - ioctl_with_val, pagesize, signal, unblock_signal, vec_with_array_field, warn, Error, EventFd, - GuestAddress, GuestMemory, MemoryMapping, MemoryMappingArena, Result, SIGRTMIN, + ioctl_with_val, pagesize, signal, unblock_signal, warn, Error, EventFd, GuestAddress, + GuestMemory, MemoryMapping, MemoryMappingArena, Result, SIGRTMIN, }; pub use crate::cap::*; diff --git a/sys_util/src/struct_util.rs b/sys_util/src/struct_util.rs index d77dd96..551204e 100644 --- a/sys_util/src/struct_util.rs +++ b/sys_util/src/struct_util.rs @@ -6,37 +6,6 @@ use std; use std::io::Read; use std::mem::size_of; -// Returns a `Vec<T>` with a size in ytes at least as large as `size_in_bytes`. -fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> { - let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>(); - let mut v = Vec::with_capacity(rounded_size); - for _ in 0..rounded_size { - v.push(T::default()) - } - v -} - -/// The kvm API has many structs that resemble the following `Foo` structure: -/// -/// ```ignore -/// #[repr(C)] -/// struct Foo { -/// some_data: u32, -/// entries: __IncompleteArrayField<__u32>, -/// } -/// ``` -/// -/// In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not -/// include any space for `entries`. To make the allocation large enough while still being aligned -/// for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used -/// as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous -/// with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries. -pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> { - let element_space = count * size_of::<F>(); - let vec_size_bytes = size_of::<T>() + element_space; - vec_with_size_in_bytes(vec_size_bytes) -} - #[derive(Debug)] pub enum Error { ReadStruct, diff --git a/usb_util/src/device.rs b/usb_util/src/device.rs index b6aed6a..aad77db 100644 --- a/usb_util/src/device.rs +++ b/usb_util/src/device.rs @@ -7,6 +7,7 @@ use crate::{ ControlRequestDataPhaseTransferDirection, ControlRequestRecipient, ControlRequestType, DeviceDescriptor, DeviceDescriptorTree, Error, Result, StandardControlRequest, }; +use data_model::vec_with_array_field; use libc::{EAGAIN, ENODEV, ENOENT}; use std::convert::TryInto; use std::fs::File; @@ -14,7 +15,7 @@ use std::io::{Seek, SeekFrom}; use std::mem::size_of_val; use std::os::raw::{c_int, c_uint, c_ulong, c_void}; use std::sync::Arc; -use sys_util::{handle_eintr_errno, vec_with_array_field}; +use sys_util::handle_eintr_errno; /// Device represents a USB device. pub struct Device { |