Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions kernel/src/driver/net/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
use crate::arch::MMArch;

use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::PageFlags;
use crate::mm::page::{PageFlags, PAGE_MANAGER};
use crate::mm::{
allocator::page_frame::{
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
Expand Down Expand Up @@ -57,7 +57,11 @@ pub unsafe fn dma_dealloc(paddr: usize, vaddr: NonNull<u8>, pages: usize) -> i32
flusher.flush();

unsafe {
deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
deallocate_page_frames(
PhysPageFrame::new(PhysAddr::new(paddr)),
page_count,
&mut PAGE_MANAGER.lock(),
);
}
return 0;
}
8 changes: 6 additions & 2 deletions kernel/src/driver/virtio/virtio_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
use crate::arch::MMArch;

use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::PageFlags;
use crate::mm::page::{PageFlags, PAGE_MANAGER};
use crate::mm::{
allocator::page_frame::{
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
Expand Down Expand Up @@ -68,7 +68,11 @@ unsafe impl Hal for HalImpl {
flusher.flush();

unsafe {
deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
deallocate_page_frames(
PhysPageFrame::new(PhysAddr::new(paddr)),
page_count,
&mut PAGE_MANAGER.lock(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个PAGE_MANAGER.lock()最好封装成函数。

并且应当是lock_irqsave?因为hzp在写的那个pagefault处理,估计中断上下文内会使用到这个东西,因此得lock irqsave

);
}
return 0;
}
Expand Down
15 changes: 14 additions & 1 deletion kernel/src/mm/allocator/page_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use core::{

use crate::{
arch::{mm::LockedFrameAllocator, MMArch},
libs::spinlock::SpinLockGuard,
mm::{MemoryManagementArch, PhysAddr, VirtAddr},
};

Expand Down Expand Up @@ -348,8 +349,20 @@ pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, P
///
/// @param frame 要释放的第一个页帧
/// @param count 要释放的页帧数量 (必须是2的n次幂)
pub unsafe fn deallocate_page_frames(frame: PhysPageFrame, count: PageFrameCount) {
pub unsafe fn deallocate_page_frames(
frame: PhysPageFrame,
count: PageFrameCount,
page_manager: &mut SpinLockGuard<'_, crate::mm::page::PageManager>,
) {
unsafe {
LockedFrameAllocator.free(frame.phys_address(), count);
}

// 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
let mut frame = frame;
for _ in 0..count.data() {
let paddr = frame.phys_address();
page_manager.remove_page(&paddr);
frame = frame.next();
}
}
77 changes: 75 additions & 2 deletions kernel/src/mm/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,88 @@ use core::{
sync::atomic::{compiler_fence, Ordering},
};

use alloc::sync::Arc;
use hashbrown::{HashMap, HashSet};

use crate::{
arch::{interrupt::ipi::send_ipi, MMArch},
exception::ipi::{IpiKind, IpiTarget},
kerror, kwarn,
libs::spinlock::SpinLock,
};

use super::{
allocator::page_frame::FrameAllocator, syscall::ProtFlags, MemoryManagementArch, PageTableKind,
PhysAddr, VirtAddr,
allocator::page_frame::FrameAllocator, syscall::ProtFlags, ucontext::LockedVMA,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
};

lazy_static! {
/// 全局物理页信息管理器
pub static ref PAGE_MANAGER: SpinLock<PageManager> = SpinLock::new(PageManager::new());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这玩意应当显式指定初始化的时机,而不是使用lazy_static

}

// 物理页管理器
pub struct PageManager {
phys2page: HashMap<PhysAddr, Page>,
}

impl PageManager {
pub fn new() -> Self {
Self {
phys2page: HashMap::new(),
}
}

pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page {
self.phys2page.get_mut(paddr).unwrap()
}

pub fn insert(&mut self, paddr: PhysAddr, page: Page) {
self.phys2page.insert(paddr, page);
}

pub fn remove_page(&mut self, paddr: &PhysAddr) {
self.phys2page.remove(paddr);
}
}

/// 物理页面信息
pub struct Page {
/// 映射计数
map_count: usize,
/// 是否为共享页
shared: bool,
/// 映射到当前page的VMA
anon_vma: HashSet<Arc<LockedVMA>>,
}

impl Page {
pub fn new(shared: bool) -> Self {
Self {
map_count: 0,
shared,
anon_vma: HashSet::new(),
}
}

/// 将vma加入anon_vma
pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
self.anon_vma.insert(vma);
self.map_count += 1;
}

/// 将vma从anon_vma中删去
pub fn remove_vma(&mut self, vma: &LockedVMA) {
self.anon_vma.remove(vma);
self.map_count -= 1;
}

/// 判断当前物理页是否能被回
pub fn can_deallocate(&self) -> bool {
self.map_count == 0 && !self.shared
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

也许这个map_count为0就能释放?不然的话如果忘记清除shared,就永远无法释放

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我一开始也是这么想的,但是Linux的共享内存即使映射计数是0,在没有设置可被回收的情况下,是不会被释放的,进程依然能够连接到这块共享内存。或者看我们想怎么设计

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我一开始也是这么想的,但是Linux的共享内存即使映射计数是0,在没有设置可被回收的情况下,是不会被释放的,进程依然能够连接到这块共享内存。或者看我们想怎么设计

哦哦哦,确实有道理。

}
}

#[derive(Debug)]
pub struct PageTable<Arch> {
/// 当前页表表示的虚拟地址空间的起始地址
Expand Down Expand Up @@ -591,6 +662,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
compiler_fence(Ordering::SeqCst);
let phys: PhysAddr = self.frame_allocator.allocate_one()?;
compiler_fence(Ordering::SeqCst);

PAGE_MANAGER.lock_irqsave().insert(phys, Page::new(false));
return self.map_phys(virt, phys, flags);
}

Expand Down
Loading