Repository: firecracker-microvm/firecracker
File: src/vmm/src/devices/virtio/queue.rs (Rust)

Code before:

    fn used_ring_size(&self) -> usize {
        std::mem::size_of::<u16>()
            + std::mem::size_of::<u16>()
            + std::mem::size_of::<UsedElement>() * usize::from(self.size)
            + std::mem::size_of::<u16>()
    }

    fn get_slice_ptr<M: GuestMemory>(
        &self,
        mem: &M,
        addr: GuestAddress,
        len: usize,
    ) -> Result<*mut u8, QueueError> {
        let slice = mem.get_slice(addr, len).map_err(QueueError::MemoryError)?;
        slice.bitmap().mark_dirty(0, len);
        Ok(slice.ptr_guard_mut().as_ptr())
    }

    /// Do final checks and setup of the queue before it can be usable.
    /// Set up pointers to the queue objects in the guest memory
    /// and mark memory dirty for those objects
    pub fn initialize<M: GuestMemory>(&mut self, mem: &M) -> Result<(), QueueError> {
        if self.max_size < self.size {
            return Err(QueueError::InvalidQueueSize(self.max_size, self.size));
        }

        self.desc_table_ptr = self
            .get_slice_ptr(mem, self.desc_table_address, self.desc_table_size())?
            .cast();
        self.avail_ring_ptr = self
            .get_slice_ptr(mem, self.avail_ring_address, self.avail_ring_size())?
            .cast();
        self.used_ring_ptr = self
            .get_slice_ptr(mem, self.used_ring_address, self.used_ring_size())?
            .cast();

        // All the above pointers are expected to be aligned properly; otherwise some methods (e.g.
        // `read_volatile()`) will panic. Such an unalignment is possible when restored from a
        // broken/fuzzed snapshot.
        //
        // Specification of those pointers' alignments
        // https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-350007
        // > ================ ==========
        // > Virtqueue Part    Alignment
        // > ================ ==========
        // > Descriptor Table 16
        // > Available Ring   2
        // > Used Ring        4
        // > ================ ==========
        if !self.desc_table_ptr.cast::<u128>().is_aligned() {

Review comment (suggestion):
This is not needed, because its already checked in `Queue::is_valid`, which is checked in `mmio.rs` before activation (so I guess this entire commit is not needed?)

Code after:
            + std::mem::size_of::<u16>()
            + std::mem::size_of::<UsedElement>() * usize::from(self.size)
            + std::mem::size_of::<u16>()
    }

    fn get_slice_ptr<M: GuestMemory>(
        &self,
        mem: &M,
        addr: GuestAddress,
        len: usize,
    ) -> Result<*mut u8, QueueError> {
        let slice = mem.get_slice(addr, len).map_err(QueueError::MemoryError)?;
        slice.bitmap().mark_dirty(0, len);
        Ok(slice.ptr_guard_mut().as_ptr())
    }

    /// Set up pointers to the queue objects in the guest memory
    /// and mark memory dirty for those objects
    pub fn initialize<M: GuestMemory>(&mut self, mem: &M) -> Result<(), QueueError> {
        self.desc_table_ptr = self
            .get_slice_ptr(mem, self.desc_table_address, self.desc_table_size())?
            .cast();
        self.avail_ring_ptr = self
            .get_slice_ptr(mem, self.avail_ring_address, self.avail_ring_size())?
            .cast();
        self.used_ring_ptr = self
            .get_slice_ptr(mem, self.used_ring_address, self.used_ring_size())?
            .cast();

        // All the above pointers are expected to be aligned properly; otherwise some methods (e.g.
        // `read_volatile()`) will panic. Such an unalignment is possible when restored from a
        // broken/fuzzed snapshot.
        //
        // Specification of those pointers' alignments
        // https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-350007
        // > ================ ==========
        // > Virtqueue Part    Alignment
        // > ================ ==========
        // > Descriptor Table 16
        // > Available Ring   2
        // > Used Ring        4
        // > ================ ==========
        if !self.desc_table_ptr.cast::<u128>().is_aligned() {
            return Err(QueueError::PointerNotAligned(
                self.desc_table_ptr as usize,
                16,
            ));
        }
        if !self.avail_ring_ptr.is_aligned() {
            return Err(QueueError::PointerNotAligned(
                self.avail_ring_ptr as usize,