diff --git a/kvm-bindings/Cargo.toml b/kvm-bindings/Cargo.toml index c5aabf79..44fdcca2 100644 --- a/kvm-bindings/Cargo.toml +++ b/kvm-bindings/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "kvm-bindings" version = "0.12.0" +edition = "2024" authors = ["Amazon firecracker team "] description = "Rust FFI bindings to KVM generated using bindgen." repository = "https://github.com/rust-vmm/kvm" diff --git a/kvm-bindings/src/arm64/bindings.rs b/kvm-bindings/src/arm64/bindings.rs index ce888550..e639e6af 100644 --- a/kvm-bindings/src/arm64/bindings.rs +++ b/kvm-bindings/src/arm64/bindings.rs @@ -22,11 +22,11 @@ impl __IncompleteArrayField { } #[inline] pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) + unsafe { ::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) + unsafe { ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } } impl ::std::fmt::Debug for __IncompleteArrayField { @@ -2067,7 +2067,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_8 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_8 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_8 {{ nr: {:?}, args: {:?}, ret: {:?}, __bindgen_anon_1: {:?} }}" , self . nr , self . args , self . ret , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_8 {{ nr: {:?}, args: {:?}, ret: {:?}, __bindgen_anon_1: {:?} }}", + self.nr, self.args, self.ret, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -2194,8 +2198,18 @@ const _: () = { ["Alignment of kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1"] [::std::mem::align_of::( ) - 1usize]; - ["Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_size"] [:: std :: mem :: offset_of ! (kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1 , insn_size) - 0usize] ; - ["Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_bytes"] [:: std :: mem :: offset_of ! (kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1 , insn_bytes) - 1usize] ; + [ + "Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_size", + ][::std::mem::offset_of!( + kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1, + insn_size + ) - 0usize]; + [ + "Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_bytes", + ][::std::mem::offset_of!( + kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1, + insn_bytes + ) - 1usize]; }; #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { @@ -2245,7 +2259,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_14 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_14 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_14 {{ suberror: {:?}, ndata: {:?}, flags: {:?}, __bindgen_anon_1: {:?} }}" , self . suberror , self . ndata , self . flags , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_14 {{ suberror: {:?}, ndata: {:?}, flags: {:?}, __bindgen_anon_1: {:?} }}", + self.suberror, self.ndata, self.flags, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -2390,7 +2408,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_19 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_19 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_19 {{ type: {:?}, ndata: {:?}, __bindgen_anon_1: {:?} }}" , self . type_ , self . ndata , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_19 {{ type: {:?}, ndata: {:?}, __bindgen_anon_1: {:?} }}", + self.type_, self.ndata, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -2705,7 +2727,23 @@ impl Default for kvm_run { } impl ::std::fmt::Debug for kvm_run { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run {{ request_interrupt_window: {:?}, immediate_exit: {:?}, padding1: {:?}, exit_reason: {:?}, ready_for_interrupt_injection: {:?}, if_flag: {:?}, flags: {:?}, cr8: {:?}, apic_base: {:?}, __bindgen_anon_1: {:?}, kvm_valid_regs: {:?}, kvm_dirty_regs: {:?}, s: {:?} }}" , self . request_interrupt_window , self . immediate_exit , self . padding1 , self . exit_reason , self . ready_for_interrupt_injection , self . if_flag , self . flags , self . cr8 , self . apic_base , self . __bindgen_anon_1 , self . kvm_valid_regs , self . kvm_dirty_regs , self . s) + write!( + f, + "kvm_run {{ request_interrupt_window: {:?}, immediate_exit: {:?}, padding1: {:?}, exit_reason: {:?}, ready_for_interrupt_injection: {:?}, if_flag: {:?}, flags: {:?}, cr8: {:?}, apic_base: {:?}, __bindgen_anon_1: {:?}, kvm_valid_regs: {:?}, kvm_dirty_regs: {:?}, s: {:?} }}", + self.request_interrupt_window, + self.immediate_exit, + self.padding1, + self.exit_reason, + self.ready_for_interrupt_injection, + self.if_flag, + self.flags, + self.cr8, + self.apic_base, + self.__bindgen_anon_1, + self.kvm_valid_regs, + self.kvm_dirty_regs, + self.s + ) } } #[repr(C)] @@ -2835,7 +2873,11 @@ impl Default for kvm_coalesced_mmio { } impl ::std::fmt::Debug for kvm_coalesced_mmio { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_coalesced_mmio {{ phys_addr: {:?}, len: {:?}, __bindgen_anon_1: {:?}, data: {:?} }}" , self . phys_addr , self . len , self . __bindgen_anon_1 , self . data) + write!( + f, + "kvm_coalesced_mmio {{ phys_addr: {:?}, len: {:?}, __bindgen_anon_1: {:?}, data: {:?} }}", + self.phys_addr, self.len, self.__bindgen_anon_1, self.data + ) } } #[repr(C)] @@ -3037,7 +3079,11 @@ impl Default for kvm_clear_dirty_log { } impl ::std::fmt::Debug for kvm_clear_dirty_log { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_clear_dirty_log {{ slot: {:?}, num_pages: {:?}, first_page: {:?}, __bindgen_anon_1: {:?} }}" , self . slot , self . num_pages , self . first_page , self . __bindgen_anon_1) + write!( + f, + "kvm_clear_dirty_log {{ slot: {:?}, num_pages: {:?}, first_page: {:?}, __bindgen_anon_1: {:?} }}", + self.slot, self.num_pages, self.first_page, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -3272,7 +3318,11 @@ impl Default for kvm_irq_routing_msi { } impl ::std::fmt::Debug for kvm_irq_routing_msi { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_irq_routing_msi {{ address_lo: {:?}, address_hi: {:?}, data: {:?}, __bindgen_anon_1: {:?} }}" , self . address_lo , self . address_hi , self . data , self . __bindgen_anon_1) + write!( + f, + "kvm_irq_routing_msi {{ address_lo: {:?}, address_hi: {:?}, data: {:?}, __bindgen_anon_1: {:?} }}", + self.address_lo, self.address_hi, self.data, self.__bindgen_anon_1 + ) } } #[repr(C)] diff --git a/kvm-bindings/src/arm64/fam_wrappers.rs b/kvm-bindings/src/arm64/fam_wrappers.rs index bbe64411..79a5d17a 100644 --- a/kvm-bindings/src/arm64/fam_wrappers.rs +++ b/kvm-bindings/src/arm64/fam_wrappers.rs @@ -3,7 +3,7 @@ use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; -use arm64::bindings::*; +use crate::arm64::bindings::*; // There is no constant in the kernel as far as the maximum number // of registers on arm, but KVM_GET_REG_LIST usually returns around 450. diff --git a/kvm-bindings/src/arm64/serialize.rs b/kvm-bindings/src/arm64/serialize.rs index a167607d..32f2af83 100644 --- a/kvm-bindings/src/arm64/serialize.rs +++ b/kvm-bindings/src/arm64/serialize.rs @@ -1,10 +1,10 @@ -use bindings::{ +use crate::bindings::{ kvm_irq_routing, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1, kvm_irq_routing_msi__bindgen_ty_1, kvm_mp_state, kvm_one_reg, kvm_regs, kvm_vcpu_init, user_fpsimd_state, user_pt_regs, }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use zerocopy::{transmute, IntoBytes}; +use zerocopy::{IntoBytes, transmute}; serde_impls! { user_pt_regs, @@ -43,8 +43,8 @@ unsafe impl IntoBytes for kvm_irq_routing_entry__bindgen_ty_1 { #[cfg(test)] mod tests { - use bindings::*; - use serde::{Deserialize, Serialize}; + use crate::bindings::*; + use crate::serde::{Deserialize, Serialize}; fn is_serde Deserialize<'de> + Default>() { let config = bincode::config::standard(); diff --git a/kvm-bindings/src/riscv64/bindings.rs b/kvm-bindings/src/riscv64/bindings.rs index 36a73728..d3085659 100644 --- a/kvm-bindings/src/riscv64/bindings.rs +++ b/kvm-bindings/src/riscv64/bindings.rs @@ -22,11 +22,11 @@ impl __IncompleteArrayField { } #[inline] pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) + unsafe { ::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) + unsafe { ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } } impl ::std::fmt::Debug for __IncompleteArrayField { @@ -1925,7 +1925,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_8 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_8 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_8 {{ nr: {:?}, args: {:?}, ret: {:?}, __bindgen_anon_1: {:?} }}" , self . nr , self . args , self . ret , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_8 {{ nr: {:?}, args: {:?}, ret: {:?}, __bindgen_anon_1: {:?} }}", + self.nr, self.args, self.ret, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -2052,8 +2056,18 @@ const _: () = { ["Alignment of kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1"] [::std::mem::align_of::( ) - 1usize]; - ["Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_size"] [:: std :: mem :: offset_of ! (kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1 , insn_size) - 0usize] ; - ["Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_bytes"] [:: std :: mem :: offset_of ! (kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1 , insn_bytes) - 1usize] ; + [ + "Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_size", + ][::std::mem::offset_of!( + kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1, + insn_size + ) - 0usize]; + [ + "Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_bytes", + ][::std::mem::offset_of!( + kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1, + insn_bytes + ) - 1usize]; }; #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { @@ -2103,7 +2117,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_14 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_14 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_14 {{ suberror: {:?}, ndata: {:?}, flags: {:?}, __bindgen_anon_1: {:?} }}" , self . suberror , self . ndata , self . flags , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_14 {{ suberror: {:?}, ndata: {:?}, flags: {:?}, __bindgen_anon_1: {:?} }}", + self.suberror, self.ndata, self.flags, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -2248,7 +2266,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_19 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_19 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_19 {{ type: {:?}, ndata: {:?}, __bindgen_anon_1: {:?} }}" , self . type_ , self . ndata , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_19 {{ type: {:?}, ndata: {:?}, __bindgen_anon_1: {:?} }}", + self.type_, self.ndata, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -2563,7 +2585,23 @@ impl Default for kvm_run { } impl ::std::fmt::Debug for kvm_run { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run {{ request_interrupt_window: {:?}, immediate_exit: {:?}, padding1: {:?}, exit_reason: {:?}, ready_for_interrupt_injection: {:?}, if_flag: {:?}, flags: {:?}, cr8: {:?}, apic_base: {:?}, __bindgen_anon_1: {:?}, kvm_valid_regs: {:?}, kvm_dirty_regs: {:?}, s: {:?} }}" , self . request_interrupt_window , self . immediate_exit , self . padding1 , self . exit_reason , self . ready_for_interrupt_injection , self . if_flag , self . flags , self . cr8 , self . apic_base , self . __bindgen_anon_1 , self . kvm_valid_regs , self . kvm_dirty_regs , self . s) + write!( + f, + "kvm_run {{ request_interrupt_window: {:?}, immediate_exit: {:?}, padding1: {:?}, exit_reason: {:?}, ready_for_interrupt_injection: {:?}, if_flag: {:?}, flags: {:?}, cr8: {:?}, apic_base: {:?}, __bindgen_anon_1: {:?}, kvm_valid_regs: {:?}, kvm_dirty_regs: {:?}, s: {:?} }}", + self.request_interrupt_window, + self.immediate_exit, + self.padding1, + self.exit_reason, + self.ready_for_interrupt_injection, + self.if_flag, + self.flags, + self.cr8, + self.apic_base, + self.__bindgen_anon_1, + self.kvm_valid_regs, + self.kvm_dirty_regs, + self.s + ) } } #[repr(C)] @@ -2693,7 +2731,11 @@ impl Default for kvm_coalesced_mmio { } impl ::std::fmt::Debug for kvm_coalesced_mmio { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_coalesced_mmio {{ phys_addr: {:?}, len: {:?}, __bindgen_anon_1: {:?}, data: {:?} }}" , self . phys_addr , self . len , self . __bindgen_anon_1 , self . data) + write!( + f, + "kvm_coalesced_mmio {{ phys_addr: {:?}, len: {:?}, __bindgen_anon_1: {:?}, data: {:?} }}", + self.phys_addr, self.len, self.__bindgen_anon_1, self.data + ) } } #[repr(C)] @@ -2895,7 +2937,11 @@ impl Default for kvm_clear_dirty_log { } impl ::std::fmt::Debug for kvm_clear_dirty_log { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_clear_dirty_log {{ slot: {:?}, num_pages: {:?}, first_page: {:?}, __bindgen_anon_1: {:?} }}" , self . slot , self . num_pages , self . first_page , self . __bindgen_anon_1) + write!( + f, + "kvm_clear_dirty_log {{ slot: {:?}, num_pages: {:?}, first_page: {:?}, __bindgen_anon_1: {:?} }}", + self.slot, self.num_pages, self.first_page, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -3130,7 +3176,11 @@ impl Default for kvm_irq_routing_msi { } impl ::std::fmt::Debug for kvm_irq_routing_msi { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_irq_routing_msi {{ address_lo: {:?}, address_hi: {:?}, data: {:?}, __bindgen_anon_1: {:?} }}" , self . address_lo , self . address_hi , self . data , self . __bindgen_anon_1) + write!( + f, + "kvm_irq_routing_msi {{ address_lo: {:?}, address_hi: {:?}, data: {:?}, __bindgen_anon_1: {:?} }}", + self.address_lo, self.address_hi, self.data, self.__bindgen_anon_1 + ) } } #[repr(C)] diff --git a/kvm-bindings/src/riscv64/fam_wrappers.rs b/kvm-bindings/src/riscv64/fam_wrappers.rs index 25b1babf..fb03545f 100644 --- a/kvm-bindings/src/riscv64/fam_wrappers.rs +++ b/kvm-bindings/src/riscv64/fam_wrappers.rs @@ -4,7 +4,7 @@ use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; -use riscv64::bindings::*; +use crate::riscv64::bindings::*; // There is no constant in the kernel as far as the maximum number // of registers on RISC-V, but KVM_GET_REG_LIST usually returns around 160. diff --git a/kvm-bindings/src/riscv64/serialize.rs b/kvm-bindings/src/riscv64/serialize.rs index 5c250cf0..5414f4e1 100644 --- a/kvm-bindings/src/riscv64/serialize.rs +++ b/kvm-bindings/src/riscv64/serialize.rs @@ -2,14 +2,14 @@ // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use bindings::{ +use crate::bindings::{ kvm_irq_routing, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1, kvm_irq_routing_msi__bindgen_ty_1, kvm_mp_state, kvm_one_reg, kvm_riscv_aia_csr, kvm_riscv_config, kvm_riscv_core, kvm_riscv_csr, kvm_riscv_sbi_sta, kvm_riscv_smstateen_csr, kvm_riscv_timer, user_regs_struct, }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use zerocopy::{transmute, IntoBytes}; +use zerocopy::{IntoBytes, transmute}; serde_impls! { kvm_mp_state, @@ -52,8 +52,8 @@ unsafe impl IntoBytes for kvm_irq_routing_entry__bindgen_ty_1 { #[cfg(test)] mod tests { - use bindings::*; - use serde::{Deserialize, Serialize}; + use crate::bindings::*; + use crate::serde::{Deserialize, Serialize}; fn is_serde Deserialize<'de> + Default>() { let config = bincode::config::standard(); diff --git a/kvm-bindings/src/x86_64/bindings.rs b/kvm-bindings/src/x86_64/bindings.rs index d328b66d..de4a13c6 100644 --- a/kvm-bindings/src/x86_64/bindings.rs +++ b/kvm-bindings/src/x86_64/bindings.rs @@ -106,11 +106,11 @@ impl __IncompleteArrayField { } #[inline] pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) + unsafe { ::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) + unsafe { ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } } impl ::std::fmt::Debug for __IncompleteArrayField { @@ -127,11 +127,11 @@ impl __BindgenUnionField { } #[inline] pub unsafe fn as_ref(&self) -> &T { - ::std::mem::transmute(self) + unsafe { ::std::mem::transmute(self) } } #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { - ::std::mem::transmute(self) + unsafe { ::std::mem::transmute(self) } } } impl ::std::default::Default for __BindgenUnionField { @@ -1100,7 +1100,11 @@ impl Default for kvm_ioapic_state { } impl ::std::fmt::Debug for kvm_ioapic_state { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_ioapic_state {{ base_address: {:?}, ioregsel: {:?}, id: {:?}, irr: {:?}, pad: {:?}, redirtbl: {:?} }}" , self . base_address , self . ioregsel , self . id , self . irr , self . pad , self . redirtbl) + write!( + f, + "kvm_ioapic_state {{ base_address: {:?}, ioregsel: {:?}, id: {:?}, irr: {:?}, pad: {:?}, redirtbl: {:?} }}", + self.base_address, self.ioregsel, self.id, self.irr, self.pad, self.redirtbl + ) } } #[repr(C)] @@ -2022,6 +2026,10 @@ impl Default for kvm_vmx_nested_state_data { } #[repr(C)] #[derive(Debug, Default, Copy, Clone, PartialEq)] +#[cfg_attr( + feature = "serde", + derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes) +)] pub struct kvm_vmx_nested_state_hdr { pub vmxon_pa: __u64, pub vmcs12_pa: __u64, @@ -2032,6 +2040,10 @@ pub struct kvm_vmx_nested_state_hdr { } #[repr(C)] #[derive(Debug, Default, Copy, Clone, PartialEq)] +#[cfg_attr( + feature = "serde", + derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes) +)] pub struct kvm_vmx_nested_state_hdr__bindgen_ty_1 { pub flags: __u16, } @@ -2088,6 +2100,10 @@ impl Default for kvm_svm_nested_state_data { } #[repr(C)] #[derive(Debug, Default, Copy, Clone, PartialEq)] +#[cfg_attr( + feature = "serde", + derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes) +)] pub struct kvm_svm_nested_state_hdr { pub vmcb_pa: __u64, } @@ -2110,6 +2126,7 @@ pub struct kvm_nested_state { } #[repr(C)] #[derive(Copy, Clone)] +#[cfg_attr(feature = "serde", derive(zerocopy::Immutable, zerocopy::FromBytes))] pub union kvm_nested_state__bindgen_ty_1 { pub vmx: kvm_vmx_nested_state_hdr, pub svm: kvm_svm_nested_state_hdr, @@ -2447,9 +2464,24 @@ const _: () = { [::std::mem::align_of::< kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1, >() - 4usize]; - ["Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1::port"] [:: std :: mem :: offset_of ! (kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1 , port) - 0usize] ; - ["Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1::vcpu"] [:: std :: mem :: offset_of ! (kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1 , vcpu) - 4usize] ; - ["Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1::priority"] [:: std :: mem :: offset_of ! (kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1 , priority) - 8usize] ; + [ + "Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1::port", + ][::std::mem::offset_of!( + kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1, + port + ) - 0usize]; + [ + "Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1::vcpu", + ][::std::mem::offset_of!( + kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1, + vcpu + ) - 4usize]; + [ + "Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1::priority", + ][::std::mem::offset_of!( + kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_1, + priority + ) - 8usize]; }; #[repr(C)] #[derive(Debug, Default, Copy, Clone, PartialEq)] @@ -2467,8 +2499,18 @@ const _: () = { [::std::mem::align_of::< kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2, >() - 4usize]; - ["Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2::port"] [:: std :: mem :: offset_of ! (kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2 , port) - 0usize] ; - ["Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2::fd"] [:: std :: mem :: offset_of ! (kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2 , fd) - 4usize] ; + [ + "Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2::port", + ][::std::mem::offset_of!( + kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2, + port + ) - 0usize]; + [ + "Offset of field: kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2::fd", + ][::std::mem::offset_of!( + kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2__bindgen_ty_1__bindgen_ty_2, + fd + ) - 4usize]; }; #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { @@ -2537,7 +2579,11 @@ impl Default for kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2 { } impl ::std::fmt::Debug for kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2 {{ send_port: {:?}, type: {:?}, flags: {:?}, deliver: {:?} }}" , self . send_port , self . type_ , self . flags , self . deliver) + write!( + f, + "kvm_xen_hvm_attr__bindgen_ty_1__bindgen_ty_2 {{ send_port: {:?}, type: {:?}, flags: {:?}, deliver: {:?} }}", + self.send_port, self.type_, self.flags, self.deliver + ) } } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -3971,7 +4017,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_8 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_8 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_8 {{ nr: {:?}, args: {:?}, ret: {:?}, __bindgen_anon_1: {:?} }}" , self . nr , self . args , self . ret , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_8 {{ nr: {:?}, args: {:?}, ret: {:?}, __bindgen_anon_1: {:?} }}", + self.nr, self.args, self.ret, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -4098,8 +4148,18 @@ const _: () = { ["Alignment of kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1"] [::std::mem::align_of::( ) - 1usize]; - ["Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_size"] [:: std :: mem :: offset_of ! (kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1 , insn_size) - 0usize] ; - ["Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_bytes"] [:: std :: mem :: offset_of ! (kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1 , insn_bytes) - 1usize] ; + [ + "Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_size", + ][::std::mem::offset_of!( + kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1, + insn_size + ) - 0usize]; + [ + "Offset of field: kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1::insn_bytes", + ][::std::mem::offset_of!( + kvm_run__bindgen_ty_1__bindgen_ty_14__bindgen_ty_1__bindgen_ty_1, + insn_bytes + ) - 1usize]; }; #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { @@ -4149,7 +4209,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_14 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_14 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_14 {{ suberror: {:?}, ndata: {:?}, flags: {:?}, __bindgen_anon_1: {:?} }}" , self . suberror , self . ndata , self . flags , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_14 {{ suberror: {:?}, ndata: {:?}, flags: {:?}, __bindgen_anon_1: {:?} }}", + self.suberror, self.ndata, self.flags, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -4294,7 +4358,11 @@ impl Default for kvm_run__bindgen_ty_1__bindgen_ty_19 { } impl ::std::fmt::Debug for kvm_run__bindgen_ty_1__bindgen_ty_19 { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run__bindgen_ty_1__bindgen_ty_19 {{ type: {:?}, ndata: {:?}, __bindgen_anon_1: {:?} }}" , self . type_ , self . ndata , self . __bindgen_anon_1) + write!( + f, + "kvm_run__bindgen_ty_1__bindgen_ty_19 {{ type: {:?}, ndata: {:?}, __bindgen_anon_1: {:?} }}", + self.type_, self.ndata, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -4609,7 +4677,23 @@ impl Default for kvm_run { } impl ::std::fmt::Debug for kvm_run { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_run {{ request_interrupt_window: {:?}, immediate_exit: {:?}, padding1: {:?}, exit_reason: {:?}, ready_for_interrupt_injection: {:?}, if_flag: {:?}, flags: {:?}, cr8: {:?}, apic_base: {:?}, __bindgen_anon_1: {:?}, kvm_valid_regs: {:?}, kvm_dirty_regs: {:?}, s: {:?} }}" , self . request_interrupt_window , self . immediate_exit , self . padding1 , self . exit_reason , self . ready_for_interrupt_injection , self . if_flag , self . flags , self . cr8 , self . apic_base , self . __bindgen_anon_1 , self . kvm_valid_regs , self . kvm_dirty_regs , self . s) + write!( + f, + "kvm_run {{ request_interrupt_window: {:?}, immediate_exit: {:?}, padding1: {:?}, exit_reason: {:?}, ready_for_interrupt_injection: {:?}, if_flag: {:?}, flags: {:?}, cr8: {:?}, apic_base: {:?}, __bindgen_anon_1: {:?}, kvm_valid_regs: {:?}, kvm_dirty_regs: {:?}, s: {:?} }}", + self.request_interrupt_window, + self.immediate_exit, + self.padding1, + self.exit_reason, + self.ready_for_interrupt_injection, + self.if_flag, + self.flags, + self.cr8, + self.apic_base, + self.__bindgen_anon_1, + self.kvm_valid_regs, + self.kvm_dirty_regs, + self.s + ) } } #[repr(C)] @@ -4739,7 +4823,11 @@ impl Default for kvm_coalesced_mmio { } impl ::std::fmt::Debug for kvm_coalesced_mmio { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_coalesced_mmio {{ phys_addr: {:?}, len: {:?}, __bindgen_anon_1: {:?}, data: {:?} }}" , self . phys_addr , self . len , self . __bindgen_anon_1 , self . data) + write!( + f, + "kvm_coalesced_mmio {{ phys_addr: {:?}, len: {:?}, __bindgen_anon_1: {:?}, data: {:?} }}", + self.phys_addr, self.len, self.__bindgen_anon_1, self.data + ) } } #[repr(C)] @@ -4941,7 +5029,11 @@ impl Default for kvm_clear_dirty_log { } impl ::std::fmt::Debug for kvm_clear_dirty_log { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_clear_dirty_log {{ slot: {:?}, num_pages: {:?}, first_page: {:?}, __bindgen_anon_1: {:?} }}" , self . slot , self . num_pages , self . first_page , self . __bindgen_anon_1) + write!( + f, + "kvm_clear_dirty_log {{ slot: {:?}, num_pages: {:?}, first_page: {:?}, __bindgen_anon_1: {:?} }}", + self.slot, self.num_pages, self.first_page, self.__bindgen_anon_1 + ) } } #[repr(C)] @@ -5176,7 +5268,11 @@ impl Default for kvm_irq_routing_msi { } impl ::std::fmt::Debug for kvm_irq_routing_msi { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - write ! (f , "kvm_irq_routing_msi {{ address_lo: {:?}, address_hi: {:?}, data: {:?}, __bindgen_anon_1: {:?} }}" , self . address_lo , self . address_hi , self . data , self . __bindgen_anon_1) + write!( + f, + "kvm_irq_routing_msi {{ address_lo: {:?}, address_hi: {:?}, data: {:?}, __bindgen_anon_1: {:?} }}", + self.address_lo, self.address_hi, self.data, self.__bindgen_anon_1 + ) } } #[repr(C)] diff --git a/kvm-bindings/src/x86_64/fam_wrappers.rs b/kvm-bindings/src/x86_64/fam_wrappers.rs index 1ac7aafa..18613532 100644 --- a/kvm-bindings/src/x86_64/fam_wrappers.rs +++ b/kvm-bindings/src/x86_64/fam_wrappers.rs @@ -3,7 +3,7 @@ use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; -use x86_64::bindings::*; +use crate::x86_64::bindings::*; /// Maximum number of CPUID entries that can be returned by a call to KVM ioctls. /// @@ -202,7 +202,7 @@ mod tests { use crate::KvmIrqRouting; use super::{CpuId, MsrList, Msrs, Xsave}; - use x86_64::bindings::kvm_cpuid_entry2; + use crate::x86_64::bindings::kvm_cpuid_entry2; use vmm_sys_util::fam::FamStruct; diff --git a/kvm-bindings/src/x86_64/mod.rs b/kvm-bindings/src/x86_64/mod.rs index 08e1bab8..85c8dfe0 100644 --- a/kvm-bindings/src/x86_64/mod.rs +++ b/kvm-bindings/src/x86_64/mod.rs @@ -6,6 +6,8 @@ pub mod bindings; #[cfg(feature = "fam-wrappers")] pub mod fam_wrappers; +pub mod nested; + #[cfg(feature = "serde")] mod serialize; diff --git a/kvm-bindings/src/x86_64/nested.rs b/kvm-bindings/src/x86_64/nested.rs new file mode 100644 index 00000000..5b1e8f08 --- /dev/null +++ b/kvm-bindings/src/x86_64/nested.rs @@ -0,0 +1,117 @@ +//! Higher-level abstractions for working with nested state. +//! +//! Getting and setting the nested KVM state is helpful if nested virtualization +//! is used and the state needs to be serialized, e.g., for live-migration or +//! state save/resume. See [`KvmNestedStateBuffer`]. + +use crate::KVM_STATE_NESTED_SVM_VMCB_SIZE; +use crate::{KVM_STATE_NESTED_VMX_VMCS_SIZE, kvm_nested_state__bindgen_ty_1}; +use core::mem; + +/// Non-zero variant of the bindgen data union. +/// +/// Please note that on SVM, this type wastes one page as the VMX state is +/// larger. +#[derive(Clone, Copy)] +#[cfg_attr(feature = "serde", derive(zerocopy::Immutable, zerocopy::FromBytes))] +#[repr(C)] +pub union kvm_nested_state__data { + pub vmx: kvm_vmx_nested_state_data, + pub svm: kvm_svm_nested_state_data, +} + +impl Default for kvm_nested_state__data { + fn default() -> Self { + // SAFETY: Every bit pattern is valid. + unsafe { mem::zeroed() } + } +} + +#[derive(Clone, Copy)] +#[cfg_attr( + feature = "serde", + derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes) +)] +#[repr(C)] +pub struct kvm_vmx_nested_state_data { + pub vmcs12: [u8; KVM_STATE_NESTED_VMX_VMCS_SIZE as usize], + pub shadow_vmcs12: [u8; KVM_STATE_NESTED_VMX_VMCS_SIZE as usize], +} + +#[derive(Clone, Copy)] +#[cfg_attr( + feature = "serde", + derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes) +)] +#[repr(C)] +pub struct kvm_svm_nested_state_data { + pub vmcb12: [u8; KVM_STATE_NESTED_SVM_VMCB_SIZE as usize], +} + +/// A stack-allocated buffer for nested KVM state including the mandatory +/// header with meta-information. +/// +/// KVM uses a dynamically sized buffer structure (with a header reporting the +/// size of the buffer/state). This helper type makes working with +/// `get_nested_state()` and `set_nested_state`() significantly more convenient +/// at the cost of a slightly higher memory footprint in some cases. +/// +/// # Type Size +/// +/// On Intel VMX, the actual state requires `128 + 8192 == 8320` bytes, on +/// AMD SVM, the actual state requires `128 + 4096 == 4224` bytes. This type +/// doesn't make a differentiation and unifies the required memory. By +/// sacrificing a few more bytes on VMX, this type is generally convenient to +/// use. +#[derive(Clone, Copy)] +#[cfg_attr( + feature = "serde", + derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes) +)] +#[repr(C)] +#[non_exhaustive] // Prevent constructor bypass in public API. +pub struct KvmNestedStateBuffer { + pub flags: u16, + pub format: u16, + pub size: u32, + pub hdr: kvm_nested_state__bindgen_ty_1, + pub data: kvm_nested_state__data, +} + +impl KvmNestedStateBuffer { + /// Creates a new empty buffer, ready for nested state to be stored in by KVM. + /// + /// The `size` property will report the size of the buffer to KVM. + pub fn empty() -> Self { + // SAFETY: Every bit pattern is valid. + let mut this: KvmNestedStateBuffer = unsafe { mem::zeroed() }; + // This way, KVM knows the size of the buffer to store state into. + // See: https://elixir.bootlin.com/linux/v6.12/source/arch/x86/kvm/x86.c#L6193 + this.size = size_of::() as u32; + this + } +} + +impl Default for KvmNestedStateBuffer { + fn default() -> Self { + Self::empty() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::kvm_nested_state as kvm_nested_state_raw_binding; + + #[test] + fn test_layout() { + assert_eq!( + align_of::(), + align_of::() + ); + assert!(size_of::() > size_of::()); + // When this fails/changes, we should re-evaluate the overall types and API + assert_eq!(size_of::(), 8320); + } +} diff --git a/kvm-bindings/src/x86_64/serialize.rs b/kvm-bindings/src/x86_64/serialize.rs index f42d5026..34530f6d 100644 --- a/kvm-bindings/src/x86_64/serialize.rs +++ b/kvm-bindings/src/x86_64/serialize.rs @@ -1,17 +1,19 @@ // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -use bindings::{ - kvm_clock_data, kvm_cpuid2, kvm_cpuid_entry2, kvm_debugregs, kvm_dtable, +use crate::bindings::{ + kvm_clock_data, kvm_cpuid_entry2, kvm_cpuid2, kvm_debugregs, kvm_dtable, kvm_ioapic_state__bindgen_ty_1, kvm_irq_routing, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1, kvm_irq_routing_msi__bindgen_ty_1, kvm_irqchip, kvm_irqchip__bindgen_ty_1, kvm_lapic_state, kvm_mp_state, kvm_msr_entry, kvm_msrs, kvm_pit_channel_state, kvm_pit_state2, kvm_regs, kvm_segment, kvm_sregs, kvm_vcpu_events, kvm_xcr, kvm_xcrs, kvm_xsave, }; -use fam_wrappers::kvm_xsave2; +use crate::fam_wrappers::kvm_xsave2; +use crate::kvm_nested_state__bindgen_ty_1; +use crate::nested::{KvmNestedStateBuffer, kvm_nested_state__data}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use zerocopy::{transmute, FromBytes, FromZeros, Immutable, IntoBytes}; +use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, transmute}; serde_impls!( kvm_regs, @@ -35,7 +37,8 @@ serde_impls!( kvm_xsave2, kvm_irqchip, kvm_irq_routing, - kvm_irq_routing_entry + kvm_irq_routing_entry, + KvmNestedStateBuffer ); // SAFETY: zerocopy's derives explicitly disallow deriving for unions where @@ -122,10 +125,34 @@ unsafe impl IntoBytes for kvm_irq_routing_entry__bindgen_ty_1 { } } +// SAFETY: zerocopy's derives explicitly disallow deriving for unions where +// the fields have different sizes, due to the smaller fields having padding. +// Miri however does not complain about these implementations (e.g. about +// reading the "padding" for one union field as valid data for a bigger one) +unsafe impl IntoBytes for kvm_nested_state__bindgen_ty_1 { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + } +} + +// SAFETY: zerocopy's derives explicitly disallow deriving for unions where +// the fields have different sizes, due to the smaller fields having padding. +// Miri however does not complain about these implementations (e.g. about +// reading the "padding" for one union field as valid data for a bigger one) +unsafe impl IntoBytes for kvm_nested_state__data { + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized, + { + } +} + #[cfg(test)] mod tests { use super::*; - use bindings::*; + use crate::bindings::*; fn is_serde Deserialize<'de> + Default>() { let config = bincode::config::standard(); @@ -182,6 +209,7 @@ mod tests { is_serde::(); is_serde::(); is_serde::(); + is_serde::(); } fn is_serde_json Deserialize<'de> + Default>() { @@ -216,5 +244,6 @@ mod tests { is_serde_json::(); is_serde_json::(); is_serde_json::(); + is_serde_json::(); } } diff --git a/kvm-ioctls/Cargo.toml b/kvm-ioctls/Cargo.toml index ef179e50..9a307bb8 100644 --- a/kvm-ioctls/Cargo.toml +++ b/kvm-ioctls/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/rust-vmm/kvm" readme = "README.md" keywords = ["kvm"] license = "Apache-2.0 OR MIT" -edition = "2021" +edition = "2024" [dependencies] libc = "0.2.39" diff --git a/kvm-ioctls/src/cap.rs b/kvm-ioctls/src/cap.rs index 311570db..3f5d6123 100644 --- a/kvm-ioctls/src/cap.rs +++ b/kvm-ioctls/src/cap.rs @@ -165,4 +165,6 @@ pub enum Cap { UserMemory2 = KVM_CAP_USER_MEMORY2, GuestMemfd = KVM_CAP_GUEST_MEMFD, MemoryAttributes = KVM_CAP_MEMORY_ATTRIBUTES, + #[cfg(target_arch = "x86_64")] + NestedState = KVM_CAP_NESTED_STATE, } diff --git a/kvm-ioctls/src/ioctls/device.rs b/kvm-ioctls/src/ioctls/device.rs index a788de3e..8f37cfb6 100644 --- a/kvm-ioctls/src/ioctls/device.rs +++ b/kvm-ioctls/src/ioctls/device.rs @@ -133,8 +133,8 @@ impl DeviceFd { /// # #[cfg(target_arch = "aarch64")] /// # { /// use kvm_bindings::{ - /// kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, - /// KVM_DEV_ARM_VGIC_GRP_NR_IRQS, + /// KVM_DEV_ARM_VGIC_GRP_NR_IRQS, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, + /// kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, /// }; /// /// // Create a GIC device. @@ -164,7 +164,7 @@ impl DeviceFd { pub unsafe fn get_device_attr(&self, device_attr: &mut kvm_device_attr) -> Result<()> { // SAFETY: Caller has ensured device_attr.addr is safe to write to. // We are calling this function with a Device fd, we trust the kernel. - let ret = ioctl_with_mut_ref(self, KVM_GET_DEVICE_ATTR(), device_attr); + let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_DEVICE_ATTR(), device_attr) }; if ret != 0 { return Err(errno::Error::last()); } @@ -192,7 +192,8 @@ impl FromRawFd for DeviceFd { /// that relies on it being true. unsafe fn from_raw_fd(fd: RawFd) -> Self { DeviceFd { - fd: File::from_raw_fd(fd), + // SAFETY: fd is a valid file descriptor obtained from KVM ioctl + fd: unsafe { File::from_raw_fd(fd) }, } } } @@ -202,13 +203,13 @@ mod tests { #![allow(clippy::undocumented_unsafe_blocks)] use super::*; use crate::ioctls::system::Kvm; + #[cfg(target_arch = "aarch64")] + use kvm_bindings::{KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD}; #[cfg(target_arch = "x86_64")] use kvm_bindings::{ - kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, kvm_device_type_KVM_DEV_TYPE_VFIO, - KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD, + KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, + kvm_device_type_KVM_DEV_TYPE_VFIO, }; - #[cfg(target_arch = "aarch64")] - use kvm_bindings::{KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD}; use kvm_bindings::KVM_CREATE_DEVICE_TEST; @@ -260,7 +261,7 @@ mod tests { fn test_create_device() { use crate::ioctls::vm::{create_gic_device, request_gic_init, set_supported_nr_irqs}; use kvm_bindings::{ - kvm_device_type_KVM_DEV_TYPE_FSL_MPIC_20, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, + KVM_DEV_ARM_VGIC_GRP_NR_IRQS, kvm_device_type_KVM_DEV_TYPE_FSL_MPIC_20, }; use vmm_sys_util::errno::Error; @@ -330,9 +331,9 @@ mod tests { fn test_create_device() { use crate::ioctls::vm::{create_aia_device, request_aia_init, set_supported_nr_irqs}; use kvm_bindings::{ - kvm_device_attr, kvm_device_type_KVM_DEV_TYPE_FSL_MPIC_20, KVM_DEV_RISCV_AIA_ADDR_APLIC, KVM_DEV_RISCV_AIA_CONFIG_SRCS, - KVM_DEV_RISCV_AIA_GRP_ADDR, KVM_DEV_RISCV_AIA_GRP_CONFIG, + KVM_DEV_RISCV_AIA_GRP_ADDR, KVM_DEV_RISCV_AIA_GRP_CONFIG, kvm_device_attr, + kvm_device_type_KVM_DEV_TYPE_FSL_MPIC_20, }; use vmm_sys_util::errno::Error; diff --git a/kvm-ioctls/src/ioctls/mod.rs b/kvm-ioctls/src/ioctls/mod.rs index a5f96c19..22cd6067 100644 --- a/kvm-ioctls/src/ioctls/mod.rs +++ b/kvm-ioctls/src/ioctls/mod.rs @@ -7,10 +7,10 @@ use std::mem::size_of; use std::os::unix::io::AsRawFd; -use std::ptr::{null_mut, NonNull}; +use std::ptr::{NonNull, null_mut}; use kvm_bindings::{ - kvm_coalesced_mmio, kvm_coalesced_mmio_ring, kvm_run, KVM_COALESCED_MMIO_PAGE_OFFSET, + KVM_COALESCED_MMIO_PAGE_OFFSET, kvm_coalesced_mmio, kvm_coalesced_mmio_ring, kvm_run, }; use vmm_sys_util::errno; diff --git a/kvm-ioctls/src/ioctls/system.rs b/kvm-ioctls/src/ioctls/system.rs index dfa20161..7286c400 100644 --- a/kvm-ioctls/src/ioctls/system.rs +++ b/kvm-ioctls/src/ioctls/system.rs @@ -4,20 +4,20 @@ // 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 THIRD-PARTY file. -use libc::{open, O_CLOEXEC, O_RDWR}; +use libc::{O_CLOEXEC, O_RDWR, open}; use std::ffi::CStr; use std::fs::File; use std::os::raw::{c_char, c_ulong}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use crate::cap::Cap; -use crate::ioctls::vm::{new_vmfd, VmFd}; use crate::ioctls::Result; +use crate::ioctls::vm::{VmFd, new_vmfd}; use crate::kvm_ioctls::*; #[cfg(target_arch = "aarch64")] use kvm_bindings::KVM_VM_TYPE_ARM_IPA_SIZE_MASK; #[cfg(target_arch = "x86_64")] -use kvm_bindings::{CpuId, MsrList, Msrs, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES}; +use kvm_bindings::{CpuId, KVM_MAX_CPUID_ENTRIES, KVM_MAX_MSR_ENTRIES, MsrList, Msrs}; use vmm_sys_util::errno; #[cfg(target_arch = "x86_64")] use vmm_sys_util::ioctl::ioctl_with_mut_ptr; @@ -282,11 +282,7 @@ impl Kvm { /// ``` pub fn get_nr_vcpus(&self) -> usize { let x = self.check_extension_int(Cap::NrVcpus); - if x > 0 { - x as usize - } else { - 4 - } + if x > 0 { x as usize } else { 4 } } /// Returns the maximum allowed memory slots per VM. @@ -305,11 +301,7 @@ impl Kvm { /// ``` pub fn get_nr_memslots(&self) -> usize { let x = self.check_extension_int(Cap::NrMemslots); - if x > 0 { - x as usize - } else { - 32 - } + if x > 0 { x as usize } else { 32 } } /// Gets the recommended maximum number of VCPUs per VM. @@ -471,7 +463,7 @@ impl Kvm { /// # Example /// /// ``` - /// use kvm_bindings::{kvm_msr_entry, Msrs}; + /// use kvm_bindings::{Msrs, kvm_msr_entry}; /// use kvm_ioctls::Kvm; /// /// let kvm = Kvm::new().unwrap(); @@ -513,7 +505,7 @@ impl Kvm { /// # Example /// /// ``` - /// use kvm_bindings::{kvm_msr_entry, Msrs}; + /// use kvm_bindings::{Msrs, kvm_msr_entry}; /// use kvm_ioctls::Kvm; /// /// let kvm = Kvm::new().unwrap(); @@ -680,7 +672,8 @@ impl Kvm { /// ``` pub unsafe fn create_vmfd_from_rawfd(&self, fd: RawFd) -> Result { let run_mmap_size = self.get_vcpu_mmap_size()?; - Ok(new_vmfd(File::from_raw_fd(fd), run_mmap_size)) + // SAFETY: fd is a valid file descriptor returned by KVM_CREATE_VM ioctl + Ok(new_vmfd(unsafe { File::from_raw_fd(fd) }, run_mmap_size)) } } @@ -720,7 +713,9 @@ impl FromRawFd for Kvm { /// ``` unsafe fn from_raw_fd(fd: RawFd) -> Self { Kvm { - kvm: File::from_raw_fd(fd), + // SAFETY: fd is a valid file descriptor obtained + // From opening /dev/kvm + kvm: unsafe { File::from_raw_fd(fd) }, } } } @@ -729,7 +724,7 @@ impl FromRawFd for Kvm { mod tests { #![allow(clippy::undocumented_unsafe_blocks)] use super::*; - use libc::{fcntl, FD_CLOEXEC, F_GETFD}; + use libc::{F_GETFD, FD_CLOEXEC, fcntl}; use std::os::fd::IntoRawFd; #[cfg(target_arch = "x86_64")] use vmm_sys_util::fam::FamStruct; diff --git a/kvm-ioctls/src/ioctls/vcpu.rs b/kvm-ioctls/src/ioctls/vcpu.rs index f450a6d3..f783ca4b 100644 --- a/kvm-ioctls/src/ioctls/vcpu.rs +++ b/kvm-ioctls/src/ioctls/vcpu.rs @@ -7,6 +7,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. +// Part of public API +#[cfg(target_arch = "x86_64")] +pub use kvm_bindings::nested::KvmNestedStateBuffer; + use kvm_bindings::*; use libc::EINVAL; use std::fs::File; @@ -17,7 +21,10 @@ use crate::kvm_ioctls::*; use vmm_sys_util::errno; use vmm_sys_util::ioctl::{ioctl, ioctl_with_mut_ref, ioctl_with_ref}; #[cfg(target_arch = "x86_64")] -use vmm_sys_util::ioctl::{ioctl_with_mut_ptr, ioctl_with_ptr, ioctl_with_val}; +use { + std::num::NonZeroUsize, + vmm_sys_util::ioctl::{ioctl_with_mut_ptr, ioctl_with_ptr, ioctl_with_val}, +}; /// Helper method to obtain the size of the register through its id #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] @@ -1017,7 +1024,8 @@ impl VcpuFd { /// ``` #[cfg(target_arch = "x86_64")] pub unsafe fn set_xsave2(&self, xsave: &Xsave) -> Result<()> { - self.set_xsave(&xsave.as_fam_struct_ref().xsave) + // SAFETY: xsave structure is properly initialized and validated + unsafe { self.set_xsave(&xsave.as_fam_struct_ref().xsave) } } /// X86 specific call that returns the vcpu's current "xcrs". @@ -1276,7 +1284,7 @@ impl VcpuFd { /// # use kvm_ioctls::Kvm; /// use std::arch::is_aarch64_feature_detected; /// - /// use kvm_bindings::{kvm_vcpu_init, KVM_ARM_VCPU_SVE}; + /// use kvm_bindings::{KVM_ARM_VCPU_SVE, kvm_vcpu_init}; /// let kvm = Kvm::new().unwrap(); /// let vm = kvm.create_vm().unwrap(); /// let vcpu = vm.create_vcpu(0).unwrap(); @@ -1983,6 +1991,93 @@ impl VcpuFd { } } + /// Returns the nested guest state using the `KVM_GET_NESTED_STATE` ioctl. + /// + /// This only works when `KVM_CAP_NESTED_STATE` is available. + /// + /// # Arguments + /// + /// - `buffer`: The buffer to be filled with the new nested state. + /// + /// # Return Value + /// If this returns `None`, KVM doesn't have nested state. Otherwise, the + /// actual length of the state is returned. + /// + /// # Example + /// + /// ```rust + /// # use kvm_ioctls::{Kvm, Cap, KvmNestedStateBuffer}; + /// let kvm = Kvm::new().unwrap(); + /// let vm = kvm.create_vm().unwrap(); + /// let vcpu = vm.create_vcpu(0).unwrap(); + /// let mut state_buffer = KvmNestedStateBuffer::empty(); + /// if kvm.check_extension(Cap::NestedState) { + /// vcpu.get_nested_state(&mut state_buffer).unwrap(); + /// // Next, serialize the actual state into a file or so. + /// } + /// ``` + /// + /// [`Kvm::check_extension_int`]: kvm_ioctls::Kvm::check_extension_int + #[cfg(target_arch = "x86_64")] + pub fn get_nested_state( + &self, + buffer: &mut KvmNestedStateBuffer, + ) -> Result> { + assert_ne!(buffer.size, 0, "buffer should not report a size of zero"); + + // SAFETY: Safe because we call this with a Vcpu fd and we trust the kernel. + let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_NESTED_STATE(), buffer) }; + match ret { + 0 => { + let size = buffer.size as usize; + if size == size_of::() { + Ok(None) + } else { + Ok(Some(NonZeroUsize::new(size).unwrap())) + } + } + _ => Err(errno::Error::last()), + } + } + + /// Sets the nested guest state using the `KVM_SET_NESTED_STATE` ioctl. + /// + /// This only works when `KVM_CAP_NESTED_STATE` is available. + /// + /// # Arguments + /// + /// - `state`: The new state to be put into KVM. The header must report the + /// `size` of the state properly. The state must be retrieved first using + /// [`Self::get_nested_state`]. + /// + /// # Example + /// + /// ```rust + /// # use kvm_ioctls::{Kvm, Cap, KvmNestedStateBuffer}; + /// let kvm = Kvm::new().unwrap(); + /// let vm = kvm.create_vm().unwrap(); + /// let vcpu = vm.create_vcpu(0).unwrap(); + /// if kvm.check_extension(Cap::NestedState) { + /// let mut state_buffer = KvmNestedStateBuffer::empty(); + /// vcpu.get_nested_state(&mut state_buffer).unwrap(); + /// // Rename the variable to better reflect the role. + /// let old_state = state_buffer; + /// + /// // now assume we transfer the state to a new location + /// // and load it back into kvm: + /// vcpu.set_nested_state(&old_state).unwrap(); + /// } + /// ``` + #[cfg(target_arch = "x86_64")] + pub fn set_nested_state(&self, state: &KvmNestedStateBuffer) -> Result<()> { + // SAFETY: Safe because we call this with a Vcpu fd and we trust the kernel. + let ret = unsafe { ioctl_with_ref(self, KVM_SET_NESTED_STATE(), state) }; + match ret { + 0 => Ok(()), + _ => Err(errno::Error::last()), + } + } + /// Queues an NMI on the thread's vcpu. Only usable if `KVM_CAP_USER_NMI` /// is available. /// @@ -3609,4 +3704,34 @@ mod tests { assert_eq!(addr, ADDR); assert_eq!(data, (DATA as u16).to_le_bytes()); } + + #[test] + #[cfg(target_arch = "x86_64")] + fn test_get_and_set_nested_state() { + let kvm = Kvm::new().unwrap(); + let vm = kvm.create_vm().unwrap(); + let vcpu = vm.create_vcpu(0).unwrap(); + + // Ensure that KVM also during runtime never wants more memory than we have pre-allocated + // by the helper type. KVM is expected to report: + // - 128+4096==4224 on SVM + // - 128+8192==8320 on VMX + let kvm_nested_state_size = kvm.check_extension_int(Cap::NestedState) as usize; + assert!(kvm_nested_state_size <= size_of::()); + + let mut state_buffer = KvmNestedStateBuffer::default(); + // Ensure that header shows full buffer length. + assert_eq!( + state_buffer.size as usize, + size_of::() + ); + + vcpu.get_nested_state(&mut state_buffer).unwrap(); + let old_state = state_buffer; + + // There is no nested guest in this test, so there is no payload. + assert_eq!(state_buffer.size as usize, size_of::()); + + vcpu.set_nested_state(&old_state).unwrap(); + } } diff --git a/kvm-ioctls/src/ioctls/vm.rs b/kvm-ioctls/src/ioctls/vm.rs index 6f34997b..f2c6a135 100644 --- a/kvm-ioctls/src/ioctls/vm.rs +++ b/kvm-ioctls/src/ioctls/vm.rs @@ -14,10 +14,10 @@ use std::os::raw::{c_int, c_ulong}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use crate::cap::Cap; -use crate::ioctls::device::new_device; use crate::ioctls::device::DeviceFd; -use crate::ioctls::vcpu::new_vcpu; +use crate::ioctls::device::new_device; use crate::ioctls::vcpu::VcpuFd; +use crate::ioctls::vcpu::new_vcpu; use crate::ioctls::{KvmRunWrapper, Result}; use crate::kvm_ioctls::*; use vmm_sys_util::errno; @@ -107,7 +107,9 @@ impl VmFd { &self, user_memory_region: kvm_userspace_memory_region, ) -> Result<()> { - let ret = ioctl_with_ref(self, KVM_SET_USER_MEMORY_REGION(), &user_memory_region); + let ret = + // SAFETY: user_memory_region is properly initialized with valid parameters + unsafe { ioctl_with_ref(self, KVM_SET_USER_MEMORY_REGION(), &user_memory_region) }; if ret == 0 { Ok(()) } else { @@ -145,8 +147,8 @@ impl VmFd { /// extern crate kvm_bindings; /// /// use kvm_bindings::{ - /// kvm_create_guest_memfd, kvm_userspace_memory_region2, KVM_CAP_GUEST_MEMFD, - /// KVM_CAP_USER_MEMORY2, KVM_MEM_GUEST_MEMFD, + /// KVM_CAP_GUEST_MEMFD, KVM_CAP_USER_MEMORY2, KVM_MEM_GUEST_MEMFD, kvm_create_guest_memfd, + /// kvm_userspace_memory_region2, /// }; /// use kvm_ioctls::{Cap, Kvm}; /// use std::os::fd::RawFd; @@ -193,7 +195,9 @@ impl VmFd { &self, user_memory_region2: kvm_userspace_memory_region2, ) -> Result<()> { - let ret = ioctl_with_ref(self, KVM_SET_USER_MEMORY_REGION2(), &user_memory_region2); + let ret = + // SAFETY: user_memory_region2 is properly initialized with valid parameters + unsafe { ioctl_with_ref(self, KVM_SET_USER_MEMORY_REGION2(), &user_memory_region2) }; if ret == 0 { Ok(()) } else { @@ -275,7 +279,7 @@ impl VmFd { /// #[cfg(target_arch = "aarch64")] /// { /// use kvm_bindings::{ - /// kvm_create_device, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, KVM_CREATE_DEVICE_TEST, + /// KVM_CREATE_DEVICE_TEST, kvm_create_device, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, /// }; /// let mut gic_device = kvm_create_device { /// type_: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, @@ -662,7 +666,7 @@ impl VmFd { /// extern crate libc; /// extern crate vmm_sys_util; /// # use kvm_ioctls::{IoEventAddress, Kvm, NoDatamatch}; - /// use libc::{eventfd, EFD_NONBLOCK}; + /// use libc::{EFD_NONBLOCK, eventfd}; /// use vmm_sys_util::eventfd::EventFd; /// let kvm = Kvm::new().unwrap(); /// let vm_fd = kvm.create_vm().unwrap(); @@ -692,8 +696,8 @@ impl VmFd { datamatch: datamatch.into(), len: std::mem::size_of::() as u32, addr: match addr { - IoEventAddress::Pio(ref p) => *p, - IoEventAddress::Mmio(ref m) => *m, + IoEventAddress::Pio(p) => *p, + IoEventAddress::Mmio(m) => *m, }, fd: fd.as_raw_fd(), flags, @@ -768,8 +772,8 @@ impl VmFd { datamatch: datamatch.into(), len: std::mem::size_of::() as u32, addr: match addr { - IoEventAddress::Pio(ref p) => *p, - IoEventAddress::Mmio(ref m) => *m, + IoEventAddress::Pio(p) => *p, + IoEventAddress::Mmio(m) => *m, }, fd: fd.as_raw_fd(), flags, @@ -1243,7 +1247,8 @@ impl VmFd { /// let vcpu = unsafe { vm.create_vcpu_from_rawfd(rawfd).unwrap() }; /// ``` pub unsafe fn create_vcpu_from_rawfd(&self, fd: RawFd) -> Result { - let vcpu = File::from_raw_fd(fd); + // SAFETY: fd is a valid file descriptor returned by KVM_CREATE_VCPU ioctl + let vcpu = unsafe { File::from_raw_fd(fd) }; let kvm_run_ptr = KvmRunWrapper::mmap_from_fd(&vcpu, self.run_size)?; Ok(new_vcpu(vcpu, kvm_run_ptr)) } @@ -1264,9 +1269,9 @@ impl VmFd { /// # extern crate kvm_bindings; /// # use kvm_ioctls::Kvm; /// use kvm_bindings::{ - /// kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, - /// kvm_device_type_KVM_DEV_TYPE_RISCV_AIA, kvm_device_type_KVM_DEV_TYPE_VFIO, - /// KVM_CREATE_DEVICE_TEST, + /// KVM_CREATE_DEVICE_TEST, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, + /// kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, kvm_device_type_KVM_DEV_TYPE_RISCV_AIA, + /// kvm_device_type_KVM_DEV_TYPE_VFIO, /// }; /// let kvm = Kvm::new().unwrap(); /// let vm = kvm.create_vm().unwrap(); @@ -1363,7 +1368,7 @@ impl VmFd { /// extern crate kvm_bindings; /// /// # use kvm_ioctls::Kvm; - /// use kvm_bindings::{kvm_enable_cap, KVM_CAP_SPLIT_IRQCHIP}; + /// use kvm_bindings::{KVM_CAP_SPLIT_IRQCHIP, kvm_enable_cap}; /// /// let kvm = Kvm::new().unwrap(); /// let vm = kvm.create_vm().unwrap(); @@ -1492,7 +1497,7 @@ impl VmFd { /// extern crate kvm_bindings; /// /// # use kvm_ioctls::{Cap, Kvm}; - /// use kvm_bindings::{kvm_create_guest_memfd, KVM_CAP_GUEST_MEMFD}; + /// use kvm_bindings::{KVM_CAP_GUEST_MEMFD, kvm_create_guest_memfd}; /// use std::os::fd::RawFd; /// /// let kvm = Kvm::new().unwrap(); @@ -1545,9 +1550,9 @@ impl VmFd { /// /// # use kvm_ioctls::{Cap, Kvm}; /// use kvm_bindings::{ - /// kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2, - /// KVM_CAP_GUEST_MEMFD, KVM_CAP_MEMORY_ATTRIBUTES, KVM_CAP_USER_MEMORY2, - /// KVM_MEMORY_ATTRIBUTE_PRIVATE, KVM_MEM_GUEST_MEMFD, + /// KVM_CAP_GUEST_MEMFD, KVM_CAP_MEMORY_ATTRIBUTES, KVM_CAP_USER_MEMORY2, KVM_MEM_GUEST_MEMFD, + /// KVM_MEMORY_ATTRIBUTE_PRIVATE, kvm_create_guest_memfd, kvm_memory_attributes, + /// kvm_userspace_memory_region2, /// }; /// use std::os::fd::RawFd; /// @@ -1648,7 +1653,8 @@ impl VmFd { /// ``` #[cfg(target_arch = "x86_64")] pub unsafe fn encrypt_op(&self, op: *mut T) -> Result<()> { - let ret = ioctl_with_mut_ptr(self, KVM_MEMORY_ENCRYPT_OP(), op); + // SAFETY: op pointer is valid and properly initialized for the ioctl operation + let ret = unsafe { ioctl_with_mut_ptr(self, KVM_MEMORY_ENCRYPT_OP(), op) }; if ret == 0 { Ok(()) } else { diff --git a/kvm-ioctls/src/kvm_ioctls.rs b/kvm-ioctls/src/kvm_ioctls.rs index 9045b9d5..43898ba3 100644 --- a/kvm-ioctls/src/kvm_ioctls.rs +++ b/kvm-ioctls/src/kvm_ioctls.rs @@ -262,6 +262,12 @@ ioctl_iow_nr!( kvm_memory_attributes ); +#[cfg(target_arch = "x86_64")] +ioctl_iowr_nr!(KVM_GET_NESTED_STATE, KVMIO, 0xbe, kvm_nested_state); + +#[cfg(target_arch = "x86_64")] +ioctl_iow_nr!(KVM_SET_NESTED_STATE, KVMIO, 0xbf, kvm_nested_state); + // Device ioctls. /* Available with KVM_CAP_DEVICE_CTRL */ @@ -279,7 +285,7 @@ mod tests { use std::fs::File; use std::os::unix::io::FromRawFd; - use libc::{c_char, open, O_RDWR}; + use libc::{O_RDWR, c_char, open}; use vmm_sys_util::ioctl::{ioctl, ioctl_with_val}; use super::*; diff --git a/kvm-ioctls/src/lib.rs b/kvm-ioctls/src/lib.rs index 278e21b7..353acc0d 100644 --- a/kvm-ioctls/src/lib.rs +++ b/kvm-ioctls/src/lib.rs @@ -65,8 +65,8 @@ //! use std::ptr::null_mut; //! use std::slice; //! -//! use kvm_bindings::kvm_userspace_memory_region; //! use kvm_bindings::KVM_MEM_LOG_DIRTY_PAGES; +//! use kvm_bindings::kvm_userspace_memory_region; //! //! let mem_size = 0x4000; //! let guest_addr = 0x1000; @@ -249,7 +249,7 @@ pub use ioctls::vcpu::reg_size; pub use ioctls::vcpu::{HypercallExit, VcpuExit, VcpuFd}; #[cfg(target_arch = "x86_64")] -pub use ioctls::vcpu::{MsrExitReason, ReadMsrExit, SyncReg, WriteMsrExit}; +pub use ioctls::vcpu::{KvmNestedStateBuffer, MsrExitReason, ReadMsrExit, SyncReg, WriteMsrExit}; pub use ioctls::vm::{IoEventAddress, NoDatamatch, VmFd}; // The following example is used to verify that our public diff --git a/rust-vmm-ci b/rust-vmm-ci index c3ef8977..aa2f8a90 160000 --- a/rust-vmm-ci +++ b/rust-vmm-ci @@ -1 +1 @@ -Subproject commit c3ef8977388ccddb8c68b106737fa2c674b0d87a +Subproject commit aa2f8a90e46533de8a58f19cd0c417de856d4437