Skip to content

Commit d3ab508

Browse files
committed
feat(mm): introduce MappedPageBox
1 parent 3158627 commit d3ab508

5 files changed

Lines changed: 93 additions & 23 deletions

File tree

src/arch/aarch64/mm/paging.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ bitflags! {
7979
}
8080

8181
impl PageTableEntryFlags {
82-
#[expect(dead_code)]
8382
pub fn present(&mut self) -> &mut Self {
8483
self.insert(PageTableEntryFlags::PRESENT);
8584
self
@@ -102,7 +101,6 @@ impl PageTableEntryFlags {
102101
self
103102
}
104103

105-
#[expect(dead_code)]
106104
pub fn read_only(&mut self) -> &mut Self {
107105
self.insert(PageTableEntryFlags::READ_ONLY);
108106
self

src/arch/x86_64/kernel/apic.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::arch::mm::paging::{
2525
BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt,
2626
};
2727
use crate::arch::swapgs;
28-
use crate::mm::PageBox;
28+
use crate::mm::{MappedPageBox, PageBox};
2929
use crate::scheduler::CoreId;
3030
use crate::{arch, scheduler};
3131

@@ -420,18 +420,13 @@ fn detect_from_mp() -> Result<PhysAddr, ()> {
420420
info!("Virtual-Wire mode implemented");
421421
}
422422

423-
let layout = PageLayout::from_size(BasePageSize::SIZE as usize).unwrap();
424-
let page_range = PageBox::new(layout).unwrap();
425-
let virtual_address = VirtAddr::from(page_range.start());
426-
427423
let mut flags = PageTableEntryFlags::empty();
428424
flags.normal().writable();
429-
paging::map::<BasePageSize>(
430-
virtual_address,
431-
PhysAddr::from((mp_float.mp_config as usize).align_down(BasePageSize::SIZE as usize)),
432-
1,
433-
flags,
434-
);
425+
let layout = PageLayout::from_size(BasePageSize::SIZE as usize).unwrap();
426+
let phys_addr =
427+
PhysAddr::from((mp_float.mp_config as usize).align_down(BasePageSize::SIZE as usize));
428+
let page_range = unsafe { MappedPageBox::map_phys(phys_addr, layout, flags).unwrap() };
429+
let virtual_address = VirtAddr::from(page_range.start());
435430

436431
let mut addr: usize =
437432
(virtual_address | (u64::from(mp_float.mp_config) & (BasePageSize::SIZE - 1))) as usize;

src/arch/x86_64/mm/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,26 @@ pub fn create_new_root_page_table() -> usize {
1616
use free_list::PageLayout;
1717
use x86_64::registers::control::Cr3;
1818

19-
use crate::mm::PageBox;
19+
use crate::mm::MappedPageBox;
2020

2121
let layout = PageLayout::from_size(BasePageSize::SIZE as usize).unwrap();
2222
let frame_range = FrameAlloc::allocate(layout).unwrap();
2323
let physaddr = PhysAddr::from(frame_range.start());
2424

25-
let layout = PageLayout::from_size(2 * BasePageSize::SIZE as usize).unwrap();
26-
let page_range = PageBox::new(layout).unwrap();
27-
let virtaddr = VirtAddr::from(page_range.start());
2825
let mut flags = PageTableEntryFlags::empty();
2926
flags.normal().writable();
3027

3128
let entry: u64 = unsafe {
3229
let (frame, _flags) = Cr3::read();
33-
paging::map::<BasePageSize>(virtaddr, frame.start_address().into(), 1, flags);
34-
let entry: &u64 = &*virtaddr.as_ptr();
30+
let page_range =
31+
MappedPageBox::map_phys(frame.start_address().into(), layout, flags).unwrap();
32+
let entry: &u64 = &*VirtAddr::from(page_range.start()).as_ptr();
3533

3634
*entry
3735
};
3836

39-
let slice_addr = virtaddr + BasePageSize::SIZE;
40-
paging::map::<BasePageSize>(slice_addr, physaddr, 1, flags);
37+
let page_range = unsafe { MappedPageBox::map_phys(physaddr, layout, flags).unwrap() };
38+
let slice_addr = VirtAddr::from(page_range.start());
4139

4240
unsafe {
4341
let pml4 = slice::from_raw_parts_mut(slice_addr.as_mut_ptr(), 512);
@@ -53,8 +51,6 @@ pub fn create_new_root_page_table() -> usize {
5351
pml4[511] = physaddr.as_u64() + 0x3; // PG_PRESENT | PG_RW
5452
};
5553

56-
paging::unmap::<BasePageSize>(virtaddr, 2);
57-
5854
physaddr.as_usize()
5955
}
6056

src/mm/mapped_page_box.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use core::alloc::AllocError;
2+
use core::ops::Deref;
3+
4+
use free_list::{PageLayout, PageRange};
5+
use memory_addresses::{PhysAddr, VirtAddr};
6+
7+
use crate::arch::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
8+
use crate::mm::{FrameBox, PageBox};
9+
10+
/// A range of pages that is mapped for as long as this box is alive.
11+
pub struct MappedPageBox {
12+
frames: Option<FrameBox>,
13+
pages: PageBox,
14+
}
15+
16+
impl MappedPageBox {
17+
/// Allocates the pages and frames described by `layout` and maps them.
18+
pub fn new(layout: PageLayout, flags: PageTableEntryFlags) -> Result<Self, AllocError> {
19+
let frames = FrameBox::new(layout)?;
20+
let pages = PageBox::new(layout)?;
21+
map(&pages, PhysAddr::from(frames.start()), flags);
22+
Ok(Self {
23+
frames: Some(frames),
24+
pages,
25+
})
26+
}
27+
28+
/// Allocates the pages described by `layout` and maps them to `phys_addr`.
29+
///
30+
/// # Safety
31+
///
32+
/// - The frames at `phys_addr` must not be deallocated while the returned box is alive.
33+
pub unsafe fn map_phys(
34+
phys_addr: PhysAddr,
35+
layout: PageLayout,
36+
flags: PageTableEntryFlags,
37+
) -> Result<Self, AllocError> {
38+
let pages = PageBox::new(layout)?;
39+
map(&pages, phys_addr, flags);
40+
Ok(Self {
41+
frames: None,
42+
pages,
43+
})
44+
}
45+
}
46+
47+
impl Drop for MappedPageBox {
48+
fn drop(&mut self) {
49+
paging::unmap::<BasePageSize>(VirtAddr::from(self.pages.start()), page_count(&self.pages));
50+
51+
// `paging::unmap` only flushes the TLB of this CPU. Request the flush on
52+
// all other CPUs before the frames can be reused.
53+
#[cfg(all(target_arch = "x86_64", feature = "smp"))]
54+
crate::arch::kernel::apic::ipi_tlb_flush();
55+
56+
drop(self.frames.take());
57+
}
58+
}
59+
60+
impl Deref for MappedPageBox {
61+
type Target = PageRange;
62+
63+
fn deref(&self) -> &Self::Target {
64+
&self.pages
65+
}
66+
}
67+
68+
fn page_count(pages: &PageBox) -> usize {
69+
pages.len().get() / BasePageSize::SIZE as usize
70+
}
71+
72+
fn map(pages: &PageBox, phys_addr: PhysAddr, flags: PageTableEntryFlags) {
73+
paging::map::<BasePageSize>(
74+
VirtAddr::from(pages.start()),
75+
phys_addr,
76+
page_count(pages),
77+
flags,
78+
);
79+
}

src/mm/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
//! ```
4242
4343
pub(crate) mod device_alloc;
44+
mod mapped_page_box;
4445
mod page_range_alloc;
4546
mod physicalmem;
4647
mod virtualmem;
@@ -57,6 +58,7 @@ use talc::TalcLock;
5758
#[cfg(target_os = "none")]
5859
use talc::source::Manual;
5960

61+
pub use self::mapped_page_box::MappedPageBox;
6062
pub use self::page_range_alloc::{PageRangeAllocator, PageRangeBox};
6163
pub use self::physicalmem::{FrameAlloc, FrameBox};
6264
pub use self::virtualmem::{PageAlloc, PageBox};

0 commit comments

Comments
 (0)