1use super::{FrameTracker, PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum, frame_alloc};
2use alloc::string::String;
3use alloc::vec;
4use alloc::vec::Vec;
5use bitflags::*;
6
7bitflags! {
8 pub struct PTEFlags: u8 {
9 const V = 1 << 0;
10 const R = 1 << 1;
11 const W = 1 << 2;
12 const X = 1 << 3;
13 const U = 1 << 4;
14 const G = 1 << 5;
15 const A = 1 << 6;
16 const D = 1 << 7;
17 }
18}
19
20#[derive(Copy, Clone)]
21#[repr(C)]
22pub struct PageTableEntry {
23 pub bits: usize,
24}
25
26impl PageTableEntry {
27 pub fn new(ppn: PhysPageNum, flags: PTEFlags) -> Self {
28 PageTableEntry {
29 bits: ppn.0 << 10 | flags.bits as usize,
30 }
31 }
32 pub fn empty() -> Self {
33 PageTableEntry { bits: 0 }
34 }
35 pub fn ppn(&self) -> PhysPageNum {
36 (self.bits >> 10 & ((1usize << 44) - 1)).into()
37 }
38 pub fn flags(&self) -> PTEFlags {
39 PTEFlags::from_bits(self.bits as u8).unwrap()
40 }
41 pub fn is_valid(&self) -> bool {
42 (self.flags() & PTEFlags::V) != PTEFlags::empty()
43 }
44 pub fn readable(&self) -> bool {
45 (self.flags() & PTEFlags::R) != PTEFlags::empty()
46 }
47 pub fn writable(&self) -> bool {
48 (self.flags() & PTEFlags::W) != PTEFlags::empty()
49 }
50 pub fn executable(&self) -> bool {
51 (self.flags() & PTEFlags::X) != PTEFlags::empty()
52 }
53}
54
55pub struct PageTable {
56 root_ppn: PhysPageNum,
57 frames: Vec<FrameTracker>,
58}
59
60impl PageTable {
62 pub fn new() -> Self {
63 let frame = frame_alloc().unwrap();
64 PageTable {
65 root_ppn: frame.ppn,
66 frames: vec![frame],
67 }
68 }
69 pub fn from_token(satp: usize) -> Self {
71 Self {
72 root_ppn: PhysPageNum::from(satp & ((1usize << 44) - 1)),
73 frames: Vec::new(),
74 }
75 }
76 fn find_pte_create(&mut self, vpn: VirtPageNum) -> Option<&mut PageTableEntry> {
77 let idxs = vpn.indexes();
78 let mut ppn = self.root_ppn;
79 let mut result: Option<&mut PageTableEntry> = None;
80 for (i, idx) in idxs.iter().enumerate() {
81 let pte = &mut ppn.get_pte_array()[*idx];
82 if i == 2 {
83 result = Some(pte);
84 break;
85 }
86 if !pte.is_valid() {
87 let frame = frame_alloc().unwrap();
88 *pte = PageTableEntry::new(frame.ppn, PTEFlags::V);
89 self.frames.push(frame);
90 }
91 ppn = pte.ppn();
92 }
93 result
94 }
95 fn find_pte(&self, vpn: VirtPageNum) -> Option<&mut PageTableEntry> {
96 let idxs = vpn.indexes();
97 let mut ppn = self.root_ppn;
98 let mut result: Option<&mut PageTableEntry> = None;
99 for (i, idx) in idxs.iter().enumerate() {
100 let pte = &mut ppn.get_pte_array()[*idx];
101 if i == 2 {
102 result = Some(pte);
103 break;
104 }
105 if !pte.is_valid() {
106 return None;
107 }
108 ppn = pte.ppn();
109 }
110 result
111 }
112 #[allow(unused)]
113 pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) {
114 let pte = self.find_pte_create(vpn).unwrap();
115 assert!(!pte.is_valid(), "vpn {:?} is mapped before mapping", vpn);
116 *pte = PageTableEntry::new(ppn, flags | PTEFlags::V);
117 }
118 #[allow(unused)]
119 pub fn unmap(&mut self, vpn: VirtPageNum) {
120 let pte = self.find_pte(vpn).unwrap();
121 assert!(pte.is_valid(), "vpn {:?} is invalid before unmapping", vpn);
122 *pte = PageTableEntry::empty();
123 }
124 pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
125 self.find_pte(vpn).map(|pte| *pte)
126 }
127 pub fn translate_va(&self, va: VirtAddr) -> Option<PhysAddr> {
128 self.find_pte(va.clone().floor()).map(|pte| {
129 let aligned_pa: PhysAddr = pte.ppn().into();
130 let offset = va.page_offset();
131 let aligned_pa_usize: usize = aligned_pa.into();
132 (aligned_pa_usize + offset).into()
133 })
134 }
135 pub fn token(&self) -> usize {
136 8usize << 60 | self.root_ppn.0
137 }
138}
139
140pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> {
141 let page_table = PageTable::from_token(token);
142 let mut start = ptr as usize;
143 let end = start + len;
144 let mut v = Vec::new();
145 while start < end {
146 let start_va = VirtAddr::from(start);
147 let mut vpn = start_va.floor();
148 let ppn = page_table.translate(vpn).unwrap().ppn();
149 vpn.step();
150 let mut end_va: VirtAddr = vpn.into();
151 end_va = end_va.min(VirtAddr::from(end));
152 if end_va.page_offset() == 0 {
153 v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]);
154 } else {
155 v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
156 }
157 start = end_va.into();
158 }
159 v
160}
161
162pub fn translated_str(token: usize, ptr: *const u8) -> String {
164 let page_table = PageTable::from_token(token);
165 let mut string = String::new();
166 let mut va = ptr as usize;
167 loop {
168 let ch: u8 = *(page_table
169 .translate_va(VirtAddr::from(va))
170 .unwrap()
171 .get_mut());
172 if ch == 0 {
173 break;
174 }
175 string.push(ch as char);
176 va += 1;
177 }
178 string
179}
180
181pub fn translated_ref<T>(token: usize, ptr: *const T) -> &'static T {
182 let page_table = PageTable::from_token(token);
183 page_table
184 .translate_va(VirtAddr::from(ptr as usize))
185 .unwrap()
186 .get_ref()
187}
188
189pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
190 let page_table = PageTable::from_token(token);
191 let va = ptr as usize;
192 page_table
193 .translate_va(VirtAddr::from(va))
194 .unwrap()
195 .get_mut()
196}
197
198pub struct UserBuffer {
199 pub buffers: Vec<&'static mut [u8]>,
200}
201
202impl UserBuffer {
203 pub fn new(buffers: Vec<&'static mut [u8]>) -> Self {
204 Self { buffers }
205 }
206 pub fn len(&self) -> usize {
207 let mut total: usize = 0;
208 for b in self.buffers.iter() {
209 total += b.len();
210 }
211 total
212 }
213}
214
215impl IntoIterator for UserBuffer {
216 type Item = *mut u8;
217 type IntoIter = UserBufferIterator;
218 fn into_iter(self) -> Self::IntoIter {
219 UserBufferIterator {
220 buffers: self.buffers,
221 current_buffer: 0,
222 current_idx: 0,
223 }
224 }
225}
226
227pub struct UserBufferIterator {
228 buffers: Vec<&'static mut [u8]>,
229 current_buffer: usize,
230 current_idx: usize,
231}
232
233impl Iterator for UserBufferIterator {
234 type Item = *mut u8;
235 fn next(&mut self) -> Option<Self::Item> {
236 if self.current_buffer >= self.buffers.len() {
237 None
238 } else {
239 let r = &mut self.buffers[self.current_buffer][self.current_idx] as *mut _;
240 if self.current_idx + 1 == self.buffers[self.current_buffer].len() {
241 self.current_idx = 0;
242 self.current_buffer += 1;
243 } else {
244 self.current_idx += 1;
245 }
246 Some(r)
247 }
248 }
249}