Repository: firecracker-microvm/firecracker
File: src/vmm/src/vstate/vm/x86_64.rs (Rust)

Code before:
pub struct ArchVm {
    pub(super) fd: VmFd,
    msrs_to_save: MsrList,
    /// Size in bytes requiring to hold the dynamically-sized `kvm_xsave` struct.
    ///
    /// `None` if `KVM_CAP_XSAVE2` not supported.
    xsave2_size: Option<usize>,
}

impl ArchVm {
    /// Create a new `Vm` struct.
    pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result<ArchVm, VmError> {
        let fd = Self::create_vm(kvm)?;

        let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?;

        // `KVM_CAP_XSAVE2` was introduced to support dynamically-sized XSTATE buffer in kernel
        // v5.17. `KVM_GET_EXTENSION(KVM_CAP_XSAVE2)` returns the required size in byte if
        // supported; otherwise returns 0.
        // https://github.com/torvalds/linux/commit/be50b2065dfa3d88428fdfdc340d154d96bf6848
        //
        // Cache the value in order not to call it at each vCPU creation.
        let xsave2_size = match fd.check_extension_int(Cap::Xsave2) {
            // Catch all negative values just in case although the possible negative retuned value
            // of ioctl() is only -1.
            i32::MIN..=-1 => {
                return Err(VmError::Arch(ArchVmError::CheckCapability(
                    Cap::Xsave2,
                    vmm_sys_util::errno::Error::last(),
                )));
            }
            0 => None,
            // SAFETY: Safe because negative values are handled above.
            ret => Some(usize::try_from(ret).unwrap()),
        };

        fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS))
            .map_err(ArchVmError::SetTssAddress)?;

        Ok(ArchVm {
            fd,
            msrs_to_save,
            xsave2_size,
        })
    }

    pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> {
        // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS`
        self.setup_irqchip()
    }


Review comment (suggestion):
nit: I think this can just be
```suggestion
            ..=-1 => {
```

Code after:
pub struct ArchVm {
    pub(super) fd: VmFd,
    msrs_to_save: MsrList,
    /// Size in bytes requiring to hold the dynamically-sized `kvm_xsave` struct.
    ///
    /// `None` if `KVM_CAP_XSAVE2` not supported.
    xsave2_size: Option<usize>,
}

impl ArchVm {
    /// Create a new `Vm` struct.
    pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result<ArchVm, VmError> {
        let fd = Self::create_vm(kvm)?;

        let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?;

        // `KVM_CAP_XSAVE2` was introduced to support dynamically-sized XSTATE buffer in kernel
        // v5.17. `KVM_GET_EXTENSION(KVM_CAP_XSAVE2)` returns the required size in byte if
        // supported; otherwise returns 0.
        // https://github.com/torvalds/linux/commit/be50b2065dfa3d88428fdfdc340d154d96bf6848
        //
        // Cache the value in order not to call it at each vCPU creation.
        let xsave2_size = match fd.check_extension_int(Cap::Xsave2) {
            // Catch all negative values just in case although the possible negative return value
            // of ioctl() is only -1.
            ..=-1 => {
                return Err(VmError::Arch(ArchVmError::CheckCapability(
                    Cap::Xsave2,
                    vmm_sys_util::errno::Error::last(),
                )));
            }
            0 => None,
            // SAFETY: Safe because negative values are handled above.
            ret => Some(usize::try_from(ret).unwrap()),
        };

        fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS))
            .map_err(ArchVmError::SetTssAddress)?;

        Ok(ArchVm {
            fd,
            msrs_to_save,
            xsave2_size,
        })
    }

    pub(super) fn arch_pre_create_vcpus(&mut self, _: u8) -> Result<(), ArchVmError> {
        // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS`
        self.setup_irqchip()
    }