diff options
author | Xiong Zhang <xiong.y.zhang@intel.corp-partner.google.com> | 2019-04-23 17:15:00 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-17 00:17:07 +0000 |
commit | bed8b0017d2cb283c20dc50241adb4f5b2668489 (patch) | |
tree | 7a76e936a9e1aede56c08c112ca7d436ab8d9e98 /sys_util/src/struct_util.rs | |
parent | 04a82c7be173b2068c4254ed4a129e24e9e3a2e4 (diff) | |
download | crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.tar crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.tar.gz crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.tar.bz2 crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.tar.lz crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.tar.xz crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.tar.zst crosvm-bed8b0017d2cb283c20dc50241adb4f5b2668489.zip |
vfio: Add msi support
crosvm doesn't support MSI/MSI-x, but kvmgt vgpu support MSI only through cfg msi capability. This is a simple msi implementation, it detects msi capability and track msi control, data and address info, then call vfio kernel to enable / disable msi interrupt. Currently it supports one vetor per MSI. It could extend to multi vetors and MSI-x. BUG=chromium:992270 TEST=none Change-Id: I04fc95f23a07f9698237c014d9f909d011f447ef Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1581142 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'sys_util/src/struct_util.rs')
-rw-r--r-- | sys_util/src/struct_util.rs | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/sys_util/src/struct_util.rs b/sys_util/src/struct_util.rs index 3d8def2..22411a1 100644 --- a/sys_util/src/struct_util.rs +++ b/sys_util/src/struct_util.rs @@ -4,7 +4,38 @@ use std; use std::io::Read; -use std::mem; +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: +/// +/// ``` +/// #[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 { @@ -21,7 +52,7 @@ pub type Result<T> = std::result::Result<T, Error>; /// * `f` - The input to read from. Often this is a file. /// * `out` - The struct to fill with data read from `f`. pub unsafe fn read_struct<T: Copy, F: Read>(f: &mut F, out: &mut T) -> Result<()> { - let out_slice = std::slice::from_raw_parts_mut(out as *mut T as *mut u8, mem::size_of::<T>()); + let out_slice = std::slice::from_raw_parts_mut(out as *mut T as *mut u8, size_of::<T>()); f.read_exact(out_slice).map_err(|_| Error::ReadStruct)?; Ok(()) } @@ -38,10 +69,8 @@ pub unsafe fn read_struct<T: Copy, F: Read>(f: &mut F, out: &mut T) -> Result<() pub unsafe fn read_struct_slice<T: Copy, F: Read>(f: &mut F, len: usize) -> Result<Vec<T>> { let mut out: Vec<T> = Vec::with_capacity(len); out.set_len(len); - let out_slice = std::slice::from_raw_parts_mut( - out.as_ptr() as *mut T as *mut u8, - mem::size_of::<T>() * len, - ); + let out_slice = + std::slice::from_raw_parts_mut(out.as_ptr() as *mut T as *mut u8, size_of::<T>() * len); f.read_exact(out_slice).map_err(|_| Error::ReadStruct)?; Ok(out) } |