tg_kernel_vm/space/
mod.rs1mod mapper;
2mod visitor;
3
4extern crate alloc;
5
6use crate::PageManager;
7use alloc::vec::Vec;
8use core::{fmt, ops::Range, ptr::NonNull};
9use mapper::Mapper;
10use page_table::{PageTable, PageTableFormatter, Pos, VAddr, VmFlags, VmMeta, PPN, VPN};
11use visitor::Visitor;
12
13pub struct AddressSpace<Meta: VmMeta, M: PageManager<Meta>> {
15 pub areas: Vec<Range<VPN<Meta>>>,
17 page_manager: M,
18}
19
20impl<Meta: VmMeta, M: PageManager<Meta>> AddressSpace<Meta, M> {
21 #[inline]
23 pub fn new() -> Self {
24 Self {
25 areas: Vec::new(),
26 page_manager: M::new_root(),
27 }
28 }
29
30 #[inline]
32 pub fn root_ppn(&self) -> PPN<Meta> {
33 self.page_manager.root_ppn()
34 }
35
36 #[inline]
38 pub fn root(&self) -> PageTable<Meta> {
39 unsafe { PageTable::from_root(self.page_manager.root_ptr()) }
42 }
43
44 pub fn map_extern(&mut self, range: Range<VPN<Meta>>, pbase: PPN<Meta>, flags: VmFlags<Meta>) {
46 self.areas.push(range.start..range.end);
48 let count = range.end.val() - range.start.val();
49 let mut root = self.root();
50 let mut mapper = Mapper::new(self, pbase..pbase + count, flags);
51 root.walk_mut(Pos::new(range.start, 0), &mut mapper);
52 if !mapper.ans() {
53 todo!()
55 }
56 }
57
58 pub fn map(
60 &mut self,
61 range: Range<VPN<Meta>>,
62 data: &[u8],
63 offset: usize,
64 mut flags: VmFlags<Meta>,
65 ) {
66 let count = range.end.val() - range.start.val();
68 let size = count << Meta::PAGE_BITS;
69 assert!(size >= data.len() + offset);
70 let page = self.page_manager.allocate(count, &mut flags);
71 unsafe {
75 use core::slice::from_raw_parts_mut as slice;
76 let mut ptr = page.as_ptr();
77 slice(ptr, offset).fill(0);
78 ptr = ptr.add(offset);
79 slice(ptr, data.len()).copy_from_slice(data);
80 ptr = ptr.add(data.len());
81 slice(ptr, page.as_ptr().add(size).offset_from(ptr) as _).fill(0);
82 }
83 self.map_extern(range, self.page_manager.v_to_p(page), flags)
84 }
85
86 pub fn unmap(&mut self, range: Range<VPN<Meta>>) {
88 let mut new_areas = Vec::new();
92 for area in self.areas.drain(..) {
93 if area.end <= range.start || area.start >= range.end {
94 new_areas.push(area);
96 } else {
97 if area.start < range.start {
99 new_areas.push(area.start..range.start);
100 }
101 if area.end > range.end {
102 new_areas.push(range.end..area.end);
103 }
104 }
105 }
106 self.areas = new_areas;
107
108 let mut vpn = range.start;
110 while vpn < range.end {
111 if let Some(pte_ptr) = self.find_pte_mut(vpn) {
113 unsafe {
114 core::ptr::write_bytes(
115 pte_ptr as *mut u8,
116 0,
117 core::mem::size_of::<page_table::Pte<Meta>>(),
118 )
119 };
120 }
121 vpn = vpn + 1;
122 }
123
124 #[cfg(target_arch = "riscv64")]
126 unsafe {
127 core::arch::asm!("sfence.vma")
128 };
129 }
130
131 fn find_pte_mut(&self, vpn: VPN<Meta>) -> Option<*mut page_table::Pte<Meta>> {
133 let mut current = self.page_manager.root_ptr();
134
135 for level in (0..=Meta::MAX_LEVEL).rev() {
136 let idx = vpn.index_in(level);
137 let pte_ptr = unsafe { current.as_ptr().add(idx) };
138 let pte = unsafe { *pte_ptr };
139
140 if level == 0 {
141 return Some(pte_ptr);
142 }
143
144 if !pte.is_valid() {
145 return None;
146 }
147
148 let flags_raw = pte.flags().val();
151 let is_leaf = (flags_raw & 0b1010) != 0; if is_leaf {
153 return Some(pte_ptr);
154 }
155
156 current = self.page_manager.p_to_v(pte.ppn());
157 }
158 None
159 }
160
161 pub fn translate<T>(&self, addr: VAddr<Meta>, flags: VmFlags<Meta>) -> Option<NonNull<T>> {
163 let mut visitor = Visitor::new(self);
164 self.root().walk(Pos::new(addr.floor(), 0), &mut visitor);
165 visitor
166 .ans()
167 .filter(|pte| pte.flags().contains(flags))
168 .map(|pte| {
169 unsafe {
174 NonNull::new_unchecked(
175 self.page_manager
176 .p_to_v::<u8>(pte.ppn())
177 .as_ptr()
178 .add(addr.offset())
179 .cast(),
180 )
181 }
182 })
183 }
184
185 pub fn cloneself(&self, new_addrspace: &mut AddressSpace<Meta, M>) {
187 let root = self.root();
189 let areas = &self.areas;
190 for (_, range) in areas.iter().enumerate() {
191 let mut visitor = Visitor::new(self);
192 let vpn = range.start;
194 root.walk(Pos::new(vpn, 0), &mut visitor);
196 let (mut flags, mut data_ptr) = visitor
198 .ans()
199 .filter(|pte| pte.is_valid())
200 .map(|pte| {
201 (pte.flags(), unsafe {
203 NonNull::new_unchecked(self.page_manager.p_to_v::<u8>(pte.ppn()).as_ptr())
204 })
205 })
206 .unwrap();
207 let vpn_range = range.start..range.end;
208 let count = range.end.val() - range.start.val();
210 let size = count << Meta::PAGE_BITS;
211 let paddr = new_addrspace.page_manager.allocate(count, &mut flags);
213 let ppn = new_addrspace.page_manager.v_to_p(paddr);
214 unsafe {
217 use core::slice::from_raw_parts_mut as slice;
218 let data = slice(data_ptr.as_mut(), size);
219 let ptr = paddr.as_ptr();
220 slice(ptr, size).copy_from_slice(data);
221 }
222 new_addrspace.map_extern(vpn_range, ppn, flags);
223 }
224 }
225}
226
227impl<Meta: VmMeta, P: PageManager<Meta>> fmt::Debug for AddressSpace<Meta, P> {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 writeln!(f, "root: {:#x}", self.root_ppn().val())?;
230 write!(
231 f,
232 "{:?}",
233 PageTableFormatter {
234 pt: self.root(),
235 f: |ppn| self.page_manager.p_to_v(ppn)
236 }
237 )
238 }
239}