Skip to main content

hermit/mm/
mapped_page_box.rs

1use core::alloc::AllocError;
2
3use free_list::{PageLayout, PageRange};
4use memory_addresses::{PhysAddr, VirtAddr};
5
6use crate::arch::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
7use crate::mm::{FrameBox, PageBox};
8
9/// A range of pages that is mapped for as long as this box is alive.
10pub struct MappedPageBox {
11	_frames: Option<FrameBox>,
12	pages: PageBox,
13}
14
15impl MappedPageBox {
16	/// Allocates the pages and frames described by `layout` and maps them.
17	pub fn new(layout: PageLayout, flags: PageTableEntryFlags) -> Result<Self, AllocError> {
18		let frames = FrameBox::new(layout)?;
19		let pages = PageBox::new(layout)?;
20		let page_count = pages.len().get() / BasePageSize::SIZE as usize;
21		paging::map::<BasePageSize>(
22			VirtAddr::from(pages.start()),
23			PhysAddr::from(frames.start()),
24			page_count,
25			flags,
26		);
27
28		Ok(Self {
29			_frames: Some(frames),
30			pages,
31		})
32	}
33
34	/// Allocates the pages described by `layout` and maps them to `phys_addr`.
35	///
36	/// # Safety
37	///
38	/// - The frames at `phys_addr` must not be deallocated while the returned box is alive.
39	pub unsafe fn map_phys(
40		phys_addr: PhysAddr,
41		layout: PageLayout,
42		flags: PageTableEntryFlags,
43	) -> Result<Self, AllocError> {
44		let pages = PageBox::new(layout)?;
45		let page_count = pages.len().get() / BasePageSize::SIZE as usize;
46		paging::map::<BasePageSize>(VirtAddr::from(pages.start()), phys_addr, page_count, flags);
47
48		Ok(Self {
49			_frames: None,
50			pages,
51		})
52	}
53
54	pub fn pages(&self) -> &PageRange {
55		&self.pages
56	}
57}
58
59impl Drop for MappedPageBox {
60	fn drop(&mut self) {
61		let page_count = self.pages.len().get() / BasePageSize::SIZE as usize;
62		paging::unmap::<BasePageSize>(VirtAddr::from(self.pages.start()), page_count);
63	}
64}