1use super::{FrameTracker, PhysPageNum, StepByOne, VirtAddr, VirtPageNum, frame_alloc};
4use alloc::vec;
5use alloc::vec::Vec;
6use bitflags::*;
7
8bitflags! {
9 pub struct PTEFlags: u8 {
11 const V = 1 << 0;
12 const R = 1 << 1;
13 const W = 1 << 2;
14 const X = 1 << 3;
15 const U = 1 << 4;
16 const G = 1 << 5;
17 const A = 1 << 6;
18 const D = 1 << 7;
19 }
20}
21
22#[derive(Copy, Clone)]
23#[repr(C)]
24pub struct PageTableEntry {
26 pub bits: usize,
27}
28
29impl PageTableEntry {
30 pub fn new(ppn: PhysPageNum, flags: PTEFlags) -> Self {
31 PageTableEntry {
32 bits: ppn.0 << 10 | flags.bits as usize,
33 }
34 }
35 pub fn empty() -> Self {
36 PageTableEntry { bits: 0 }
37 }
38 pub fn ppn(&self) -> PhysPageNum {
39 (self.bits >> 10 & ((1usize << 44) - 1)).into()
40 }
41 pub fn flags(&self) -> PTEFlags {
42 PTEFlags::from_bits(self.bits as u8).unwrap()
43 }
44 pub fn is_valid(&self) -> bool {
45 (self.flags() & PTEFlags::V) != PTEFlags::empty()
46 }
47 pub fn readable(&self) -> bool {
48 (self.flags() & PTEFlags::R) != PTEFlags::empty()
49 }
50 pub fn writable(&self) -> bool {
51 (self.flags() & PTEFlags::W) != PTEFlags::empty()
52 }
53 pub fn executable(&self) -> bool {
54 (self.flags() & PTEFlags::X) != PTEFlags::empty()
55 }
56}
57
58pub struct PageTable {
60 root_ppn: PhysPageNum,
61 frames: Vec<FrameTracker>,
62}
63
64impl PageTable {
66 pub fn new() -> Self {
67 let frame = frame_alloc().unwrap();
68 PageTable {
69 root_ppn: frame.ppn,
70 frames: vec![frame],
71 }
72 }
73 pub fn from_token(satp: usize) -> Self {
75 Self {
76 root_ppn: PhysPageNum::from(satp & ((1usize << 44) - 1)),
77 frames: Vec::new(),
78 }
79 }
80 fn find_pte_create(&mut self, vpn: VirtPageNum) -> Option<&mut PageTableEntry> {
81 let idxs = vpn.indexes();
82 let mut ppn = self.root_ppn;
83 let mut result: Option<&mut PageTableEntry> = None;
84 for (i, idx) in idxs.iter().enumerate() {
85 let pte = &mut ppn.get_pte_array()[*idx];
86 if i == 2 {
87 result = Some(pte);
88 break;
89 }
90 if !pte.is_valid() {
91 let frame = frame_alloc().unwrap();
92 *pte = PageTableEntry::new(frame.ppn, PTEFlags::V);
93 self.frames.push(frame);
94 }
95 ppn = pte.ppn();
96 }
97 result
98 }
99 fn find_pte(&self, vpn: VirtPageNum) -> Option<&mut PageTableEntry> {
100 let idxs = vpn.indexes();
101 let mut ppn = self.root_ppn;
102 let mut result: Option<&mut PageTableEntry> = None;
103 for (i, idx) in idxs.iter().enumerate() {
104 let pte = &mut ppn.get_pte_array()[*idx];
105 if i == 2 {
106 result = Some(pte);
107 break;
108 }
109 if !pte.is_valid() {
110 return None;
111 }
112 ppn = pte.ppn();
113 }
114 result
115 }
116 #[allow(unused)]
117 pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) {
118 let pte = self.find_pte_create(vpn).unwrap();
119 assert!(!pte.is_valid(), "vpn {:?} is mapped before mapping", vpn);
120 *pte = PageTableEntry::new(ppn, flags | PTEFlags::V);
121 }
122 #[allow(unused)]
123 pub fn unmap(&mut self, vpn: VirtPageNum) {
124 let pte = self.find_pte(vpn).unwrap();
125 assert!(pte.is_valid(), "vpn {:?} is invalid before unmapping", vpn);
126 *pte = PageTableEntry::empty();
127 }
128 pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
129 self.find_pte(vpn).map(|pte| *pte)
130 }
131 pub fn token(&self) -> usize {
132 8usize << 60 | self.root_ppn.0
133 }
134}
135
136pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> {
138 let page_table = PageTable::from_token(token);
139 let mut start = ptr as usize;
140 let end = start + len;
141 let mut v = Vec::new();
142 while start < end {
143 let start_va = VirtAddr::from(start);
144 let mut vpn = start_va.floor();
145 let ppn = page_table.translate(vpn).unwrap().ppn();
146 vpn.step();
147 let mut end_va: VirtAddr = vpn.into();
148 end_va = end_va.min(VirtAddr::from(end));
149 if end_va.page_offset() == 0 {
150 v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]);
151 } else {
152 v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
153 }
154 start = end_va.into();
155 }
156 v
157}