Repository: firecracker-microvm/firecracker
File: src/vmm/src/devices/acpi/vmclock.rs (Rust)

Code before:
    /// Data we expose to the guest
    pub inner: vmclock_abi,
}

/// Errors for restoring VmClock from snapshot
#[derive(Debug, thiserror::Error, displaydoc::Display)]
pub enum VmClockPersistError {
    /// Too large guest address ({0:#}) would cause overflow when adding field offsets, implying snapshot corruption
    TooLargeGuestAddress(u64),
}

impl<'a> Persist<'a> for VmClock {
    type State = VmClockState;
    type ConstructorArgs = ();
    type Error = VmClockPersistError;

    fn save(&self) -> Self::State {
        VmClockState {
            guest_address: self.guest_address.0,
            gsi: self.gsi,
            inner: self.inner,
        }
    }

    fn restore(vm: Self::ConstructorArgs, state: &Self::State) -> Result<Self, Self::Error> {
        if state.guest_address > u64::MAX - VMCLOCK_SIZE as u64 {
            return Err(VmClockPersistError::TooLargeGuestAddress(
                state.guest_address,
            ));
        }
        let interrupt_evt = EventFdTrigger::new(
            EventFd::new(libc::EFD_NONBLOCK)
                .expect("vmclock: Could not create EventFd for VMClock device: {err}"),
        );
        Ok(VmClock {
            guest_address: GuestAddress(state.guest_address),
            interrupt_evt,
            gsi: state.gsi,
            inner: state.inner,
        })
    }
}

impl Aml for VmClock {
    fn append_aml_bytes(&self, v: &mut Vec<u8>) -> Result<(), aml::AmlError> {
        aml::Device::new(
            "_SB_.VCLK".try_into()?,
            vec![
                &aml::Name::new("_HID".try_into()?, &"AMZNC10C")?,
                &aml::Name::new("_CID".try_into()?, &"VMCLOCK")?,
                &aml::Name::new("_DDN".try_into()?, &"VMCLOCK")?,

Review comment (bug):
shouldn't the `mem.write_slice(self.inner.as_slice(), self.guest_address)?;` in the `activate` fail with an error already? If not, why?

Code after:
    /// Data we expose to the guest
    pub inner: vmclock_abi,
}

impl<'a> Persist<'a> for VmClock {
    type State = VmClockState;
    type ConstructorArgs = ();
    type Error = Infallible;

    fn save(&self) -> Self::State {
        VmClockState {
            guest_address: self.guest_address.0,
            gsi: self.gsi,
            inner: self.inner,
        }
    }

    fn restore(vm: Self::ConstructorArgs, state: &Self::State) -> Result<Self, Self::Error> {
        let interrupt_evt = EventFdTrigger::new(
            EventFd::new(libc::EFD_NONBLOCK)
                .expect("vmclock: Could not create EventFd for VMClock device: {err}"),
        );
        Ok(VmClock {
            guest_address: GuestAddress(state.guest_address),
            interrupt_evt,
            gsi: state.gsi,
            inner: state.inner,
        })
    }
}

impl Aml for VmClock {
    fn append_aml_bytes(&self, v: &mut Vec<u8>) -> Result<(), aml::AmlError> {
        aml::Device::new(
            "_SB_.VCLK".try_into()?,
            vec![
                &aml::Name::new("_HID".try_into()?, &"AMZNC10C")?,
                &aml::Name::new("_CID".try_into()?, &"VMCLOCK")?,
                &aml::Name::new("_DDN".try_into()?, &"VMCLOCK")?,
                &aml::Method::new(
                    "_STA".try_into()?,
                    0,
                    false,
                    vec![&aml::Return::new(&0x0fu8)],
                ),
                &aml::Name::new(
                    "_CRS".try_into()?,
                    &aml::ResourceTemplate::new(vec![&aml::AddressSpace::new_memory(
                        aml::AddressSpaceCacheable::Cacheable,
                        false,
                        self.guest_address.0,