Skip to content

Commit 2020156

Browse files
authored
Update PagingHandler, adding methods for allocating/deallocating multiple frames (#37)
* add methods for allocating/deallocating multiple frams to `PagingHandler`, add default implementation for single-page allocation/deallocation * bump to 0.6.0
1 parent 7825acd commit 2020156

File tree

5 files changed

+77
-9
lines changed

5 files changed

+77
-9
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ resolver = "2"
44
members = ["page_table_multiarch", "page_table_entry"]
55

66
[workspace.package]
7-
version = "0.5.7"
7+
version = "0.6.0"
88
edition = "2024"
99
authors = ["Yuekai Jia <[email protected]>"]
1010
license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPSL-2.0"
@@ -17,4 +17,4 @@ rust-version = "1.85"
1717

1818
[workspace.dependencies]
1919
memory_addr = "0.4"
20-
page_table_entry = { path = "page_table_entry", version = "0.5" }
20+
page_table_entry = { path = "page_table_entry", version = "0.6" }

page_table_multiarch/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,20 @@ impl PagingHandler for PagingHandlerImpl {
4949
Some(PhysAddr::from(ptr as usize))
5050
}
5151

52+
fn alloc_frames(num: usize, align_pow2: usize) -> Option<PhysAddr> {
53+
todo!();
54+
}
55+
5256
fn dealloc_frame(paddr: PhysAddr) {
5357
let layout = Layout::from_size_align(0x1000, 0x1000).unwrap();
5458
let ptr = paddr.as_usize() as *mut u8;
5559
unsafe { alloc::alloc::dealloc(ptr, layout) };
5660
}
5761

62+
fn dealloc_frames(paddr: PhysAddr, num: usize) {
63+
todo!();
64+
}
65+
5866
fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
5967
VirtAddr::from(paddr.as_usize())
6068
}

page_table_multiarch/src/lib.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod bits64;
1010

1111
use core::{fmt::Debug, marker::PhantomData};
1212

13-
use memory_addr::{MemoryAddr, PhysAddr, VirtAddr};
13+
use memory_addr::{MemoryAddr, PAGE_SIZE_4K, PhysAddr, VirtAddr};
1414
#[doc(no_inline)]
1515
pub use page_table_entry::{GenericPTE, MappingFlags};
1616

@@ -90,9 +90,20 @@ pub trait PagingMetaData: Sync + Send {
9090
/// [`PageTable64`].
9191
pub trait PagingHandler: Sized {
9292
/// Request to allocate a 4K-sized physical frame.
93-
fn alloc_frame() -> Option<PhysAddr>;
93+
fn alloc_frame() -> Option<PhysAddr> {
94+
Self::alloc_frames(1, PAGE_SIZE_4K)
95+
}
96+
/// Allocate `num` contiguous physical frames, with the starting physical
97+
/// address aligned to `align` bytes (must be a power of two, and must be
98+
/// a multiple of 4K).
99+
fn alloc_frames(num: usize, align: usize) -> Option<PhysAddr>;
94100
/// Request to free a allocated physical frame.
95-
fn dealloc_frame(paddr: PhysAddr);
101+
fn dealloc_frame(paddr: PhysAddr) {
102+
Self::dealloc_frames(paddr, 1)
103+
}
104+
/// Free `num` contiguous physical frames starting from the given physical
105+
/// address. The `num` must be the same as that used in allocation.
106+
fn dealloc_frames(paddr: PhysAddr, num: usize);
96107
/// Returns a virtual address that maps to the given physical address.
97108
///
98109
/// Used to access the physical memory directly in page table

page_table_multiarch/tests/alloc_tests.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
alloc::{self, Layout},
33
cell::RefCell,
4-
collections::HashSet,
4+
collections::{HashMap, HashSet},
55
marker::PhantomData,
66
};
77

@@ -10,10 +10,23 @@ use page_table_entry::{GenericPTE, MappingFlags};
1010
use page_table_multiarch::{PageSize, PageTable64, PagingHandler, PagingMetaData, PagingResult};
1111
use rand::{Rng, SeedableRng, rngs::SmallRng};
1212

13-
const PAGE_LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(4096, 4096) };
13+
/// Creates a layout for allocating `num` pages with alignment of `2^align_pow2`
14+
/// pages.
15+
const fn pages_layout(num: usize, align: usize) -> Layout {
16+
if !align.is_power_of_two() {
17+
panic!("alignment must be a power of two");
18+
}
19+
if align % 4096 != 0 {
20+
panic!("alignment must be a multiple of 4K");
21+
}
22+
unsafe { Layout::from_size_align_unchecked(4096 * num, align) }
23+
}
24+
25+
const PAGE_LAYOUT: Layout = pages_layout(1, 4096);
1426

1527
thread_local! {
1628
static ALLOCATED: RefCell<HashSet<usize>> = RefCell::default();
29+
static ALIGN: RefCell<HashMap<usize, usize>> = RefCell::default();
1730
}
1831

1932
struct TrackPagingHandler<M: PagingMetaData>(PhantomData<M>);
@@ -29,6 +42,24 @@ impl<M: PagingMetaData> PagingHandler for TrackPagingHandler<M> {
2942
Some(PhysAddr::from_usize(ptr))
3043
}
3144

45+
fn alloc_frames(num: usize, align: usize) -> Option<PhysAddr> {
46+
let layout = pages_layout(num, align);
47+
let ptr = unsafe { alloc::alloc(layout) } as usize;
48+
assert!(
49+
ptr <= M::PA_MAX_ADDR,
50+
"allocated frame address exceeds PA_MAX_ADDR"
51+
);
52+
ALLOCATED.with_borrow_mut(|it| {
53+
for i in 0..num {
54+
it.insert(ptr + i * 4096);
55+
}
56+
});
57+
ALIGN.with_borrow_mut(|it| {
58+
it.insert(ptr, align);
59+
});
60+
Some(PhysAddr::from_usize(ptr))
61+
}
62+
3263
fn dealloc_frame(paddr: PhysAddr) {
3364
let ptr = paddr.as_usize();
3465
ALLOCATED.with_borrow_mut(|it| {
@@ -39,6 +70,24 @@ impl<M: PagingMetaData> PagingHandler for TrackPagingHandler<M> {
3970
}
4071
}
4172

73+
fn dealloc_frames(paddr: PhysAddr, num: usize) {
74+
let ptr = paddr.as_usize();
75+
ALLOCATED.with_borrow_mut(|it| {
76+
for i in 0..num {
77+
let addr = ptr + i * 4096;
78+
assert!(it.remove(&addr), "dealloc a frame that was not allocated");
79+
}
80+
});
81+
let align = ALIGN.with_borrow_mut(|it| {
82+
it.remove(&ptr)
83+
.expect("dealloc frames that were not allocated")
84+
});
85+
let layout = pages_layout(num, align);
86+
unsafe {
87+
alloc::dealloc(ptr as _, layout);
88+
}
89+
}
90+
4291
fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
4392
assert!(paddr.as_usize() > 0);
4493
VirtAddr::from_usize(paddr.as_usize())

0 commit comments

Comments
 (0)