mm.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. use core::{marker::PhantomData, ptr::NonNull};
  2. use eonix_mm::{
  3. address::{Addr as _, PAddr},
  4. page_table::{PageAttribute, PageTableLevel, PagingMode, RawPageTable, PTE},
  5. paging::{PageBlock, PFN},
  6. };
  7. pub const PAGE_SIZE: usize = 0x1000;
  8. const PAGE_TABLE_BASE: PFN = PFN::from_val(0x8030_0000 >> 12);
  9. const PA_V: u64 = 0b1 << 0;
  10. const PA_R: u64 = 0b1 << 1;
  11. const PA_W: u64 = 0b1 << 2;
  12. const PA_X: u64 = 0b1 << 3;
  13. const PA_U: u64 = 0b1 << 4;
  14. const PA_G: u64 = 0b1 << 5;
  15. const PA_A: u64 = 0b1 << 6;
  16. const PA_D: u64 = 0b1 << 7;
  17. // in RSW
  18. const PA_COW: u64 = 0b1 << 8;
  19. const PA_MMAP: u64 = 0b1 << 9;
  20. const PA_SHIFT: u64 = 10;
  21. const PA_MASK: u64 = 0xFFC0_0000_0000_03FF; // 44 bit PPN, from 10 to 53
  22. // Bit 0-9 (V, R, W, X, U, G, A, D, RSW)
  23. const PA_FLAGS_MASK: u64 = 0x3FF; // 0b11_1111_1111
  24. #[repr(transparent)]
  25. pub struct PTE64(u64);
  26. #[derive(Clone, Copy)]
  27. pub struct PageAttribute64(u64);
  28. pub struct RawPageTableSv39<'a>(NonNull<PTE64>, PhantomData<&'a ()>);
  29. pub struct PagingModeSv39;
  30. impl PTE for PTE64 {
  31. type Attr = PageAttribute64;
  32. fn set(&mut self, pfn: PFN, attr: Self::Attr) {
  33. self.0 = (PAddr::from(pfn).addr() as u64 & !PA_MASK) | (attr.0 & PA_MASK);
  34. }
  35. fn get(&self) -> (PFN, Self::Attr) {
  36. (
  37. PFN::from(PAddr::from((self.0 & !PA_MASK) as usize)),
  38. PageAttribute64(self.0 & PA_MASK),
  39. )
  40. }
  41. fn take(&mut self) -> (PFN, Self::Attr) {
  42. let pfn_attr = self.get();
  43. self.0 = 0;
  44. pfn_attr
  45. }
  46. }
  47. impl PagingMode for PagingModeSv39 {
  48. type Entry = PTE64;
  49. type RawTable<'a> = RawPageTableSv39<'a>;
  50. const LEVELS: &'static [PageTableLevel] = &[
  51. PageTableLevel::new(30, 9),
  52. PageTableLevel::new(21, 9),
  53. PageTableLevel::new(12, 9),
  54. ];
  55. const KERNEL_ROOT_TABLE_PFN: PFN = PAGE_TABLE_BASE;
  56. }
  57. impl<'a> RawPageTable<'a> for RawPageTableSv39<'a> {
  58. type Entry = PTE64;
  59. fn index(&self, index: u16) -> &'a Self::Entry {
  60. unsafe { &self.0.cast::<[PTE64; 512]>().as_ref()[index as usize] }
  61. }
  62. fn index_mut(&mut self, index: u16) -> &'a mut Self::Entry {
  63. unsafe { &mut self.0.cast::<[PTE64; 512]>().as_mut()[index as usize] }
  64. }
  65. unsafe fn from_ptr(ptr: NonNull<PageBlock>) -> Self {
  66. Self(ptr.cast(), PhantomData)
  67. }
  68. }
  69. impl PageAttribute for PageAttribute64 {
  70. fn new() -> Self {
  71. Self(PA_R)
  72. }
  73. fn present(self, present: bool) -> Self {
  74. if present {
  75. Self(self.0 | PA_V)
  76. } else {
  77. Self(self.0 & !PA_V)
  78. }
  79. }
  80. fn write(self, write: bool) -> Self {
  81. if write {
  82. Self(self.0 | PA_W)
  83. } else {
  84. Self(self.0 & !PA_W)
  85. }
  86. }
  87. fn execute(self, execute: bool) -> Self {
  88. if execute {
  89. Self(self.0 | PA_X)
  90. } else {
  91. Self(self.0 & !PA_X)
  92. }
  93. }
  94. fn user(self, user: bool) -> Self {
  95. if user {
  96. Self(self.0 | PA_U)
  97. } else {
  98. Self(self.0 & !PA_U)
  99. }
  100. }
  101. fn accessed(self, accessed: bool) -> Self {
  102. if accessed {
  103. Self(self.0 | PA_A)
  104. } else {
  105. Self(self.0 & !PA_A)
  106. }
  107. }
  108. fn dirty(self, dirty: bool) -> Self {
  109. if dirty {
  110. Self(self.0 | PA_D)
  111. } else {
  112. Self(self.0 & !PA_D)
  113. }
  114. }
  115. fn global(self, global: bool) -> Self {
  116. if global {
  117. Self(self.0 | PA_G)
  118. } else {
  119. Self(self.0 & !PA_G)
  120. }
  121. }
  122. fn copy_on_write(self, cow: bool) -> Self {
  123. if cow {
  124. Self(self.0 | PA_COW)
  125. } else {
  126. Self(self.0 & !PA_COW)
  127. }
  128. }
  129. fn mapped(self, mmap: bool) -> Self {
  130. if mmap {
  131. Self(self.0 | PA_MMAP)
  132. } else {
  133. Self(self.0 & !PA_MMAP)
  134. }
  135. }
  136. fn is_present(&self) -> bool {
  137. self.0 & PA_V != 0
  138. }
  139. fn is_write(&self) -> bool {
  140. self.0 & PA_W != 0
  141. }
  142. fn is_execute(&self) -> bool {
  143. self.0 & PA_X != 0
  144. }
  145. fn is_user(&self) -> bool {
  146. self.0 & PA_U != 0
  147. }
  148. fn is_accessed(&self) -> bool {
  149. self.0 & PA_A != 0
  150. }
  151. fn is_dirty(&self) -> bool {
  152. self.0 & PA_D != 0
  153. }
  154. fn is_global(&self) -> bool {
  155. self.0 & PA_G != 0
  156. }
  157. fn is_copy_on_write(&self) -> bool {
  158. self.0 & PA_COW != 0
  159. }
  160. fn is_mapped(&self) -> bool {
  161. self.0 & PA_MMAP != 0
  162. }
  163. }
  164. pub type DefaultPagingMode = PagingModeSv39;