page_table.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. use super::{
  2. paging_mode::PageTableLevel,
  3. pte::{RawAttribute, TableAttribute},
  4. pte_iterator::{KernelIterator, UserIterator},
  5. PagingMode, PTE,
  6. };
  7. use crate::{
  8. address::{PAddr, VRange},
  9. page_table::PageTableIterator,
  10. paging::{GlobalPageAlloc, Page, PageAccess, PageAlloc, PageBlock},
  11. };
  12. use core::{marker::PhantomData, ptr::NonNull};
  13. pub trait RawPageTable<'a>: 'a {
  14. type Entry: PTE + 'a;
  15. /// Return the entry at the given index.
  16. fn index(&self, index: u16) -> &'a Self::Entry;
  17. /// Return a mutable reference to the entry at the given index.
  18. fn index_mut(&mut self, index: u16) -> &'a mut Self::Entry;
  19. /// Get the page table pointed to by raw pointer `ptr`.
  20. unsafe fn from_ptr(ptr: NonNull<PageBlock>) -> Self;
  21. }
  22. pub struct PageTable<'a, M, A, X>
  23. where
  24. M: PagingMode,
  25. M::Entry: 'a,
  26. A: PageAlloc,
  27. X: PageAccess,
  28. {
  29. root_table_page: Page<A>,
  30. phantom: PhantomData<&'a (M, X)>,
  31. }
  32. impl<'a, M, A, X> PageTable<'a, M, A, X>
  33. where
  34. M: PagingMode,
  35. M::Entry: 'a,
  36. A: PageAlloc,
  37. X: PageAccess,
  38. {
  39. pub fn with_root_table(root_table_page: Page<A>) -> Self {
  40. Self {
  41. root_table_page,
  42. phantom: PhantomData,
  43. }
  44. }
  45. pub fn clone_global<'b, B>(&self) -> PageTable<'b, M, B, X>
  46. where
  47. B: GlobalPageAlloc,
  48. {
  49. self.clone_in(B::global())
  50. }
  51. pub fn clone_in<'b, B>(&self, alloc: B) -> PageTable<'b, M, B, X>
  52. where
  53. B: PageAlloc,
  54. {
  55. let new_root_table_page = Page::alloc_in(alloc);
  56. let new_table_data = X::get_ptr_for_page(&new_root_table_page);
  57. let kernel_table_data = X::get_ptr_for_page(&self.root_table_page);
  58. unsafe {
  59. // SAFETY: `new_table_data` and `kernel_table_data` are both valid pointers
  60. // to **different** page tables.
  61. new_table_data.copy_from_nonoverlapping(kernel_table_data, 1);
  62. }
  63. let mut root_page_table = unsafe {
  64. // SAFETY: `page_table_ptr` is a valid pointer to a page table.
  65. M::RawTable::from_ptr(new_table_data)
  66. };
  67. let level0 = M::LEVELS[0];
  68. for idx in 0..=level0.max_index() / 2 {
  69. // We consider the first half of the page table as user space.
  70. // Clear all (potential) user space mappings.
  71. root_page_table.index_mut(idx).take();
  72. }
  73. PageTable::with_root_table(new_root_table_page)
  74. }
  75. pub fn addr(&self) -> PAddr {
  76. self.root_table_page.start()
  77. }
  78. pub fn iter_user(&self, range: VRange) -> impl Iterator<Item = &mut M::Entry> {
  79. let alloc = self.root_table_page.allocator();
  80. let page_table_ptr = X::get_ptr_for_page(&self.root_table_page);
  81. let root_page_table = unsafe {
  82. // SAFETY: `page_table_ptr` is a valid pointer to a page table.
  83. M::RawTable::from_ptr(page_table_ptr)
  84. };
  85. PageTableIterator::<M, A, X, UserIterator>::new(root_page_table, range, alloc.clone())
  86. }
  87. pub fn iter_kernel(&self, range: VRange) -> impl Iterator<Item = &mut M::Entry> {
  88. self.iter_kernel_levels(range, M::LEVELS)
  89. }
  90. /// Iterates over the kernel space entries in the page table for the specified levels.
  91. ///
  92. /// # Parameters
  93. /// - `range`: The virtual address range to iterate over.
  94. /// - `levels`: A slice of `PageTableLevel` that specifies which levels of the page table
  95. /// should be included in the iteration. Each level corresponds to a level in the page
  96. /// table hierarchy, and the iterator will traverse entries at these levels.
  97. ///
  98. /// # Returns
  99. /// An iterator over mutable references to the page table entries (`M::Entry`) within the
  100. /// specified range and levels.
  101. ///
  102. /// # Example
  103. /// ```
  104. /// let range = VRange::new(0x1234000, 0x1300000);
  105. /// let levels = &M::LEVELS[..2];
  106. /// for pte in page_table.iter_kernel_levels(range, levels) {
  107. /// // Process each entry
  108. /// }
  109. /// ```
  110. pub fn iter_kernel_levels(
  111. &self,
  112. range: VRange,
  113. levels: &'static [PageTableLevel],
  114. ) -> impl Iterator<Item = &mut M::Entry> {
  115. self.iter_kernel_in(range, levels, self.root_table_page.allocator())
  116. }
  117. /// Iterates over the kernel space entries in the page table for the specified levels
  118. /// with a given page allocator.
  119. ///
  120. /// # Parameters
  121. /// - `range`: The virtual address range to iterate over.
  122. /// - `levels`: A slice of `PageTableLevel` that specifies which levels of the page table
  123. /// should be included in the iteration. Each level corresponds to a level in the page
  124. /// table hierarchy, and the iterator will traverse entries at these levels.
  125. /// - `alloc`: A page allocator that provides memory for the page table entries.
  126. ///
  127. /// # Returns
  128. /// An iterator over mutable references to the page table entries (`M::Entry`) within the
  129. /// specified range and levels.
  130. ///
  131. /// # Example
  132. /// ```no_run
  133. /// let range = VRange::new(0x1234000, 0x1300000);
  134. /// let levels = &M::LEVELS[..2];
  135. /// for pte in page_table.iter_kernel_in(range, levels, NoAlloc) {
  136. /// // Process each entry
  137. /// }
  138. /// ```
  139. pub fn iter_kernel_in<A1: PageAlloc>(
  140. &self,
  141. range: VRange,
  142. levels: &'static [PageTableLevel],
  143. alloc: A1,
  144. ) -> impl Iterator<Item = &mut M::Entry> {
  145. let page_table_ptr = X::get_ptr_for_page(&self.root_table_page);
  146. let root_page_table = unsafe {
  147. // SAFETY: `page_table_ptr` is a valid pointer to a page table.
  148. M::RawTable::from_ptr(page_table_ptr)
  149. };
  150. PageTableIterator::<M, A1, X, KernelIterator>::with_levels(
  151. root_page_table,
  152. range,
  153. alloc,
  154. levels,
  155. )
  156. }
  157. fn drop_page_table_recursive(page_table: &Page<A>, levels: &[PageTableLevel]) {
  158. let [level, remaining_levels @ ..] = levels else { return };
  159. let alloc = page_table.allocator();
  160. let page_table_ptr = X::get_ptr_for_page(page_table);
  161. let mut page_table = unsafe {
  162. // SAFETY: `page_table_ptr` is a valid pointer to a page table.
  163. M::RawTable::from_ptr(page_table_ptr)
  164. };
  165. for pte in (0..=level.max_index()).map(|i| page_table.index_mut(i)) {
  166. let (pfn, attr) = pte.take();
  167. let Some(attr) = attr.as_table_attr() else {
  168. continue;
  169. };
  170. if !attr.contains(TableAttribute::PRESENT | TableAttribute::USER) {
  171. continue;
  172. }
  173. let page_table = unsafe {
  174. // SAFETY: We got the pfn from a valid page table entry, so it should be valid.
  175. Page::from_raw_in(pfn, alloc.clone())
  176. };
  177. Self::drop_page_table_recursive(&page_table, remaining_levels);
  178. }
  179. }
  180. }
  181. impl<'a, M, A, X> Drop for PageTable<'a, M, A, X>
  182. where
  183. M: PagingMode,
  184. M::Entry: 'a,
  185. A: PageAlloc,
  186. X: PageAccess,
  187. {
  188. fn drop(&mut self) {
  189. Self::drop_page_table_recursive(&self.root_table_page, M::LEVELS);
  190. }
  191. }