Repository: firecracker-microvm/firecracker
File: src/vmm/src/gdb/target.rs (Rust)

Code before:
        arch::read_registers(&self.vcpu_state[tid_to_vcpuid(tid)].vcpu_fd, regs)?;

        Ok(())
    }

    /// Writes to the registers for the Vcpu
    fn write_registers(&mut self, regs: &CoreRegs, tid: Tid) -> TargetResult<(), Self> {
        arch::write_registers(&self.vcpu_state[tid_to_vcpuid(tid)].vcpu_fd, regs)?;

        Ok(())
    }

    /// Writes data to a guest virtual address for the Vcpu
    fn read_addrs(
        &mut self,
        mut gva: <Self::Arch as Arch>::Usize,
        mut data: &mut [u8],
        tid: Tid,
    ) -> TargetResult<usize, Self> {
        let data_len = data.len();
        let vcpu_state = &self.vcpu_state[tid_to_vcpuid(tid)];

        let vmm = &self.vmm.lock().map_err(|_| {
            error!("Error locking vmm in read addr");
            TargetError::Fatal(GdbTargetError::VmmLockError)
        })?;

        while !data.is_empty() {
            let gpa = arch::translate_gva(&vcpu_state.vcpu_fd, gva, &vmm).map_err(|e| {
                error!("Error {e:?} translating gva on read address: {gva:X}");
            })?;

            // Compute the amount space left in the page after the gpa
            let read_len = std::cmp::min(
                data.len(),
                PAGE_SIZE - (u64_to_usize(gpa) & (PAGE_SIZE - 1)),
            );

            vmm.guest_memory()
                .read(&mut data[..read_len], GuestAddress(gpa as u64))
                .map_err(|e| {
                    error!("Error reading memory {e:?} gpa is {gpa}");
                })?;

            data = &mut data[read_len..];
            gva += read_len as u64;
        }

        Ok(data_len)
    }


Review comment (bug):
Maybe we should just `unwrap` on `lock`. I feel if this even occurs this just means we have a bug somewhere, so it is better to panic. Also there are already places where we just `unwrap`.

Code after:
        arch::read_registers(&self.vcpu_state[tid_to_vcpuid(tid)].vcpu_fd, regs)?;

        Ok(())
    }

    /// Writes to the registers for the Vcpu
    fn write_registers(&mut self, regs: &CoreRegs, tid: Tid) -> TargetResult<(), Self> {
        arch::write_registers(&self.vcpu_state[tid_to_vcpuid(tid)].vcpu_fd, regs)?;

        Ok(())
    }

    /// Writes data to a guest virtual address for the Vcpu
    fn read_addrs(
        &mut self,
        mut gva: <Self::Arch as Arch>::Usize,
        mut data: &mut [u8],
        tid: Tid,
    ) -> TargetResult<usize, Self> {
        let data_len = data.len();
        let vcpu_state = &self.vcpu_state[tid_to_vcpuid(tid)];

        let vmm = &self.vmm.lock().expect("Error locking vmm in read addr");

        while !data.is_empty() {
            let gpa = arch::translate_gva(&vcpu_state.vcpu_fd, gva, &vmm).map_err(|e| {
                error!("Error {e:?} translating gva on read address: {gva:X}");
            })?;

            // Compute the amount space left in the page after the gpa
            let read_len = std::cmp::min(
                data.len(),
                PAGE_SIZE - (u64_to_usize(gpa) & (PAGE_SIZE - 1)),
            );

            vmm.guest_memory()
                .read(&mut data[..read_len], GuestAddress(gpa as u64))
                .map_err(|e| {
                    error!("Error reading memory {e:?} gpa is {gpa}");
                })?;

            data = &mut data[read_len..];
            gva += read_len as u64;
        }

        Ok(data_len)
    }

    /// Writes data at a guest virtual address for the Vcpu
    fn write_addrs(
        &mut self,