1 use alloc::string::ToString;
2 use core::{
3 fmt::{self, Debug, Error, Formatter},
4 marker::PhantomData,
5 mem,
6 ops::Add,
7 sync::atomic::{compiler_fence, Ordering},
8 };
9 use system_error::SystemError;
10 use unified_init::macros::unified_init;
11
12 use alloc::sync::Arc;
13 use hashbrown::{HashMap, HashSet};
14 use log::{error, info};
15 use lru::LruCache;
16
17 use crate::{
18 arch::{interrupt::ipi::send_ipi, mm::LockedFrameAllocator, MMArch},
19 exception::ipi::{IpiKind, IpiTarget},
20 filesystem::vfs::{file::PageCache, FilePrivateData},
21 init::initcall::INITCALL_CORE,
22 ipc::shm::ShmId,
23 libs::{
24 rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
25 spinlock::{SpinLock, SpinLockGuard},
26 },
27 process::{ProcessControlBlock, ProcessManager},
28 time::{sleep::nanosleep, PosixTimeSpec},
29 };
30
31 use super::{
32 allocator::page_frame::{FrameAllocator, PageFrameCount},
33 syscall::ProtFlags,
34 ucontext::LockedVMA,
35 MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
36 };
37
38 pub const PAGE_4K_SHIFT: usize = 12;
39 #[allow(dead_code)]
40 pub const PAGE_2M_SHIFT: usize = 21;
41 pub const PAGE_1G_SHIFT: usize = 30;
42
43 pub const PAGE_4K_SIZE: usize = 1 << PAGE_4K_SHIFT;
44 pub const PAGE_2M_SIZE: usize = 1 << PAGE_2M_SHIFT;
45
46 /// 全局物理页信息管理器
47 pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None;
48
49 /// 初始化PAGE_MANAGER
page_manager_init()50 pub fn page_manager_init() {
51 info!("page_manager_init");
52 let page_manager = SpinLock::new(PageManager::new());
53
54 compiler_fence(Ordering::SeqCst);
55 unsafe { PAGE_MANAGER = Some(page_manager) };
56 compiler_fence(Ordering::SeqCst);
57
58 info!("page_manager_init done");
59 }
60
page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager>61 pub fn page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager> {
62 unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() }
63 }
64
65 // 物理页管理器
66 pub struct PageManager {
67 phys2page: HashMap<PhysAddr, Arc<Page>>,
68 }
69
70 impl PageManager {
new() -> Self71 pub fn new() -> Self {
72 Self {
73 phys2page: HashMap::new(),
74 }
75 }
76
contains(&self, paddr: &PhysAddr) -> bool77 pub fn contains(&self, paddr: &PhysAddr) -> bool {
78 self.phys2page.contains_key(paddr)
79 }
80
get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>>81 pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
82 page_reclaimer_lock_irqsave().get(paddr);
83 self.phys2page.get(paddr).cloned()
84 }
85
get_unwrap(&mut self, paddr: &PhysAddr) -> Arc<Page>86 pub fn get_unwrap(&mut self, paddr: &PhysAddr) -> Arc<Page> {
87 page_reclaimer_lock_irqsave().get(paddr);
88 self.phys2page
89 .get(paddr)
90 .unwrap_or_else(|| panic!("Phys Page not found, {:?}", paddr))
91 .clone()
92 }
93
insert(&mut self, paddr: PhysAddr, page: &Arc<Page>)94 pub fn insert(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
95 self.phys2page.insert(paddr, page.clone());
96 }
97
remove_page(&mut self, paddr: &PhysAddr)98 pub fn remove_page(&mut self, paddr: &PhysAddr) {
99 self.phys2page.remove(paddr);
100 }
101 }
102
103 pub static mut PAGE_RECLAIMER: Option<SpinLock<PageReclaimer>> = None;
104
page_reclaimer_init()105 pub fn page_reclaimer_init() {
106 info!("page_reclaimer_init");
107 let page_reclaimer = SpinLock::new(PageReclaimer::new());
108
109 compiler_fence(Ordering::SeqCst);
110 unsafe { PAGE_RECLAIMER = Some(page_reclaimer) };
111 compiler_fence(Ordering::SeqCst);
112
113 info!("page_reclaimer_init done");
114 }
115
116 /// 页面回收线程
117 static mut PAGE_RECLAIMER_THREAD: Option<Arc<ProcessControlBlock>> = None;
118
119 /// 页面回收线程初始化函数
120 #[unified_init(INITCALL_CORE)]
page_reclaimer_thread_init() -> Result<(), SystemError>121 fn page_reclaimer_thread_init() -> Result<(), SystemError> {
122 let closure = crate::process::kthread::KernelThreadClosure::StaticEmptyClosure((
123 &(page_reclaim_thread as fn() -> i32),
124 (),
125 ));
126 let pcb = crate::process::kthread::KernelThreadMechanism::create_and_run(
127 closure,
128 "page_reclaim".to_string(),
129 )
130 .ok_or("")
131 .expect("create tty_refresh thread failed");
132 unsafe {
133 PAGE_RECLAIMER_THREAD = Some(pcb);
134 }
135 Ok(())
136 }
137
138 /// 页面回收线程执行的函数
page_reclaim_thread() -> i32139 fn page_reclaim_thread() -> i32 {
140 loop {
141 let usage = unsafe { LockedFrameAllocator.usage() };
142 // log::info!("usage{:?}", usage);
143
144 // 保留4096个页面,总计16MB的空闲空间
145 if usage.free().data() < 4096 {
146 let page_to_free = 4096;
147 page_reclaimer_lock_irqsave().shrink_list(PageFrameCount::new(page_to_free));
148 } else {
149 //TODO 暂时让页面回收线程负责脏页回写任务,后续需要分离
150 page_reclaimer_lock_irqsave().flush_dirty_pages();
151 // 休眠5秒
152 // log::info!("sleep");
153 let _ = nanosleep(PosixTimeSpec::new(5, 0));
154 }
155 }
156 }
157
158 /// 获取页面回收器
page_reclaimer_lock_irqsave() -> SpinLockGuard<'static, PageReclaimer>159 pub fn page_reclaimer_lock_irqsave() -> SpinLockGuard<'static, PageReclaimer> {
160 unsafe { PAGE_RECLAIMER.as_ref().unwrap().lock_irqsave() }
161 }
162
163 /// 页面回收器
164 pub struct PageReclaimer {
165 lru: LruCache<PhysAddr, Arc<Page>>,
166 }
167
168 impl PageReclaimer {
new() -> Self169 pub fn new() -> Self {
170 Self {
171 lru: LruCache::unbounded(),
172 }
173 }
174
get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>>175 pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
176 self.lru.get(paddr).cloned()
177 }
178
insert_page(&mut self, paddr: PhysAddr, page: &Arc<Page>)179 pub fn insert_page(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
180 self.lru.put(paddr, page.clone());
181 }
182
183 /// lru链表缩减
184 /// ## 参数
185 ///
186 /// - `count`: 需要缩减的页面数量
shrink_list(&mut self, count: PageFrameCount)187 pub fn shrink_list(&mut self, count: PageFrameCount) {
188 for _ in 0..count.data() {
189 let (paddr, page) = self.lru.pop_lru().expect("pagecache is empty");
190 let page_cache = page.read_irqsave().page_cache().unwrap();
191 for vma in page.read_irqsave().anon_vma() {
192 let address_space = vma.lock_irqsave().address_space().unwrap();
193 let address_space = address_space.upgrade().unwrap();
194 let mut guard = address_space.write();
195 let mapper = &mut guard.user_mapper.utable;
196 let virt = vma.lock_irqsave().page_address(&page).unwrap();
197 unsafe {
198 mapper.unmap(virt, false).unwrap().flush();
199 }
200 }
201 page_cache.remove_page(page.read_irqsave().index().unwrap());
202 page_manager_lock_irqsave().remove_page(&paddr);
203 if page.read_irqsave().flags.contains(PageFlags::PG_DIRTY) {
204 Self::page_writeback(&page, true);
205 }
206 }
207 }
208
209 /// 唤醒页面回收线程
wakeup_claim_thread()210 pub fn wakeup_claim_thread() {
211 // log::info!("wakeup_claim_thread");
212 let _ = ProcessManager::wakeup(unsafe { PAGE_RECLAIMER_THREAD.as_ref().unwrap() });
213 }
214
215 /// 脏页回写函数
216 /// ## 参数
217 ///
218 /// - `page`: 需要回写的脏页
219 /// - `unmap`: 是否取消映射
220 ///
221 /// ## 返回值
222 /// - VmFaultReason: 页面错误处理信息标志
page_writeback(page: &Arc<Page>, unmap: bool)223 pub fn page_writeback(page: &Arc<Page>, unmap: bool) {
224 if !unmap {
225 page.write_irqsave().remove_flags(PageFlags::PG_DIRTY);
226 }
227
228 for vma in page.read_irqsave().anon_vma() {
229 let address_space = vma.lock_irqsave().address_space().unwrap();
230 let address_space = address_space.upgrade().unwrap();
231 let mut guard = address_space.write();
232 let mapper = &mut guard.user_mapper.utable;
233 let virt = vma.lock_irqsave().page_address(page).unwrap();
234 if unmap {
235 unsafe {
236 mapper.unmap(virt, false).unwrap().flush();
237 }
238 } else {
239 unsafe {
240 // 保护位设为只读
241 mapper.remap(
242 virt,
243 mapper.get_entry(virt, 0).unwrap().flags().set_write(false),
244 )
245 };
246 }
247 }
248 let inode = page
249 .read_irqsave()
250 .page_cache
251 .clone()
252 .unwrap()
253 .inode()
254 .clone()
255 .unwrap()
256 .upgrade()
257 .unwrap();
258 inode
259 .write_at(
260 page.read_irqsave().index().unwrap(),
261 MMArch::PAGE_SIZE,
262 unsafe {
263 core::slice::from_raw_parts(
264 MMArch::phys_2_virt(page.read_irqsave().phys_addr)
265 .unwrap()
266 .data() as *mut u8,
267 MMArch::PAGE_SIZE,
268 )
269 },
270 SpinLock::new(FilePrivateData::Unused).lock(),
271 )
272 .unwrap();
273 }
274
275 /// lru脏页刷新
flush_dirty_pages(&self)276 pub fn flush_dirty_pages(&self) {
277 // log::info!("flush_dirty_pages");
278 let iter = self.lru.iter();
279 for (_, page) in iter {
280 if page.read_irqsave().flags().contains(PageFlags::PG_DIRTY) {
281 Self::page_writeback(page, false);
282 }
283 }
284 }
285 }
286
287 bitflags! {
288 pub struct PageFlags: u64 {
289 const PG_LOCKED = 1 << 0;
290 const PG_WRITEBACK = 1 << 1;
291 const PG_REFERENCED = 1 << 2;
292 const PG_UPTODATE = 1 << 3;
293 const PG_DIRTY = 1 << 4;
294 const PG_LRU = 1 << 5;
295 const PG_HEAD = 1 << 6;
296 const PG_WAITERS = 1 << 7;
297 const PG_ACTIVE = 1 << 8;
298 const PG_WORKINGSET = 1 << 9;
299 const PG_ERROR = 1 << 10;
300 const PG_SLAB = 1 << 11;
301 const PG_RESERVED = 1 << 14;
302 const PG_PRIVATE = 1 << 15;
303 const PG_RECLAIM = 1 << 18;
304 const PG_SWAPBACKED = 1 << 19;
305 }
306 }
307
308 #[derive(Debug)]
309 pub struct Page {
310 inner: RwLock<InnerPage>,
311 }
312
313 impl Page {
new(shared: bool, phys_addr: PhysAddr) -> Self314 pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
315 let inner = InnerPage::new(shared, phys_addr);
316 Self {
317 inner: RwLock::new(inner),
318 }
319 }
320
read_irqsave(&self) -> RwLockReadGuard<InnerPage>321 pub fn read_irqsave(&self) -> RwLockReadGuard<InnerPage> {
322 self.inner.read_irqsave()
323 }
324
write_irqsave(&self) -> RwLockWriteGuard<InnerPage>325 pub fn write_irqsave(&self) -> RwLockWriteGuard<InnerPage> {
326 self.inner.write_irqsave()
327 }
328 }
329
330 #[derive(Debug)]
331 /// 物理页面信息
332 pub struct InnerPage {
333 /// 映射计数
334 map_count: usize,
335 /// 是否为共享页
336 shared: bool,
337 /// 映射计数为0时,是否可回收
338 free_when_zero: bool,
339 /// 共享页id(如果是共享页)
340 shm_id: Option<ShmId>,
341 /// 映射到当前page的VMA
342 anon_vma: HashSet<Arc<LockedVMA>>,
343 /// 标志
344 flags: PageFlags,
345 /// 页所在的物理页帧号
346 phys_addr: PhysAddr,
347 /// 在pagecache中的偏移
348 index: Option<usize>,
349 page_cache: Option<Arc<PageCache>>,
350 }
351
352 impl InnerPage {
new(shared: bool, phys_addr: PhysAddr) -> Self353 pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
354 let dealloc_when_zero = !shared;
355 Self {
356 map_count: 0,
357 shared,
358 free_when_zero: dealloc_when_zero,
359 shm_id: None,
360 anon_vma: HashSet::new(),
361 flags: PageFlags::empty(),
362 phys_addr,
363 index: None,
364 page_cache: None,
365 }
366 }
367
368 /// 将vma加入anon_vma
insert_vma(&mut self, vma: Arc<LockedVMA>)369 pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
370 self.anon_vma.insert(vma);
371 self.map_count += 1;
372 }
373
374 /// 将vma从anon_vma中删去
remove_vma(&mut self, vma: &LockedVMA)375 pub fn remove_vma(&mut self, vma: &LockedVMA) {
376 self.anon_vma.remove(vma);
377 self.map_count -= 1;
378 }
379
380 /// 判断当前物理页是否能被回
can_deallocate(&self) -> bool381 pub fn can_deallocate(&self) -> bool {
382 self.map_count == 0 && self.free_when_zero
383 }
384
shared(&self) -> bool385 pub fn shared(&self) -> bool {
386 self.shared
387 }
388
shm_id(&self) -> Option<ShmId>389 pub fn shm_id(&self) -> Option<ShmId> {
390 self.shm_id
391 }
392
index(&self) -> Option<usize>393 pub fn index(&self) -> Option<usize> {
394 self.index
395 }
396
page_cache(&self) -> Option<Arc<PageCache>>397 pub fn page_cache(&self) -> Option<Arc<PageCache>> {
398 self.page_cache.clone()
399 }
400
set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>)401 pub fn set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>) {
402 self.page_cache = page_cache;
403 }
404
set_index(&mut self, index: Option<usize>)405 pub fn set_index(&mut self, index: Option<usize>) {
406 self.index = index;
407 }
408
set_page_cache_index( &mut self, page_cache: Option<Arc<PageCache>>, index: Option<usize>, )409 pub fn set_page_cache_index(
410 &mut self,
411 page_cache: Option<Arc<PageCache>>,
412 index: Option<usize>,
413 ) {
414 self.page_cache = page_cache;
415 self.index = index;
416 }
417
set_shm_id(&mut self, shm_id: ShmId)418 pub fn set_shm_id(&mut self, shm_id: ShmId) {
419 self.shm_id = Some(shm_id);
420 }
421
set_dealloc_when_zero(&mut self, dealloc_when_zero: bool)422 pub fn set_dealloc_when_zero(&mut self, dealloc_when_zero: bool) {
423 self.free_when_zero = dealloc_when_zero;
424 }
425
426 #[inline(always)]
anon_vma(&self) -> &HashSet<Arc<LockedVMA>>427 pub fn anon_vma(&self) -> &HashSet<Arc<LockedVMA>> {
428 &self.anon_vma
429 }
430
431 #[inline(always)]
map_count(&self) -> usize432 pub fn map_count(&self) -> usize {
433 self.map_count
434 }
435
436 #[inline(always)]
flags(&self) -> &PageFlags437 pub fn flags(&self) -> &PageFlags {
438 &self.flags
439 }
440
441 #[inline(always)]
set_flags(&mut self, flags: PageFlags)442 pub fn set_flags(&mut self, flags: PageFlags) {
443 self.flags = flags
444 }
445
446 #[inline(always)]
add_flags(&mut self, flags: PageFlags)447 pub fn add_flags(&mut self, flags: PageFlags) {
448 self.flags = self.flags.union(flags);
449 }
450
451 #[inline(always)]
remove_flags(&mut self, flags: PageFlags)452 pub fn remove_flags(&mut self, flags: PageFlags) {
453 self.flags = self.flags.difference(flags);
454 }
455
456 #[inline(always)]
phys_address(&self) -> PhysAddr457 pub fn phys_address(&self) -> PhysAddr {
458 self.phys_addr
459 }
460 }
461
462 #[derive(Debug)]
463 pub struct PageTable<Arch> {
464 /// 当前页表表示的虚拟地址空间的起始地址
465 base: VirtAddr,
466 /// 当前页表所在的物理地址
467 phys: PhysAddr,
468 /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1])
469 level: usize,
470 phantom: PhantomData<Arch>,
471 }
472
473 #[allow(dead_code)]
474 impl<Arch: MemoryManagementArch> PageTable<Arch> {
new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self475 pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self {
476 Self {
477 base,
478 phys,
479 level,
480 phantom: PhantomData,
481 }
482 }
483
484 /// 获取顶级页表
485 ///
486 /// ## 参数
487 ///
488 /// - table_kind 页表类型
489 ///
490 /// ## 返回值
491 ///
492 /// 返回顶级页表
top_level_table(table_kind: PageTableKind) -> Self493 pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self {
494 return Self::new(
495 VirtAddr::new(0),
496 Arch::table(table_kind),
497 Arch::PAGE_LEVELS - 1,
498 );
499 }
500
501 /// 获取当前页表的物理地址
502 #[inline(always)]
phys(&self) -> PhysAddr503 pub fn phys(&self) -> PhysAddr {
504 self.phys
505 }
506
507 /// 当前页表表示的虚拟地址空间的起始地址
508 #[inline(always)]
base(&self) -> VirtAddr509 pub fn base(&self) -> VirtAddr {
510 self.base
511 }
512
513 /// 获取当前页表的层级
514 #[inline(always)]
level(&self) -> usize515 pub fn level(&self) -> usize {
516 self.level
517 }
518
519 /// 获取当前页表自身所在的虚拟地址
520 #[inline(always)]
virt(&self) -> VirtAddr521 pub unsafe fn virt(&self) -> VirtAddr {
522 return Arch::phys_2_virt(self.phys).unwrap();
523 }
524
525 /// 获取第i个页表项所表示的虚拟内存空间的起始地址
entry_base(&self, i: usize) -> Option<VirtAddr>526 pub fn entry_base(&self, i: usize) -> Option<VirtAddr> {
527 if i < Arch::PAGE_ENTRY_NUM {
528 let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
529 return Some(self.base.add(i << shift));
530 } else {
531 return None;
532 }
533 }
534
535 /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分)
entry_virt(&self, i: usize) -> Option<VirtAddr>536 pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> {
537 if i < Arch::PAGE_ENTRY_NUM {
538 return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE));
539 } else {
540 return None;
541 }
542 }
543
544 /// 获取当前页表的第i个页表项
entry(&self, i: usize) -> Option<PageEntry<Arch>>545 pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
546 let entry_virt = self.entry_virt(i)?;
547 return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt)));
548 }
549
550 /// 设置当前页表的第i个页表项
set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()>551 pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> {
552 let entry_virt = self.entry_virt(i)?;
553 Arch::write::<usize>(entry_virt, entry.data());
554 return Some(());
555 }
556
557 /// 判断当前页表的第i个页表项是否已经填写了值
558 ///
559 /// ## 参数
560 /// - Some(true) 如果已经填写了值
561 /// - Some(false) 如果未填写值
562 /// - None 如果i超出了页表项的范围
entry_mapped(&self, i: usize) -> Option<bool>563 pub fn entry_mapped(&self, i: usize) -> Option<bool> {
564 let etv = unsafe { self.entry_virt(i) }?;
565 if unsafe { Arch::read::<usize>(etv) } != 0 {
566 return Some(true);
567 } else {
568 return Some(false);
569 }
570 }
571
572 /// 根据虚拟地址,获取对应的页表项在页表中的下标
573 ///
574 /// ## 参数
575 ///
576 /// - addr: 虚拟地址
577 ///
578 /// ## 返回值
579 ///
580 /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None
index_of(&self, addr: VirtAddr) -> Option<usize>581 pub fn index_of(&self, addr: VirtAddr) -> Option<usize> {
582 let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK);
583 let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
584
585 let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1;
586 if addr < self.base || addr >= self.base.add(mask) {
587 return None;
588 } else {
589 return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK);
590 }
591 }
592
593 /// 获取第i个页表项指向的下一级页表
next_level_table(&self, index: usize) -> Option<Self>594 pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> {
595 if self.level == 0 {
596 return None;
597 }
598
599 // 返回下一级页表
600 return Some(PageTable::new(
601 self.entry_base(index)?,
602 self.entry(index)?.address().ok()?,
603 self.level - 1,
604 ));
605 }
606
607 /// 拷贝页表
608 /// ## 参数
609 ///
610 /// - `allocator`: 物理页框分配器
611 /// - `copy_on_write`: 是否写时复制
clone( &self, allocator: &mut impl FrameAllocator, copy_on_write: bool, ) -> Option<PageTable<Arch>>612 pub unsafe fn clone(
613 &self,
614 allocator: &mut impl FrameAllocator,
615 copy_on_write: bool,
616 ) -> Option<PageTable<Arch>> {
617 // 分配新页面作为新的页表
618 let phys = allocator.allocate_one()?;
619 let frame = MMArch::phys_2_virt(phys).unwrap();
620 MMArch::write_bytes(frame, 0, MMArch::PAGE_SIZE);
621 let new_table = PageTable::new(self.base, phys, self.level);
622 if self.level == 0 {
623 for i in 0..Arch::PAGE_ENTRY_NUM {
624 if let Some(mut entry) = self.entry(i) {
625 if entry.present() {
626 if copy_on_write {
627 let mut new_flags = entry.flags().set_write(false);
628 entry.set_flags(new_flags);
629 self.set_entry(i, entry);
630 new_flags = new_flags.set_dirty(false);
631 entry.set_flags(new_flags);
632 new_table.set_entry(i, entry);
633 } else {
634 let phys = allocator.allocate_one()?;
635 let mut page_manager_guard = page_manager_lock_irqsave();
636 let old_phys = entry.address().unwrap();
637 let old_page = page_manager_guard.get_unwrap(&old_phys);
638 let new_page =
639 Arc::new(Page::new(old_page.read_irqsave().shared(), phys));
640 if let Some(ref page_cache) = old_page.read_irqsave().page_cache() {
641 new_page.write_irqsave().set_page_cache_index(
642 Some(page_cache.clone()),
643 old_page.read_irqsave().index(),
644 );
645 }
646
647 page_manager_guard.insert(phys, &new_page);
648 let old_phys = entry.address().unwrap();
649 let frame = MMArch::phys_2_virt(phys).unwrap().data() as *mut u8;
650 frame.copy_from_nonoverlapping(
651 MMArch::phys_2_virt(old_phys).unwrap().data() as *mut u8,
652 MMArch::PAGE_SIZE,
653 );
654 new_table.set_entry(i, PageEntry::new(phys, entry.flags()));
655 }
656 }
657 }
658 }
659 } else {
660 // 非一级页表拷贝时,对每个页表项对应的页表都进行拷贝
661 for i in 0..MMArch::PAGE_ENTRY_NUM {
662 if let Some(next_table) = self.next_level_table(i) {
663 let table = next_table.clone(allocator, copy_on_write)?;
664 let old_entry = self.entry(i).unwrap();
665 let entry = PageEntry::new(table.phys(), old_entry.flags());
666 new_table.set_entry(i, entry);
667 }
668 }
669 }
670 Some(new_table)
671 }
672 }
673
674 /// 页表项
675 #[derive(Copy, Clone)]
676 pub struct PageEntry<Arch> {
677 data: usize,
678 phantom: PhantomData<Arch>,
679 }
680
681 impl<Arch> Debug for PageEntry<Arch> {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>682 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
683 f.write_fmt(format_args!("PageEntry({:#x})", self.data))
684 }
685 }
686
687 impl<Arch: MemoryManagementArch> PageEntry<Arch> {
688 #[inline(always)]
new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self689 pub fn new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self {
690 Self {
691 data: MMArch::make_entry(paddr, flags.data()),
692 phantom: PhantomData,
693 }
694 }
695 #[inline(always)]
from_usize(data: usize) -> Self696 pub fn from_usize(data: usize) -> Self {
697 Self {
698 data,
699 phantom: PhantomData,
700 }
701 }
702
703 #[inline(always)]
data(&self) -> usize704 pub fn data(&self) -> usize {
705 self.data
706 }
707
708 /// 获取当前页表项指向的物理地址
709 ///
710 /// ## 返回值
711 ///
712 /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址
713 /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
714 #[inline(always)]
address(&self) -> Result<PhysAddr, PhysAddr>715 pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
716 let paddr: PhysAddr = {
717 #[cfg(target_arch = "x86_64")]
718 {
719 PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK)
720 }
721
722 #[cfg(target_arch = "riscv64")]
723 {
724 let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1);
725 super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
726 }
727 };
728
729 if self.present() {
730 Ok(paddr)
731 } else {
732 Err(paddr)
733 }
734 }
735
736 #[inline(always)]
flags(&self) -> EntryFlags<Arch>737 pub fn flags(&self) -> EntryFlags<Arch> {
738 unsafe { EntryFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
739 }
740
741 #[inline(always)]
set_flags(&mut self, flags: EntryFlags<Arch>)742 pub fn set_flags(&mut self, flags: EntryFlags<Arch>) {
743 self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
744 }
745
746 #[inline(always)]
present(&self) -> bool747 pub fn present(&self) -> bool {
748 return self.data & Arch::ENTRY_FLAG_PRESENT != 0;
749 }
750
751 #[inline(always)]
empty(&self) -> bool752 pub fn empty(&self) -> bool {
753 self.data & !(Arch::ENTRY_FLAG_DIRTY & Arch::ENTRY_FLAG_ACCESSED) == 0
754 }
755
756 #[inline(always)]
protnone(&self) -> bool757 pub fn protnone(&self) -> bool {
758 return self.data & (Arch::ENTRY_FLAG_PRESENT | Arch::ENTRY_FLAG_GLOBAL)
759 == Arch::ENTRY_FLAG_GLOBAL;
760 }
761
762 #[inline(always)]
write(&self) -> bool763 pub fn write(&self) -> bool {
764 return self.data & Arch::ENTRY_FLAG_READWRITE != 0;
765 }
766 }
767
768 /// 页表项的标志位
769 #[derive(Copy, Clone, Hash)]
770 pub struct EntryFlags<Arch> {
771 data: usize,
772 phantom: PhantomData<Arch>,
773 }
774
775 impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> {
default() -> Self776 fn default() -> Self {
777 Self::new()
778 }
779 }
780
781 #[allow(dead_code)]
782 impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
783 #[inline(always)]
new() -> Self784 pub fn new() -> Self {
785 let mut r = unsafe {
786 Self::from_data(
787 Arch::ENTRY_FLAG_DEFAULT_PAGE
788 | Arch::ENTRY_FLAG_READONLY
789 | Arch::ENTRY_FLAG_NO_EXEC,
790 )
791 };
792
793 #[cfg(target_arch = "x86_64")]
794 {
795 if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
796 r = r.set_execute(true);
797 }
798 }
799
800 return r;
801 }
802
803 /// 根据ProtFlags生成EntryFlags
804 ///
805 /// ## 参数
806 ///
807 /// - prot_flags: 页的保护标志
808 /// - user: 用户空间是否可访问
from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self809 pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self {
810 if Arch::PAGE_FAULT_ENABLED {
811 let vm_flags = super::VmFlags::from(prot_flags);
812 Arch::vm_get_page_prot(vm_flags).set_user(user)
813 } else {
814 EntryFlags::new()
815 .set_user(user)
816 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
817 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE))
818 }
819 }
820
821 #[inline(always)]
data(&self) -> usize822 pub fn data(&self) -> usize {
823 self.data
824 }
825
826 #[inline(always)]
from_data(data: usize) -> Self827 pub const unsafe fn from_data(data: usize) -> Self {
828 return Self {
829 data,
830 phantom: PhantomData,
831 };
832 }
833
834 /// 为新页表的页表项设置默认值
835 ///
836 /// 默认值为:
837 /// - present
838 /// - read only
839 /// - kernel space
840 /// - no exec
841 #[inline(always)]
new_page_table(user: bool) -> Self842 pub fn new_page_table(user: bool) -> Self {
843 return unsafe {
844 let r = {
845 #[cfg(target_arch = "x86_64")]
846 {
847 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE)
848 }
849
850 #[cfg(target_arch = "riscv64")]
851 {
852 // riscv64指向下一级页表的页表项,不应设置R/W/X权限位
853 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
854 }
855 };
856
857 #[cfg(target_arch = "x86_64")]
858 {
859 if user {
860 r.set_user(true)
861 } else {
862 r
863 }
864 }
865
866 #[cfg(target_arch = "riscv64")]
867 {
868 r
869 }
870 };
871 }
872
873 /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。
874 ///
875 /// ## 参数
876 /// - flag 要更新的标志位的值
877 /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0
878 ///
879 /// ## 返回值
880 ///
881 /// 更新后的页表项
882 #[inline(always)]
883 #[must_use]
update_flags(mut self, flag: usize, value: bool) -> Self884 pub fn update_flags(mut self, flag: usize, value: bool) -> Self {
885 if value {
886 self.data |= flag;
887 } else {
888 self.data &= !flag;
889 }
890 return self;
891 }
892
893 /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true)
894 #[inline(always)]
has_flag(&self, flag: usize) -> bool895 pub fn has_flag(&self, flag: usize) -> bool {
896 return self.data & flag == flag;
897 }
898
899 #[inline(always)]
present(&self) -> bool900 pub fn present(&self) -> bool {
901 return self.has_flag(Arch::ENTRY_FLAG_PRESENT);
902 }
903
904 /// 设置当前页表项的权限
905 ///
906 /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问
907 #[must_use]
908 #[inline(always)]
set_user(self, value: bool) -> Self909 pub fn set_user(self, value: bool) -> Self {
910 return self.update_flags(Arch::ENTRY_FLAG_USER, value);
911 }
912
913 /// 用户态是否可以访问当前页表项
914 #[inline(always)]
has_user(&self) -> bool915 pub fn has_user(&self) -> bool {
916 return self.has_flag(Arch::ENTRY_FLAG_USER);
917 }
918
919 /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读
920 ///
921 /// ## 返回值
922 ///
923 /// 更新后的页表项.
924 ///
925 /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项
926 #[must_use]
927 #[inline(always)]
set_write(self, value: bool) -> Self928 pub fn set_write(self, value: bool) -> Self {
929 #[cfg(target_arch = "x86_64")]
930 {
931 // 有的架构同时具有可写和不可写的标志位,因此需要同时更新
932 return self
933 .update_flags(Arch::ENTRY_FLAG_READONLY, !value)
934 .update_flags(Arch::ENTRY_FLAG_READWRITE, value);
935 }
936
937 #[cfg(target_arch = "riscv64")]
938 {
939 if value {
940 return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
941 } else {
942 return self
943 .update_flags(Arch::ENTRY_FLAG_READONLY, true)
944 .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false);
945 }
946 }
947 }
948
949 /// 当前页表项是否可写
950 #[inline(always)]
has_write(&self) -> bool951 pub fn has_write(&self) -> bool {
952 // 有的架构同时具有可写和不可写的标志位,因此需要同时判断
953 return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY)
954 == Arch::ENTRY_FLAG_READWRITE;
955 }
956
957 /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行
958 #[must_use]
959 #[inline(always)]
set_execute(self, mut value: bool) -> Self960 pub fn set_execute(self, mut value: bool) -> Self {
961 #[cfg(target_arch = "x86_64")]
962 {
963 // 如果xd位被保留,那么将可执行性设置为true
964 if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
965 value = true;
966 }
967 }
968
969 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新
970 return self
971 .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value)
972 .update_flags(Arch::ENTRY_FLAG_EXEC, value);
973 }
974
975 /// 当前页表项是否可执行
976 #[inline(always)]
has_execute(&self) -> bool977 pub fn has_execute(&self) -> bool {
978 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断
979 return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC)
980 == Arch::ENTRY_FLAG_EXEC;
981 }
982
983 /// 设置当前页表项的缓存策略
984 ///
985 /// ## 参数
986 ///
987 /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。
988 #[inline(always)]
set_page_cache_disable(self, value: bool) -> Self989 pub fn set_page_cache_disable(self, value: bool) -> Self {
990 return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value);
991 }
992
993 /// 获取当前页表项的缓存策略
994 ///
995 /// ## 返回值
996 ///
997 /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。
998 #[inline(always)]
has_page_cache_disable(&self) -> bool999 pub fn has_page_cache_disable(&self) -> bool {
1000 return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE);
1001 }
1002
1003 /// 设置当前页表项的写穿策略
1004 ///
1005 /// ## 参数
1006 ///
1007 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
1008 #[inline(always)]
set_page_write_through(self, value: bool) -> Self1009 pub fn set_page_write_through(self, value: bool) -> Self {
1010 return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value);
1011 }
1012
1013 #[inline(always)]
set_page_global(self, value: bool) -> Self1014 pub fn set_page_global(self, value: bool) -> Self {
1015 return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value);
1016 }
1017
1018 /// 获取当前页表项的写穿策略
1019 ///
1020 /// ## 返回值
1021 ///
1022 /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。
1023 #[inline(always)]
has_page_write_through(&self) -> bool1024 pub fn has_page_write_through(&self) -> bool {
1025 return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH);
1026 }
1027
1028 /// 设置当前页表是否为脏页
1029 ///
1030 /// ## 参数
1031 ///
1032 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
1033 #[inline(always)]
set_dirty(self, value: bool) -> Self1034 pub fn set_dirty(self, value: bool) -> Self {
1035 return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value);
1036 }
1037
1038 /// 设置当前页表被访问
1039 ///
1040 /// ## 参数
1041 ///
1042 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。
1043 #[inline(always)]
set_access(self, value: bool) -> Self1044 pub fn set_access(self, value: bool) -> Self {
1045 return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value);
1046 }
1047
1048 /// 设置指向的页是否为大页
1049 ///
1050 /// ## 参数
1051 ///
1052 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。
1053 #[inline(always)]
set_huge_page(self, value: bool) -> Self1054 pub fn set_huge_page(self, value: bool) -> Self {
1055 return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value);
1056 }
1057
1058 /// MMIO内存的页表项标志
1059 #[inline(always)]
mmio_flags() -> Self1060 pub fn mmio_flags() -> Self {
1061 #[cfg(target_arch = "x86_64")]
1062 {
1063 Self::new()
1064 .set_user(false)
1065 .set_write(true)
1066 .set_execute(true)
1067 .set_page_cache_disable(true)
1068 .set_page_write_through(true)
1069 .set_page_global(true)
1070 }
1071
1072 #[cfg(target_arch = "riscv64")]
1073 {
1074 Self::new()
1075 .set_user(false)
1076 .set_write(true)
1077 .set_execute(true)
1078 .set_page_global(true)
1079 }
1080 }
1081 }
1082
1083 impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 f.debug_struct("EntryFlags")
1086 .field("bits", &format_args!("{:#0x}", self.data))
1087 .field("present", &self.present())
1088 .field("has_write", &self.has_write())
1089 .field("has_execute", &self.has_execute())
1090 .field("has_user", &self.has_user())
1091 .finish()
1092 }
1093 }
1094
1095 /// 页表映射器
1096 #[derive(Hash)]
1097 pub struct PageMapper<Arch, F> {
1098 /// 页表类型
1099 table_kind: PageTableKind,
1100 /// 根页表物理地址
1101 table_paddr: PhysAddr,
1102 /// 页分配器
1103 frame_allocator: F,
1104 phantom: PhantomData<fn() -> Arch>,
1105 }
1106
1107 impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
1108 /// 创建新的页面映射器
1109 ///
1110 /// ## 参数
1111 /// - table_kind 页表类型
1112 /// - table_paddr 根页表物理地址
1113 /// - allocator 页分配器
1114 ///
1115 /// ## 返回值
1116 ///
1117 /// 页面映射器
new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self1118 pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self {
1119 return Self {
1120 table_kind,
1121 table_paddr,
1122 frame_allocator: allocator,
1123 phantom: PhantomData,
1124 };
1125 }
1126
1127 /// 创建页表,并为这个页表创建页面映射器
create(table_kind: PageTableKind, mut allocator: F) -> Option<Self>1128 pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> {
1129 let table_paddr = allocator.allocate_one()?;
1130 // 清空页表
1131 let table_vaddr = Arch::phys_2_virt(table_paddr)?;
1132 Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE);
1133 return Some(Self::new(table_kind, table_paddr, allocator));
1134 }
1135
1136 /// 获取当前页表的页面映射器
1137 #[inline(always)]
current(table_kind: PageTableKind, allocator: F) -> Self1138 pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self {
1139 let table_paddr = Arch::table(table_kind);
1140 return Self::new(table_kind, table_paddr, allocator);
1141 }
1142
1143 /// 判断当前页表分配器所属的页表是否是当前页表
1144 #[inline(always)]
is_current(&self) -> bool1145 pub fn is_current(&self) -> bool {
1146 return unsafe { self.table().phys() == Arch::table(self.table_kind) };
1147 }
1148
1149 /// 将当前页表分配器所属的页表设置为当前页表
1150 #[inline(always)]
make_current(&self)1151 pub unsafe fn make_current(&self) {
1152 Arch::set_table(self.table_kind, self.table_paddr);
1153 }
1154
1155 /// 获取当前页表分配器所属的根页表的结构体
1156 #[inline(always)]
table(&self) -> PageTable<Arch>1157 pub fn table(&self) -> PageTable<Arch> {
1158 // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的
1159 return unsafe {
1160 PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1)
1161 };
1162 }
1163
1164 /// 获取当前PageMapper所对应的页分配器实例的引用
1165 #[inline(always)]
1166 #[allow(dead_code)]
allocator_ref(&self) -> &F1167 pub fn allocator_ref(&self) -> &F {
1168 return &self.frame_allocator;
1169 }
1170
1171 /// 获取当前PageMapper所对应的页分配器实例的可变引用
1172 #[inline(always)]
allocator_mut(&mut self) -> &mut F1173 pub fn allocator_mut(&mut self) -> &mut F {
1174 return &mut self.frame_allocator;
1175 }
1176
1177 /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址
map( &mut self, virt: VirtAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1178 pub unsafe fn map(
1179 &mut self,
1180 virt: VirtAddr,
1181 flags: EntryFlags<Arch>,
1182 ) -> Option<PageFlush<Arch>> {
1183 compiler_fence(Ordering::SeqCst);
1184 let phys: PhysAddr = self.frame_allocator.allocate_one()?;
1185 compiler_fence(Ordering::SeqCst);
1186
1187 unsafe {
1188 let vaddr = MMArch::phys_2_virt(phys).unwrap();
1189 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE);
1190 }
1191
1192 let mut page_manager_guard: SpinLockGuard<'static, PageManager> =
1193 page_manager_lock_irqsave();
1194 if !page_manager_guard.contains(&phys) {
1195 page_manager_guard.insert(phys, &Arc::new(Page::new(false, phys)))
1196 }
1197 drop(page_manager_guard);
1198 return self.map_phys(virt, phys, flags);
1199 }
1200
1201 /// 映射一个物理页到指定的虚拟地址
map_phys( &mut self, virt: VirtAddr, phys: PhysAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1202 pub unsafe fn map_phys(
1203 &mut self,
1204 virt: VirtAddr,
1205 phys: PhysAddr,
1206 flags: EntryFlags<Arch>,
1207 ) -> Option<PageFlush<Arch>> {
1208 // 验证虚拟地址和物理地址是否对齐
1209 if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
1210 error!(
1211 "Try to map unaligned page: virt={:?}, phys={:?}",
1212 virt, phys
1213 );
1214 return None;
1215 }
1216
1217 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
1218
1219 // TODO: 验证flags是否合法
1220
1221 // 创建页表项
1222 let entry = PageEntry::new(phys, flags);
1223 let mut table = self.table();
1224 loop {
1225 let i = table.index_of(virt)?;
1226
1227 assert!(i < Arch::PAGE_ENTRY_NUM);
1228 if table.level() == 0 {
1229 compiler_fence(Ordering::SeqCst);
1230
1231 table.set_entry(i, entry);
1232 compiler_fence(Ordering::SeqCst);
1233 return Some(PageFlush::new(virt));
1234 } else {
1235 let next_table = table.next_level_table(i);
1236 if let Some(next_table) = next_table {
1237 table = next_table;
1238 // debug!("Mapping {:?} to next level table...", virt);
1239 } else {
1240 // 分配下一级页表
1241 let frame = self.frame_allocator.allocate_one()?;
1242
1243 // 清空这个页帧
1244 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
1245 // 设置页表项的flags
1246 let flags: EntryFlags<Arch> =
1247 EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
1248
1249 // 把新分配的页表映射到当前页表
1250 table.set_entry(i, PageEntry::new(frame, flags));
1251
1252 // 获取新分配的页表
1253 table = table.next_level_table(i)?;
1254 }
1255 }
1256 }
1257 }
1258
1259 /// 进行大页映射
map_huge_page( &mut self, virt: VirtAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1260 pub unsafe fn map_huge_page(
1261 &mut self,
1262 virt: VirtAddr,
1263 flags: EntryFlags<Arch>,
1264 ) -> Option<PageFlush<Arch>> {
1265 // 验证虚拟地址是否对齐
1266 if !(virt.check_aligned(Arch::PAGE_SIZE)) {
1267 error!("Try to map unaligned page: virt={:?}", virt);
1268 return None;
1269 }
1270
1271 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
1272
1273 let mut table = self.table();
1274 loop {
1275 let i = table.index_of(virt)?;
1276 assert!(i < Arch::PAGE_ENTRY_NUM);
1277 let next_table = table.next_level_table(i);
1278 if let Some(next_table) = next_table {
1279 table = next_table;
1280 } else {
1281 break;
1282 }
1283 }
1284
1285 // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页
1286 if table.level == 0 || table.level > 2 {
1287 return None;
1288 }
1289
1290 let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new(
1291 Arch::PAGE_ENTRY_NUM.pow(table.level as u32),
1292 ))?;
1293
1294 MMArch::write_bytes(
1295 MMArch::phys_2_virt(phys).unwrap(),
1296 0,
1297 MMArch::PAGE_SIZE * count.data(),
1298 );
1299
1300 table.set_entry(
1301 table.index_of(virt)?,
1302 PageEntry::new(phys, flags.set_huge_page(true)),
1303 )?;
1304 Some(PageFlush::new(virt))
1305 }
1306
1307 /// 为虚拟地址分配指定层级的页表
1308 /// ## 参数
1309 ///
1310 /// - `virt`: 虚拟地址
1311 /// - `level`: 指定页表层级
1312 ///
1313 /// ## 返回值
1314 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表
1315 /// - None: 对应页表不存在
allocate_table( &mut self, virt: VirtAddr, level: usize, ) -> Option<PageTable<Arch>>1316 pub unsafe fn allocate_table(
1317 &mut self,
1318 virt: VirtAddr,
1319 level: usize,
1320 ) -> Option<PageTable<Arch>> {
1321 let table = self.get_table(virt, level + 1)?;
1322 let i = table.index_of(virt)?;
1323 let frame = self.frame_allocator.allocate_one()?;
1324
1325 // 清空这个页帧
1326 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
1327
1328 // 设置页表项的flags
1329 let flags: EntryFlags<Arch> =
1330 EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
1331
1332 table.set_entry(i, PageEntry::new(frame, flags));
1333 table.next_level_table(i)
1334 }
1335
1336 /// 获取虚拟地址的指定层级页表
1337 /// ## 参数
1338 ///
1339 /// - `virt`: 虚拟地址
1340 /// - `level`: 指定页表层级
1341 ///
1342 /// ## 返回值
1343 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表
1344 /// - None: 对应页表不存在
get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>>1345 pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> {
1346 let mut table = self.table();
1347 if level > Arch::PAGE_LEVELS - 1 {
1348 return None;
1349 }
1350
1351 unsafe {
1352 loop {
1353 if table.level == level {
1354 return Some(table);
1355 }
1356 let i = table.index_of(virt)?;
1357 assert!(i < Arch::PAGE_ENTRY_NUM);
1358
1359 table = table.next_level_table(i)?;
1360 }
1361 }
1362 }
1363
1364 /// 获取虚拟地址在指定层级页表的PageEntry
1365 /// ## 参数
1366 ///
1367 /// - `virt`: 虚拟地址
1368 /// - `level`: 指定页表层级
1369 ///
1370 /// ## 返回值
1371 /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry
1372 /// - None: 无对应的有效PageEntry
get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>>1373 pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> {
1374 let table = self.get_table(virt, level)?;
1375 let i = table.index_of(virt)?;
1376 let entry = unsafe { table.entry(i) }?;
1377
1378 if !entry.empty() {
1379 Some(entry)
1380 } else {
1381 None
1382 }
1383
1384 // let mut table = self.table();
1385 // if level > Arch::PAGE_LEVELS - 1 {
1386 // return None;
1387 // }
1388 // unsafe {
1389 // loop {
1390 // let i = table.index_of(virt)?;
1391 // assert!(i < Arch::PAGE_ENTRY_NUM);
1392
1393 // if table.level == level {
1394 // let entry = table.entry(i)?;
1395 // if !entry.empty() {
1396 // return Some(entry);
1397 // } else {
1398 // return None;
1399 // }
1400 // }
1401
1402 // table = table.next_level_table(i)?;
1403 // }
1404 // }
1405 }
1406
1407 /// 拷贝用户空间映射
1408 /// ## 参数
1409 ///
1410 /// - `umapper`: 要拷贝的用户空间
1411 /// - `copy_on_write`: 是否写时复制
clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool)1412 pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) {
1413 let old_table = umapper.table();
1414 let new_table = self.table();
1415 let allocator = self.allocator_mut();
1416 // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射
1417 for entry_index in 0..Arch::PAGE_KERNEL_INDEX {
1418 if let Some(next_table) = old_table.next_level_table(entry_index) {
1419 let table = next_table.clone(allocator, copy_on_write).unwrap();
1420 let old_entry = old_table.entry(entry_index).unwrap();
1421 let entry = PageEntry::new(table.phys(), old_entry.flags());
1422 new_table.set_entry(entry_index, entry);
1423 }
1424 }
1425 }
1426
1427 /// 将物理地址映射到具有线性偏移量的虚拟地址
1428 #[allow(dead_code)]
map_linearly( &mut self, phys: PhysAddr, flags: EntryFlags<Arch>, ) -> Option<(VirtAddr, PageFlush<Arch>)>1429 pub unsafe fn map_linearly(
1430 &mut self,
1431 phys: PhysAddr,
1432 flags: EntryFlags<Arch>,
1433 ) -> Option<(VirtAddr, PageFlush<Arch>)> {
1434 let virt: VirtAddr = Arch::phys_2_virt(phys)?;
1435 return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
1436 }
1437
1438 /// 修改虚拟地址的页表项的flags,并返回页表项刷新器
1439 ///
1440 /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效
1441 ///
1442 /// ## 参数
1443 /// - virt 虚拟地址
1444 /// - flags 新的页表项的flags
1445 ///
1446 /// ## 返回值
1447 ///
1448 /// 如果修改成功,返回刷新器,否则返回None
remap( &mut self, virt: VirtAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1449 pub unsafe fn remap(
1450 &mut self,
1451 virt: VirtAddr,
1452 flags: EntryFlags<Arch>,
1453 ) -> Option<PageFlush<Arch>> {
1454 return self
1455 .visit(virt, |p1, i| {
1456 let mut entry = p1.entry(i)?;
1457
1458 entry.set_flags(flags);
1459 p1.set_entry(i, entry);
1460 Some(PageFlush::new(virt))
1461 })
1462 .flatten();
1463 }
1464
1465 /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags
1466 ///
1467 /// ## 参数
1468 ///
1469 /// - virt 虚拟地址
1470 ///
1471 /// ## 返回值
1472 ///
1473 /// 如果查找成功,返回物理地址和页表项的flags,否则返回None
translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)>1474 pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> {
1475 let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
1476 let paddr = entry.address().ok()?;
1477 let flags = entry.flags();
1478 return Some((paddr, flags));
1479 }
1480
1481 /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器
1482 ///
1483 /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效
1484 ///
1485 /// ## 参数
1486 ///
1487 /// - virt 虚拟地址
1488 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
1489 ///
1490 /// ## 返回值
1491 /// 如果取消成功,返回刷新器,否则返回None
1492 #[allow(dead_code)]
unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>>1493 pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
1494 let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
1495 self.frame_allocator.free_one(paddr);
1496 return Some(flusher);
1497 }
1498
1499 /// 取消虚拟地址的映射,并返回物理地址和页表项的flags
1500 ///
1501 /// ## 参数
1502 ///
1503 /// - vaddr 虚拟地址
1504 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
1505 ///
1506 /// ## 返回值
1507 ///
1508 /// 如果取消成功,返回物理地址和页表项的flags,否则返回None
unmap_phys( &mut self, virt: VirtAddr, unmap_parents: bool, ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)>1509 pub unsafe fn unmap_phys(
1510 &mut self,
1511 virt: VirtAddr,
1512 unmap_parents: bool,
1513 ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> {
1514 if !virt.check_aligned(Arch::PAGE_SIZE) {
1515 error!("Try to unmap unaligned page: virt={:?}", virt);
1516 return None;
1517 }
1518
1519 let table = self.table();
1520 return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut())
1521 .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt)));
1522 }
1523
1524 /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F
visit<T>( &self, virt: VirtAddr, f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, ) -> Option<T>1525 fn visit<T>(
1526 &self,
1527 virt: VirtAddr,
1528 f: impl FnOnce(&mut PageTable<Arch>, usize) -> T,
1529 ) -> Option<T> {
1530 let mut table = self.table();
1531 unsafe {
1532 loop {
1533 let i = table.index_of(virt)?;
1534 if table.level() == 0 {
1535 return Some(f(&mut table, i));
1536 } else {
1537 table = table.next_level_table(i)?;
1538 }
1539 }
1540 }
1541 }
1542 }
1543
1544 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】
1545 ///
1546 /// ## 参数
1547 ///
1548 /// - vaddr 虚拟地址
1549 /// - table 页表
1550 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
1551 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内)
1552 ///
1553 /// ## 返回值
1554 ///
1555 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None
unmap_phys_inner<Arch: MemoryManagementArch>( vaddr: VirtAddr, table: &PageTable<Arch>, unmap_parents: bool, allocator: &mut impl FrameAllocator, ) -> Option<(PhysAddr, EntryFlags<Arch>)>1556 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
1557 vaddr: VirtAddr,
1558 table: &PageTable<Arch>,
1559 unmap_parents: bool,
1560 allocator: &mut impl FrameAllocator,
1561 ) -> Option<(PhysAddr, EntryFlags<Arch>)> {
1562 // 获取页表项的索引
1563 let i = table.index_of(vaddr)?;
1564
1565 // 如果当前是最后一级页表,直接取消页面映射
1566 if table.level() == 0 {
1567 let entry = table.entry(i)?;
1568 table.set_entry(i, PageEntry::from_usize(0));
1569 return Some((entry.address().ok()?, entry.flags()));
1570 }
1571
1572 let subtable = table.next_level_table(i)?;
1573 // 递归地取消映射
1574 let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?;
1575
1576 // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables,
1577 // as these mappings may become out of sync
1578 if unmap_parents {
1579 // 如果子页表已经没有映射的页面了,就取消子页表的映射
1580
1581 // 检查子页表中是否还有映射的页面
1582 let x = (0..Arch::PAGE_ENTRY_NUM)
1583 .map(|k| subtable.entry(k).expect("invalid page entry"))
1584 .any(|e| e.present());
1585 if !x {
1586 // 如果没有,就取消子页表的映射
1587 table.set_entry(i, PageEntry::from_usize(0));
1588 // 释放子页表
1589 allocator.free_one(subtable.phys());
1590 }
1591 }
1592
1593 return Some(result);
1594 }
1595
1596 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1597 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1598 f.debug_struct("PageMapper")
1599 .field("table_paddr", &self.table_paddr)
1600 .field("frame_allocator", &self.frame_allocator)
1601 .finish()
1602 }
1603 }
1604
1605 /// 页表刷新器的trait
1606 pub trait Flusher<Arch: MemoryManagementArch> {
1607 /// 取消对指定的page flusher的刷新
consume(&mut self, flush: PageFlush<Arch>)1608 fn consume(&mut self, flush: PageFlush<Arch>);
1609 }
1610
1611 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法,
1612 /// 否则会造成对页表的更改被忽略,这是不安全的
1613 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
1614 pub struct PageFlush<Arch: MemoryManagementArch> {
1615 virt: VirtAddr,
1616 phantom: PhantomData<Arch>,
1617 }
1618
1619 impl<Arch: MemoryManagementArch> PageFlush<Arch> {
new(virt: VirtAddr) -> Self1620 pub fn new(virt: VirtAddr) -> Self {
1621 return Self {
1622 virt,
1623 phantom: PhantomData,
1624 };
1625 }
1626
flush(self)1627 pub fn flush(self) {
1628 unsafe { Arch::invalidate_page(self.virt) };
1629 }
1630
1631 /// 忽略掉这个刷新器
ignore(self)1632 pub unsafe fn ignore(self) {
1633 mem::forget(self);
1634 }
1635 }
1636
1637 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> {
drop(&mut self)1638 fn drop(&mut self) {
1639 unsafe {
1640 MMArch::invalidate_page(self.virt);
1641 }
1642 }
1643 }
1644
1645 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法,
1646 /// 否则会造成对页表的更改被忽略,这是不安全的
1647 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
1648 pub struct PageFlushAll<Arch: MemoryManagementArch> {
1649 phantom: PhantomData<fn() -> Arch>,
1650 }
1651
1652 #[allow(dead_code)]
1653 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> {
new() -> Self1654 pub fn new() -> Self {
1655 return Self {
1656 phantom: PhantomData,
1657 };
1658 }
1659
flush(self)1660 pub fn flush(self) {
1661 unsafe { Arch::invalidate_all() };
1662 }
1663
1664 /// 忽略掉这个刷新器
ignore(self)1665 pub unsafe fn ignore(self) {
1666 mem::forget(self);
1667 }
1668 }
1669
1670 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> {
1671 /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了)
consume(&mut self, flush: PageFlush<Arch>)1672 fn consume(&mut self, flush: PageFlush<Arch>) {
1673 unsafe { flush.ignore() };
1674 }
1675 }
1676
1677 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T {
1678 /// 允许一个flusher consume掉另一个flusher
consume(&mut self, flush: PageFlush<Arch>)1679 fn consume(&mut self, flush: PageFlush<Arch>) {
1680 <T as Flusher<Arch>>::consume(self, flush);
1681 }
1682 }
1683
1684 impl<Arch: MemoryManagementArch> Flusher<Arch> for () {
consume(&mut self, _flush: PageFlush<Arch>)1685 fn consume(&mut self, _flush: PageFlush<Arch>) {}
1686 }
1687
1688 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> {
drop(&mut self)1689 fn drop(&mut self) {
1690 unsafe {
1691 Arch::invalidate_all();
1692 }
1693 }
1694 }
1695
1696 /// 未在当前CPU上激活的页表的刷新器
1697 ///
1698 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表
1699 ///
1700 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销)
1701 #[derive(Debug)]
1702 pub struct InactiveFlusher;
1703
1704 impl InactiveFlusher {
new() -> Self1705 pub fn new() -> Self {
1706 return Self {};
1707 }
1708 }
1709
1710 impl Flusher<MMArch> for InactiveFlusher {
consume(&mut self, flush: PageFlush<MMArch>)1711 fn consume(&mut self, flush: PageFlush<MMArch>) {
1712 unsafe {
1713 flush.ignore();
1714 }
1715 }
1716 }
1717
1718 impl Drop for InactiveFlusher {
drop(&mut self)1719 fn drop(&mut self) {
1720 // 发送刷新页表的IPI
1721 send_ipi(IpiKind::FlushTLB, IpiTarget::Other);
1722 }
1723 }
1724
1725 /// # 把一个地址向下对齐到页大小
round_down_to_page_size(addr: usize) -> usize1726 pub fn round_down_to_page_size(addr: usize) -> usize {
1727 addr & !(MMArch::PAGE_SIZE - 1)
1728 }
1729
1730 /// # 把一个地址向上对齐到页大小
round_up_to_page_size(addr: usize) -> usize1731 pub fn round_up_to_page_size(addr: usize) -> usize {
1732 round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1)
1733 }
1734