20240527 0010

This commit is contained in:
MemoryShore
2024-05-27 00:10:41 +08:00
parent 80ca935a8d
commit d1d0aca49e
5 changed files with 69 additions and 44 deletions

View File

@ -12,7 +12,7 @@ use crate::{
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
},
kernel_mapper::KernelMapper,
page::{PageEntry, EntryFlags, PAGE_1G_SHIFT},
page::{EntryFlags, PageEntry, PAGE_1G_SHIFT},
ucontext::UserMapper,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
},

View File

@ -27,7 +27,7 @@ use crate::{
};
use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::{PageEntry, EntryFlags, PAGE_1G_SHIFT};
use crate::mm::page::{EntryFlags, PageEntry, PAGE_1G_SHIFT};
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
use crate::{kdebug, kinfo, kwarn};
use system_error::SystemError;

View File

@ -13,7 +13,7 @@ use crate::{
base::{block::SeekFrom, device::DevicePrivateData},
tty::tty_device::TtyFilePrivateData,
},
filesystem::{fat::fs::LockedFATInode, procfs::ProcfsFilePrivateData},
filesystem::procfs::ProcfsFilePrivateData,
ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
kerror,
libs::{rwlock::RwLock, spinlock::SpinLock},
@ -25,7 +25,7 @@ use crate::{
process::ProcessManager,
};
use super::{mount::MountFSInode, Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
/// 文件私有信息的枚举类型
#[derive(Debug, Clone)]
@ -121,6 +121,7 @@ impl FileMode {
}
}
#[allow(dead_code)]
pub struct PageCache {
inode_ref: Weak<dyn IndexNode>,
map: HashMap<usize, Arc<Page>>,
@ -134,12 +135,12 @@ impl PageCache {
}
}
pub fn set_page(&mut self, offset: usize, page: Arc<Page>) {
pub fn add_page(&mut self, offset: usize, page: Arc<Page>) {
self.map.insert(offset, page);
}
pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> {
self.map.get(&offset).map(|page| page.clone())
self.map.get(&offset).cloned()
}
// pub fn get_pages(&self, start_pgoff: usize, end_pgoff: usize) -> Vec<Arc<Page>> {
@ -158,16 +159,6 @@ pub trait PageCacheOperations: IndexNode {
fn read_ahead(&self);
}
impl PageCacheOperations for LockedFATInode {
fn write_page(&self, page: Page) {
todo!()
}
fn read_ahead(&self) {
todo!()
}
}
/// @brief 抽象文件结构体
#[derive(Debug)]
pub struct File {

View File

@ -1,6 +1,6 @@
use core::{alloc::Layout, cmp::min, intrinsics::unlikely, panic};
use alloc::sync::Arc;
use alloc::{sync::Arc, vec::Vec};
use crate::{
arch::{mm::PageMapper, MMArch},
@ -15,7 +15,8 @@ use crate::{
use crate::mm::MemoryManagementArch;
use super::{
page::{self, PageFlags},
allocator::page_frame::{FrameAllocator, PhysPageFrame},
page::{Page, PageFlags},
phys_2_virt,
};
@ -309,19 +310,20 @@ impl PageFaultHandler {
/// - VmFaultReason: 页面错误处理信息标志
#[allow(dead_code, unused_variables)]
pub unsafe fn do_read_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
panic!(
"do_read_fault has not yet been implemented,
fault message: {:?},
pid: {}\n",
pfm,
crate::process::ProcessManager::current_pid().data()
);
// panic!(
// "do_read_fault has not yet been implemented,
// fault message: {:?},
// pid: {}\n",
// pfm,
// crate::process::ProcessManager::current_pid().data()
// );
// TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_read_fault
let mut ret = VmFaultReason::empty();
ret = Self::do_fault_around(pfm, mapper);
ret = Self::filemap_fault(pfm, mapper);
return ret;
let ret = Self::do_fault_around(pfm.clone(), mapper);
if !ret.is_empty() {
return ret;
}
return Self::filemap_fault(pfm.clone(), mapper);
}
/// 处理对共享文件映射区写入引起的缺页
@ -433,20 +435,24 @@ impl PageFaultHandler {
}
pub unsafe fn do_fault_around(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
mapper
.allocate_table(*pfm.address(), 0)
.expect("failed to allocate pte table");
if mapper.get_table(*pfm.address(), 0).is_none() {
mapper
.allocate_table(*pfm.address(), 0)
.expect("failed to allocate pte table");
}
let vma = pfm.vma();
let vma_guard = vma.lock();
let vma_region = vma_guard.region();
// 缺页在VMA中的偏移量
let vm_pgoff = (*pfm.address() - vma_region.start()) >> MMArch::PAGE_SHIFT;
// 缺页在PTE中的偏移量
let pte_pgoff = (pfm.address().data() >> MMArch::PAGE_SHIFT) & (1 << MMArch::PAGE_SIZE);
let pte_pgoff =
(pfm.address().data() >> MMArch::PAGE_SHIFT) & (1 << MMArch::PAGE_ENTRY_SHIFT);
let vma_pages_count = (vma_region.end() - vma_region.start()) >> MMArch::PAGE_SHIFT;
// 开始位置不能超出当前pte和vma头部的最小值
// 开始位置不能超出当前pte和vma头部
let from_pte = pte_pgoff - min(vm_pgoff, pte_pgoff);
let fault_around_page_number = 16;
@ -464,11 +470,11 @@ impl PageFaultHandler {
);
// 预先分配pte页表如果不存在
if mapper.get_table(*pfm.address(), 0).is_none() {
if mapper.allocate_table(*pfm.address(), 0).is_none() {
return VmFaultReason::VM_FAULT_OOM;
}
};
if mapper.get_table(*pfm.address(), 0).is_none()
&& mapper.allocate_table(*pfm.address(), 0).is_none()
{
return VmFaultReason::VM_FAULT_OOM;
}
// from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移加上pfm.file_pgoff缺失页在文件中的偏移得出起始页在文件中的偏移结束pte同理
Self::filemap_map_pages(
@ -515,7 +521,7 @@ impl PageFaultHandler {
let frame = virt as *mut u8;
let new_frame =
phys_2_virt(mapper.translate(address).unwrap().0.data()) as *mut u8;
frame.copy_from_nonoverlapping(new_frame, MMArch::PAGE_SIZE);
new_frame.copy_from_nonoverlapping(frame, MMArch::PAGE_SIZE);
}
}
}
@ -526,22 +532,44 @@ impl PageFaultHandler {
let vma = pfm.vma();
let vma_guard = vma.lock();
let file = vma_guard.vm_file().expect("no vm_file in vma");
let page_cache = file.inode().page_cache().unwrap();
let mut page_cache = file.inode().page_cache().unwrap();
if let Some(page) = page_cache.get_page(pfm.file_pgoff) {
// TODO 异步从磁盘中预读页面进PageCache
let address = vma_guard.region().start
+ (pfm.file_pgoff
+ ((pfm.file_pgoff
- vma_guard
.file_page_offset()
.expect("file_page_offset is none")
.expect("file_page_offset is none"))
<< MMArch::PAGE_SHIFT);
mapper.map(address, vma_guard.flags()).unwrap().flush();
let frame = phys_2_virt(page.phys_frame().phys_address().data()) as *mut u8;
let new_frame = phys_2_virt(mapper.translate(address).unwrap().0.data()) as *mut u8;
frame.copy_from_nonoverlapping(new_frame, MMArch::PAGE_SIZE);
new_frame.copy_from_nonoverlapping(frame, MMArch::PAGE_SIZE);
} else {
// TODO 同步预读
let mut buf: Vec<u8> = vec![0; MMArch::PAGE_SIZE];
file.pread(
pfm.file_pgoff * MMArch::PAGE_SIZE,
MMArch::PAGE_SIZE,
&mut buf[..],
)
.unwrap();
let allocator = mapper.allocator_mut();
// 分配一个物理页面作为加入PageCache的新页
let new_cache_page = allocator.allocate_one().unwrap();
(phys_2_virt(new_cache_page.data()) as *mut u8)
.copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
page_cache.add_page(
pfm.file_pgoff,
Arc::new(Page::new(false, PhysPageFrame::new(new_cache_page))),
);
// 分配空白页并映射到缺页地址
mapper.map(pfm.address, vma_guard.flags()).unwrap().flush();
let new_frame = phys_2_virt(mapper.translate(pfm.address).unwrap().0.data());
(new_frame as *mut u8).copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
}
VmFaultReason::VM_FAULT_COMPLETED
}

View File

@ -495,6 +495,12 @@ pub struct EntryFlags<Arch> {
phantom: PhantomData<Arch>,
}
impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> {
fn default() -> Self {
Self::new()
}
}
#[allow(dead_code)]
impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
#[inline(always)]