diff --git a/Cargo.lock b/Cargo.lock index 31115a07af4..6da57c81e3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,8 +30,8 @@ version = "0.1.0" dependencies = [ "arch_gen 0.1.0", "device_tree 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvm-bindings 0.2.0 (git+https://github.com/firecracker-microvm/kvm-bindings?tag=v0.2.0-2)", - "kvm-ioctls 0.5.0 (git+https://github.com/firecracker-microvm/kvm-ioctls?tag=v0.5.0-2)", + "kvm-bindings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvm-ioctls 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", "utils 0.1.0", "vm-memory 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -69,8 +69,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "cpuid" version = "0.1.0" dependencies = [ - "kvm-bindings 0.2.0 (git+https://github.com/firecracker-microvm/kvm-bindings?tag=v0.2.0-2)", - "kvm-ioctls 0.5.0 (git+https://github.com/firecracker-microvm/kvm-ioctls?tag=v0.5.0-2)", + "kvm-bindings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvm-ioctls 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "utils 0.1.0", ] @@ -187,9 +187,17 @@ dependencies = [ [[package]] name = "kvm-bindings" -version = "0.2.0" -source = "git+https://github.com/firecracker-microvm/kvm-bindings?tag=v0.2.0-2#035141b47659a1d3532101c86bd196de3f1454e9" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "vmm-sys-util 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvm-bindings-versionize" +version = "0.3.0" dependencies = [ + "kvm-bindings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "versionize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "versionize_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "vmm-sys-util 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -198,9 +206,9 @@ dependencies = [ [[package]] name = "kvm-ioctls" version = "0.5.0" -source = "git+https://github.com/firecracker-microvm/kvm-ioctls?tag=v0.5.0-2#870c7cc848a9a01c705e8a7a7b794a550fb78580" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kvm-bindings 0.2.0 (git+https://github.com/firecracker-microvm/kvm-bindings?tag=v0.2.0-2)", + "kvm-bindings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", "vmm-sys-util 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -469,8 +477,9 @@ dependencies = [ "cpuid 0.1.0", "devices 0.1.0", "kernel 0.1.0", - "kvm-bindings 0.2.0 (git+https://github.com/firecracker-microvm/kvm-bindings?tag=v0.2.0-2)", - "kvm-ioctls 0.5.0 (git+https://github.com/firecracker-microvm/kvm-ioctls?tag=v0.5.0-2)", + "kvm-bindings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvm-bindings-versionize 0.3.0", + "kvm-ioctls 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", "logger 0.1.0", @@ -539,8 +548,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvm-bindings 0.2.0 (git+https://github.com/firecracker-microvm/kvm-bindings?tag=v0.2.0-2)" = "" -"checksum kvm-ioctls 0.5.0 (git+https://github.com/firecracker-microvm/kvm-ioctls?tag=v0.5.0-2)" = "" +"checksum kvm-bindings 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1c07667561c3d12d77342baf28ca5d0f8c3ea2160778485640ec84a4571da2" +"checksum kvm-ioctls 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d99720f5df3814a7188f095ad6774775b7635dfdd62b7c091ce7e00a51c3c109" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" diff --git a/src/arch/Cargo.toml b/src/arch/Cargo.toml index f95438ee4d1..060312202bf 100644 --- a/src/arch/Cargo.toml +++ b/src/arch/Cargo.toml @@ -5,8 +5,8 @@ authors = ["The Chromium OS Authors"] edition = "2018" [dependencies] -kvm-bindings = { git = "https://github.com/firecracker-microvm/kvm-bindings", tag = "v0.2.0-2", features = ["fam-wrappers"] } -kvm-ioctls = { git = "https://github.com/firecracker-microvm/kvm-ioctls", tag = "v0.5.0-2" } +kvm-bindings = ">=0.3.0" +kvm-ioctls = ">=0.5.0" libc = ">=0.2.39" vm-memory = { version = ">=0.2.2", features = ["backend-mmap"] } diff --git a/src/cpuid/Cargo.toml b/src/cpuid/Cargo.toml index 05a082dd11c..b3a4a66fa07 100644 --- a/src/cpuid/Cargo.toml +++ b/src/cpuid/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Amazon Firecracker team "] edition = "2018" [dependencies] -kvm-bindings = { git = "https://github.com/firecracker-microvm/kvm-bindings", tag = "v0.2.0-2", features = ["fam-wrappers"] } -kvm-ioctls = { git = "https://github.com/firecracker-microvm/kvm-ioctls", tag = "v0.5.0-2" } +kvm-bindings = ">=0.3.0" +kvm-ioctls = ">=0.5.0" utils = { path = "../utils"} diff --git a/src/kvm_bindings_versionize/.cargo/config b/src/kvm_bindings_versionize/.cargo/config new file mode 100644 index 00000000000..bf8523e02f4 --- /dev/null +++ b/src/kvm_bindings_versionize/.cargo/config @@ -0,0 +1,5 @@ +# This workaround is needed because the linker is unable to find __addtf3, +# __multf3 and __subtf3. +# Related issue: https://github.com/rust-lang/compiler-builtins/issues/201 +[target.aarch64-unknown-linux-musl] +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc"] diff --git a/src/kvm_bindings_versionize/Cargo.toml b/src/kvm_bindings_versionize/Cargo.toml new file mode 100644 index 00000000000..cc4475a134d --- /dev/null +++ b/src/kvm_bindings_versionize/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "kvm-bindings-versionize" +version = "0.3.0" +authors = ["Amazon firecracker team "] +description = "Rust FFI bindings to KVM generated using bindgen." +repository = "https://github.com/rust-vmm/kvm-bindings" +readme = "README.md" +keywords = ["kvm"] +license = "Apache-2.0" + +[dependencies] +kvm-bindings = ">=0.3.0" +vmm-sys-util = { version = ">=0.2.0" } + +versionize = { version = ">=0.1.1" } +versionize_derive = { version = ">=0.1.1" } diff --git a/src/kvm_bindings_versionize/src/lib.rs b/src/kvm_bindings_versionize/src/lib.rs new file mode 100644 index 00000000000..56dac5d1391 --- /dev/null +++ b/src/kvm_bindings_versionize/src/lib.rs @@ -0,0 +1,84 @@ +// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +#[macro_use] +extern crate vmm_sys_util; + +extern crate kvm_bindings; +extern crate versionize; +extern crate versionize_derive; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod x86; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub use self::x86::*; + +use std::mem::{align_of, size_of}; +use std::ptr; + +use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; + +fn convert_bitwise(t: &T) -> U { + assert_eq!(align_of::(), align_of::()); + assert_eq!(size_of::(), size_of::()); + // Safe because `src` is aligned, the two types have the same size and alignment, + // and they are both plain old data structs. + unsafe { ptr::read(t as *const T as *const U) } +} + +// This requires `upstream` to be a valid module path/alias in the scope that's invoking the +// macro (i.e. `use kvm_bindings as upstream;`). It also requires the `convert_bitwise` +// function above to be in scope. +#[macro_export] +macro_rules! impl_conversions { + ($T:ident) => { + impl From for $T { + fn from(other: upstream::$T) -> Self { + convert_bitwise(&other) + } + } + + impl From<$T> for upstream::$T { + fn from(other: $T) -> Self { + convert_bitwise(&other) + } + } + + impl From<&upstream::$T> for $T { + fn from(other: &upstream::$T) -> Self { + convert_bitwise(other) + } + } + + impl From<&$T> for upstream::$T { + fn from(other: &$T) -> Self { + convert_bitwise(other) + } + } + }; +} + +/// Helper function for FamStructWrapper conversion. Can/should be replaced by implementing +/// `From` for `FamStructWrapper` in `vmm-sys-util`. +pub fn convert_fam_struct_wrapper<'a, T, U>(src: &'a FamStructWrapper) -> FamStructWrapper +where + T: Default + FamStruct + 'static, + U: Default + FamStruct + From<&'a T> + 'static, + T::Entry: 'static, + U::Entry: From<&'a T::Entry> + 'static, +{ + // The `FamStructWrapper.len()` method is private for some reason. + let mut dst = FamStructWrapper::new(src.as_slice().len()); + *dst.as_mut_fam_struct() = src.as_fam_struct_ref().into(); + + for (index, entry) in src.as_slice().iter().enumerate() { + dst.as_mut_slice()[index] = entry.into(); + } + + dst +} diff --git a/src/kvm_bindings_versionize/src/x86/bindings/mod.rs b/src/kvm_bindings_versionize/src/x86/bindings/mod.rs new file mode 100644 index 00000000000..ec2c58fbf16 --- /dev/null +++ b/src/kvm_bindings_versionize/src/x86/bindings/mod.rs @@ -0,0 +1,463 @@ +// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +/* automatically generated by rust-bindgen */ + +#[cfg(test)] +mod tests; + +use versionize::{VersionMap, Versionize, VersionizeResult}; +use versionize_derive::Versionize; + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + storage: Storage, + align: [Align; 0], +} +// Implementing Versionize by hand due to some weird errors when trying to derive (most likely +// because versionize_derive does not support structs with generics at this point). +impl Versionize for __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]> + Versionize, +{ + fn serialize( + &self, + writer: &mut W, + version_map: &VersionMap, + app_version: u16, + ) -> VersionizeResult<()> { + Versionize::serialize(&self.storage, writer, version_map, app_version) + } + + fn deserialize( + reader: &mut R, + version_map: &VersionMap, + app_version: u16, + ) -> VersionizeResult { + let storage = Versionize::deserialize(reader, version_map, app_version)?; + + Ok(__BindgenBitfieldUnit { storage, align: [] }) + } + + fn version() -> u16 { + 1 + } +} + +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub unsafe fn as_ptr(&self) -> *const T { + ::std::mem::transmute(self) + } + #[inline] + 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 ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} + +impl ::std::clone::Clone for __IncompleteArrayField { + #[inline] + fn clone(&self) -> Self { + Self::new() + } +} + +impl Versionize for __IncompleteArrayField { + #[inline] + fn serialize( + &self, + _writer: &mut W, + _version_map: &VersionMap, + _app_version: u16, + ) -> VersionizeResult<()> { + Ok(()) + } + + #[inline] + fn deserialize( + _reader: &mut R, + _version_map: &VersionMap, + _app_version: u16, + ) -> VersionizeResult { + Ok(Self::new()) + } + + // Not used. + fn version() -> u16 { + 1 + } +} + +pub type __s8 = ::std::os::raw::c_schar; +pub type __u8 = ::std::os::raw::c_uchar; +pub type __s16 = ::std::os::raw::c_short; +pub type __u16 = ::std::os::raw::c_ushort; +pub type __s32 = ::std::os::raw::c_int; +pub type __u32 = ::std::os::raw::c_uint; +pub type __s64 = ::std::os::raw::c_longlong; +pub type __u64 = ::std::os::raw::c_ulonglong; + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_pic_state { + pub last_irr: __u8, + pub irr: __u8, + pub imr: __u8, + pub isr: __u8, + pub priority_add: __u8, + pub irq_base: __u8, + pub read_reg_select: __u8, + pub poll: __u8, + pub special_mask: __u8, + pub init_state: __u8, + pub auto_eoi: __u8, + pub rotate_on_auto_eoi: __u8, + pub special_fully_nested_mode: __u8, + pub init4: __u8, + pub elcr: __u8, + pub elcr_mask: __u8, +} + +#[repr(C)] +#[derive(Copy, Clone, Versionize)] +pub struct kvm_ioapic_state { + pub base_address: __u64, + pub ioregsel: __u32, + pub id: __u32, + pub irr: __u32, + pub pad: __u32, + pub redirtbl: [kvm_ioapic_state__bindgen_ty_1; 24usize], +} + +#[repr(C)] +#[derive(Copy, Clone, Versionize)] +pub union kvm_ioapic_state__bindgen_ty_1 { + pub bits: __u64, + pub fields: kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1, + _bindgen_union_align: u64, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1 { + pub vector: __u8, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>, + pub reserved: [__u8; 4usize], + pub dest_id: __u8, +} + +impl Default for kvm_ioapic_state__bindgen_ty_1 { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} + +impl Default for kvm_ioapic_state { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_regs { + pub rax: __u64, + pub rbx: __u64, + pub rcx: __u64, + pub rdx: __u64, + pub rsi: __u64, + pub rdi: __u64, + pub rsp: __u64, + pub rbp: __u64, + pub r8: __u64, + pub r9: __u64, + pub r10: __u64, + pub r11: __u64, + pub r12: __u64, + pub r13: __u64, + pub r14: __u64, + pub r15: __u64, + pub rip: __u64, + pub rflags: __u64, +} + +#[repr(C)] +#[derive(Copy, Clone, Versionize)] +pub struct kvm_lapic_state { + pub regs: [::std::os::raw::c_char; 1024usize], +} + +impl Default for kvm_lapic_state { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_segment { + pub base: __u64, + pub limit: __u32, + pub selector: __u16, + pub type_: __u8, + pub present: __u8, + pub dpl: __u8, + pub db: __u8, + pub s: __u8, + pub l: __u8, + pub g: __u8, + pub avl: __u8, + pub unusable: __u8, + pub padding: __u8, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_dtable { + pub base: __u64, + pub limit: __u16, + pub padding: [__u16; 3usize], +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_sregs { + pub cs: kvm_segment, + pub ds: kvm_segment, + pub es: kvm_segment, + pub fs: kvm_segment, + pub gs: kvm_segment, + pub ss: kvm_segment, + pub tr: kvm_segment, + pub ldt: kvm_segment, + pub gdt: kvm_dtable, + pub idt: kvm_dtable, + pub cr0: __u64, + pub cr2: __u64, + pub cr3: __u64, + pub cr4: __u64, + pub cr8: __u64, + pub efer: __u64, + pub apic_base: __u64, + pub interrupt_bitmap: [__u64; 4usize], +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_msr_entry { + pub index: __u32, + pub reserved: __u32, + pub data: __u64, +} + +#[repr(C)] +#[derive(Debug, Default, Versionize)] +pub struct kvm_msrs { + pub nmsrs: __u32, + pub pad: __u32, + pub entries: __IncompleteArrayField, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_cpuid_entry2 { + pub function: __u32, + pub index: __u32, + pub flags: __u32, + pub eax: __u32, + pub ebx: __u32, + pub ecx: __u32, + pub edx: __u32, + pub padding: [__u32; 3usize], +} + +#[repr(C)] +#[derive(Debug, Default, Versionize)] +pub struct kvm_cpuid2 { + pub nent: __u32, + pub padding: __u32, + pub entries: __IncompleteArrayField, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_pit_channel_state { + pub count: __u32, + pub latched_count: __u16, + pub count_latched: __u8, + pub status_latched: __u8, + pub status: __u8, + pub read_state: __u8, + pub write_state: __u8, + pub write_latch: __u8, + pub rw_mode: __u8, + pub mode: __u8, + pub bcd: __u8, + pub gate: __u8, + pub count_load_time: __s64, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_pit_state2 { + pub channels: [kvm_pit_channel_state; 3usize], + pub flags: __u32, + pub reserved: [__u32; 9usize], +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_vcpu_events { + pub exception: kvm_vcpu_events__bindgen_ty_1, + pub interrupt: kvm_vcpu_events__bindgen_ty_2, + pub nmi: kvm_vcpu_events__bindgen_ty_3, + pub sipi_vector: __u32, + pub flags: __u32, + pub smi: kvm_vcpu_events__bindgen_ty_4, + pub reserved: [__u8; 27usize], + pub exception_has_payload: __u8, + pub exception_payload: __u64, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_vcpu_events__bindgen_ty_1 { + pub injected: __u8, + pub nr: __u8, + pub has_error_code: __u8, + pub pending: __u8, + pub error_code: __u32, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_vcpu_events__bindgen_ty_2 { + pub injected: __u8, + pub nr: __u8, + pub soft: __u8, + pub shadow: __u8, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_vcpu_events__bindgen_ty_3 { + pub injected: __u8, + pub pending: __u8, + pub masked: __u8, + pub pad: __u8, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_vcpu_events__bindgen_ty_4 { + pub smm: __u8, + pub pending: __u8, + pub smm_inside_nmi: __u8, + pub latched_init: __u8, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_debugregs { + pub db: [__u64; 4usize], + pub dr6: __u64, + pub dr7: __u64, + pub flags: __u64, + pub reserved: [__u64; 9usize], +} + +#[repr(C)] +#[derive(Copy, Clone, Versionize)] +pub struct kvm_xsave { + pub region: [__u32; 1024usize], +} + +impl Default for kvm_xsave { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_xcr { + pub xcr: __u32, + pub reserved: __u32, + pub value: __u64, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_xcrs { + pub nr_xcrs: __u32, + pub flags: __u32, + pub xcrs: [kvm_xcr; 16usize], + pub padding: [__u64; 16usize], +} + +#[repr(C)] +#[derive(Copy, Clone, Versionize)] +pub struct kvm_irqchip { + pub chip_id: __u32, + pub pad: __u32, + pub chip: kvm_irqchip__bindgen_ty_1, +} + +#[repr(C)] +#[derive(Copy, Clone, Versionize)] +pub union kvm_irqchip__bindgen_ty_1 { + pub dummy: [::std::os::raw::c_char; 512usize], + pub pic: kvm_pic_state, + pub ioapic: kvm_ioapic_state, + _bindgen_union_align: [u64; 64usize], +} + +impl Default for kvm_irqchip__bindgen_ty_1 { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} + +impl Default for kvm_irqchip { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_mp_state { + pub mp_state: __u32, +} + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Versionize)] +pub struct kvm_clock_data { + pub clock: __u64, + pub flags: __u32, + pub pad: [__u32; 9usize], +} diff --git a/src/kvm_bindings_versionize/src/x86/bindings/tests.rs b/src/kvm_bindings_versionize/src/x86/bindings/tests.rs new file mode 100644 index 00000000000..05ed1a6ccbf --- /dev/null +++ b/src/kvm_bindings_versionize/src/x86/bindings/tests.rs @@ -0,0 +1,2096 @@ +//! Import layout tests from upstream to ensure our struct definitions match. + +use super::*; + +#[test] +fn bindgen_test_layout_kvm_pic_state() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(kvm_pic_state)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(kvm_pic_state)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).last_irr as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(last_irr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).irr as *const _ as usize }, + 1usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(irr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).imr as *const _ as usize }, + 2usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(imr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).isr as *const _ as usize }, + 3usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(isr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).priority_add as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(priority_add) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).irq_base as *const _ as usize }, + 5usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(irq_base) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).read_reg_select as *const _ as usize }, + 6usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(read_reg_select) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).poll as *const _ as usize }, + 7usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(poll) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).special_mask as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(special_mask) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).init_state as *const _ as usize }, + 9usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(init_state) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).auto_eoi as *const _ as usize }, + 10usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(auto_eoi) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).rotate_on_auto_eoi as *const _ as usize + }, + 11usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(rotate_on_auto_eoi) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).special_fully_nested_mode as *const _ as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(special_fully_nested_mode) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).init4 as *const _ as usize }, + 13usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(init4) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).elcr as *const _ as usize }, + 14usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(elcr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).elcr_mask as *const _ as usize }, + 15usize, + concat!( + "Offset of field: ", + stringify!(kvm_pic_state), + "::", + stringify!(elcr_mask) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!( + "Size of: ", + stringify!(kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1) + ) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!( + "Alignment of ", + stringify!(kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).vector + as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1), + "::", + stringify!(vector) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).reserved + as *const _ as usize + }, + 3usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1), + "::", + stringify!(reserved) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).dest_id + as *const _ as usize + }, + 7usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state__bindgen_ty_1__bindgen_ty_1), + "::", + stringify!(dest_id) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_ioapic_state__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(kvm_ioapic_state__bindgen_ty_1)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_ioapic_state__bindgen_ty_1)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).bits as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state__bindgen_ty_1), + "::", + stringify!(bits) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).fields as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state__bindgen_ty_1), + "::", + stringify!(fields) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_ioapic_state() { + assert_eq!( + ::std::mem::size_of::(), + 216usize, + concat!("Size of: ", stringify!(kvm_ioapic_state)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_ioapic_state)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).base_address as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state), + "::", + stringify!(base_address) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ioregsel as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state), + "::", + stringify!(ioregsel) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state), + "::", + stringify!(id) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).irr as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state), + "::", + stringify!(irr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).pad as *const _ as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state), + "::", + stringify!(pad) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).redirtbl as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(kvm_ioapic_state), + "::", + stringify!(redirtbl) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_regs() { + assert_eq!( + ::std::mem::size_of::(), + 144usize, + concat!("Size of: ", stringify!(kvm_regs)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_regs)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rax as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rax) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rbx as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rbx) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rcx as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rcx) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rdx as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rdx) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rsi as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rsi) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rdi as *const _ as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rdi) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rsp as *const _ as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rsp) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rbp as *const _ as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rbp) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r8 as *const _ as usize }, + 64usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r8) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r9 as *const _ as usize }, + 72usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r9) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r10 as *const _ as usize }, + 80usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r10) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r11 as *const _ as usize }, + 88usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r11) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r12 as *const _ as usize }, + 96usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r12) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r13 as *const _ as usize }, + 104usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r13) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r14 as *const _ as usize }, + 112usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r14) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).r15 as *const _ as usize }, + 120usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(r15) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rip as *const _ as usize }, + 128usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rip) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rflags as *const _ as usize }, + 136usize, + concat!( + "Offset of field: ", + stringify!(kvm_regs), + "::", + stringify!(rflags) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_lapic_state() { + assert_eq!( + ::std::mem::size_of::(), + 1024usize, + concat!("Size of: ", stringify!(kvm_lapic_state)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(kvm_lapic_state)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).regs as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_lapic_state), + "::", + stringify!(regs) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_segment() { + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(kvm_segment)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_segment)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).base as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(base) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).limit as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(limit) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).selector as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(selector) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, + 14usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(type_) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).present as *const _ as usize }, + 15usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(present) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).dpl as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(dpl) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).db as *const _ as usize }, + 17usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(db) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).s as *const _ as usize }, + 18usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(s) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).l as *const _ as usize }, + 19usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(l) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).g as *const _ as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(g) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).avl as *const _ as usize }, + 21usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(avl) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).unusable as *const _ as usize }, + 22usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(unusable) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).padding as *const _ as usize }, + 23usize, + concat!( + "Offset of field: ", + stringify!(kvm_segment), + "::", + stringify!(padding) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_dtable() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(kvm_dtable)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_dtable)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).base as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_dtable), + "::", + stringify!(base) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).limit as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_dtable), + "::", + stringify!(limit) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).padding as *const _ as usize }, + 10usize, + concat!( + "Offset of field: ", + stringify!(kvm_dtable), + "::", + stringify!(padding) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_sregs() { + assert_eq!( + ::std::mem::size_of::(), + 312usize, + concat!("Size of: ", stringify!(kvm_sregs)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_sregs)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).cs as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(cs) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ds as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(ds) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).es as *const _ as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(es) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).fs as *const _ as usize }, + 72usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(fs) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).gs as *const _ as usize }, + 96usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(gs) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ss as *const _ as usize }, + 120usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(ss) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).tr as *const _ as usize }, + 144usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(tr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ldt as *const _ as usize }, + 168usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(ldt) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).gdt as *const _ as usize }, + 192usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(gdt) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).idt as *const _ as usize }, + 208usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(idt) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).cr0 as *const _ as usize }, + 224usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(cr0) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).cr2 as *const _ as usize }, + 232usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(cr2) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).cr3 as *const _ as usize }, + 240usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(cr3) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).cr4 as *const _ as usize }, + 248usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(cr4) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).cr8 as *const _ as usize }, + 256usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(cr8) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).efer as *const _ as usize }, + 264usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(efer) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).apic_base as *const _ as usize }, + 272usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(apic_base) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).interrupt_bitmap as *const _ as usize }, + 280usize, + concat!( + "Offset of field: ", + stringify!(kvm_sregs), + "::", + stringify!(interrupt_bitmap) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_msr_entry() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(kvm_msr_entry)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_msr_entry)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).index as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_msr_entry), + "::", + stringify!(index) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_msr_entry), + "::", + stringify!(reserved) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_msr_entry), + "::", + stringify!(data) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_msrs() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(kvm_msrs)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_msrs)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).nmsrs as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_msrs), + "::", + stringify!(nmsrs) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).pad as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_msrs), + "::", + stringify!(pad) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).entries as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_msrs), + "::", + stringify!(entries) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_cpuid_entry2() { + assert_eq!( + ::std::mem::size_of::(), + 40usize, + concat!("Size of: ", stringify!(kvm_cpuid_entry2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(kvm_cpuid_entry2)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).function as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(function) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).index as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(index) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).eax as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(eax) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ebx as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(ebx) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ecx as *const _ as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(ecx) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).edx as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(edx) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).padding as *const _ as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid_entry2), + "::", + stringify!(padding) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_cpuid2() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(kvm_cpuid2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(kvm_cpuid2)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).nent as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid2), + "::", + stringify!(nent) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).padding as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid2), + "::", + stringify!(padding) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).entries as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_cpuid2), + "::", + stringify!(entries) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_pit_channel_state() { + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(kvm_pit_channel_state)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_pit_channel_state)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).count as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(count) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).latched_count as *const _ as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(latched_count) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).count_latched as *const _ as usize + }, + 6usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(count_latched) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).status_latched as *const _ as usize + }, + 7usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(status_latched) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).status as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(status) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).read_state as *const _ as usize + }, + 9usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(read_state) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).write_state as *const _ as usize + }, + 10usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(write_state) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).write_latch as *const _ as usize + }, + 11usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(write_latch) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).rw_mode as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(rw_mode) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).mode as *const _ as usize }, + 13usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(mode) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).bcd as *const _ as usize }, + 14usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(bcd) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).gate as *const _ as usize }, + 15usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(gate) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).count_load_time as *const _ as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_channel_state), + "::", + stringify!(count_load_time) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_pit_state2() { + assert_eq!( + ::std::mem::size_of::(), + 112usize, + concat!("Size of: ", stringify!(kvm_pit_state2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_pit_state2)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).channels as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_state2), + "::", + stringify!(channels) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 72usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_state2), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, + 76usize, + concat!( + "Offset of field: ", + stringify!(kvm_pit_state2), + "::", + stringify!(reserved) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_vcpu_events__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(kvm_vcpu_events__bindgen_ty_1)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(kvm_vcpu_events__bindgen_ty_1)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).injected as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_1), + "::", + stringify!(injected) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).nr as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_1), + "::", + stringify!(nr) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).has_error_code as *const _ + as usize + }, + 2usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_1), + "::", + stringify!(has_error_code) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).pending as *const _ as usize + }, + 3usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_1), + "::", + stringify!(pending) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).error_code as *const _ + as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_1), + "::", + stringify!(error_code) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_vcpu_events__bindgen_ty_2() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(kvm_vcpu_events__bindgen_ty_2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(kvm_vcpu_events__bindgen_ty_2)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).injected as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_2), + "::", + stringify!(injected) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).nr as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_2), + "::", + stringify!(nr) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).soft as *const _ as usize + }, + 2usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_2), + "::", + stringify!(soft) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).shadow as *const _ as usize + }, + 3usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_2), + "::", + stringify!(shadow) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_vcpu_events__bindgen_ty_3() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(kvm_vcpu_events__bindgen_ty_3)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(kvm_vcpu_events__bindgen_ty_3)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).injected as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_3), + "::", + stringify!(injected) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).pending as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_3), + "::", + stringify!(pending) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).masked as *const _ as usize + }, + 2usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_3), + "::", + stringify!(masked) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).pad as *const _ as usize + }, + 3usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_3), + "::", + stringify!(pad) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_vcpu_events__bindgen_ty_4() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(kvm_vcpu_events__bindgen_ty_4)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(kvm_vcpu_events__bindgen_ty_4)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).smm as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_4), + "::", + stringify!(smm) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).pending as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_4), + "::", + stringify!(pending) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).smm_inside_nmi as *const _ + as usize + }, + 2usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_4), + "::", + stringify!(smm_inside_nmi) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).latched_init as *const _ + as usize + }, + 3usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events__bindgen_ty_4), + "::", + stringify!(latched_init) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_vcpu_events() { + assert_eq!( + ::std::mem::size_of::(), + 64usize, + concat!("Size of: ", stringify!(kvm_vcpu_events)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_vcpu_events)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).exception as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(exception) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).interrupt as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(interrupt) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).nmi as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(nmi) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).sipi_vector as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(sipi_vector) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).smi as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(smi) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(reserved) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).exception_has_payload as *const _ as usize + }, + 55usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(exception_has_payload) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).exception_payload as *const _ as usize + }, + 56usize, + concat!( + "Offset of field: ", + stringify!(kvm_vcpu_events), + "::", + stringify!(exception_payload) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_debugregs() { + assert_eq!( + ::std::mem::size_of::(), + 128usize, + concat!("Size of: ", stringify!(kvm_debugregs)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_debugregs)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).db as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_debugregs), + "::", + stringify!(db) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).dr6 as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(kvm_debugregs), + "::", + stringify!(dr6) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).dr7 as *const _ as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(kvm_debugregs), + "::", + stringify!(dr7) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(kvm_debugregs), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(kvm_debugregs), + "::", + stringify!(reserved) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_xsave() { + assert_eq!( + ::std::mem::size_of::(), + 4096usize, + concat!("Size of: ", stringify!(kvm_xsave)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(kvm_xsave)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).region as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_xsave), + "::", + stringify!(region) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_xcr() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(kvm_xcr)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_xcr)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).xcr as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcr), + "::", + stringify!(xcr) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcr), + "::", + stringify!(reserved) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).value as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcr), + "::", + stringify!(value) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_xcrs() { + assert_eq!( + ::std::mem::size_of::(), + 392usize, + concat!("Size of: ", stringify!(kvm_xcrs)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_xcrs)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).nr_xcrs as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcrs), + "::", + stringify!(nr_xcrs) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcrs), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).xcrs as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcrs), + "::", + stringify!(xcrs) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).padding as *const _ as usize }, + 264usize, + concat!( + "Offset of field: ", + stringify!(kvm_xcrs), + "::", + stringify!(padding) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_irqchip__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 512usize, + concat!("Size of: ", stringify!(kvm_irqchip__bindgen_ty_1)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_irqchip__bindgen_ty_1)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).dummy as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_irqchip__bindgen_ty_1), + "::", + stringify!(dummy) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).pic as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_irqchip__bindgen_ty_1), + "::", + stringify!(pic) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).ioapic as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_irqchip__bindgen_ty_1), + "::", + stringify!(ioapic) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_irqchip() { + assert_eq!( + ::std::mem::size_of::(), + 520usize, + concat!("Size of: ", stringify!(kvm_irqchip)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_irqchip)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).chip_id as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_irqchip), + "::", + stringify!(chip_id) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).pad as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(kvm_irqchip), + "::", + stringify!(pad) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).chip as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_irqchip), + "::", + stringify!(chip) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_mp_state() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(kvm_mp_state)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(kvm_mp_state)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).mp_state as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_mp_state), + "::", + stringify!(mp_state) + ) + ); +} + +#[test] +fn bindgen_test_layout_kvm_clock_data() { + assert_eq!( + ::std::mem::size_of::(), + 48usize, + concat!("Size of: ", stringify!(kvm_clock_data)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(kvm_clock_data)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).clock as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(kvm_clock_data), + "::", + stringify!(clock) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(kvm_clock_data), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).pad as *const _ as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(kvm_clock_data), + "::", + stringify!(pad) + ) + ); +} diff --git a/src/kvm_bindings_versionize/src/x86/convert.rs b/src/kvm_bindings_versionize/src/x86/convert.rs new file mode 100644 index 00000000000..a71b70221fa --- /dev/null +++ b/src/kvm_bindings_versionize/src/x86/convert.rs @@ -0,0 +1,102 @@ +use kvm_bindings as upstream; + +use crate::{convert_bitwise, impl_conversions}; + +use super::*; + +impl_conversions!(kvm_vcpu_events); +impl_conversions!(kvm_lapic_state); +impl_conversions!(kvm_debugregs); +impl_conversions!(kvm_xcrs); +impl_conversions!(kvm_xsave); +impl_conversions!(kvm_sregs); +impl_conversions!(kvm_regs); +impl_conversions!(kvm_mp_state); +impl_conversions!(kvm_cpuid2); +impl_conversions!(kvm_cpuid_entry2); +impl_conversions!(kvm_irqchip); +impl_conversions!(kvm_clock_data); +impl_conversions!(kvm_pit_state2); +impl_conversions!(kvm_msrs); +impl_conversions!(kvm_msr_entry); + +#[cfg(test)] +mod tests { + use std::mem::size_of; + use std::slice; + + use super::*; + + fn as_byte_slice(t: &T) -> &[u8] { + let len = size_of::(); + // This is actually safe because we're dealing with plain old data objects. + unsafe { slice::from_raw_parts(t as *const T as *const u8, len) } + } + + fn as_mut_byte_slice(t: &mut T) -> &mut [u8] { + let len = size_of::(); + // This is actually safe because we're dealing with plain old data objects. + unsafe { slice::from_raw_parts_mut(t as *mut T as *mut u8, len) } + } + + // This should produce the same result for repeated invocations with the same type parameter + // for `check_conversion` to work properly. + fn init_with_bytes() -> T { + let mut obj = T::default(); + let slice = as_mut_byte_slice(&mut obj); + + // Initialize the object with bytes to improve chances of detecting conversion mismatches. + // The heterogeneity of the sequence can be improved :-s + for (i, byte) in slice.iter_mut().enumerate() { + *byte = i as u8; + } + + obj + } + + // This is a very stringent test, which checks for bitwise equality. Other variations are + // possible if we ever want to introduce differences between proxy structs and their + // upstream correspondents. + fn check_conversion() + where + T: Default + From, + U: Default + From, + { + { + let t = init_with_bytes::(); + let u = U::from(init_with_bytes::()); + assert_eq!(as_byte_slice(&t), as_byte_slice(&u)); + } + + { + let u = init_with_bytes::(); + let t = T::from(init_with_bytes::()); + assert_eq!(as_byte_slice(&t), as_byte_slice(&u)); + } + } + + macro_rules! test_conversion { + ($t:ident) => { + check_conversion::<$t, upstream::$t>(); + }; + } + + #[test] + fn test_conversions() { + test_conversion!(kvm_vcpu_events); + test_conversion!(kvm_lapic_state); + test_conversion!(kvm_debugregs); + test_conversion!(kvm_xcrs); + test_conversion!(kvm_xsave); + test_conversion!(kvm_sregs); + test_conversion!(kvm_regs); + test_conversion!(kvm_mp_state); + test_conversion!(kvm_cpuid2); + test_conversion!(kvm_cpuid_entry2); + test_conversion!(kvm_irqchip); + test_conversion!(kvm_clock_data); + test_conversion!(kvm_pit_state2); + test_conversion!(kvm_msrs); + test_conversion!(kvm_msr_entry); + } +} diff --git a/src/kvm_bindings_versionize/src/x86/fam_wrappers.rs b/src/kvm_bindings_versionize/src/x86/fam_wrappers.rs new file mode 100644 index 00000000000..10871e5df86 --- /dev/null +++ b/src/kvm_bindings_versionize/src/x86/fam_wrappers.rs @@ -0,0 +1,52 @@ +// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; + +use x86::bindings::*; + +/// Maximum number of CPUID entries that can be returned by a call to KVM ioctls. +/// +/// See arch/x86/include/asm/kvm_host.h +pub const KVM_MAX_CPUID_ENTRIES: usize = 80; + +/// Maximum number of MSRs KVM supports (See arch/x86/kvm/x86.c). +pub const KVM_MAX_MSR_ENTRIES: usize = 256; + +// Implement the FamStruct trait for kvm_cpuid2. +generate_fam_struct_impl!( + kvm_cpuid2, + kvm_cpuid_entry2, + entries, + u32, + nent, + KVM_MAX_CPUID_ENTRIES +); + +/// Wrapper over the `kvm_cpuid2` structure. +/// +/// The `kvm_cpuid2` structure contains a flexible array member. For details check the +/// [KVM API](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt) +/// documentation on `kvm_cpuid2`. To provide safe access to +/// the array elements, this type is implemented using +/// [FamStructWrapper](../vmm_sys_util/fam/struct.FamStructWrapper.html). +pub type CpuId = FamStructWrapper; + +// Implement the FamStruct trait for kvm_msrs. +generate_fam_struct_impl!( + kvm_msrs, + kvm_msr_entry, + entries, + u32, + nmsrs, + KVM_MAX_MSR_ENTRIES +); + +/// Wrapper over the `kvm_msrs` structure. +/// +/// The `kvm_msrs` structure contains a flexible array member. For details check the +/// [KVM API](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt) +/// documentation on `kvm_msrs`. To provide safe access to +/// the array elements, this type is implemented using +/// [FamStructWrapper](../vmm_sys_util/fam/struct.FamStructWrapper.html). +pub type Msrs = FamStructWrapper; diff --git a/src/kvm_bindings_versionize/src/x86/mod.rs b/src/kvm_bindings_versionize/src/x86/mod.rs new file mode 100644 index 00000000000..6ceb856a6af --- /dev/null +++ b/src/kvm_bindings_versionize/src/x86/mod.rs @@ -0,0 +1,11 @@ +// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#[allow(clippy::all)] +mod bindings; +mod convert; +mod fam_wrappers; + +pub use self::bindings::*; +pub use self::convert::*; +pub use self::fam_wrappers::*; diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 87f356a56fe..07781726314 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -5,6 +5,8 @@ authors = ["Amazon Firecracker team "] edition = "2018" [dependencies] +kvm-bindings = ">=0.3.0" +kvm-ioctls = ">=0.5.0" lazy_static = ">=1.4.0" libc = ">=0.2.39" serde = { version = ">=1.0.27", features = ["derive"] } @@ -17,8 +19,7 @@ vm-memory = { version = ">=0.2.2", features = ["backend-mmap"] } arch = { path = "../arch" } devices = { path = "../devices" } kernel = { path = "../kernel" } -kvm-bindings = { git = "https://github.com/firecracker-microvm/kvm-bindings", tag = "v0.2.0-2", features = ["fam-wrappers"] } -kvm-ioctls = { git = "https://github.com/firecracker-microvm/kvm-ioctls", tag = "v0.5.0-2" } +kvm-bindings-versionize = { path = "../kvm_bindings_versionize" } logger = { path = "../logger" } mmds = { path = "../mmds" } polly = { path = "../polly" } diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs index 79dbba6e7ab..44b32c95a0e 100644 --- a/src/vmm/src/vstate/vcpu/x86_64.rs +++ b/src/vmm/src/vstate/vcpu/x86_64.rs @@ -16,10 +16,8 @@ use crate::vstate::{ vm::Vm, }; use cpuid::{c3, filter_cpuid, t2, VmSpec}; -use kvm_bindings::{ - kvm_debugregs, kvm_lapic_state, kvm_mp_state, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, - kvm_xsave, CpuId, MsrList, Msrs, -}; +use kvm_bindings::{CpuId, MsrList, Msrs}; +use kvm_bindings_versionize::{self, convert_fam_struct_wrapper}; use kvm_ioctls::{VcpuExit, VcpuFd}; use logger::{error, Metric, METRICS}; use versionize::{VersionMap, Versionize, VersionizeResult}; @@ -274,20 +272,22 @@ impl KvmVcpu { .get_vcpu_events() .map_err(Error::VcpuGetVcpuEvents)?; + let cpuid = self + .fd + .get_cpuid2(kvm_bindings::KVM_MAX_CPUID_ENTRIES) + .map_err(Error::VcpuGetCpuid)?; + Ok(VcpuState { - cpuid: self - .fd - .get_cpuid2(kvm_bindings::KVM_MAX_CPUID_ENTRIES) - .map_err(Error::VcpuGetCpuid)?, - msrs, - debug_regs, - lapic, - mp_state, - regs, - sregs, - vcpu_events, - xcrs, - xsave, + cpuid: convert_fam_struct_wrapper(&cpuid), + msrs: convert_fam_struct_wrapper(&msrs), + debug_regs: debug_regs.into(), + lapic: lapic.into(), + mp_state: mp_state.into(), + regs: regs.into(), + sregs: sregs.into(), + vcpu_events: vcpu_events.into(), + xcrs: xcrs.into(), + xsave: xsave.into(), }) } @@ -315,29 +315,35 @@ impl KvmVcpu { * SET_LAPIC must come before SET_MSRS, because the TSC deadline MSR * only restores successfully, when the LAPIC is correctly configured. */ + let cpuid = convert_fam_struct_wrapper(&state.cpuid); + self.fd.set_cpuid2(&cpuid).map_err(Error::VcpuSetCpuid)?; self.fd - .set_cpuid2(&state.cpuid) - .map_err(Error::VcpuSetCpuid)?; - self.fd - .set_mp_state(state.mp_state) + .set_mp_state(state.mp_state.into()) .map_err(Error::VcpuSetMpState)?; - self.fd.set_regs(&state.regs).map_err(Error::VcpuSetRegs)?; self.fd - .set_sregs(&state.sregs) + .set_regs(&state.regs.into()) + .map_err(Error::VcpuSetRegs)?; + self.fd + .set_sregs(&state.sregs.into()) .map_err(Error::VcpuSetSregs)?; self.fd - .set_xsave(&state.xsave) + .set_xsave(&state.xsave.into()) .map_err(Error::VcpuSetXsave)?; - self.fd.set_xcrs(&state.xcrs).map_err(Error::VcpuSetXcrs)?; self.fd - .set_debug_regs(&state.debug_regs) + .set_xcrs(&state.xcrs.into()) + .map_err(Error::VcpuSetXcrs)?; + self.fd + .set_debug_regs(&state.debug_regs.into()) .map_err(Error::VcpuSetDebugRegs)?; self.fd - .set_lapic(&state.lapic) + .set_lapic(&state.lapic.into()) .map_err(Error::VcpuSetLapic)?; - self.fd.set_msrs(&state.msrs).map_err(Error::VcpuSetMsrs)?; + + let msrs = convert_fam_struct_wrapper(&state.msrs); + self.fd.set_msrs(&msrs).map_err(Error::VcpuSetMsrs)?; + self.fd - .set_vcpu_events(&state.vcpu_events) + .set_vcpu_events(&state.vcpu_events.into()) .map_err(Error::VcpuSetVcpuEvents)?; Ok(()) } @@ -378,16 +384,16 @@ impl KvmVcpu { #[derive(Clone, Versionize)] /// Structure holding VCPU kvm state. pub struct VcpuState { - cpuid: CpuId, - msrs: Msrs, - debug_regs: kvm_debugregs, - lapic: kvm_lapic_state, - mp_state: kvm_mp_state, - regs: kvm_regs, - sregs: kvm_sregs, - vcpu_events: kvm_vcpu_events, - xcrs: kvm_xcrs, - xsave: kvm_xsave, + cpuid: kvm_bindings_versionize::CpuId, + msrs: kvm_bindings_versionize::Msrs, + debug_regs: kvm_bindings_versionize::kvm_debugregs, + lapic: kvm_bindings_versionize::kvm_lapic_state, + mp_state: kvm_bindings_versionize::kvm_mp_state, + regs: kvm_bindings_versionize::kvm_regs, + sregs: kvm_bindings_versionize::kvm_sregs, + vcpu_events: kvm_bindings_versionize::kvm_vcpu_events, + xcrs: kvm_bindings_versionize::kvm_xcrs, + xsave: kvm_bindings_versionize::kvm_xsave, } #[cfg(test)] @@ -400,8 +406,8 @@ mod tests { impl Default for VcpuState { fn default() -> Self { VcpuState { - cpuid: CpuId::new(1), - msrs: Msrs::new(1), + cpuid: kvm_bindings_versionize::CpuId::new(1), + msrs: kvm_bindings_versionize::Msrs::new(1), debug_regs: Default::default(), lapic: Default::default(), mp_state: Default::default(), diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 8cec3eeb6ec..7976a3ac531 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -14,9 +14,8 @@ use std::{ use arch::aarch64::gic::GICDevice; #[cfg(target_arch = "x86_64")] use kvm_bindings::{ - kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, CpuId, MsrList, - KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, - KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY, + kvm_irqchip, kvm_pit_config, CpuId, MsrList, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, + KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY, }; use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES}; use kvm_ioctls::{Kvm, VmFd}; @@ -232,11 +231,11 @@ impl Vm { .map_err(Error::VmGetIrqChip)?; Ok(VmState { - pitstate, - clock, - pic_master, - pic_slave, - ioapic, + pitstate: pitstate.into(), + clock: clock.into(), + pic_master: pic_master.into(), + pic_slave: pic_slave.into(), + ioapic: ioapic.into(), }) } @@ -244,17 +243,19 @@ impl Vm { /// Restores the Kvm Vm state. pub fn restore_state(&self, state: &VmState) -> Result<()> { self.fd - .set_pit2(&state.pitstate) + .set_pit2(&state.pitstate.into()) .map_err(Error::VmSetPit2)?; - self.fd.set_clock(&state.clock).map_err(Error::VmSetClock)?; self.fd - .set_irqchip(&state.pic_master) + .set_clock(&state.clock.into()) + .map_err(Error::VmSetClock)?; + self.fd + .set_irqchip(&state.pic_master.into()) .map_err(Error::VmSetIrqChip)?; self.fd - .set_irqchip(&state.pic_slave) + .set_irqchip(&state.pic_slave.into()) .map_err(Error::VmSetIrqChip)?; self.fd - .set_irqchip(&state.ioapic) + .set_irqchip(&state.ioapic.into()) .map_err(Error::VmSetIrqChip)?; Ok(()) } @@ -291,11 +292,11 @@ impl Vm { #[derive(Versionize)] /// Structure holding VM kvm state. pub struct VmState { - pitstate: kvm_pit_state2, - clock: kvm_clock_data, - pic_master: kvm_irqchip, - pic_slave: kvm_irqchip, - ioapic: kvm_irqchip, + pitstate: kvm_bindings_versionize::kvm_pit_state2, + clock: kvm_bindings_versionize::kvm_clock_data, + pic_master: kvm_bindings_versionize::kvm_irqchip, + pic_slave: kvm_bindings_versionize::kvm_irqchip, + ioapic: kvm_bindings_versionize::kvm_irqchip, } #[cfg(test)]