Jelajahi Sumber

refactor(mm): add level choose in kernel iterator

Heinz 8 bulan lalu
induk
melakukan
1fa2d6f94d

+ 5 - 3
crates/eonix_mm/src/page_table/page_table.rs

@@ -83,10 +83,12 @@ where
             M::RawTable::from_ptr(page_table_ptr)
         };
 
-        PageTableIterator::<M, A, X, UserIterator>::new(root_page_table, range, alloc.clone())
+        // default 3 level
+        PageTableIterator::<M, A, X, UserIterator>::new(root_page_table, range, alloc.clone(), M::LEVELS.len() - 1)
     }
 
-    pub fn iter_kernel(&self, range: VRange) -> impl Iterator<Item = &mut M::Entry> {
+    pub fn iter_kernel(&self, range: VRange, level_in_array: usize) -> impl Iterator<Item = &mut M::Entry> {
+        assert!(0 < level_in_array && level_in_array < M::LEVELS.len(), "Invalid page table level");
         let alloc = self.root_table_page.allocator();
         let page_table_ptr = X::get_ptr_for_page(&self.root_table_page);
         let root_page_table = unsafe {
@@ -94,7 +96,7 @@ where
             M::RawTable::from_ptr(page_table_ptr)
         };
 
-        PageTableIterator::<M, A, X, KernelIterator>::new(root_page_table, range, alloc.clone())
+        PageTableIterator::<M, A, X, KernelIterator>::new(root_page_table, range, alloc.clone(), level_in_array)
     }
 
     fn drop_page_table_recursive(page_table: &Page<A>, levels: &[PageTableLevel]) {

+ 21 - 12
crates/eonix_mm/src/page_table/pte_iterator.rs

@@ -4,9 +4,9 @@ use super::{
 };
 use crate::{
     address::{AddrOps as _, VRange},
-    paging::{Page, PageAccess, PageAlloc, PAGE_SIZE},
+    paging::{Page, PageAccess, PageAlloc, LEVEL0_PAGE_SIZE, LEVEL1_PAGE_SIZE, LEVEL2_PAGE_SIZE},
 };
-use core::marker::PhantomData;
+use core::{marker::PhantomData, panic};
 
 pub struct KernelIterator;
 pub struct UserIterator;
@@ -60,6 +60,8 @@ where
     X: PageAccess,
     K: IteratorType<M>,
 {
+    // from root to down: 0 1 2 3
+    level_in_array: usize,
     remaining: usize,
 
     indicies: [u16; 8],
@@ -78,13 +80,12 @@ where
     K: IteratorType<M>,
 {
     fn parse_tables_starting_from(&mut self, idx_level: usize) {
-        let levels_len = M::LEVELS.len();
 
         for (idx, &pt_idx) in self
             .indicies
             .iter()
             .enumerate()
-            .take(levels_len - 1)
+            .take(self.level_in_array)
             .skip(idx_level)
         {
             let [parent_table, child_table] = unsafe {
@@ -99,12 +100,20 @@ where
         }
     }
 
-    pub fn new(page_table: M::RawTable<'a>, range: VRange, alloc: A) -> Self {
+    pub fn new(page_table: M::RawTable<'a>, range: VRange, alloc: A, level_in_array: usize) -> Self {
         let start = range.start().floor();
         let end = range.end().ceil();
 
+        // not allow to modify root page table
+        let page_size = match level_in_array {
+            1 => LEVEL2_PAGE_SIZE,
+            2 => LEVEL1_PAGE_SIZE,
+            3 => LEVEL0_PAGE_SIZE,
+            _ => panic!("Out of index"),
+        };
         let mut me = Self {
-            remaining: (end - start) / PAGE_SIZE,
+            level_in_array,
+            remaining: (end - start) / page_size,
             indicies: [0; 8],
             tables: [const { None }; 8],
             alloc,
@@ -139,25 +148,25 @@ where
             self.remaining -= 1;
         }
 
-        let len_levels = M::LEVELS.len();
-
-        let retval = self.tables[len_levels - 1]
+        let retval = self.tables[self.level_in_array]
             .as_mut()
             .unwrap()
-            .index_mut(self.indicies[len_levels - 1]);
+            .index_mut(self.indicies[self.level_in_array]);
 
         let idx_level_start_updating = M::LEVELS
             .iter()
             .zip(self.indicies.iter_mut())
             .enumerate()
             .rev()
-            .skip_while(|(_, (level, idx))| **idx == level.max_index())
+            .skip_while(|(i, (level, idx))| {
+                *i >= self.level_in_array && **idx == level.max_index()
+            })
             .map(|(i, _)| i)
             .next()
             .expect("Index out of bounds");
 
         self.indicies[idx_level_start_updating] += 1;
-        self.indicies[idx_level_start_updating + 1..len_levels].fill(0);
+        self.indicies[idx_level_start_updating + 1..self.level_in_array].fill(0);
         self.parse_tables_starting_from(idx_level_start_updating);
 
         Some(retval)

+ 1 - 1
crates/eonix_mm/src/paging.rs

@@ -3,7 +3,7 @@ mod page_alloc;
 mod pfn;
 mod raw_page;
 
-pub use page::{Page, PageAccess, PageBlock, PAGE_SIZE, PAGE_SIZE_BITS};
+pub use page::{Page, PageAccess, PageBlock, PAGE_SIZE, LEVEL0_PAGE_SIZE, LEVEL1_PAGE_SIZE, LEVEL2_PAGE_SIZE, PAGE_SIZE_BITS};
 pub use page_alloc::{GlobalPageAlloc, PageAlloc};
 pub use pfn::PFN;
 pub use raw_page::RawPage;

+ 3 - 0
crates/eonix_mm/src/paging/page.rs

@@ -3,6 +3,9 @@ use crate::address::{AddrRange, PAddr};
 use core::{fmt, mem::ManuallyDrop, ptr::NonNull, sync::atomic::Ordering};
 
 pub const PAGE_SIZE: usize = 4096;
+pub const LEVEL0_PAGE_SIZE: usize = 4096;
+pub const LEVEL1_PAGE_SIZE: usize = 2 * 1024 * 1024;
+pub const LEVEL2_PAGE_SIZE: usize = 1 * 1024 * 1024 * 1024;
 pub const PAGE_SIZE_BITS: u32 = PAGE_SIZE.trailing_zeros();
 
 /// A block of memory that is aligned to the page size and can be used for