| 2124 | |
| 2125 | impl<M: GuestAddressSpace + Sync + Send> ExternalDmaMapping for VfioDmaMapping<M> { |
| 2126 | fn map(&self, iova: u64, gpa: u64, size: u64) -> std::result::Result<(), io::Error> { |
| 2127 | let Ok(usize_size): Result<usize, _> = size.try_into() else { |
| 2128 | return Err(io::Error::other(format!("size {size} overflows usize"))); |
| 2129 | }; |
| 2130 | let mem = self.memory.memory(); |
| 2131 | let guest_addr = GuestAddress(gpa); |
| 2132 | let user_addr = if mem.check_range(guest_addr, usize_size) { |
| 2133 | match mem.get_slice(guest_addr, usize_size) { |
| 2134 | Ok(t) => { |
| 2135 | assert!(t.len() >= usize_size); |
| 2136 | Ok(t.ptr_guard_mut()) |
| 2137 | } |
| 2138 | Err(e) => { |
| 2139 | return Err(io::Error::other(format!( |
| 2140 | "unable to retrieve user address for gpa 0x{gpa:x} from guest memory region: {e}" |
| 2141 | ))); |
| 2142 | } |
| 2143 | } |
| 2144 | } else if self.mmio_regions.lock().unwrap().check_range(gpa, size) { |
| 2145 | Err(self |
| 2146 | .mmio_regions |
| 2147 | .lock() |
| 2148 | .unwrap() |
| 2149 | .find_user_address(gpa, size)?) |
| 2150 | } else { |
| 2151 | return Err(io::Error::other(format!( |
| 2152 | "failed to locate guest address 0x{gpa:x} in guest memory" |
| 2153 | ))); |
| 2154 | }; |
| 2155 | let user_addr = match user_addr { |
| 2156 | Ok(p) => p.as_ptr(), |
| 2157 | Err(p) => p, |
| 2158 | }; |
| 2159 | |
| 2160 | // vfio_dma_map is unsound and ought to be marked as unsafe |
| 2161 | #[allow(unused_unsafe)] |
| 2162 | // SAFETY: find_user_address and GuestMemory::get_slice() guarantee that |
| 2163 | // the returned pointer is valid for up to `usize_size` bytes. |
| 2164 | // `usize_size` is always equal to `size` due to the above `try_into()` call. |
| 2165 | unsafe { self.vfio_ops.vfio_dma_map(iova, size as usize, user_addr) }.map_err(|e| { |
| 2166 | io::Error::other(format!( |
| 2167 | "failed to map memory into the host IOMMU address space, \ |
| 2168 | iova 0x{iova:x}, gpa 0x{gpa:x}, size 0x{size:x}: {e:?}" |
| 2169 | )) |
| 2170 | }) |
| 2171 | } |
| 2172 | |
| 2173 | fn unmap(&self, iova: u64, size: u64) -> std::result::Result<(), io::Error> { |
| 2174 | self.vfio_ops |