Skip to content

Commit 2a111e6

Browse files
committed
feat: copy-from
1 parent fb367e4 commit 2a111e6

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

Cargo.lock

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

page_table_multiarch/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ keywords.workspace = true
1212
categories.workspace = true
1313
rust-version.workspace = true
1414

15+
[features]
16+
default = []
17+
copy-from = ["dep:bitmaps"]
18+
1519
[dependencies]
1620
log = "0.4"
1721
memory_addr.workspace = true
1822
page_table_entry = { path = "../page_table_entry", version = "0.5.2" }
23+
bitmaps = { version = "3.2", default-features = false, optional = true }
1924

2025
[target.'cfg(any(target_arch = "x86_64", doc))'.dependencies]
2126
x86 = "0.52"

page_table_multiarch/src/bits64.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const fn p1_index(vaddr: usize) -> usize {
2727
/// When the [`PageTable64`] itself is dropped.
2828
pub struct PageTable64<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> {
2929
root_paddr: PhysAddr,
30+
#[cfg(feature = "copy-from")]
31+
borrowed_entries: bitmaps::Bitmap<ENTRY_COUNT>,
3032
_phantom: PhantomData<(M, PTE, H)>,
3133
}
3234

@@ -38,6 +40,8 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
3840
let root_paddr = Self::alloc_table()?;
3941
Ok(Self {
4042
root_paddr,
43+
#[cfg(feature = "copy-from")]
44+
borrowed_entries: bitmaps::Bitmap::new(),
4145
_phantom: PhantomData,
4246
})
4347
}
@@ -325,6 +329,7 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
325329
}
326330

327331
/// Copy entries from another page table within the given virtual memory range.
332+
#[cfg(feature = "copy-from")]
328333
pub fn copy_from(&mut self, other: &Self, start: M::VirtAddr, size: usize) {
329334
if size == 0 {
330335
return;
@@ -342,7 +347,13 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
342347
let end_idx = index_fn(start.into() + size - 1) + 1;
343348
assert!(start_idx < ENTRY_COUNT);
344349
assert!(end_idx <= ENTRY_COUNT);
345-
dst_table[start_idx..end_idx].copy_from_slice(&src_table[start_idx..end_idx]);
350+
for i in start_idx..end_idx {
351+
let entry = &mut dst_table[i];
352+
if !self.borrowed_entries.set(i, true) {
353+
self.dealloc_tree(entry, 1);
354+
}
355+
*entry = src_table[i];
356+
}
346357
}
347358
}
348359

@@ -520,20 +531,31 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> PageTable64<M, PTE, H
520531
}
521532
Ok(())
522533
}
534+
535+
fn dealloc_tree(&self, entry: &PTE, level: usize) {
536+
// don't free the entries in last level, they are not array.
537+
if level < M::LEVELS - 1 {
538+
if let Ok(table) = self.next_table(entry) {
539+
for entry in table {
540+
self.dealloc_tree(entry, level + 1);
541+
}
542+
H::dealloc_frame(entry.paddr());
543+
}
544+
}
545+
}
523546
}
524547

525548
impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler> Drop for PageTable64<M, PTE, H> {
526549
fn drop(&mut self) {
527-
// don't free the entries in last level, they are not array.
528-
let _ = self.walk(
529-
usize::MAX,
530-
None,
531-
Some(&|level, _index, _vaddr, entry: &PTE| {
532-
if level < M::LEVELS - 1 && entry.is_present() && !entry.is_huge() {
533-
H::dealloc_frame(entry.paddr());
534-
}
535-
}),
536-
);
550+
let root = self.table_of(self.root_paddr);
551+
#[allow(unused_variables)]
552+
for (i, entry) in root.iter().enumerate() {
553+
#[cfg(feature = "copy-from")]
554+
if self.borrowed_entries.get(i) {
555+
continue;
556+
}
557+
self.dealloc_tree(entry, 1);
558+
}
537559
H::dealloc_frame(self.root_paddr());
538560
}
539561
}

0 commit comments

Comments
 (0)