xref: /DragonOS/kernel/src/mm/allocator/page_frame.rs (revision 01c18c64b14b4ebabd98fa92c587c26874275eb1)
1 use core::{
2     intrinsics::unlikely,
3     ops::{Add, AddAssign, Mul, Sub, SubAssign},
4 };
5 
6 use crate::{
7     arch::{mm::LockedFrameAllocator, MMArch},
8     ipc::shm::shm_manager_lock,
9     libs::spinlock::SpinLockGuard,
10     mm::{MemoryManagementArch, PhysAddr, VirtAddr},
11 };
12 
13 /// @brief 物理页帧的表示
14 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
15 pub struct PhysPageFrame {
16     /// 物理页页号
17     number: usize,
18 }
19 
20 #[allow(dead_code)]
21 impl PhysPageFrame {
22     pub fn new(paddr: PhysAddr) -> Self {
23         return Self {
24             number: paddr.data() >> MMArch::PAGE_SHIFT,
25         };
26     }
27 
28     /// 从物理页号创建PhysPageFrame结构体
29     pub fn from_ppn(ppn: usize) -> Self {
30         return Self { number: ppn };
31     }
32 
33     /// 获取当前页对应的物理页号
34     pub fn ppn(&self) -> usize {
35         return self.number;
36     }
37 
38     /// @brief 获取当前页对应的物理地址
39     pub fn phys_address(&self) -> PhysAddr {
40         return PhysAddr::new(self.number * MMArch::PAGE_SIZE);
41     }
42 
43     pub fn next_by(&self, n: usize) -> Self {
44         return Self {
45             number: self.number + n,
46         };
47     }
48 
49     pub fn next(&self) -> Self {
50         return self.next_by(1);
51     }
52 
53     /// 构造物理页帧的迭代器,范围为[start, end)
54     pub fn iter_range(start: Self, end: Self) -> PhysPageFrameIter {
55         return PhysPageFrameIter::new(start, end);
56     }
57 }
58 
59 /// @brief 物理页帧的迭代器
60 #[derive(Debug)]
61 pub struct PhysPageFrameIter {
62     current: PhysPageFrame,
63     /// 结束的物理页帧(不包含)
64     end: PhysPageFrame,
65 }
66 
67 impl PhysPageFrameIter {
68     pub fn new(start: PhysPageFrame, end: PhysPageFrame) -> Self {
69         return Self {
70             current: start,
71             end,
72         };
73     }
74 }
75 
76 impl Iterator for PhysPageFrameIter {
77     type Item = PhysPageFrame;
78 
79     fn next(&mut self) -> Option<Self::Item> {
80         if unlikely(self.current == self.end) {
81             return None;
82         }
83         let current: PhysPageFrame = self.current;
84         self.current = self.current.next_by(1);
85         return Some(current);
86     }
87 }
88 
89 /// 虚拟页帧的表示
90 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
91 pub struct VirtPageFrame {
92     /// 虚拟页页号
93     number: usize,
94 }
95 
96 impl VirtPageFrame {
97     pub fn new(vaddr: VirtAddr) -> Self {
98         return Self {
99             number: vaddr.data() / MMArch::PAGE_SIZE,
100         };
101     }
102 
103     /// 从虚拟页号创建PhysPageFrame结构体
104     #[allow(dead_code)]
105     pub fn from_vpn(vpn: usize) -> Self {
106         return Self { number: vpn };
107     }
108 
109     /// 获取当前虚拟页对应的虚拟地址
110     pub fn virt_address(&self) -> VirtAddr {
111         return VirtAddr::new(self.number * MMArch::PAGE_SIZE);
112     }
113 
114     pub fn next_by(&self, n: usize) -> Self {
115         return Self {
116             number: self.number + n,
117         };
118     }
119 
120     pub fn next(&self) -> Self {
121         return self.next_by(1);
122     }
123 
124     /// 构造虚拟页帧的迭代器,范围为[start, end)
125     pub fn iter_range(start: Self, end: Self) -> VirtPageFrameIter {
126         return VirtPageFrameIter {
127             current: start,
128             end,
129         };
130     }
131 
132     pub fn add(&self, n: PageFrameCount) -> Self {
133         return Self {
134             number: self.number + n.data(),
135         };
136     }
137 }
138 
139 /// 虚拟页帧的迭代器
140 #[derive(Debug)]
141 pub struct VirtPageFrameIter {
142     current: VirtPageFrame,
143     /// 结束的虚拟页帧(不包含)
144     end: VirtPageFrame,
145 }
146 
147 impl VirtPageFrameIter {
148     /// @brief 构造虚拟页帧的迭代器,范围为[start, end)
149     pub fn new(start: VirtPageFrame, end: VirtPageFrame) -> Self {
150         return Self {
151             current: start,
152             end,
153         };
154     }
155 }
156 
157 impl Iterator for VirtPageFrameIter {
158     type Item = VirtPageFrame;
159 
160     fn next(&mut self) -> Option<Self::Item> {
161         if unlikely(self.current == self.end) {
162             return None;
163         }
164         let current: VirtPageFrame = self.current;
165         self.current = self.current.next_by(1);
166         return Some(current);
167     }
168 }
169 
170 /// 页帧使用的数量
171 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
172 #[repr(transparent)]
173 pub struct PageFrameCount(usize);
174 
175 impl PageFrameCount {
176     // @brief 初始化PageFrameCount
177     pub const fn new(count: usize) -> Self {
178         return Self(count);
179     }
180     // @brief 获取页帧数量
181     pub fn data(&self) -> usize {
182         return self.0;
183     }
184 
185     /// 计算这一段页帧占用的字节数
186     pub fn bytes(&self) -> usize {
187         return self.0 * MMArch::PAGE_SIZE;
188     }
189 
190     /// 将字节数转换为页帧数量
191     ///
192     /// 如果字节数不是页帧大小的整数倍,则返回None. 否则返回页帧数量
193     pub fn from_bytes(bytes: usize) -> Option<Self> {
194         if bytes & MMArch::PAGE_OFFSET_MASK != 0 {
195             return None;
196         } else {
197             return Some(Self(bytes / MMArch::PAGE_SIZE));
198         }
199     }
200 
201     #[inline(always)]
202     pub fn next_power_of_two(&self) -> Self {
203         Self::new(self.0.next_power_of_two())
204     }
205 }
206 
207 impl Add for PageFrameCount {
208     type Output = Self;
209 
210     fn add(self, rhs: Self) -> Self::Output {
211         return Self(self.0 + rhs.0);
212     }
213 }
214 
215 impl AddAssign for PageFrameCount {
216     fn add_assign(&mut self, rhs: Self) {
217         self.0 += rhs.0;
218     }
219 }
220 
221 impl Sub for PageFrameCount {
222     type Output = Self;
223 
224     fn sub(self, rhs: Self) -> Self::Output {
225         return Self(self.0 - rhs.0);
226     }
227 }
228 
229 impl SubAssign for PageFrameCount {
230     fn sub_assign(&mut self, rhs: Self) {
231         self.0 -= rhs.0;
232     }
233 }
234 
235 impl Mul for PageFrameCount {
236     type Output = Self;
237 
238     fn mul(self, rhs: Self) -> Self::Output {
239         return Self(self.0 * rhs.0);
240     }
241 }
242 
243 impl Add<usize> for PageFrameCount {
244     type Output = Self;
245 
246     fn add(self, rhs: usize) -> Self::Output {
247         return Self(self.0 + rhs);
248     }
249 }
250 
251 impl AddAssign<usize> for PageFrameCount {
252     fn add_assign(&mut self, rhs: usize) {
253         self.0 += rhs;
254     }
255 }
256 
257 impl Sub<usize> for PageFrameCount {
258     type Output = Self;
259 
260     fn sub(self, rhs: usize) -> Self::Output {
261         return Self(self.0 - rhs);
262     }
263 }
264 
265 impl SubAssign<usize> for PageFrameCount {
266     fn sub_assign(&mut self, rhs: usize) {
267         self.0 -= rhs;
268     }
269 }
270 
271 impl Mul<usize> for PageFrameCount {
272     type Output = Self;
273 
274     fn mul(self, rhs: usize) -> Self::Output {
275         return Self(self.0 * rhs);
276     }
277 }
278 
279 // 页帧使用情况
280 #[derive(Debug)]
281 pub struct PageFrameUsage {
282     used: PageFrameCount,
283     total: PageFrameCount,
284 }
285 
286 #[allow(dead_code)]
287 impl PageFrameUsage {
288     /// @brief:  初始化FrameUsage
289     /// @param PageFrameCount used 已使用的页帧数量
290     /// @param PageFrameCount total 总的页帧数量
291     pub fn new(used: PageFrameCount, total: PageFrameCount) -> Self {
292         return Self { used, total };
293     }
294     // @brief 获取已使用的页帧数量
295     pub fn used(&self) -> PageFrameCount {
296         return self.used;
297     }
298     // @brief 获取空闲的页帧数量
299     pub fn free(&self) -> PageFrameCount {
300         return self.total - self.used;
301     }
302     // @brief 获取总的页帧数量
303     pub fn total(&self) -> PageFrameCount {
304         return self.total;
305     }
306 }
307 
308 /// 能够分配页帧的分配器需要实现的trait
309 pub trait FrameAllocator {
310     // @brief 分配count个页帧
311     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)>;
312 
313     // @brief 通过地址释放count个页帧
314     unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount);
315     // @brief 分配一个页帧
316     unsafe fn allocate_one(&mut self) -> Option<PhysAddr> {
317         return self.allocate(PageFrameCount::new(1)).map(|(addr, _)| addr);
318     }
319     // @brief 通过地址释放一个页帧
320     unsafe fn free_one(&mut self, address: PhysAddr) {
321         return self.free(address, PageFrameCount::new(1));
322     }
323     // @brief 获取页帧使用情况
324     unsafe fn usage(&self) -> PageFrameUsage;
325 }
326 
327 /// @brief 通过一个 &mut T 的引用来对一个实现了 FrameAllocator trait 的类型进行调用,使代码更加灵活
328 impl<T: FrameAllocator> FrameAllocator for &mut T {
329     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
330         return T::allocate(self, count);
331     }
332     unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
333         return T::free(self, address, count);
334     }
335     unsafe fn allocate_one(&mut self) -> Option<PhysAddr> {
336         return T::allocate_one(self);
337     }
338     unsafe fn free_one(&mut self, address: PhysAddr) {
339         return T::free_one(self, address);
340     }
341     unsafe fn usage(&self) -> PageFrameUsage {
342         return T::usage(self);
343     }
344 }
345 
346 /// @brief 从全局的页帧分配器中分配连续count个页帧
347 ///
348 /// @param count 请求分配的页帧数量
349 pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
350     let frame = unsafe { LockedFrameAllocator.allocate(count)? };
351     return Some(frame);
352 }
353 
354 /// @brief 向全局页帧分配器释放连续count个页帧
355 ///
356 /// @param frame 要释放的第一个页帧
357 /// @param count 要释放的页帧数量 (必须是2的n次幂)
358 pub unsafe fn deallocate_page_frames(
359     frame: PhysPageFrame,
360     count: PageFrameCount,
361     page_manager_guard: &mut SpinLockGuard<'_, crate::mm::page::PageManager>,
362 ) {
363     unsafe {
364         LockedFrameAllocator.free(frame.phys_address(), count);
365     }
366 
367     let mut frame = frame;
368     for _ in 0..count.data() {
369         let paddr = frame.phys_address();
370         let page = page_manager_guard.get(&paddr);
371 
372         if let Some(page) = page {
373             // 如果page是共享页,将其共享页信息从SHM_MANAGER中删去
374             let page_guard = page.read_irqsave();
375             if page_guard.shared() {
376                 shm_manager_lock().free_id(&page_guard.shm_id().unwrap());
377             }
378         }
379 
380         // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
381         page_manager_guard.remove_page(&paddr);
382         frame = frame.next();
383     }
384 }
385