pte_iterator.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. use super::{
  2. pte::{RawAttribute, TableAttribute},
  3. PageTableLevel, PagingMode, RawPageTable as _, PTE,
  4. };
  5. use crate::{
  6. address::{AddrOps as _, VRange},
  7. paging::{Page, PageAccess, PageAlloc, PAGE_SIZE},
  8. };
  9. use core::marker::PhantomData;
  10. pub struct KernelIterator;
  11. pub struct UserIterator;
  12. pub trait IteratorType<M: PagingMode> {
  13. fn page_table_attributes() -> TableAttribute;
  14. fn get_page_table<'a, A, X>(pte: &mut M::Entry, alloc: &A) -> M::RawTable<'a>
  15. where
  16. A: PageAlloc,
  17. X: PageAccess,
  18. {
  19. let attr = pte.get_attr().as_table_attr().expect("Not a page table");
  20. if attr.contains(TableAttribute::PRESENT) {
  21. let pfn = pte.get_pfn();
  22. unsafe {
  23. // SAFETY: We are creating a pointer to a page referenced to in
  24. // some page table, which should be valid.
  25. let page_table_ptr = X::get_ptr_for_pfn(pfn);
  26. // SAFETY: `page_table_ptr` is a valid pointer to a page table.
  27. M::RawTable::from_ptr(page_table_ptr)
  28. }
  29. } else {
  30. let page = Page::alloc_in(alloc.clone());
  31. let page_table_ptr = X::get_ptr_for_page(&page);
  32. unsafe {
  33. // SAFETY: `page_table_ptr` is good for writing and properly aligned.
  34. page_table_ptr.write_bytes(0, 1);
  35. }
  36. pte.set(
  37. page.into_raw(),
  38. <M::Entry as PTE>::Attr::from_table_attr(Self::page_table_attributes()),
  39. );
  40. unsafe {
  41. // SAFETY: `page_table_ptr` is a valid pointer to a page table.
  42. M::RawTable::from_ptr(page_table_ptr)
  43. }
  44. }
  45. }
  46. }
  47. pub struct PageTableIterator<'a, M, A, X, K>
  48. where
  49. M: PagingMode,
  50. M::Entry: 'a,
  51. A: PageAlloc,
  52. X: PageAccess,
  53. {
  54. /// Specifies the hierarchy of page table levels to iterate over.
  55. /// This field determines the sequence of levels in the page table
  56. /// hierarchy that the iterator will traverse, starting from the
  57. /// highest level and moving down to the lowest.
  58. levels: &'static [PageTableLevel],
  59. remaining: usize,
  60. indicies: [u16; 8],
  61. tables: [Option<M::RawTable<'a>>; 8],
  62. alloc: A,
  63. _phantom: PhantomData<&'a (X, K)>,
  64. }
  65. impl<'a, M, A, X, K> PageTableIterator<'a, M, A, X, K>
  66. where
  67. M: PagingMode,
  68. M::Entry: 'a,
  69. A: PageAlloc,
  70. X: PageAccess,
  71. K: IteratorType<M>,
  72. {
  73. fn parse_tables_starting_from(&mut self, idx_level: usize) {
  74. for (idx, &pt_idx) in self
  75. .indicies
  76. .iter()
  77. .enumerate()
  78. .take(self.levels.len() - 1)
  79. .skip(idx_level)
  80. {
  81. let [parent_table, child_table] = unsafe {
  82. // SAFETY: `idx` and `idx + 1` must not overlap.
  83. // `idx + 1` is always less than `levels_len` since we iterate
  84. // until `levels_len - 1`.
  85. self.tables.get_disjoint_unchecked_mut([idx, idx + 1])
  86. };
  87. let parent_table = parent_table.as_mut().expect("Parent table is None");
  88. let next_pte = parent_table.index_mut(pt_idx);
  89. child_table.replace(K::get_page_table::<A, X>(next_pte, &self.alloc));
  90. }
  91. }
  92. pub fn new(page_table: M::RawTable<'a>, range: VRange, alloc: A) -> Self {
  93. Self::with_levels(page_table, range, alloc, M::LEVELS)
  94. }
  95. pub fn with_levels(
  96. page_table: M::RawTable<'a>,
  97. range: VRange,
  98. alloc: A,
  99. levels: &'static [PageTableLevel],
  100. ) -> Self {
  101. let start = range.start().floor();
  102. let end = range.end().ceil();
  103. let [.., last_level] = levels else { unreachable!() };
  104. let mut me = Self {
  105. levels,
  106. remaining: (end - start) / last_level.page_size(),
  107. indicies: [0; 8],
  108. tables: [const { None }; 8],
  109. alloc,
  110. _phantom: PhantomData,
  111. };
  112. for (i, level) in levels.iter().enumerate() {
  113. me.indicies[i] = level.index_of(start);
  114. }
  115. me.tables[0] = Some(page_table);
  116. me.parse_tables_starting_from(0);
  117. me
  118. }
  119. }
  120. impl<'a, M, A, X, K> Iterator for PageTableIterator<'a, M, A, X, K>
  121. where
  122. M: PagingMode,
  123. M::Entry: 'a,
  124. A: PageAlloc,
  125. X: PageAccess,
  126. K: IteratorType<M>,
  127. {
  128. type Item = &'a mut M::Entry;
  129. fn next(&mut self) -> Option<Self::Item> {
  130. if self.remaining == 0 {
  131. return None;
  132. } else {
  133. self.remaining -= 1;
  134. }
  135. let table_level = self.levels.len() - 1;
  136. let retval = self.tables[table_level]
  137. .as_mut()
  138. .unwrap()
  139. .index_mut(self.indicies[table_level]);
  140. let idx_level_start_updating = self
  141. .levels
  142. .iter()
  143. .zip(self.indicies.iter_mut())
  144. .enumerate()
  145. .rev()
  146. .skip_while(|(_, (level, idx))| **idx == level.max_index())
  147. .map(|(i, _)| i)
  148. .next()
  149. .expect("Index out of bounds");
  150. self.indicies[idx_level_start_updating] += 1;
  151. self.indicies[idx_level_start_updating + 1..=table_level].fill(0);
  152. self.parse_tables_starting_from(idx_level_start_updating);
  153. Some(retval)
  154. }
  155. }
  156. impl<M: PagingMode> IteratorType<M> for KernelIterator {
  157. fn page_table_attributes() -> TableAttribute {
  158. TableAttribute::PRESENT | TableAttribute::GLOBAL
  159. }
  160. }
  161. impl<M: PagingMode> IteratorType<M> for UserIterator {
  162. fn page_table_attributes() -> TableAttribute {
  163. TableAttribute::PRESENT | TableAttribute::USER
  164. }
  165. }