Allocate a consecutive set of frames num_frames The number of frames required max_address The maximum physical address in the set e.g. for 32-bit addresses 0xFFFF_FFFF Returns the number of the first frame, or None if a set could not be found. Brute force search of lowest level bitmap. This is not very efficient, and is not intended to be called in performance-critical code.
(
&mut self,
needed_frames: u64,
max_address: u64
)
| 300 | /// very efficient, and is not intended to be called in |
| 301 | /// performance-critical code. |
| 302 | fn consecutive_frames( |
| 303 | &mut self, |
| 304 | needed_frames: u64, |
| 305 | max_address: u64 |
| 306 | ) -> Option<u64> { |
| 307 | // Ensure that there is at least one frame in range |
| 308 | if max_address < (self.frame_phys_addr.as_u64() + 4095) { |
| 309 | return None; |
| 310 | } |
| 311 | |
| 312 | // Restrict the number of frames to those under the address limit |
| 313 | let max_frames = (max_address + 1 - self.frame_phys_addr.as_u64()) >> 12; |
| 314 | let nframes = if max_frames < self.nframes {max_frames} else {self.nframes}; |
| 315 | |
| 316 | // Number of 32-bit chunks to search |
| 317 | let nchunks = (nframes >> 5) + if nframes & 31 != 0 {1} else {0}; |
| 318 | |
| 319 | // Pointer to lowest level frame bitmap |
| 320 | let ptr = self.bitmap_virt_addr[0].as_mut_ptr() as *mut u32; |
| 321 | |
| 322 | let mut count = 0; // How many consecutive frames found so far? |
| 323 | for chunk in 0..nchunks { |
| 324 | let bitmap = unsafe{*ptr.offset(chunk as isize)}; |
| 325 | |
| 326 | for pos in 0..32 { |
| 327 | if bitmap & (1 << pos) == 0 { |
| 328 | // Not available |
| 329 | count = 0; |
| 330 | } else { |
| 331 | // Available frame |
| 332 | count += 1; |
| 333 | if count == needed_frames { |
| 334 | // Found a consecutive set of frames |
| 335 | let start_frame = (chunk << 5) + pos + 1 - count; |
| 336 | |
| 337 | // Mark each frame as taken |
| 338 | for frame in start_frame..(start_frame + needed_frames) { |
| 339 | let mut chunk_number = frame; |
| 340 | |
| 341 | // Clear higher bitmaps if the chunk is empty |
| 342 | for level in 0..self.nlevels { |
| 343 | // Low 5 bits of the chunk at the lower level are the index at this level |
| 344 | let index = chunk_number & 31; |
| 345 | // High bits are the chunk at this level |
| 346 | chunk_number = chunk_number >> 5; |
| 347 | |
| 348 | let ptr = unsafe{(self.bitmap_virt_addr[level].as_mut_ptr() as *mut u32) |
| 349 | .offset(chunk_number as isize)}; |
| 350 | let mut bitmap = unsafe{*ptr}; |
| 351 | |
| 352 | bitmap &= !(1 << index); // clear bit |
| 353 | unsafe {core::ptr::write(ptr, bitmap)}; |
| 354 | |
| 355 | if bitmap != 0 { |
| 356 | // This chunk still has frames => stop clearing |
| 357 | break; |
| 358 | } |
| 359 | } |
no test coverage detected