Skip to content

Commit 56cc4db

Browse files
authored
实现页面反向映射 (#670)
* 实现页面反向映射 * 完善PAGE_MANAGER初始化时机 && 封装lock函数 && 删掉过时注释
1 parent 924d64d commit 56cc4db

File tree

6 files changed

+222
-48
lines changed

6 files changed

+222
-48
lines changed

kernel/src/driver/net/dma.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
33
use crate::arch::MMArch;
44

55
use crate::mm::kernel_mapper::KernelMapper;
6-
use crate::mm::page::PageFlags;
6+
use crate::mm::page::{page_manager_lock_irasave, PageFlags};
77
use crate::mm::{
88
allocator::page_frame::{
99
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
@@ -57,7 +57,11 @@ pub unsafe fn dma_dealloc(paddr: usize, vaddr: NonNull<u8>, pages: usize) -> i32
5757
flusher.flush();
5858

5959
unsafe {
60-
deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
60+
deallocate_page_frames(
61+
PhysPageFrame::new(PhysAddr::new(paddr)),
62+
page_count,
63+
&mut page_manager_lock_irasave(),
64+
);
6165
}
6266
return 0;
6367
}

kernel/src/driver/virtio/virtio_impl.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
33
use crate::arch::MMArch;
44

55
use crate::mm::kernel_mapper::KernelMapper;
6-
use crate::mm::page::PageFlags;
6+
use crate::mm::page::{page_manager_lock_irasave, PageFlags};
77
use crate::mm::{
88
allocator::page_frame::{
99
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
@@ -68,7 +68,11 @@ unsafe impl Hal for HalImpl {
6868
flusher.flush();
6969

7070
unsafe {
71-
deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
71+
deallocate_page_frames(
72+
PhysPageFrame::new(PhysAddr::new(paddr)),
73+
page_count,
74+
&mut page_manager_lock_irasave(),
75+
);
7276
}
7377
return 0;
7478
}

kernel/src/mm/allocator/page_frame.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use core::{
55

66
use crate::{
77
arch::{mm::LockedFrameAllocator, MMArch},
8+
libs::spinlock::SpinLockGuard,
89
mm::{MemoryManagementArch, PhysAddr, VirtAddr},
910
};
1011

@@ -348,8 +349,20 @@ pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, P
348349
///
349350
/// @param frame 要释放的第一个页帧
350351
/// @param count 要释放的页帧数量 (必须是2的n次幂)
351-
pub unsafe fn deallocate_page_frames(frame: PhysPageFrame, count: PageFrameCount) {
352+
pub unsafe fn deallocate_page_frames(
353+
frame: PhysPageFrame,
354+
count: PageFrameCount,
355+
page_manager: &mut SpinLockGuard<'_, crate::mm::page::PageManager>,
356+
) {
352357
unsafe {
353358
LockedFrameAllocator.free(frame.phys_address(), count);
354359
}
360+
361+
// 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
362+
let mut frame = frame;
363+
for _ in 0..count.data() {
364+
let paddr = frame.phys_address();
365+
page_manager.remove_page(&paddr);
366+
frame = frame.next();
367+
}
355368
}

kernel/src/mm/init.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use core::{fmt::Write, sync::atomic::Ordering};
22

33
use crate::{
4-
arch::MMArch, driver::serial::serial8250::send_to_default_serial8250_port,
5-
filesystem::procfs::kmsg::kmsg_init, libs::printk::PrintkWriter, mm::mmio_buddy::mmio_init,
4+
arch::MMArch,
5+
driver::serial::serial8250::send_to_default_serial8250_port,
6+
filesystem::procfs::kmsg::kmsg_init,
7+
libs::printk::PrintkWriter,
8+
mm::{mmio_buddy::mmio_init, page::page_manager_init},
69
};
710

811
use super::MemoryManagementArch;
@@ -44,6 +47,8 @@ pub unsafe fn mm_init() {
4447
mmio_init();
4548
// enable KMSG
4649
kmsg_init();
50+
// enable PAGE_MANAGER
51+
page_manager_init();
4752

4853
MM_INIT
4954
.compare_exchange(

kernel/src/mm/page.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,102 @@ use core::{
66
sync::atomic::{compiler_fence, Ordering},
77
};
88

9+
use alloc::sync::Arc;
10+
use hashbrown::{HashMap, HashSet};
11+
912
use crate::{
1013
arch::{interrupt::ipi::send_ipi, MMArch},
1114
exception::ipi::{IpiKind, IpiTarget},
1215
kerror, kwarn,
16+
libs::spinlock::{SpinLock, SpinLockGuard},
1317
};
1418

1519
use super::{
16-
allocator::page_frame::FrameAllocator, syscall::ProtFlags, MemoryManagementArch, PageTableKind,
17-
PhysAddr, VirtAddr,
20+
allocator::page_frame::FrameAllocator, syscall::ProtFlags, ucontext::LockedVMA,
21+
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
1822
};
1923

24+
/// 全局物理页信息管理器
25+
pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None;
26+
27+
/// 初始化PAGE_MANAGER
28+
pub fn page_manager_init() {
29+
kinfo!("page_manager_init");
30+
let page_manager = SpinLock::new(PageManager::new());
31+
32+
compiler_fence(Ordering::SeqCst);
33+
unsafe { PAGE_MANAGER = Some(page_manager) };
34+
compiler_fence(Ordering::SeqCst);
35+
36+
kinfo!("page_manager_init done");
37+
}
38+
39+
pub fn page_manager_lock_irasave() -> SpinLockGuard<'static, PageManager> {
40+
unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() }
41+
}
42+
43+
// 物理页管理器
44+
pub struct PageManager {
45+
phys2page: HashMap<PhysAddr, Page>,
46+
}
47+
48+
impl PageManager {
49+
pub fn new() -> Self {
50+
Self {
51+
phys2page: HashMap::new(),
52+
}
53+
}
54+
55+
pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page {
56+
self.phys2page.get_mut(paddr).unwrap()
57+
}
58+
59+
pub fn insert(&mut self, paddr: PhysAddr, page: Page) {
60+
self.phys2page.insert(paddr, page);
61+
}
62+
63+
pub fn remove_page(&mut self, paddr: &PhysAddr) {
64+
self.phys2page.remove(paddr);
65+
}
66+
}
67+
68+
/// 物理页面信息
69+
pub struct Page {
70+
/// 映射计数
71+
map_count: usize,
72+
/// 是否为共享页
73+
shared: bool,
74+
/// 映射到当前page的VMA
75+
anon_vma: HashSet<Arc<LockedVMA>>,
76+
}
77+
78+
impl Page {
79+
pub fn new(shared: bool) -> Self {
80+
Self {
81+
map_count: 0,
82+
shared,
83+
anon_vma: HashSet::new(),
84+
}
85+
}
86+
87+
/// 将vma加入anon_vma
88+
pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
89+
self.anon_vma.insert(vma);
90+
self.map_count += 1;
91+
}
92+
93+
/// 将vma从anon_vma中删去
94+
pub fn remove_vma(&mut self, vma: &LockedVMA) {
95+
self.anon_vma.remove(vma);
96+
self.map_count -= 1;
97+
}
98+
99+
/// 判断当前物理页是否能被回
100+
pub fn can_deallocate(&self) -> bool {
101+
self.map_count == 0 && !self.shared
102+
}
103+
}
104+
20105
#[derive(Debug)]
21106
pub struct PageTable<Arch> {
22107
/// 当前页表表示的虚拟地址空间的起始地址
@@ -591,6 +676,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
591676
compiler_fence(Ordering::SeqCst);
592677
let phys: PhysAddr = self.frame_allocator.allocate_one()?;
593678
compiler_fence(Ordering::SeqCst);
679+
680+
page_manager_lock_irasave().insert(phys, Page::new(false));
594681
return self.map_phys(virt, phys, flags);
595682
}
596683

0 commit comments

Comments
 (0)