pte_iterator.rs 5.3 KB

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