pte_iterator.rs 4.9 KB

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