From d1d0aca49e5d7f57e05f071a05303829a6a41894 Mon Sep 17 00:00:00 2001 From: MemoryShore <1353318529@qq.com> Date: Mon, 27 May 2024 00:10:41 +0800 Subject: [PATCH] 20240527 0010 --- kernel/src/arch/riscv64/mm/mod.rs | 2 +- kernel/src/arch/x86_64/mm/mod.rs | 2 +- kernel/src/filesystem/vfs/file.rs | 19 ++----- kernel/src/mm/fault.rs | 84 ++++++++++++++++++++----------- kernel/src/mm/page.rs | 6 +++ 5 files changed, 69 insertions(+), 44 deletions(-) diff --git a/kernel/src/arch/riscv64/mm/mod.rs b/kernel/src/arch/riscv64/mm/mod.rs index c157ba55..a335dee5 100644 --- a/kernel/src/arch/riscv64/mm/mod.rs +++ b/kernel/src/arch/riscv64/mm/mod.rs @@ -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, }, diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 18c210a8..b6c2b47c 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -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; diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index e71f975d..81a134cb 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -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, map: HashMap>, @@ -134,12 +135,12 @@ impl PageCache { } } - pub fn set_page(&mut self, offset: usize, page: Arc) { + pub fn add_page(&mut self, offset: usize, page: Arc) { self.map.insert(offset, page); } pub fn get_page(&self, offset: usize) -> Option> { - 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> { @@ -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 { diff --git a/kernel/src/mm/fault.rs b/kernel/src/mm/fault.rs index d26fa492..63116c04 100644 --- a/kernel/src/mm/fault.rs +++ b/kernel/src/mm/fault.rs @@ -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 = 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 } diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index 456bd9ca..96cf958b 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -495,6 +495,12 @@ pub struct EntryFlags { phantom: PhantomData, } +impl Default for EntryFlags { + fn default() -> Self { + Self::new() + } +} + #[allow(dead_code)] impl EntryFlags { #[inline(always)]