Create user-accessible pages, which are allocated on demand ie when written to. One frame is allocated, and made writable through the first page in the range. The other pages point to the same frame but are read-only. Writes to those frames trigger a page fault, and the handler allocates a frame. This allows large user heaps to be created without using a lot of memory. Inputs ------ size Size
(
level_4_physaddr: u64,
start_addr: VirtAddr,
size: u64)
| 323 | /// size Size of memory region in bytes |
| 324 | /// |
| 325 | pub fn create_user_ondemand_pages( |
| 326 | level_4_physaddr: u64, |
| 327 | start_addr: VirtAddr, |
| 328 | size: u64) |
| 329 | -> Result<(), MapToError<Size4KiB>> { |
| 330 | |
| 331 | let memory_info = unsafe {MEMORY_INFO.as_mut().unwrap()}; |
| 332 | let frame_allocator = &mut memory_info.frame_allocator; |
| 333 | |
| 334 | let l4_table: &mut PageTable = unsafe { |
| 335 | &mut *(memory_info.physical_memory_offset |
| 336 | + level_4_physaddr).as_mut_ptr()}; |
| 337 | |
| 338 | let mut mapper = unsafe { |
| 339 | OffsetPageTable::new(l4_table, |
| 340 | memory_info.physical_memory_offset)}; |
| 341 | |
| 342 | let page_range = { |
| 343 | let end_addr = start_addr + size - 1u64; |
| 344 | let start_page = Page::containing_address(start_addr); |
| 345 | let end_page = Page::containing_address(end_addr); |
| 346 | Page::range_inclusive(start_page, end_page) |
| 347 | }; |
| 348 | |
| 349 | // Only allocating one frame |
| 350 | let frame = frame_allocator |
| 351 | .allocate_frame() |
| 352 | .ok_or(MapToError::FrameAllocationFailed)?; |
| 353 | |
| 354 | for page in page_range { |
| 355 | unsafe { |
| 356 | mapper.map_to_with_table_flags(page, |
| 357 | frame, |
| 358 | // Page not writable |
| 359 | PageTableFlags::PRESENT | |
| 360 | PageTableFlags::USER_ACCESSIBLE, |
| 361 | // Parent table flags include writable |
| 362 | PageTableFlags::PRESENT | |
| 363 | PageTableFlags::WRITABLE | |
| 364 | PageTableFlags::USER_ACCESSIBLE, |
| 365 | frame_allocator)?.flush() |
| 366 | }; |
| 367 | } |
| 368 | |
| 369 | // Make one page writable, so this 'owns' the frame |
| 370 | unsafe { |
| 371 | mapper.update_flags(page_range.start, |
| 372 | PageTableFlags::PRESENT | |
| 373 | PageTableFlags::WRITABLE | |
| 374 | PageTableFlags::USER_ACCESSIBLE) |
| 375 | .map_err(|_| MapToError::FrameAllocationFailed)? |
| 376 | .flush(); // Update page table |
| 377 | } |
| 378 | |
| 379 | Ok(()) |
| 380 | } |
| 381 | |
| 382 | /// Map a consecutive set of pages to a consecutive set of frames |
no test coverage detected