DragonOS/kernel/src/mm/allocator/page_frame.rs
MemoryShore cf7f801e1d
feat(mm): 简单实现fat文件系统的文件映射 (#840)
- 添加文件映射相关接口,目前已简单实现fat文件系统的私有映射和共享映射
- 添加msync系统调用(由于当前未实现脏页自动回写,需要手动调用msync进行同步)
- 简单实现PageCache(暂时使用HashMap进行文件页号与页的映射)
- 添加新的PageFlags标志结构,原PageFlags改名为EntryFlags
- 参考linux使用protection_map映射表进行页面标志的获取
- 添加页面回收机制
- 添加页面回收内核线程
- 缺页中断使用的锁修改为irq_save; 添加脏页回写机制
- 修复do_cow_page死锁问题
- 访问非法地址时发送信号终止进程
- 修复重复插入反向vma表的错误
- 添加test_filemap文件映射测试程序
2024-09-05 00:35:27 +08:00

385 lines
9.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::{
intrinsics::unlikely,
ops::{Add, AddAssign, Mul, Sub, SubAssign},
};
use crate::{
arch::{mm::LockedFrameAllocator, MMArch},
ipc::shm::shm_manager_lock,
libs::spinlock::SpinLockGuard,
mm::{MemoryManagementArch, PhysAddr, VirtAddr},
};
/// @brief 物理页帧的表示
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct PhysPageFrame {
/// 物理页页号
number: usize,
}
#[allow(dead_code)]
impl PhysPageFrame {
pub fn new(paddr: PhysAddr) -> Self {
return Self {
number: paddr.data() >> MMArch::PAGE_SHIFT,
};
}
/// 从物理页号创建PhysPageFrame结构体
pub fn from_ppn(ppn: usize) -> Self {
return Self { number: ppn };
}
/// 获取当前页对应的物理页号
pub fn ppn(&self) -> usize {
return self.number;
}
/// @brief 获取当前页对应的物理地址
pub fn phys_address(&self) -> PhysAddr {
return PhysAddr::new(self.number * MMArch::PAGE_SIZE);
}
pub fn next_by(&self, n: usize) -> Self {
return Self {
number: self.number + n,
};
}
pub fn next(&self) -> Self {
return self.next_by(1);
}
/// 构造物理页帧的迭代器,范围为[start, end)
pub fn iter_range(start: Self, end: Self) -> PhysPageFrameIter {
return PhysPageFrameIter::new(start, end);
}
}
/// @brief 物理页帧的迭代器
#[derive(Debug)]
pub struct PhysPageFrameIter {
current: PhysPageFrame,
/// 结束的物理页帧(不包含)
end: PhysPageFrame,
}
impl PhysPageFrameIter {
pub fn new(start: PhysPageFrame, end: PhysPageFrame) -> Self {
return Self {
current: start,
end,
};
}
}
impl Iterator for PhysPageFrameIter {
type Item = PhysPageFrame;
fn next(&mut self) -> Option<Self::Item> {
if unlikely(self.current == self.end) {
return None;
}
let current: PhysPageFrame = self.current;
self.current = self.current.next_by(1);
return Some(current);
}
}
/// 虚拟页帧的表示
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct VirtPageFrame {
/// 虚拟页页号
number: usize,
}
impl VirtPageFrame {
pub fn new(vaddr: VirtAddr) -> Self {
return Self {
number: vaddr.data() / MMArch::PAGE_SIZE,
};
}
/// 从虚拟页号创建PhysPageFrame结构体
#[allow(dead_code)]
pub fn from_vpn(vpn: usize) -> Self {
return Self { number: vpn };
}
/// 获取当前虚拟页对应的虚拟地址
pub fn virt_address(&self) -> VirtAddr {
return VirtAddr::new(self.number * MMArch::PAGE_SIZE);
}
pub fn next_by(&self, n: usize) -> Self {
return Self {
number: self.number + n,
};
}
pub fn next(&self) -> Self {
return self.next_by(1);
}
/// 构造虚拟页帧的迭代器,范围为[start, end)
pub fn iter_range(start: Self, end: Self) -> VirtPageFrameIter {
return VirtPageFrameIter {
current: start,
end,
};
}
pub fn add(&self, n: PageFrameCount) -> Self {
return Self {
number: self.number + n.data(),
};
}
}
/// 虚拟页帧的迭代器
#[derive(Debug)]
pub struct VirtPageFrameIter {
current: VirtPageFrame,
/// 结束的虚拟页帧(不包含)
end: VirtPageFrame,
}
impl VirtPageFrameIter {
/// @brief 构造虚拟页帧的迭代器,范围为[start, end)
pub fn new(start: VirtPageFrame, end: VirtPageFrame) -> Self {
return Self {
current: start,
end,
};
}
}
impl Iterator for VirtPageFrameIter {
type Item = VirtPageFrame;
fn next(&mut self) -> Option<Self::Item> {
if unlikely(self.current == self.end) {
return None;
}
let current: VirtPageFrame = self.current;
self.current = self.current.next_by(1);
return Some(current);
}
}
/// 页帧使用的数量
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct PageFrameCount(usize);
impl PageFrameCount {
// @brief 初始化PageFrameCount
pub const fn new(count: usize) -> Self {
return Self(count);
}
// @brief 获取页帧数量
pub fn data(&self) -> usize {
return self.0;
}
/// 计算这一段页帧占用的字节数
pub fn bytes(&self) -> usize {
return self.0 * MMArch::PAGE_SIZE;
}
/// 将字节数转换为页帧数量
///
/// 如果字节数不是页帧大小的整数倍则返回None. 否则返回页帧数量
pub fn from_bytes(bytes: usize) -> Option<Self> {
if bytes & MMArch::PAGE_OFFSET_MASK != 0 {
return None;
} else {
return Some(Self(bytes / MMArch::PAGE_SIZE));
}
}
#[inline(always)]
pub fn next_power_of_two(&self) -> Self {
Self::new(self.0.next_power_of_two())
}
}
impl Add for PageFrameCount {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
return Self(self.0 + rhs.0);
}
}
impl AddAssign for PageFrameCount {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Sub for PageFrameCount {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
return Self(self.0 - rhs.0);
}
}
impl SubAssign for PageFrameCount {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
}
}
impl Mul for PageFrameCount {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
return Self(self.0 * rhs.0);
}
}
impl Add<usize> for PageFrameCount {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
return Self(self.0 + rhs);
}
}
impl AddAssign<usize> for PageFrameCount {
fn add_assign(&mut self, rhs: usize) {
self.0 += rhs;
}
}
impl Sub<usize> for PageFrameCount {
type Output = Self;
fn sub(self, rhs: usize) -> Self::Output {
return Self(self.0 - rhs);
}
}
impl SubAssign<usize> for PageFrameCount {
fn sub_assign(&mut self, rhs: usize) {
self.0 -= rhs;
}
}
impl Mul<usize> for PageFrameCount {
type Output = Self;
fn mul(self, rhs: usize) -> Self::Output {
return Self(self.0 * rhs);
}
}
// 页帧使用情况
#[derive(Debug)]
pub struct PageFrameUsage {
used: PageFrameCount,
total: PageFrameCount,
}
#[allow(dead_code)]
impl PageFrameUsage {
/// @brief: 初始化FrameUsage
/// @param PageFrameCount used 已使用的页帧数量
/// @param PageFrameCount total 总的页帧数量
pub fn new(used: PageFrameCount, total: PageFrameCount) -> Self {
return Self { used, total };
}
// @brief 获取已使用的页帧数量
pub fn used(&self) -> PageFrameCount {
return self.used;
}
// @brief 获取空闲的页帧数量
pub fn free(&self) -> PageFrameCount {
return self.total - self.used;
}
// @brief 获取总的页帧数量
pub fn total(&self) -> PageFrameCount {
return self.total;
}
}
/// 能够分配页帧的分配器需要实现的trait
pub trait FrameAllocator {
// @brief 分配count个页帧
unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)>;
// @brief 通过地址释放count个页帧
unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount);
// @brief 分配一个页帧
unsafe fn allocate_one(&mut self) -> Option<PhysAddr> {
return self.allocate(PageFrameCount::new(1)).map(|(addr, _)| addr);
}
// @brief 通过地址释放一个页帧
unsafe fn free_one(&mut self, address: PhysAddr) {
return self.free(address, PageFrameCount::new(1));
}
// @brief 获取页帧使用情况
unsafe fn usage(&self) -> PageFrameUsage;
}
/// @brief 通过一个 &mut T 的引用来对一个实现了 FrameAllocator trait 的类型进行调用,使代码更加灵活
impl<T: FrameAllocator> FrameAllocator for &mut T {
unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
return T::allocate(self, count);
}
unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
return T::free(self, address, count);
}
unsafe fn allocate_one(&mut self) -> Option<PhysAddr> {
return T::allocate_one(self);
}
unsafe fn free_one(&mut self, address: PhysAddr) {
return T::free_one(self, address);
}
unsafe fn usage(&self) -> PageFrameUsage {
return T::usage(self);
}
}
/// @brief 从全局的页帧分配器中分配连续count个页帧
///
/// @param count 请求分配的页帧数量
pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
let frame = unsafe { LockedFrameAllocator.allocate(count)? };
return Some(frame);
}
/// @brief 向全局页帧分配器释放连续count个页帧
///
/// @param frame 要释放的第一个页帧
/// @param count 要释放的页帧数量 (必须是2的n次幂)
pub unsafe fn deallocate_page_frames(
frame: PhysPageFrame,
count: PageFrameCount,
page_manager_guard: &mut SpinLockGuard<'_, crate::mm::page::PageManager>,
) {
unsafe {
LockedFrameAllocator.free(frame.phys_address(), count);
}
let mut frame = frame;
for _ in 0..count.data() {
let paddr = frame.phys_address();
let page = page_manager_guard.get(&paddr);
if let Some(page) = page {
// 如果page是共享页将其共享页信息从SHM_MANAGER中删去
let page_guard = page.read_irqsave();
if page_guard.shared() {
shm_manager_lock().free_id(&page_guard.shm_id().unwrap());
}
}
// 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
page_manager_guard.remove_page(&paddr);
frame = frame.next();
}
}