pte_iterator.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. use super::{
  2. pte::{RawAttribute, TableAttribute},
  3. 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. K: IteratorType<M>,
  54. {
  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. let levels_len = M::LEVELS.len();
  71. for (idx, &pt_idx) in self
  72. .indicies
  73. .iter()
  74. .enumerate()
  75. .take(levels_len - 1)
  76. .skip(idx_level)
  77. {
  78. let [parent_table, child_table] = unsafe {
  79. // SAFETY: `idx` and `idx + 1` must not overlap.
  80. // `idx + 1` is always less than `levels_len` since we iterate
  81. // until `levels_len - 1`.
  82. self.tables.get_disjoint_unchecked_mut([idx, idx + 1])
  83. };
  84. let parent_table = parent_table.as_mut().expect("Parent table is None");
  85. let next_pte = parent_table.index_mut(pt_idx);
  86. child_table.replace(K::get_page_table::<A, X>(next_pte, &self.alloc));
  87. }
  88. }
  89. pub fn new(page_table: M::RawTable<'a>, range: VRange, alloc: A) -> Self {
  90. let start = range.start().floor();
  91. let end = range.end().ceil();
  92. let mut me = Self {
  93. remaining: (end - start) / PAGE_SIZE,
  94. indicies: [0; 8],
  95. tables: [const { None }; 8],
  96. alloc,
  97. _phantom: PhantomData,
  98. };
  99. for (i, level) in M::LEVELS.iter().enumerate() {
  100. me.indicies[i] = level.index_of(start);
  101. }
  102. me.tables[0] = Some(page_table);
  103. me.parse_tables_starting_from(0);
  104. me
  105. }
  106. }
  107. impl<'a, M, A, X, K> Iterator for PageTableIterator<'a, M, A, X, K>
  108. where
  109. M: PagingMode,
  110. M::Entry: 'a,
  111. A: PageAlloc,
  112. X: PageAccess,
  113. K: IteratorType<M>,
  114. {
  115. type Item = &'a mut M::Entry;
  116. fn next(&mut self) -> Option<Self::Item> {
  117. if self.remaining == 0 {
  118. return None;
  119. } else {
  120. self.remaining -= 1;
  121. }
  122. let len_levels = M::LEVELS.len();
  123. let retval = self.tables[len_levels - 1]
  124. .as_mut()
  125. .unwrap()
  126. .index_mut(self.indicies[len_levels - 1]);
  127. let idx_level_start_updating = M::LEVELS
  128. .iter()
  129. .zip(self.indicies.iter_mut())
  130. .enumerate()
  131. .rev()
  132. .skip_while(|(_, (level, idx))| **idx == level.max_index())
  133. .map(|(i, _)| i)
  134. .next()
  135. .expect("Index out of bounds");
  136. self.indicies[idx_level_start_updating] += 1;
  137. self.indicies[idx_level_start_updating + 1..len_levels].fill(0);
  138. self.parse_tables_starting_from(idx_level_start_updating);
  139. Some(retval)
  140. }
  141. }
  142. impl<M: PagingMode> IteratorType<M> for KernelIterator {
  143. fn page_table_attributes() -> TableAttribute {
  144. TableAttribute::PRESENT | TableAttribute::GLOBAL
  145. }
  146. }
  147. impl<M: PagingMode> IteratorType<M> for UserIterator {
  148. fn page_table_attributes() -> TableAttribute {
  149. TableAttribute::PRESENT | TableAttribute::USER
  150. }
  151. }