浏览代码

20240527 0010

MemoryShore 11 月之前
父节点
当前提交
d1d0aca49e

+ 1 - 1
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,
     },

+ 1 - 1
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;

+ 5 - 14
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<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 {

+ 56 - 28
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<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
     }

+ 6 - 0
kernel/src/mm/page.rs

@@ -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)]