| // Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. |
| // SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause |
| // |
| // Portions Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| // |
| // Portions Copyright 2017 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-BSD-Google file. |
| |
| /* Auto-generated by bindgen then manually edited for simplicity */ |
| |
| #![allow(non_upper_case_globals)] |
| #![allow(non_camel_case_types)] |
| #![allow(non_snake_case)] |
| #![allow(missing_docs)] |
| #![allow(clippy::missing_safety_doc)] |
| |
| use crate::{Error, Result}; |
| use std::os::raw; |
| |
| pub const VHOST: raw::c_uint = 0xaf; |
| pub const VHOST_VRING_F_LOG: raw::c_uint = 0; |
| pub const VHOST_ACCESS_RO: raw::c_uint = 1; |
| pub const VHOST_ACCESS_WO: raw::c_uint = 2; |
| pub const VHOST_ACCESS_RW: raw::c_uint = 3; |
| pub const VHOST_IOTLB_MISS: raw::c_uint = 1; |
| pub const VHOST_IOTLB_UPDATE: raw::c_uint = 2; |
| pub const VHOST_IOTLB_INVALIDATE: raw::c_uint = 3; |
| pub const VHOST_IOTLB_ACCESS_FAIL: raw::c_uint = 4; |
| pub const VHOST_IOTLB_MSG: raw::c_uint = 1; |
| pub const VHOST_PAGE_SIZE: raw::c_uint = 4096; |
| pub const VHOST_VIRTIO: raw::c_uint = 175; |
| pub const VHOST_VRING_LITTLE_ENDIAN: raw::c_uint = 0; |
| pub const VHOST_VRING_BIG_ENDIAN: raw::c_uint = 1; |
| pub const VHOST_F_LOG_ALL: raw::c_uint = 26; |
| pub const VHOST_NET_F_VIRTIO_NET_HDR: raw::c_uint = 27; |
| pub const VHOST_SCSI_ABI_VERSION: raw::c_uint = 1; |
| |
| ioctl_ior_nr!(VHOST_GET_FEATURES, VHOST, 0x00, raw::c_ulonglong); |
| ioctl_iow_nr!(VHOST_SET_FEATURES, VHOST, 0x00, raw::c_ulonglong); |
| ioctl_io_nr!(VHOST_SET_OWNER, VHOST, 0x01); |
| ioctl_io_nr!(VHOST_RESET_OWNER, VHOST, 0x02); |
| ioctl_iow_nr!(VHOST_SET_MEM_TABLE, VHOST, 0x03, vhost_memory); |
| ioctl_iow_nr!(VHOST_SET_LOG_BASE, VHOST, 0x04, raw::c_ulonglong); |
| ioctl_iow_nr!(VHOST_SET_LOG_FD, VHOST, 0x07, raw::c_int); |
| ioctl_iow_nr!(VHOST_SET_VRING_NUM, VHOST, 0x10, vhost_vring_state); |
| ioctl_iow_nr!(VHOST_SET_VRING_ADDR, VHOST, 0x11, vhost_vring_addr); |
| ioctl_iow_nr!(VHOST_SET_VRING_BASE, VHOST, 0x12, vhost_vring_state); |
| ioctl_iowr_nr!(VHOST_GET_VRING_BASE, VHOST, 0x12, vhost_vring_state); |
| ioctl_iow_nr!(VHOST_SET_VRING_KICK, VHOST, 0x20, vhost_vring_file); |
| ioctl_iow_nr!(VHOST_SET_VRING_CALL, VHOST, 0x21, vhost_vring_file); |
| ioctl_iow_nr!(VHOST_SET_VRING_ERR, VHOST, 0x22, vhost_vring_file); |
| ioctl_iow_nr!(VHOST_NET_SET_BACKEND, VHOST, 0x30, vhost_vring_file); |
| ioctl_iow_nr!(VHOST_SCSI_SET_ENDPOINT, VHOST, 0x40, vhost_scsi_target); |
| ioctl_iow_nr!(VHOST_SCSI_CLEAR_ENDPOINT, VHOST, 0x41, vhost_scsi_target); |
| ioctl_iow_nr!(VHOST_SCSI_GET_ABI_VERSION, VHOST, 0x42, raw::c_int); |
| ioctl_iow_nr!(VHOST_SCSI_SET_EVENTS_MISSED, VHOST, 0x43, raw::c_uint); |
| ioctl_iow_nr!(VHOST_SCSI_GET_EVENTS_MISSED, VHOST, 0x44, raw::c_uint); |
| ioctl_iow_nr!(VHOST_VSOCK_SET_GUEST_CID, VHOST, 0x60, raw::c_ulonglong); |
| ioctl_iow_nr!(VHOST_VSOCK_SET_RUNNING, VHOST, 0x61, raw::c_int); |
| |
| #[repr(C)] |
| #[derive(Default)] |
| pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>); |
| |
| impl<T> __IncompleteArrayField<T> { |
| #[inline] |
| pub fn new() -> Self { |
| __IncompleteArrayField(::std::marker::PhantomData) |
| } |
| |
| #[inline] |
| #[allow(clippy::trivially_copy_pass_by_ref)] |
| #[allow(clippy::useless_transmute)] |
| pub unsafe fn as_ptr(&self) -> *const T { |
| ::std::mem::transmute(self) |
| } |
| |
| #[inline] |
| #[allow(clippy::useless_transmute)] |
| pub unsafe fn as_mut_ptr(&mut self) -> *mut T { |
| ::std::mem::transmute(self) |
| } |
| |
| #[inline] |
| pub unsafe fn as_slice(&self, len: usize) -> &[T] { |
| ::std::slice::from_raw_parts(self.as_ptr(), len) |
| } |
| |
| #[inline] |
| pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { |
| ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) |
| } |
| } |
| |
| impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> { |
| fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |
| fmt.write_str("__IncompleteArrayField") |
| } |
| } |
| |
| impl<T> ::std::clone::Clone for __IncompleteArrayField<T> { |
| #[inline] |
| fn clone(&self) -> Self { |
| Self::new() |
| } |
| } |
| |
| impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {} |
| |
| #[repr(C)] |
| #[derive(Debug, Default, Copy, Clone)] |
| pub struct vhost_vring_state { |
| pub index: raw::c_uint, |
| pub num: raw::c_uint, |
| } |
| |
| #[repr(C)] |
| #[derive(Debug, Default, Copy, Clone)] |
| pub struct vhost_vring_file { |
| pub index: raw::c_uint, |
| pub fd: raw::c_int, |
| } |
| |
| #[repr(C)] |
| #[derive(Debug, Default, Copy, Clone)] |
| pub struct vhost_vring_addr { |
| pub index: raw::c_uint, |
| pub flags: raw::c_uint, |
| pub desc_user_addr: raw::c_ulonglong, |
| pub used_user_addr: raw::c_ulonglong, |
| pub avail_user_addr: raw::c_ulonglong, |
| pub log_guest_addr: raw::c_ulonglong, |
| } |
| |
| #[repr(C)] |
| #[derive(Debug, Default, Copy, Clone)] |
| pub struct vhost_iotlb_msg { |
| pub iova: raw::c_ulonglong, |
| pub size: raw::c_ulonglong, |
| pub uaddr: raw::c_ulonglong, |
| pub perm: raw::c_uchar, |
| pub type_: raw::c_uchar, |
| } |
| |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub struct vhost_msg { |
| pub type_: raw::c_int, |
| pub __bindgen_anon_1: vhost_msg__bindgen_ty_1, |
| } |
| |
| impl Default for vhost_msg { |
| fn default() -> Self { |
| unsafe { ::std::mem::zeroed() } |
| } |
| } |
| |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub union vhost_msg__bindgen_ty_1 { |
| pub iotlb: vhost_iotlb_msg, |
| pub padding: [raw::c_uchar; 64usize], |
| _bindgen_union_align: [u64; 8usize], |
| } |
| |
| impl Default for vhost_msg__bindgen_ty_1 { |
| fn default() -> Self { |
| unsafe { ::std::mem::zeroed() } |
| } |
| } |
| |
| #[repr(C)] |
| #[derive(Debug, Default, Copy, Clone)] |
| pub struct vhost_memory_region { |
| pub guest_phys_addr: raw::c_ulonglong, |
| pub memory_size: raw::c_ulonglong, |
| pub userspace_addr: raw::c_ulonglong, |
| pub flags_padding: raw::c_ulonglong, |
| } |
| |
| #[repr(C)] |
| #[derive(Debug, Default, Clone)] |
| pub struct vhost_memory { |
| pub nregions: raw::c_uint, |
| pub padding: raw::c_uint, |
| pub regions: __IncompleteArrayField<vhost_memory_region>, |
| __force_alignment: [u64; 0], |
| } |
| |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub struct vhost_scsi_target { |
| pub abi_version: raw::c_int, |
| pub vhost_wwpn: [raw::c_char; 224usize], |
| pub vhost_tpgt: raw::c_ushort, |
| pub reserved: raw::c_ushort, |
| } |
| |
| impl Default for vhost_scsi_target { |
| fn default() -> Self { |
| unsafe { ::std::mem::zeroed() } |
| } |
| } |
| |
| /// Helper to support vhost::set_mem_table() |
| pub struct VhostMemory { |
| buf: Vec<vhost_memory>, |
| } |
| |
| impl VhostMemory { |
| // Limit number of regions to u16 to simplify error handling |
| pub fn new(entries: u16) -> Self { |
| let size = std::mem::size_of::<vhost_memory_region>() * entries as usize; |
| let count = (size + 2 * std::mem::size_of::<vhost_memory>() - 1) |
| / std::mem::size_of::<vhost_memory>(); |
| let mut buf: Vec<vhost_memory> = vec![Default::default(); count]; |
| buf[0].nregions = u32::from(entries); |
| VhostMemory { buf } |
| } |
| |
| pub fn as_ptr(&self) -> *const char { |
| &self.buf[0] as *const vhost_memory as *const char |
| } |
| |
| pub fn get_header(&self) -> &vhost_memory { |
| &self.buf[0] |
| } |
| |
| pub fn get_region(&self, index: u32) -> Option<&vhost_memory_region> { |
| if index >= self.buf[0].nregions { |
| return None; |
| } |
| // Safe because we have allocated enough space nregions |
| let regions = unsafe { self.buf[0].regions.as_slice(self.buf[0].nregions as usize) }; |
| Some(®ions[index as usize]) |
| } |
| |
| pub fn set_region(&mut self, index: u32, region: &vhost_memory_region) -> Result<()> { |
| if index >= self.buf[0].nregions { |
| return Err(Error::InvalidGuestMemory); |
| } |
| // Safe because we have allocated enough space nregions and checked the index. |
| let regions = unsafe { self.buf[0].regions.as_mut_slice(index as usize + 1) }; |
| regions[index as usize] = *region; |
| Ok(()) |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn bindgen_test_layout_vhost_vring_state() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_vring_state>(), |
| 8usize, |
| concat!("Size of: ", stringify!(vhost_vring_state)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_vring_state>(), |
| 4usize, |
| concat!("Alignment of ", stringify!(vhost_vring_state)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_vring_file() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_vring_file>(), |
| 8usize, |
| concat!("Size of: ", stringify!(vhost_vring_file)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_vring_file>(), |
| 4usize, |
| concat!("Alignment of ", stringify!(vhost_vring_file)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_vring_addr() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_vring_addr>(), |
| 40usize, |
| concat!("Size of: ", stringify!(vhost_vring_addr)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_vring_addr>(), |
| 8usize, |
| concat!("Alignment of ", stringify!(vhost_vring_addr)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_msg__bindgen_ty_1() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_msg__bindgen_ty_1>(), |
| 64usize, |
| concat!("Size of: ", stringify!(vhost_msg__bindgen_ty_1)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_msg__bindgen_ty_1>(), |
| 8usize, |
| concat!("Alignment of ", stringify!(vhost_msg__bindgen_ty_1)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_msg() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_msg>(), |
| 72usize, |
| concat!("Size of: ", stringify!(vhost_msg)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_msg>(), |
| 8usize, |
| concat!("Alignment of ", stringify!(vhost_msg)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_memory_region() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_memory_region>(), |
| 32usize, |
| concat!("Size of: ", stringify!(vhost_memory_region)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_memory_region>(), |
| 8usize, |
| concat!("Alignment of ", stringify!(vhost_memory_region)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_memory() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_memory>(), |
| 8usize, |
| concat!("Size of: ", stringify!(vhost_memory)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_memory>(), |
| 8usize, |
| concat!("Alignment of ", stringify!(vhost_memory)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_iotlb_msg() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_iotlb_msg>(), |
| 32usize, |
| concat!("Size of: ", stringify!(vhost_iotlb_msg)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_iotlb_msg>(), |
| 8usize, |
| concat!("Alignment of ", stringify!(vhost_iotlb_msg)) |
| ); |
| } |
| |
| #[test] |
| fn bindgen_test_layout_vhost_scsi_target() { |
| assert_eq!( |
| ::std::mem::size_of::<vhost_scsi_target>(), |
| 232usize, |
| concat!("Size of: ", stringify!(vhost_scsi_target)) |
| ); |
| assert_eq!( |
| ::std::mem::align_of::<vhost_scsi_target>(), |
| 4usize, |
| concat!("Alignment of ", stringify!(vhost_scsi_target)) |
| ); |
| } |
| |
| #[test] |
| fn test_vhostmemory() { |
| let mut obj = VhostMemory::new(2); |
| let region = vhost_memory_region { |
| guest_phys_addr: 0x1000u64, |
| memory_size: 0x2000u64, |
| userspace_addr: 0x300000u64, |
| flags_padding: 0u64, |
| }; |
| assert!(obj.get_region(2).is_none()); |
| |
| { |
| let header = obj.get_header(); |
| assert_eq!(header.nregions, 2u32); |
| } |
| { |
| assert!(obj.set_region(0, ®ion).is_ok()); |
| assert!(obj.set_region(1, ®ion).is_ok()); |
| assert!(obj.set_region(2, ®ion).is_err()); |
| } |
| |
| let region1 = obj.get_region(1).unwrap(); |
| assert_eq!(region1.guest_phys_addr, 0x1000u64); |
| assert_eq!(region1.memory_size, 0x2000u64); |
| assert_eq!(region1.userspace_addr, 0x300000u64); |
| } |
| } |