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);
47 let count = range.end.val() - range.start.val();
48 let mut root = self.root();
49 let mut mapper = Mapper::new(self, pbase..pbase + count, flags);
50 root.walk_mut(Pos::new(range.start, 0), &mut mapper);
51 if !mapper.ans() {
52 todo!()
54 }
55 }
56
57 pub fn map(
59 &mut self,
60 range: Range<VPN<Meta>>,
61 data: &[u8],
62 offset: usize,
63 mut flags: VmFlags<Meta>,
64 ) {
65 let count = range.end.val() - range.start.val();
66 let size = count << Meta::PAGE_BITS;
67 assert!(size >= data.len() + offset);
68 let page = self.page_manager.allocate(count, &mut flags);
69 unsafe {
73 use core::slice::from_raw_parts_mut as slice;
74 let mut ptr = page.as_ptr();
75 slice(ptr, offset).fill(0);
76 ptr = ptr.add(offset);
77 slice(ptr, data.len()).copy_from_slice(data);
78 ptr = ptr.add(data.len());
79 slice(ptr, page.as_ptr().add(size).offset_from(ptr) as _).fill(0);
80 }
81 self.map_extern(range, self.page_manager.v_to_p(page), flags)
82 }
83
84 pub fn translate<T>(&self, addr: VAddr<Meta>, flags: VmFlags<Meta>) -> Option<NonNull<T>> {
86 let mut visitor = Visitor::new(self);
87 self.root().walk(Pos::new(addr.floor(), 0), &mut visitor);
88 visitor
89 .ans()
90 .filter(|pte| pte.flags().contains(flags))
91 .map(|pte| {
92 unsafe {
97 NonNull::new_unchecked(
98 self.page_manager
99 .p_to_v::<u8>(pte.ppn())
100 .as_ptr()
101 .add(addr.offset())
102 .cast(),
103 )
104 }
105 })
106 }
107
108 pub fn cloneself(&self, new_addrspace: &mut AddressSpace<Meta, M>) {
110 let root = self.root();
111 let areas = &self.areas;
112 for (_, range) in areas.iter().enumerate() {
113 let mut visitor = Visitor::new(self);
114 let vpn = range.start;
116 root.walk(Pos::new(vpn, 0), &mut visitor);
118 let (mut flags, mut data_ptr) = visitor
120 .ans()
121 .filter(|pte| pte.is_valid())
122 .map(|pte| {
123 (pte.flags(), unsafe {
125 NonNull::new_unchecked(self.page_manager.p_to_v::<u8>(pte.ppn()).as_ptr())
126 })
127 })
128 .unwrap();
129 let vpn_range = range.start..range.end;
130 let count = range.end.val() - range.start.val();
132 let size = count << Meta::PAGE_BITS;
133 let paddr = new_addrspace.page_manager.allocate(count, &mut flags);
135 let ppn = new_addrspace.page_manager.v_to_p(paddr);
136 unsafe {
139 use core::slice::from_raw_parts_mut as slice;
140 let data = slice(data_ptr.as_mut(), size);
141 let ptr = paddr.as_ptr();
142 slice(ptr, size).copy_from_slice(data);
143 }
144 new_addrspace.map_extern(vpn_range, ppn, flags);
145 }
146 }
147}
148
149impl<Meta: VmMeta, P: PageManager<Meta>> fmt::Debug for AddressSpace<Meta, P> {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 writeln!(f, "root: {:#x}", self.root_ppn().val())?;
152 write!(
153 f,
154 "{:?}",
155 PageTableFormatter {
156 pt: self.root(),
157 f: |ppn| self.page_manager.p_to_v(ppn)
158 }
159 )
160 }
161}