use vmm_sys_util::fam::{FamStruct, FamStructWrapper};
use super::bindings::*;
pub const KVM_MAX_CPUID_ENTRIES: usize = 256;
pub const KVM_MAX_MSR_ENTRIES: usize = 256;
generate_fam_struct_impl!(
kvm_cpuid2,
kvm_cpuid_entry2,
entries,
u32,
nent,
KVM_MAX_CPUID_ENTRIES
);
impl PartialEq for kvm_cpuid2 {
fn eq(&self, other: &kvm_cpuid2) -> bool {
self.nent == other.nent && self.padding == other.padding
}
}
pub type CpuId = FamStructWrapper<kvm_cpuid2>;
generate_fam_struct_impl!(
kvm_msrs,
kvm_msr_entry,
entries,
u32,
nmsrs,
KVM_MAX_MSR_ENTRIES
);
impl PartialEq for kvm_msrs {
fn eq(&self, other: &kvm_msrs) -> bool {
self.nmsrs == other.nmsrs && self.pad == other.pad
}
}
pub type Msrs = FamStructWrapper<kvm_msrs>;
generate_fam_struct_impl!(
kvm_irq_routing,
kvm_irq_routing_entry,
entries,
u32,
nr,
1024
);
impl PartialEq for kvm_irq_routing {
fn eq(&self, other: &kvm_irq_routing) -> bool {
self.nr == other.nr && self.flags == other.flags
}
}
pub type KvmIrqRouting = FamStructWrapper<kvm_irq_routing>;
generate_fam_struct_impl!(kvm_msr_list, u32, indices, u32, nmsrs, KVM_MAX_MSR_ENTRIES);
impl PartialEq for kvm_msr_list {
fn eq(&self, other: &kvm_msr_list) -> bool {
self.nmsrs == other.nmsrs
}
}
pub type MsrList = FamStructWrapper<kvm_msr_list>;
#[repr(C)]
#[derive(Debug, Default)]
#[cfg_attr(
feature = "serde",
derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::FromBytes)
)]
pub struct kvm_xsave2 {
pub len: usize,
pub xsave: kvm_xsave,
}
impl From<kvm_xsave> for kvm_xsave2 {
fn from(xsave: kvm_xsave) -> Self {
kvm_xsave2 { len: 0, xsave }
}
}
unsafe impl FamStruct for kvm_xsave2 {
type Entry = __u32;
fn len(&self) -> usize {
self.len
}
unsafe fn set_len(&mut self, len: usize) {
self.len = len;
}
fn max_len() -> usize {
__u32::MAX as usize
}
fn as_slice(&self) -> &[<Self as FamStruct>::Entry] {
let len = self.len();
unsafe { self.xsave.extra.as_slice(len) }
}
fn as_mut_slice(&mut self) -> &mut [<Self as FamStruct>::Entry] {
let len = self.len();
unsafe { self.xsave.extra.as_mut_slice(len) }
}
}
pub type Xsave = FamStructWrapper<kvm_xsave2>;
#[cfg(test)]
mod tests {
use super::*;
use crate::KvmIrqRouting;
use vmm_sys_util::fam::FamStruct;
#[test]
fn test_cpuid_eq() {
let entries = &[kvm_cpuid_entry2::default(); 2];
let mut wrapper = CpuId::from_entries(entries).unwrap();
assert_eq!(wrapper.as_slice().len(), 2);
let mut wrapper2 = wrapper.clone();
assert!(wrapper == wrapper2);
wrapper.as_mut_slice()[1].index = 1;
assert!(wrapper != wrapper2);
wrapper2.as_mut_slice()[1].index = 1;
assert!(wrapper == wrapper2);
}
#[test]
fn test_msrs_eq() {
let mut wrapper = Msrs::new(2).unwrap();
assert_eq!(wrapper.as_slice().len(), 2);
let mut wrapper2 = wrapper.clone();
assert!(wrapper == wrapper2);
unsafe {
wrapper.as_mut_fam_struct().pad = 1;
}
assert!(wrapper != wrapper2);
unsafe {
wrapper2.as_mut_fam_struct().pad = 1;
}
assert!(wrapper == wrapper2);
wrapper.as_mut_slice()[1].data = 1;
assert!(wrapper != wrapper2);
assert!(wrapper.as_slice() != wrapper2.as_slice());
wrapper2.as_mut_slice()[1].data = 1;
assert!(wrapper == wrapper2);
assert!(wrapper.as_slice() == wrapper2.as_slice());
}
#[test]
fn test_msrs_list_eq() {
let mut wrapper = MsrList::new(1).unwrap();
assert_eq!(wrapper.as_slice().len(), 1);
let mut wrapper2 = wrapper.clone();
assert!(wrapper == wrapper2);
wrapper.as_mut_slice()[0] = 1;
assert!(wrapper != wrapper2);
wrapper2.as_mut_slice()[0] = 1;
assert!(wrapper == wrapper2);
}
#[test]
fn test_xsave() {
let wrapper = Xsave::new(1).unwrap();
assert_eq!(wrapper.as_slice().len(), 1);
assert_eq!(wrapper.as_fam_struct_ref().len(), 1);
assert_eq!(wrapper.as_fam_struct_ref().len, 1);
}
#[test]
fn test_kvm_irq_routing() {
let wrapper = KvmIrqRouting::new(1).unwrap();
assert_eq!(wrapper.as_slice().len(), 1);
assert_eq!(wrapper.as_fam_struct_ref().len(), 1);
assert_eq!(wrapper.as_fam_struct_ref().nr, 1);
}
}