(&mut self, queue_index: usize)
| 270 | } |
| 271 | |
| 272 | fn process_queue(&mut self, queue_index: usize) -> result::Result<(), Error> { |
| 273 | let mut used_descs = false; |
| 274 | while let Some(mut desc_chain) = |
| 275 | self.queues[queue_index].pop_descriptor_chain(self.mem.memory()) |
| 276 | { |
| 277 | let data_chunk_size = size_of::<u32>(); |
| 278 | |
| 279 | while let Some(desc) = desc_chain.next() { |
| 280 | if desc.is_write_only() { |
| 281 | warn!("Skipping device-writable descriptor on inflate/deflate queue"); |
| 282 | continue; |
| 283 | } |
| 284 | if !(desc.len() as usize).is_multiple_of(data_chunk_size) { |
| 285 | warn!( |
| 286 | "Skipping descriptor with length {} not a multiple of {data_chunk_size}", |
| 287 | desc.len() |
| 288 | ); |
| 289 | continue; |
| 290 | } |
| 291 | if desc.len() > VIRTIO_BALLOON_MAX_PFN_BYTES { |
| 292 | warn!( |
| 293 | "Skipping descriptor with length {} exceeding cap {VIRTIO_BALLOON_MAX_PFN_BYTES}", |
| 294 | desc.len() |
| 295 | ); |
| 296 | continue; |
| 297 | } |
| 298 | |
| 299 | let mut offset = 0u64; |
| 300 | while offset < desc.len() as u64 { |
| 301 | let Some(base) = desc.addr().checked_add(offset) else { |
| 302 | warn!("Address overflow in balloon descriptor"); |
| 303 | break; |
| 304 | }; |
| 305 | let addr = match base |
| 306 | .translate_gva(self.access_platform.as_deref(), data_chunk_size) |
| 307 | { |
| 308 | Ok(a) => a, |
| 309 | Err(e) => { |
| 310 | warn!("Failed to translate descriptor address: {e}"); |
| 311 | break; |
| 312 | } |
| 313 | }; |
| 314 | let pfn: u32 = match desc_chain.memory().read_obj(addr) { |
| 315 | Ok(v) => v, |
| 316 | Err(e) => { |
| 317 | warn!("Failed to read PFN from descriptor: {e}"); |
| 318 | break; |
| 319 | } |
| 320 | }; |
| 321 | offset += data_chunk_size as u64; |
| 322 | |
| 323 | match queue_index { |
| 324 | 0 => { |
| 325 | if let Err(e) = Self::release_memory_range_4k( |
| 326 | &mut self.pbp, |
| 327 | desc_chain.memory(), |
| 328 | pfn, |
| 329 | ) { |
no test coverage detected