Browse Source

feat(mm): 简单实现fat文件系统的文件映射 (#840)

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

+ 2 - 1
kernel/Cargo.toml

@@ -57,7 +57,8 @@ wait_queue_macros = { path = "crates/wait_queue_macros" }
 paste = "=1.0.14"
 slabmalloc = { path = "crates/rust-slabmalloc" }
 log = "0.4.21"
-
+xarray = "0.1.0"
+lru = "0.12.3"
 
 # target为x86_64时,使用下面的依赖
 [target.'cfg(target_arch = "x86_64")'.dependencies]

+ 70 - 4
kernel/src/arch/riscv64/mm/mod.rs

@@ -12,9 +12,9 @@ use crate::{
             page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
         },
         kernel_mapper::KernelMapper,
-        page::{PageEntry, PageFlags, PAGE_1G_SHIFT},
+        page::{EntryFlags, PageEntry, PAGE_1G_SHIFT},
         ucontext::UserMapper,
-        MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
+        MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags,
     },
     smp::cpu::ProcessorId,
 };
@@ -256,8 +256,74 @@ impl MemoryManagementArch for RiscV64MMArch {
     ) -> bool {
         true
     }
+
+    const PAGE_NONE: usize = Self::ENTRY_FLAG_GLOBAL | Self::ENTRY_FLAG_READONLY;
+
+    const PAGE_READ: usize = PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY;
+
+    const PAGE_WRITE: usize =
+        PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY | Self::ENTRY_FLAG_WRITEABLE;
+
+    const PAGE_EXEC: usize = PAGE_ENTRY_BASE | Self::ENTRY_FLAG_EXEC;
+
+    const PAGE_READ_EXEC: usize =
+        PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY | Self::ENTRY_FLAG_EXEC;
+
+    const PAGE_WRITE_EXEC: usize = PAGE_ENTRY_BASE
+        | Self::ENTRY_FLAG_READONLY
+        | Self::ENTRY_FLAG_EXEC
+        | Self::ENTRY_FLAG_WRITEABLE;
+
+    const PAGE_COPY: usize = Self::PAGE_READ;
+    const PAGE_COPY_EXEC: usize = Self::PAGE_READ_EXEC;
+    const PAGE_SHARED: usize = Self::PAGE_WRITE;
+    const PAGE_SHARED_EXEC: usize = Self::PAGE_WRITE_EXEC;
+
+    const PAGE_COPY_NOEXEC: usize = 0;
+    const PAGE_READONLY: usize = 0;
+    const PAGE_READONLY_EXEC: usize = 0;
+
+    const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();
+}
+
+const fn protection_map() -> [EntryFlags<MMArch>; 16] {
+    let mut map = [0; 16];
+    map[VmFlags::VM_NONE.bits()] = MMArch::PAGE_NONE;
+    map[VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY;
+    map[VmFlags::VM_WRITE.bits()] = MMArch::PAGE_COPY;
+    map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_COPY;
+    map[VmFlags::VM_EXEC.bits()] = MMArch::PAGE_READONLY_EXEC;
+    map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY_EXEC;
+    map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] = MMArch::PAGE_COPY_EXEC;
+    map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
+        MMArch::PAGE_COPY_EXEC;
+    map[VmFlags::VM_SHARED.bits()] = MMArch::PAGE_NONE;
+    map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY;
+    map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] = MMArch::PAGE_SHARED;
+    map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
+        MMArch::PAGE_SHARED;
+    map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] = MMArch::PAGE_READONLY_EXEC;
+    map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
+        MMArch::PAGE_READONLY_EXEC;
+    map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
+        MMArch::PAGE_SHARED_EXEC;
+    map[VmFlags::VM_SHARED.bits()
+        | VmFlags::VM_EXEC.bits()
+        | VmFlags::VM_WRITE.bits()
+        | VmFlags::VM_READ.bits()] = MMArch::PAGE_SHARED_EXEC;
+    let mut ret = [unsafe { EntryFlags::from_data(0) }; 16];
+    let mut index = 0;
+    while index < 16 {
+        ret[index] = unsafe { EntryFlags::from_data(map[index]) };
+        index += 1;
+    }
+    ret
 }
 
+const PAGE_ENTRY_BASE: usize = RiscV64MMArch::ENTRY_FLAG_PRESENT
+    | RiscV64MMArch::ENTRY_FLAG_ACCESSED
+    | RiscV64MMArch::ENTRY_FLAG_USER;
+
 impl VirtAddr {
     /// 判断虚拟地址是否合法
     #[inline(always)]
@@ -270,8 +336,8 @@ impl VirtAddr {
 }
 
 /// 获取内核地址默认的页面标志
-pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
-    PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
+pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> EntryFlags<A> {
+    EntryFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
         .set_user(false)
         .set_execute(true)
 }

+ 2 - 2
kernel/src/arch/x86_64/kvm/vmx/ept.rs

@@ -1,7 +1,7 @@
 use crate::arch::mm::LockedFrameAllocator;
 use crate::arch::mm::PageMapper;
 use crate::arch::MMArch;
-use crate::mm::page::PageFlags;
+use crate::mm::page::EntryFlags;
 use crate::mm::{PageTableKind, PhysAddr, VirtAddr};
 use crate::smp::core::smp_get_processor_id;
 use crate::smp::cpu::AtomicProcessorId;
@@ -92,7 +92,7 @@ impl EptMapper {
         &mut self,
         gpa: u64,
         hpa: u64,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
     ) -> Result<(), SystemError> {
         if self.readonly {
             return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);

+ 2 - 2
kernel/src/arch/x86_64/kvm/vmx/mmu.rs

@@ -1,7 +1,7 @@
 use crate::{
     arch::kvm::vmx::ept::EptMapper,
     libs::mutex::Mutex,
-    mm::{page::PageFlags, syscall::ProtFlags},
+    mm::{page::EntryFlags, syscall::ProtFlags},
     virt::kvm::host_mem::{__gfn_to_pfn, kvm_vcpu_gfn_to_memslot, PAGE_MASK, PAGE_SHIFT},
 };
 use bitfield_struct::bitfield;
@@ -218,7 +218,7 @@ pub fn __direct_map(
     }
     // 把gpa映射到hpa
     let mut ept_mapper = EptMapper::lock();
-    let page_flags = PageFlags::from_prot_flags(ProtFlags::from_bits_truncate(0x7_u64), false);
+    let page_flags = EntryFlags::from_prot_flags(ProtFlags::from_bits_truncate(0x7_u64), false);
     unsafe {
         assert!(ept_mapper.walk(gpa, pfn << PAGE_SHIFT, page_flags).is_ok());
     }

+ 34 - 16
kernel/src/arch/x86_64/mm/fault.rs

@@ -10,15 +10,18 @@ use x86::{bits64::rflags::RFlags, controlregs::Cr4};
 use crate::{
     arch::{
         interrupt::{trap::X86PfErrorCode, TrapFrame},
+        ipc::signal::{SigCode, Signal},
         mm::{MemoryManagementArch, X86_64MMArch},
         CurrentIrqArch, MMArch,
     },
     exception::InterruptArch,
+    ipc::signal_types::{SigInfo, SigType},
     mm::{
         fault::{FaultFlags, PageFaultHandler, PageFaultMessage},
         ucontext::{AddressSpace, LockedVMA},
         VirtAddr, VmFaultReason, VmFlags,
     },
+    process::ProcessManager,
 };
 
 use super::LockedFrameAllocator;
@@ -28,7 +31,7 @@ pub type PageMapper =
 
 impl X86_64MMArch {
     pub fn vma_access_error(vma: Arc<LockedVMA>, error_code: X86PfErrorCode) -> bool {
-        let vm_flags = *vma.lock().vm_flags();
+        let vm_flags = *vma.lock_irqsave().vm_flags();
         let foreign = false;
         if error_code.contains(X86PfErrorCode::X86_PF_PK) {
             return true;
@@ -223,20 +226,30 @@ impl X86_64MMArch {
         }
 
         let current_address_space: Arc<AddressSpace> = AddressSpace::current().unwrap();
-        let mut space_guard = current_address_space.write();
+        let mut space_guard = current_address_space.write_irqsave();
         let mut fault;
         loop {
             let vma = space_guard.mappings.find_nearest(address);
             // let vma = space_guard.mappings.contains(address);
 
-            let vma = vma.unwrap_or_else(|| {
-                panic!(
-                    "can not find nearest vma, error_code: {:#b}, address: {:#x}",
-                    error_code,
-                    address.data(),
-                )
-            });
-            let guard = vma.lock();
+            let vma = match vma {
+                Some(vma) => vma,
+                None => {
+                    log::error!(
+                        "can not find nearest vma, error_code: {:#b}, address: {:#x}",
+                        error_code,
+                        address.data(),
+                    );
+                    let pid = ProcessManager::current_pid();
+                    let mut info =
+                        SigInfo::new(Signal::SIGSEGV, 0, SigCode::User, SigType::Kill(pid));
+                    Signal::SIGSEGV
+                        .send_signal_info(Some(&mut info), pid)
+                        .expect("failed to send SIGSEGV to process");
+                    return;
+                }
+            };
+            let guard = vma.lock_irqsave();
             let region = *guard.region();
             let vm_flags = *guard.vm_flags();
             drop(guard);
@@ -253,11 +266,18 @@ impl X86_64MMArch {
                             )
                         });
                 } else {
-                    panic!(
+                    log::error!(
                         "No mapped vma, error_code: {:#b}, address: {:#x}",
                         error_code,
                         address.data(),
-                    )
+                    );
+                    let pid = ProcessManager::current_pid();
+                    let mut info =
+                        SigInfo::new(Signal::SIGSEGV, 0, SigCode::User, SigType::Kill(pid));
+                    Signal::SIGSEGV
+                        .send_signal_info(Some(&mut info), pid)
+                        .expect("failed to send SIGSEGV to process");
+                    return;
                 }
             }
 
@@ -269,11 +289,9 @@ impl X86_64MMArch {
                 );
             }
             let mapper = &mut space_guard.user_mapper.utable;
+            let message = PageFaultMessage::new(vma.clone(), address, flags, mapper);
 
-            fault = PageFaultHandler::handle_mm_fault(
-                PageFaultMessage::new(vma.clone(), address, flags),
-                mapper,
-            );
+            fault = PageFaultHandler::handle_mm_fault(message);
 
             if fault.contains(VmFaultReason::VM_FAULT_COMPLETED) {
                 return;

+ 93 - 6
kernel/src/arch/x86_64/mm/mod.rs

@@ -28,8 +28,8 @@ use crate::{
 };
 
 use crate::mm::kernel_mapper::KernelMapper;
-use crate::mm::page::{PageEntry, PageFlags, PAGE_1G_SHIFT};
-use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
+use crate::mm::page::{EntryFlags, PageEntry, PAGE_1G_SHIFT};
+use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags};
 
 use system_error::SystemError;
 
@@ -326,6 +326,93 @@ impl MemoryManagementArch for X86_64MMArch {
         }
         pkru::pkru_allows_pkey(pkru::vma_pkey(vma), write)
     }
+
+    const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();
+
+    const PAGE_NONE: usize =
+        Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_ACCESSED | Self::ENTRY_FLAG_GLOBAL;
+
+    const PAGE_SHARED: usize = Self::ENTRY_FLAG_PRESENT
+        | Self::ENTRY_FLAG_READWRITE
+        | Self::ENTRY_FLAG_USER
+        | Self::ENTRY_FLAG_ACCESSED
+        | Self::ENTRY_FLAG_NO_EXEC;
+
+    const PAGE_SHARED_EXEC: usize = Self::ENTRY_FLAG_PRESENT
+        | Self::ENTRY_FLAG_READWRITE
+        | Self::ENTRY_FLAG_USER
+        | Self::ENTRY_FLAG_ACCESSED;
+
+    const PAGE_COPY_NOEXEC: usize = Self::ENTRY_FLAG_PRESENT
+        | Self::ENTRY_FLAG_USER
+        | Self::ENTRY_FLAG_ACCESSED
+        | Self::ENTRY_FLAG_NO_EXEC;
+
+    const PAGE_COPY_EXEC: usize =
+        Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_USER | Self::ENTRY_FLAG_ACCESSED;
+
+    const PAGE_COPY: usize = Self::ENTRY_FLAG_PRESENT
+        | Self::ENTRY_FLAG_USER
+        | Self::ENTRY_FLAG_ACCESSED
+        | Self::ENTRY_FLAG_NO_EXEC;
+
+    const PAGE_READONLY: usize = Self::ENTRY_FLAG_PRESENT
+        | Self::ENTRY_FLAG_USER
+        | Self::ENTRY_FLAG_ACCESSED
+        | Self::ENTRY_FLAG_NO_EXEC;
+
+    const PAGE_READONLY_EXEC: usize =
+        Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_USER | Self::ENTRY_FLAG_ACCESSED;
+
+    const PAGE_READ: usize = 0;
+    const PAGE_READ_EXEC: usize = 0;
+    const PAGE_WRITE: usize = 0;
+    const PAGE_WRITE_EXEC: usize = 0;
+    const PAGE_EXEC: usize = 0;
+}
+
+/// 获取保护标志的映射表
+///
+///
+/// ## 返回值
+/// - `[usize; 16]`: 长度为16的映射表
+const fn protection_map() -> [EntryFlags<MMArch>; 16] {
+    let mut map = [unsafe { EntryFlags::from_data(0) }; 16];
+    unsafe {
+        map[VmFlags::VM_NONE.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE);
+        map[VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY);
+        map[VmFlags::VM_WRITE.bits()] = EntryFlags::from_data(MMArch::PAGE_COPY);
+        map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_COPY);
+        map[VmFlags::VM_EXEC.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
+        map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
+        map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_COPY_EXEC);
+        map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_COPY_EXEC);
+        map[VmFlags::VM_SHARED.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE);
+        map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_READONLY);
+        map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_SHARED);
+        map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_SHARED);
+        map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
+        map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
+        map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
+            EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC);
+        map[VmFlags::VM_SHARED.bits()
+            | VmFlags::VM_EXEC.bits()
+            | VmFlags::VM_WRITE.bits()
+            | VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC);
+    }
+    // if X86_64MMArch::is_xd_reserved() {
+    //     map.iter_mut().for_each(|x| *x &= !Self::ENTRY_FLAG_NO_EXEC)
+    // }
+    map
 }
 
 impl X86_64MMArch {
@@ -650,17 +737,17 @@ impl FrameAllocator for LockedFrameAllocator {
 }
 
 /// 获取内核地址默认的页面标志
-pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> {
+pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> EntryFlags<A> {
     let info: X86_64MMBootstrapInfo = BOOTSTRAP_MM_INFO.unwrap();
 
     if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end {
         // Remap kernel code  execute
-        return PageFlags::new().set_execute(true).set_write(true);
+        return EntryFlags::new().set_execute(true).set_write(true);
     } else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end {
         // Remap kernel rodata read only
-        return PageFlags::new().set_execute(true);
+        return EntryFlags::new().set_execute(true);
     } else {
-        return PageFlags::new().set_write(true).set_execute(true);
+        return EntryFlags::new().set_write(true).set_execute(true);
     }
 }
 

+ 2 - 2
kernel/src/arch/x86_64/mm/pkru.rs

@@ -16,8 +16,8 @@ const PKEY_MASK: usize = 1 << 32 | 1 << 33 | 1 << 34 | 1 << 35;
 /// ## 返回值
 /// - `u16`: vma的protection_key
 pub fn vma_pkey(vma: Arc<LockedVMA>) -> u16 {
-    let guard = vma.lock();
-    ((guard.vm_flags().bits() & PKEY_MASK as u64) >> VM_PKEY_SHIFT) as u16
+    let guard = vma.lock_irqsave();
+    ((guard.vm_flags().bits() & PKEY_MASK) >> VM_PKEY_SHIFT) as u16
 }
 
 // TODO pkru实现参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/pkru.h

+ 2 - 2
kernel/src/driver/net/dma.rs

@@ -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::{page_manager_lock_irqsave, PageFlags};
+use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
 use crate::mm::{
     allocator::page_frame::{
         allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
@@ -25,7 +25,7 @@ pub fn dma_alloc(pages: usize) -> (usize, NonNull<u8>) {
         // 清空这块区域,防止出现脏数据
         core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
 
-        let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();
+        let dma_flags: EntryFlags<MMArch> = EntryFlags::mmio_flags();
 
         let mut kernel_mapper = KernelMapper::lock();
         let kernel_mapper = kernel_mapper.as_mut().unwrap();

+ 2 - 2
kernel/src/driver/video/mod.rs

@@ -10,7 +10,7 @@ use crate::{
         spinlock::SpinLock,
     },
     mm::{
-        allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::PageFlags,
+        allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::EntryFlags,
         MemoryManagementArch,
     },
     time::timer::{Timer, TimerFunction},
@@ -95,7 +95,7 @@ impl VideoRefreshManager {
         let count = PageFrameCount::new(
             page_align_up(frame_buffer_info_guard.buf_size()) / MMArch::PAGE_SIZE,
         );
-        let page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
+        let page_flags: EntryFlags<MMArch> = EntryFlags::new().set_execute(true).set_write(true);
 
         let mut kernel_mapper = KernelMapper::lock();
         let mut kernel_mapper = kernel_mapper.as_mut();

+ 2 - 2
kernel/src/driver/virtio/virtio_impl.rs

@@ -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::{page_manager_lock_irqsave, PageFlags};
+use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
 use crate::mm::{
     allocator::page_frame::{
         allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
@@ -32,7 +32,7 @@ unsafe impl Hal for HalImpl {
             // 清空这块区域,防止出现脏数据
             core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
 
-            let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();
+            let dma_flags: EntryFlags<MMArch> = EntryFlags::mmio_flags();
 
             let mut kernel_mapper = KernelMapper::lock();
             let kernel_mapper = kernel_mapper.as_mut().unwrap();

+ 30 - 0
kernel/src/filesystem/fat/fs.rs

@@ -14,9 +14,12 @@ use alloc::{
 
 use crate::driver::base::block::gendisk::GenDisk;
 use crate::driver::base::device::device_number::DeviceNumber;
+use crate::filesystem::vfs::file::PageCache;
 use crate::filesystem::vfs::utils::DName;
 use crate::filesystem::vfs::{Magic, SpecialNodeData, SuperBlock};
 use crate::ipc::pipe::LockedPipeInode;
+use crate::mm::fault::{PageFaultHandler, PageFaultMessage};
+use crate::mm::VmFaultReason;
 use crate::{
     driver::base::block::{block_device::LBA_SIZE, disk_info::Partition, SeekFrom},
     filesystem::vfs::{
@@ -119,6 +122,9 @@ pub struct FATInode {
 
     /// 目录名
     dname: DName,
+
+    /// 页缓存
+    page_cache: Option<Arc<PageCache>>,
 }
 
 impl FATInode {
@@ -216,8 +222,14 @@ impl LockedFATInode {
             },
             special_node: None,
             dname,
+            page_cache: None,
         })));
 
+        if !inode.0.lock().inode_type.is_dir() {
+            let page_cache = PageCache::new(Some(Arc::downgrade(&inode) as Weak<dyn IndexNode>));
+            inode.0.lock().page_cache = Some(page_cache);
+        }
+
         inode.0.lock().self_ref = Arc::downgrade(&inode);
 
         inode.0.lock().update_metadata();
@@ -272,6 +284,19 @@ impl FileSystem for FATFileSystem {
             FAT_MAX_NAMELEN,
         )
     }
+
+    unsafe fn fault(&self, pfm: &mut PageFaultMessage) -> VmFaultReason {
+        PageFaultHandler::filemap_fault(pfm)
+    }
+
+    unsafe fn map_pages(
+        &self,
+        pfm: &mut PageFaultMessage,
+        start_pgoff: usize,
+        end_pgoff: usize,
+    ) -> VmFaultReason {
+        PageFaultHandler::filemap_map_pages(pfm, start_pgoff, end_pgoff)
+    }
 }
 
 impl FATFileSystem {
@@ -348,6 +373,7 @@ impl FATFileSystem {
             },
             special_node: None,
             dname: DName::default(),
+            page_cache: None,
         })));
 
         let result: Arc<FATFileSystem> = Arc::new(FATFileSystem {
@@ -1824,6 +1850,10 @@ impl IndexNode for LockedFATInode {
             .map(|item| item as Arc<dyn IndexNode>)
             .ok_or(SystemError::EINVAL)
     }
+
+    fn page_cache(&self) -> Option<Arc<PageCache>> {
+        self.0.lock().page_cache.clone()
+    }
 }
 
 impl Default for FATFsInfo {

+ 63 - 1
kernel/src/filesystem/vfs/file.rs

@@ -7,10 +7,12 @@ use alloc::{
 };
 use log::error;
 use system_error::SystemError;
+use xarray::XArray;
 
 use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
 use crate::filesystem::eventfd::EventFdInode;
 use crate::{
+    arch::MMArch,
     driver::{
         base::{block::SeekFrom, device::DevicePrivateData},
         tty::tty_device::TtyFilePrivateData,
@@ -18,6 +20,7 @@ use crate::{
     filesystem::procfs::ProcfsFilePrivateData,
     ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
     libs::{rwlock::RwLock, spinlock::SpinLock},
+    mm::{page::Page, MemoryManagementArch},
     net::{
         event_poll::{EPollItem, EPollPrivateData, EventPoll},
         socket::SocketInode,
@@ -118,6 +121,66 @@ impl FileMode {
         return self.bits() & FileMode::O_ACCMODE.bits();
     }
 }
+
+/// 页面缓存
+pub struct PageCache {
+    xarray: SpinLock<XArray<Arc<Page>>>,
+    inode: Option<Weak<dyn IndexNode>>,
+}
+
+impl core::fmt::Debug for PageCache {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        f.debug_struct("PageCache")
+            .field(
+                "xarray",
+                &self
+                    .xarray
+                    .lock()
+                    .range(0..((MMArch::PAGE_ADDRESS_SIZE >> MMArch::PAGE_SHIFT) as u64))
+                    .map(|(_, r)| (*r).clone())
+                    .collect::<Vec<Arc<Page>>>(),
+            )
+            .finish()
+    }
+}
+
+impl PageCache {
+    pub fn new(inode: Option<Weak<dyn IndexNode>>) -> Arc<PageCache> {
+        let page_cache = Self {
+            xarray: SpinLock::new(XArray::new()),
+            inode,
+        };
+        Arc::new(page_cache)
+    }
+
+    pub fn inode(&self) -> Option<Weak<dyn IndexNode>> {
+        self.inode.clone()
+    }
+
+    pub fn add_page(&self, offset: usize, page: &Arc<Page>) {
+        let mut guard = self.xarray.lock();
+        let mut cursor = guard.cursor_mut(offset as u64);
+        cursor.store(page.clone());
+    }
+
+    pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> {
+        let mut guard = self.xarray.lock();
+        let mut cursor = guard.cursor_mut(offset as u64);
+        let page = cursor.load().map(|r| (*r).clone());
+        page
+    }
+
+    pub fn remove_page(&self, offset: usize) {
+        let mut guard = self.xarray.lock();
+        let mut cursor = guard.cursor_mut(offset as u64);
+        cursor.remove();
+    }
+
+    pub fn set_inode(&mut self, inode: Weak<dyn IndexNode>) {
+        self.inode = Some(inode)
+    }
+}
+
 /// @brief 抽象文件结构体
 #[derive(Debug)]
 pub struct File {
@@ -683,7 +746,6 @@ impl FileDescriptorVec {
         // 把文件描述符数组对应位置设置为空
         let file = self.fds[fd as usize].take().unwrap();
 
-        assert!(Arc::strong_count(&file) == 1);
         return Ok(file);
     }
 

+ 34 - 1
kernel/src/filesystem/vfs/mod.rs

@@ -20,10 +20,16 @@ use crate::{
         casting::DowncastArc,
         spinlock::{SpinLock, SpinLockGuard},
     },
+    mm::{fault::PageFaultMessage, VmFaultReason},
     time::PosixTimeSpec,
 };
 
-use self::{core::generate_inode_id, file::FileMode, syscall::ModeType, utils::DName};
+use self::{
+    core::generate_inode_id,
+    file::{FileMode, PageCache},
+    syscall::ModeType,
+    utils::DName,
+};
 pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
 
 /// vfs容许的最大的路径名称长度
@@ -556,6 +562,14 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
     fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
         return self.find("..");
     }
+
+    fn page_cache(&self) -> Option<Arc<PageCache>> {
+        log::error!(
+            "function page_cache() has not yet been implemented for inode:{}",
+            crate::libs::name::get_type_name(&self)
+        );
+        None
+    }
 }
 
 impl DowncastArc for dyn IndexNode {
@@ -805,6 +819,25 @@ pub trait FileSystem: Any + Sync + Send + Debug {
     fn name(&self) -> &str;
 
     fn super_block(&self) -> SuperBlock;
+
+    unsafe fn fault(&self, _pfm: &mut PageFaultMessage) -> VmFaultReason {
+        panic!(
+            "fault() has not yet been implemented for filesystem: {}",
+            crate::libs::name::get_type_name(&self)
+        )
+    }
+
+    unsafe fn map_pages(
+        &self,
+        _pfm: &mut PageFaultMessage,
+        _start_pgoff: usize,
+        _end_pgoff: usize,
+    ) -> VmFaultReason {
+        panic!(
+            "map_pages() has not yet been implemented for filesystem: {}",
+            crate::libs::name::get_type_name(&self)
+        )
+    }
 }
 
 impl DowncastArc for dyn FileSystem {

+ 22 - 2
kernel/src/filesystem/vfs/mount.rs

@@ -19,11 +19,14 @@ use crate::{
         rwlock::RwLock,
         spinlock::{SpinLock, SpinLockGuard},
     },
+    mm::{fault::PageFaultMessage, VmFaultReason},
 };
 
 use super::{
-    file::FileMode, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, FileType,
-    IndexNode, InodeId, Magic, SuperBlock,
+    file::{FileMode, PageCache},
+    syscall::ModeType,
+    utils::DName,
+    FilePrivateData, FileSystem, FileType, IndexNode, InodeId, Magic, SuperBlock,
 };
 
 const MOUNTFS_BLOCK_SIZE: u64 = 512;
@@ -501,6 +504,10 @@ impl IndexNode for MountFSInode {
     fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
         return self.do_parent().map(|inode| inode as Arc<dyn IndexNode>);
     }
+
+    fn page_cache(&self) -> Option<Arc<PageCache>> {
+        self.inner_inode.page_cache()
+    }
 }
 
 impl FileSystem for MountFS {
@@ -528,6 +535,19 @@ impl FileSystem for MountFS {
     fn super_block(&self) -> SuperBlock {
         SuperBlock::new(Magic::MOUNT_MAGIC, MOUNTFS_BLOCK_SIZE, MOUNTFS_MAX_NAMELEN)
     }
+
+    unsafe fn fault(&self, pfm: &mut PageFaultMessage) -> VmFaultReason {
+        self.inner_filesystem.fault(pfm)
+    }
+
+    unsafe fn map_pages(
+        &self,
+        pfm: &mut PageFaultMessage,
+        start_pgoff: usize,
+        end_pgoff: usize,
+    ) -> VmFaultReason {
+        self.inner_filesystem.map_pages(pfm, start_pgoff, end_pgoff)
+    }
 }
 
 /// MountList

+ 9 - 8
kernel/src/ipc/shm.rs

@@ -14,7 +14,7 @@ use crate::{
     syscall::user_access::{UserBufferReader, UserBufferWriter},
     time::PosixTimeSpec,
 };
-use alloc::vec::Vec;
+use alloc::{sync::Arc, vec::Vec};
 use core::sync::atomic::{compiler_fence, Ordering};
 use hashbrown::{HashMap, HashSet};
 use ida::IdAllocator;
@@ -165,10 +165,10 @@ impl ShmManager {
         let mut page_manager_guard = page_manager_lock_irqsave();
         let mut cur_phys = PhysPageFrame::new(phys_page.0);
         for _ in 0..page_count.data() {
-            let mut page = Page::new(true);
-            page.set_shm_id(shm_id);
+            let page = Arc::new(Page::new(true, cur_phys.phys_address()));
+            page.write_irqsave().set_shm_id(shm_id);
             let paddr = cur_phys.phys_address();
-            page_manager_guard.insert(paddr, page);
+            page_manager_guard.insert(paddr, &page);
             cur_phys = cur_phys.next();
         }
 
@@ -324,8 +324,8 @@ impl ShmManager {
         if map_count > 0 {
             // 设置共享内存物理页当映射计数等于0时可被回收
             for _ in 0..count.data() {
-                let page = page_manager_guard.get_mut(&cur_phys.phys_address());
-                page.set_dealloc_when_zero(true);
+                let page = page_manager_guard.get_unwrap(&cur_phys.phys_address());
+                page.write_irqsave().set_dealloc_when_zero(true);
 
                 cur_phys = cur_phys.next();
             }
@@ -436,7 +436,7 @@ impl KernelShm {
 
     /// 共享内存段的映射计数(有多少个不同的VMA映射)
     pub fn map_count(&self) -> usize {
-        let page_manager_guard = page_manager_lock_irqsave();
+        let mut page_manager_guard = page_manager_lock_irqsave();
         let mut id_set: HashSet<usize> = HashSet::new();
         let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr);
         let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap();
@@ -444,7 +444,8 @@ impl KernelShm {
         for _ in 0..page_count.data() {
             let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
             id_set.extend(
-                page.anon_vma()
+                page.read_irqsave()
+                    .anon_vma()
                     .iter()
                     .map(|vma| vma.id())
                     .collect::<Vec<_>>(),

+ 11 - 10
kernel/src/ipc/syscall.rs

@@ -20,7 +20,7 @@ use crate::{
     libs::spinlock::SpinLock,
     mm::{
         allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
-        page::{page_manager_lock_irqsave, PageFlags, PageFlushAll},
+        page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
         syscall::ProtFlags,
         ucontext::{AddressSpace, VMA},
         VirtAddr, VmFlags,
@@ -324,8 +324,8 @@ impl Syscall {
                     .ok_or(SystemError::EINVAL)?;
                 let vm_flags = VmFlags::from(shmflg);
                 let destination = VirtPageFrame::new(region.start());
-                let page_flags: PageFlags<MMArch> =
-                    PageFlags::from_prot_flags(ProtFlags::from(vm_flags), true);
+                let page_flags: EntryFlags<MMArch> =
+                    EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true);
                 let flusher: PageFlushAll<MMArch> = PageFlushAll::new();
 
                 // 将共享内存映射到对应虚拟区域
@@ -351,14 +351,14 @@ impl Syscall {
                     .mappings
                     .contains(vaddr)
                     .ok_or(SystemError::EINVAL)?;
-                if vma.lock().region().start() != vaddr {
+                if vma.lock_irqsave().region().start() != vaddr {
                     return Err(SystemError::EINVAL);
                 }
 
                 // 验证用户虚拟内存区域是否有效
                 let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?;
 
-                // 必须在取消映射前获取到PageFlags
+                // 必须在取消映射前获取到EntryFlags
                 let page_flags = address_write_guard
                     .user_mapper
                     .utable
@@ -386,7 +386,8 @@ impl Syscall {
 
                     // 将vma加入到对应Page的anon_vma
                     page_manager_guard
-                        .get_mut(&phys.phys_address())
+                        .get_unwrap(&phys.phys_address())
+                        .write_irqsave()
                         .insert_vma(vma.clone());
 
                     phys = phys.next();
@@ -394,7 +395,7 @@ impl Syscall {
                 }
 
                 // 更新vma的映射状态
-                vma.lock().set_mapped(true);
+                vma.lock_irqsave().set_mapped(true);
 
                 vaddr.data()
             }
@@ -427,7 +428,7 @@ impl Syscall {
             .ok_or(SystemError::EINVAL)?;
 
         // 判断vaddr是否为起始地址
-        if vma.lock().region().start() != vaddr {
+        if vma.lock_irqsave().region().start() != vaddr {
             return Err(SystemError::EINVAL);
         }
 
@@ -440,9 +441,9 @@ impl Syscall {
             .0;
 
         // 如果物理页的shm_id为None,代表不是共享页
-        let page_manager_guard = page_manager_lock_irqsave();
+        let mut page_manager_guard = page_manager_lock_irqsave();
         let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?;
-        let shm_id = page.shm_id().ok_or(SystemError::EINVAL)?;
+        let shm_id = page.read_irqsave().shm_id().ok_or(SystemError::EINVAL)?;
         drop(page_manager_guard);
 
         // 获取对应共享页管理信息

+ 1 - 0
kernel/src/libs/mod.rs

@@ -26,3 +26,4 @@ pub mod rand;
 pub mod wait_queue;
 
 pub mod font;
+pub mod name;

+ 13 - 0
kernel/src/libs/name.rs

@@ -0,0 +1,13 @@
+use core::any::type_name;
+
+use alloc::string::{String, ToString};
+
+#[allow(dead_code)]
+pub fn get_full_type_name<T>(_: &T) -> String {
+    type_name::<T>().to_string()
+}
+
+pub fn get_type_name<T>(_: &T) -> String {
+    let full_name = type_name::<T>();
+    full_name[(full_name.rfind("::").unwrap_or(0) + 2)..].to_string()
+}

+ 3 - 2
kernel/src/mm/allocator/page_frame.rs

@@ -371,8 +371,9 @@ pub unsafe fn deallocate_page_frames(
 
         if let Some(page) = page {
             // 如果page是共享页,将其共享页信息从SHM_MANAGER中删去
-            if page.shared() {
-                shm_manager_lock().free_id(&page.shm_id().unwrap());
+            let page_guard = page.read_irqsave();
+            if page_guard.shared() {
+                shm_manager_lock().free_id(&page_guard.shm_id().unwrap());
             }
         }
 

+ 2 - 2
kernel/src/mm/c_adapter.rs

@@ -15,7 +15,7 @@ use crate::{
 
 use super::{
     allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
-    no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
+    no_init::pseudo_map_phys, page::EntryFlags, MemoryManagementArch, PhysAddr, VirtAddr,
 };
 
 lazy_static! {
@@ -40,7 +40,7 @@ pub unsafe extern "C" fn rs_map_phys(vaddr: usize, paddr: usize, size: usize, fl
     let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
     // debug!("rs_map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
 
-    let mut page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
+    let mut page_flags: EntryFlags<MMArch> = EntryFlags::new().set_execute(true).set_write(true);
     if flags & PAGE_U_S as usize != 0 {
         page_flags = page_flags.set_user(true);
     }

+ 429 - 118
kernel/src/mm/fault.rs

@@ -1,11 +1,17 @@
-use core::{alloc::Layout, intrinsics::unlikely, panic};
+use core::{
+    alloc::Layout,
+    cmp::{max, min},
+    intrinsics::unlikely,
+    panic,
+};
 
 use alloc::sync::Arc;
 
 use crate::{
     arch::{mm::PageMapper, MMArch},
+    libs::align::align_down,
     mm::{
-        page::{page_manager_lock_irqsave, PageFlags},
+        page::{page_manager_lock_irqsave, EntryFlags},
         ucontext::LockedVMA,
         VirtAddr, VmFaultReason, VmFlags,
     },
@@ -14,39 +20,68 @@ use crate::{
 
 use crate::mm::MemoryManagementArch;
 
+use super::{
+    allocator::page_frame::FrameAllocator,
+    page::{page_reclaimer_lock_irqsave, Page, PageFlags},
+};
+
 bitflags! {
     pub struct FaultFlags: u64{
-    const FAULT_FLAG_WRITE = 1 << 0;
-    const FAULT_FLAG_MKWRITE = 1 << 1;
-    const FAULT_FLAG_ALLOW_RETRY = 1 << 2;
-    const FAULT_FLAG_RETRY_NOWAIT = 1 << 3;
-    const FAULT_FLAG_KILLABLE = 1 << 4;
-    const FAULT_FLAG_TRIED = 1 << 5;
-    const FAULT_FLAG_USER = 1 << 6;
-    const FAULT_FLAG_REMOTE = 1 << 7;
-    const FAULT_FLAG_INSTRUCTION = 1 << 8;
-    const FAULT_FLAG_INTERRUPTIBLE =1 << 9;
-    const FAULT_FLAG_UNSHARE = 1 << 10;
-    const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11;
-    const FAULT_FLAG_VMA_LOCK = 1 << 12;
+        const FAULT_FLAG_WRITE = 1 << 0;
+        const FAULT_FLAG_MKWRITE = 1 << 1;
+        const FAULT_FLAG_ALLOW_RETRY = 1 << 2;
+        const FAULT_FLAG_RETRY_NOWAIT = 1 << 3;
+        const FAULT_FLAG_KILLABLE = 1 << 4;
+        const FAULT_FLAG_TRIED = 1 << 5;
+        const FAULT_FLAG_USER = 1 << 6;
+        const FAULT_FLAG_REMOTE = 1 << 7;
+        const FAULT_FLAG_INSTRUCTION = 1 << 8;
+        const FAULT_FLAG_INTERRUPTIBLE =1 << 9;
+        const FAULT_FLAG_UNSHARE = 1 << 10;
+        const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11;
+        const FAULT_FLAG_VMA_LOCK = 1 << 12;
     }
 }
 
 /// # 缺页异常信息结构体
 /// 包含了页面错误处理的相关信息,例如出错的地址、VMA等
 #[derive(Debug)]
-pub struct PageFaultMessage {
+pub struct PageFaultMessage<'a> {
+    /// 产生缺页的VMA结构体
     vma: Arc<LockedVMA>,
+    /// 缺页地址
     address: VirtAddr,
+    /// 异常处理标志
     flags: FaultFlags,
+    /// 页表映射器
+    mapper: &'a mut PageMapper,
+    /// 缺页的文件页在文件中的偏移量
+    file_pgoff: Option<usize>,
+    /// 缺页对应PageCache中的文件页
+    page: Option<Arc<Page>>,
+    /// 写时拷贝需要的页面
+    cow_page: Option<Arc<Page>>,
 }
 
-impl PageFaultMessage {
-    pub fn new(vma: Arc<LockedVMA>, address: VirtAddr, flags: FaultFlags) -> Self {
+impl<'a> PageFaultMessage<'a> {
+    pub fn new(
+        vma: Arc<LockedVMA>,
+        address: VirtAddr,
+        flags: FaultFlags,
+        mapper: &'a mut PageMapper,
+    ) -> Self {
+        let guard = vma.lock_irqsave();
+        let file_pgoff = guard.file_page_offset().map(|file_page_offset| {
+            ((address - guard.region().start()) >> MMArch::PAGE_SHIFT) + file_page_offset
+        });
         Self {
             vma: vma.clone(),
-            address,
+            address: VirtAddr::new(crate::libs::align::page_align_down(address.data())),
             flags,
+            file_pgoff,
+            page: None,
+            mapper,
+            cow_page: None,
         }
     }
 
@@ -75,16 +110,6 @@ impl PageFaultMessage {
     }
 }
 
-impl Clone for PageFaultMessage {
-    fn clone(&self) -> Self {
-        Self {
-            vma: self.vma.clone(),
-            address: self.address,
-            flags: self.flags,
-        }
-    }
-}
-
 /// 缺页中断处理结构体
 pub struct PageFaultHandler;
 
@@ -97,7 +122,7 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    pub unsafe fn handle_mm_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
+    pub unsafe fn handle_mm_fault(mut pfm: PageFaultMessage) -> VmFaultReason {
         let flags = pfm.flags();
         let vma = pfm.vma();
         let current_pcb = ProcessManager::current_pcb();
@@ -113,13 +138,13 @@ impl PageFaultHandler {
             return VmFaultReason::VM_FAULT_SIGSEGV;
         }
 
-        let guard = vma.lock();
+        let guard = vma.lock_irqsave();
         let vm_flags = *guard.vm_flags();
         drop(guard);
         if unlikely(vm_flags.contains(VmFlags::VM_HUGETLB)) {
             //TODO: 添加handle_hugetlb_fault处理大页缺页异常
         } else {
-            Self::handle_normal_fault(pfm, mapper);
+            Self::handle_normal_fault(&mut pfm);
         }
 
         VmFaultReason::VM_FAULT_COMPLETED
@@ -133,18 +158,16 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    pub unsafe fn handle_normal_fault(
-        pfm: PageFaultMessage,
-        mapper: &mut PageMapper,
-    ) -> VmFaultReason {
+    pub unsafe fn handle_normal_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
         let address = pfm.address_aligned_down();
         let vma = pfm.vma.clone();
+        let mapper = &mut pfm.mapper;
         if mapper.get_entry(address, 3).is_none() {
             mapper
                 .allocate_table(address, 2)
                 .expect("failed to allocate PUD table");
         }
-        let page_flags = vma.lock().flags();
+        let page_flags = vma.lock_irqsave().flags();
 
         for level in 2..=3 {
             let level = MMArch::PAGE_LEVELS - level;
@@ -159,7 +182,7 @@ impl PageFaultHandler {
             }
         }
 
-        Self::handle_pte_fault(pfm, mapper)
+        Self::handle_pte_fault(pfm)
     }
 
     /// 处理页表项异常
@@ -170,35 +193,37 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    pub unsafe fn handle_pte_fault(
-        pfm: PageFaultMessage,
-        mapper: &mut PageMapper,
-    ) -> VmFaultReason {
+    pub unsafe fn handle_pte_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
         let address = pfm.address_aligned_down();
         let flags = pfm.flags;
         let vma = pfm.vma.clone();
         let mut ret = VmFaultReason::VM_FAULT_COMPLETED;
+        let mapper = &pfm.mapper;
+
+        // pte存在
         if let Some(mut entry) = mapper.get_entry(address, 0) {
             if !entry.present() {
-                ret = Self::do_swap_page(pfm.clone(), mapper);
+                ret = Self::do_swap_page(pfm);
             }
+
             if entry.protnone() && vma.is_accessible() {
-                ret = Self::do_numa_page(pfm.clone(), mapper);
+                ret = Self::do_numa_page(pfm);
             }
+
             if flags.intersects(FaultFlags::FAULT_FLAG_WRITE | FaultFlags::FAULT_FLAG_UNSHARE) {
                 if !entry.write() {
-                    ret = Self::do_wp_page(pfm.clone(), mapper);
+                    ret = Self::do_wp_page(pfm);
                 } else {
-                    entry.set_flags(PageFlags::from_data(MMArch::ENTRY_FLAG_DIRTY));
+                    entry.set_flags(EntryFlags::from_data(MMArch::ENTRY_FLAG_DIRTY));
                 }
             }
         } else if vma.is_anonymous() {
-            ret = Self::do_anonymous_page(pfm.clone(), mapper);
+            ret = Self::do_anonymous_page(pfm);
         } else {
-            ret = Self::do_fault(pfm.clone(), mapper);
+            ret = Self::do_fault(pfm);
         }
 
-        vma.lock().set_mapped(true);
+        vma.lock_irqsave().set_mapped(true);
 
         return ret;
     }
@@ -211,13 +236,12 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    pub unsafe fn do_anonymous_page(
-        pfm: PageFaultMessage,
-        mapper: &mut PageMapper,
-    ) -> VmFaultReason {
+    pub unsafe fn do_anonymous_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
         let address = pfm.address_aligned_down();
         let vma = pfm.vma.clone();
-        let guard = vma.lock();
+        let guard = vma.lock_irqsave();
+        let mapper = &mut pfm.mapper;
+
         if let Some(flush) = mapper.map(address, guard.flags()) {
             flush.flush();
             crate::debug::klog::mm::mm_debug_log(
@@ -229,9 +253,9 @@ impl PageFaultHandler {
                 klog_types::LogSource::Buddy,
             );
             let paddr = mapper.translate(address).unwrap().0;
-            let mut anon_vma_guard = page_manager_lock_irqsave();
-            let page = anon_vma_guard.get_mut(&paddr);
-            page.insert_vma(vma.clone());
+            let mut page_manager_guard = page_manager_lock_irqsave();
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write_irqsave().insert_vma(vma.clone());
             VmFaultReason::VM_FAULT_COMPLETED
         } else {
             VmFaultReason::VM_FAULT_OOM
@@ -246,16 +270,19 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    #[allow(unused_variables)]
-    pub unsafe fn do_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
-        panic!(
-            "do_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_fault
+    pub unsafe fn do_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        if !pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE) {
+            return Self::do_read_fault(pfm);
+        } else if !pfm
+            .vma()
+            .lock_irqsave()
+            .vm_flags()
+            .contains(VmFlags::VM_SHARED)
+        {
+            return Self::do_cow_fault(pfm);
+        } else {
+            return Self::do_shared_fault(pfm);
+        }
     }
 
     /// 处理私有文件映射的写时复制
@@ -266,16 +293,51 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    #[allow(dead_code, unused_variables)]
-    pub unsafe fn do_cow_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
-        panic!(
-            "do_cow_fault has not yet been implemented, 
-        fault message: {:?}, 
-        pid: {}\n",
-            pfm,
-            crate::process::ProcessManager::current_pid().data()
+    pub unsafe fn do_cow_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        let mut ret = Self::filemap_fault(pfm);
+
+        if unlikely(ret.intersects(
+            VmFaultReason::VM_FAULT_ERROR
+                | VmFaultReason::VM_FAULT_NOPAGE
+                | VmFaultReason::VM_FAULT_RETRY
+                | VmFaultReason::VM_FAULT_DONE_COW,
+        )) {
+            return ret;
+        }
+
+        let cache_page = pfm.page.clone().unwrap();
+        let mapper = &mut pfm.mapper;
+
+        let cow_page_phys = mapper.allocator_mut().allocate_one();
+        if cow_page_phys.is_none() {
+            return VmFaultReason::VM_FAULT_OOM;
+        }
+        let cow_page_phys = cow_page_phys.unwrap();
+
+        let cow_page = Arc::new(Page::new(false, cow_page_phys));
+        pfm.cow_page = Some(cow_page.clone());
+
+        //复制PageCache内容到新的页内
+        let new_frame = MMArch::phys_2_virt(cow_page_phys).unwrap();
+        (new_frame.data() as *mut u8).copy_from_nonoverlapping(
+            MMArch::phys_2_virt(cache_page.read_irqsave().phys_address())
+                .unwrap()
+                .data() as *mut u8,
+            MMArch::PAGE_SIZE,
         );
-        // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_cow_fault
+
+        let mut page_manager_guard = page_manager_lock_irqsave();
+
+        // 新页加入页管理器中
+        page_manager_guard.insert(cow_page_phys, &cow_page);
+        cow_page.write_irqsave().set_page_cache_index(
+            cache_page.read_irqsave().page_cache(),
+            cache_page.read_irqsave().index(),
+        );
+
+        ret = ret.union(Self::finish_fault(pfm));
+
+        ret
     }
 
     /// 处理文件映射页的缺页异常
@@ -286,16 +348,19 @@ 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()
-        );
-        // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_read_fault
+    pub unsafe fn do_read_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs();
+
+        let mut ret = Self::do_fault_around(pfm);
+        if !ret.is_empty() {
+            return ret;
+        }
+
+        ret = fs.fault(pfm);
+
+        ret = ret.union(Self::finish_fault(pfm));
+
+        ret
     }
 
     /// 处理对共享文件映射区写入引起的缺页
@@ -306,16 +371,16 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    #[allow(dead_code, unused_variables)]
-    pub unsafe fn do_shared_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
-        panic!(
-            "do_shared_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_shared_fault
+    pub unsafe fn do_shared_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        let mut ret = Self::filemap_fault(pfm);
+
+        let cache_page = pfm.page.clone().expect("no cache_page in PageFaultMessage");
+
+        // 将pagecache页设为脏页,以便回收时能够回写
+        cache_page.write_irqsave().add_flags(PageFlags::PG_DIRTY);
+        ret = ret.union(Self::finish_fault(pfm));
+
+        ret
     }
 
     /// 处理被置换页面的缺页异常
@@ -327,7 +392,7 @@ impl PageFaultHandler {
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
     #[allow(unused_variables)]
-    pub unsafe fn do_swap_page(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
+    pub unsafe fn do_swap_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
         panic!(
             "do_swap_page has not yet been implemented, 
         fault message: {:?}, 
@@ -347,7 +412,7 @@ impl PageFaultHandler {
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
     #[allow(unused_variables)]
-    pub unsafe fn do_numa_page(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
+    pub unsafe fn do_numa_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
         panic!(
             "do_numa_page has not yet been implemented, 
         fault message: {:?}, 
@@ -366,43 +431,289 @@ impl PageFaultHandler {
     ///
     /// ## 返回值
     /// - VmFaultReason: 页面错误处理信息标志
-    pub unsafe fn do_wp_page(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
+    pub unsafe fn do_wp_page(pfm: &mut PageFaultMessage) -> VmFaultReason {
         let address = pfm.address_aligned_down();
         let vma = pfm.vma.clone();
+        let mapper = &mut pfm.mapper;
+
         let old_paddr = mapper.translate(address).unwrap().0;
         let mut page_manager = page_manager_lock_irqsave();
-        let map_count = page_manager.get_mut(&old_paddr).map_count();
+        let old_page = page_manager.get_unwrap(&old_paddr);
+        let map_count = old_page.read_irqsave().map_count();
         drop(page_manager);
 
         let mut entry = mapper.get_entry(address, 0).unwrap();
-        let new_flags = entry.flags().set_write(true);
+        let new_flags = entry.flags().set_write(true).set_dirty(true);
 
-        if map_count == 1 {
+        if vma.lock().vm_flags().contains(VmFlags::VM_SHARED) {
+            // 共享映射,直接修改页表项保护位,标记为脏页
             let table = mapper.get_table(address, 0).unwrap();
             let i = table.index_of(address).unwrap();
             entry.set_flags(new_flags);
             table.set_entry(i, entry);
+
+            old_page.write_irqsave().add_flags(PageFlags::PG_DIRTY);
+
             VmFaultReason::VM_FAULT_COMPLETED
-        } else if let Some(flush) = mapper.map(address, new_flags) {
-            let mut page_manager = page_manager_lock_irqsave();
-            let old_page = page_manager.get_mut(&old_paddr);
-            old_page.remove_vma(&vma);
-            drop(page_manager);
+        } else if vma.is_anonymous() {
+            // 私有匿名映射,根据引用计数判断是否拷贝页面
+            if map_count == 1 {
+                let table = mapper.get_table(address, 0).unwrap();
+                let i = table.index_of(address).unwrap();
+                entry.set_flags(new_flags);
+                table.set_entry(i, entry);
+                VmFaultReason::VM_FAULT_COMPLETED
+            } else if let Some(flush) = mapper.map(address, new_flags) {
+                let mut page_manager_guard = page_manager_lock_irqsave();
+                let old_page = page_manager_guard.get_unwrap(&old_paddr);
+                old_page.write_irqsave().remove_vma(&vma);
+                // drop(page_manager_guard);
+
+                flush.flush();
+                let paddr = mapper.translate(address).unwrap().0;
+                // let mut page_manager_guard = page_manager_lock_irqsave();
+                let page = page_manager_guard.get_unwrap(&paddr);
+                page.write_irqsave().insert_vma(vma.clone());
+
+                (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
+                    MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
+                    MMArch::PAGE_SIZE,
+                );
+
+                VmFaultReason::VM_FAULT_COMPLETED
+            } else {
+                VmFaultReason::VM_FAULT_OOM
+            }
+        } else {
+            // 私有文件映射,必须拷贝页面
+            if let Some(flush) = mapper.map(address, new_flags) {
+                let mut page_manager_guard = page_manager_lock_irqsave();
+                let old_page = page_manager_guard.get_unwrap(&old_paddr);
+                old_page.write_irqsave().remove_vma(&vma);
+                // drop(page_manager_guard);
+
+                flush.flush();
+                let paddr = mapper.translate(address).unwrap().0;
+                // let mut page_manager_guard = page_manager_lock_irqsave();
+                let page = page_manager_guard.get_unwrap(&paddr);
+                page.write_irqsave().insert_vma(vma.clone());
+
+                (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
+                    MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
+                    MMArch::PAGE_SIZE,
+                );
+
+                VmFaultReason::VM_FAULT_COMPLETED
+            } else {
+                VmFaultReason::VM_FAULT_OOM
+            }
+        }
+    }
 
-            flush.flush();
-            let paddr = mapper.translate(address).unwrap().0;
-            let mut anon_vma_guard = page_manager_lock_irqsave();
-            let page = anon_vma_guard.get_mut(&paddr);
-            page.insert_vma(vma.clone());
+    /// 缺页附近页预读
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
+    pub unsafe fn do_fault_around(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        let vma = pfm.vma();
+        let address = pfm.address();
+        let mapper = &mut pfm.mapper;
 
-            (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
-                MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
-                MMArch::PAGE_SIZE,
-            );
+        if mapper.get_table(address, 0).is_none() {
+            mapper
+                .allocate_table(address, 0)
+                .expect("failed to allocate pte table");
+        }
+        let vma_guard = vma.lock_irqsave();
+        let vma_region = *vma_guard.region();
+        drop(vma_guard);
 
-            VmFaultReason::VM_FAULT_COMPLETED
+        // 缺页在VMA中的偏移量
+        let vm_pgoff = (address - vma_region.start()) >> MMArch::PAGE_SHIFT;
+
+        // 缺页在PTE中的偏移量
+        let pte_pgoff = (address.data() >> MMArch::PAGE_SHIFT) & (1 << MMArch::PAGE_ENTRY_SHIFT);
+
+        // 缺页在文件中的偏移量
+        let file_pgoff = pfm.file_pgoff.expect("no file_pgoff");
+
+        let vma_pages_count = (vma_region.end() - vma_region.start()) >> MMArch::PAGE_SHIFT;
+
+        let fault_around_page_number = 16;
+
+        // 开始位置不能超出当前pte和vma头部
+        let from_pte = max(
+            align_down(pte_pgoff, fault_around_page_number),
+            pte_pgoff - min(vm_pgoff, pte_pgoff),
+        );
+
+        // pte结束位置不能超过:
+        // 1.最大预读上限(默认16)
+        // 2.最大pte(512)
+        // 3.vma结束位置(pte_pgoff + (vma_pages_count - vm_pgoff)计算出vma结束页号对当前pte开头的偏移)
+        let to_pte = min(
+            from_pte + fault_around_page_number,
+            min(
+                1 << MMArch::PAGE_SHIFT,
+                pte_pgoff + (vma_pages_count - vm_pgoff),
+            ),
+        );
+
+        // 预先分配pte页表(如果不存在)
+        if mapper.get_table(address, 0).is_none() && mapper.allocate_table(address, 0).is_none() {
+            return VmFaultReason::VM_FAULT_OOM;
+        }
+
+        let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs();
+        // from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移,加上pfm.file_pgoff(缺失页在文件中的偏移)得出起始页在文件中的偏移,结束pte同理
+        fs.map_pages(
+            pfm,
+            file_pgoff + (from_pte - pte_pgoff),
+            file_pgoff + (to_pte - pte_pgoff),
+        );
+
+        VmFaultReason::empty()
+    }
+
+    /// 通用的VMA文件映射页面映射函数,将PageCache中的页面映射到进程空间
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
+    pub unsafe fn filemap_map_pages(
+        pfm: &mut PageFaultMessage,
+
+        start_pgoff: usize,
+        end_pgoff: usize,
+    ) -> VmFaultReason {
+        let vma = pfm.vma();
+        let vma_guard = vma.lock_irqsave();
+        let file = vma_guard.vm_file().expect("no vm_file in vma");
+        let page_cache = file.inode().page_cache().unwrap();
+        let mapper = &mut pfm.mapper;
+
+        // 起始页地址
+        let addr = vma_guard.region().start
+            + ((start_pgoff
+                - vma_guard
+                    .file_page_offset()
+                    .expect("file_page_offset is none"))
+                << MMArch::PAGE_SHIFT);
+
+        for pgoff in start_pgoff..=end_pgoff {
+            if let Some(page) = page_cache.get_page(pgoff) {
+                let page_guard = page.read_irqsave();
+                if page_guard.flags().contains(PageFlags::PG_UPTODATE) {
+                    let phys = page_guard.phys_address();
+
+                    let address =
+                        VirtAddr::new(addr.data() + ((pgoff - start_pgoff) << MMArch::PAGE_SHIFT));
+                    mapper
+                        .map_phys(address, phys, vma_guard.flags())
+                        .unwrap()
+                        .flush();
+                }
+            }
+        }
+        VmFaultReason::empty()
+    }
+
+    /// 通用的VMA文件映射错误处理函数
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
+    pub unsafe fn filemap_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        let vma = pfm.vma();
+        let vma_guard = vma.lock_irqsave();
+        let file = vma_guard.vm_file().expect("no vm_file in vma");
+        let page_cache = file.inode().page_cache().unwrap();
+        let file_pgoff = pfm.file_pgoff.expect("no file_pgoff");
+        let mapper = &mut pfm.mapper;
+        let mut ret = VmFaultReason::empty();
+
+        if let Some(page) = page_cache.get_page(file_pgoff) {
+            // TODO 异步从磁盘中预读页面进PageCache
+
+            // 直接将PageCache中的页面作为要映射的页面
+            pfm.page = Some(page.clone());
         } else {
-            VmFaultReason::VM_FAULT_OOM
+            // TODO 同步预读
+            //涉及磁盘IO,返回标志为VM_FAULT_MAJOR
+            ret = VmFaultReason::VM_FAULT_MAJOR;
+            // let mut buf: Vec<u8> = vec![0; MMArch::PAGE_SIZE];
+
+            let allocator = mapper.allocator_mut();
+
+            // 分配一个物理页面作为加入PageCache的新页
+            let new_cache_page = allocator.allocate_one().unwrap();
+            // (MMArch::phys_2_virt(new_cache_page).unwrap().data() as *mut u8)
+            //     .copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
+            file.pread(
+                file_pgoff * MMArch::PAGE_SIZE,
+                MMArch::PAGE_SIZE,
+                core::slice::from_raw_parts_mut(
+                    MMArch::phys_2_virt(new_cache_page).unwrap().data() as *mut u8,
+                    MMArch::PAGE_SIZE,
+                ),
+            )
+            .expect("failed to read file to create pagecache page");
+
+            let page = Arc::new(Page::new(true, new_cache_page));
+            pfm.page = Some(page.clone());
+
+            page.write_irqsave().add_flags(PageFlags::PG_LRU);
+            page_manager_lock_irqsave().insert(new_cache_page, &page);
+            page_reclaimer_lock_irqsave().insert_page(new_cache_page, &page);
+            page_cache.add_page(file_pgoff, &page);
+
+            page.write_irqsave()
+                .set_page_cache_index(Some(page_cache), Some(file_pgoff));
         }
+        ret
+    }
+
+    /// 将文件页映射到缺页地址
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
+    pub unsafe fn finish_fault(pfm: &mut PageFaultMessage) -> VmFaultReason {
+        let vma = pfm.vma();
+        let vma_guard = vma.lock_irqsave();
+        let flags = pfm.flags();
+        let cache_page = pfm.page.clone();
+        let cow_page = pfm.cow_page.clone();
+        let address = pfm.address();
+        let mapper = &mut pfm.mapper;
+
+        let page_to_map = if flags.contains(FaultFlags::FAULT_FLAG_WRITE)
+            && !vma_guard.vm_flags().contains(VmFlags::VM_SHARED)
+        {
+            // 私有文件映射的写时复制
+            cow_page.expect("no cow_page in PageFaultMessage")
+        } else {
+            // 直接映射到PageCache
+            cache_page.expect("no cache_page in PageFaultMessage")
+        };
+
+        let page_phys = page_to_map.read_irqsave().phys_address();
+
+        mapper.map_phys(address, page_phys, vma_guard.flags());
+        page_to_map.write_irqsave().insert_vma(pfm.vma());
+        VmFaultReason::VM_FAULT_COMPLETED
     }
 }

+ 7 - 1
kernel/src/mm/init.rs

@@ -8,7 +8,11 @@ use crate::{
     filesystem::procfs::kmsg::kmsg_init,
     ipc::shm::shm_manager_init,
     libs::printk::PrintkWriter,
-    mm::{allocator::slab::slab_init, mmio_buddy::mmio_init, page::page_manager_init},
+    mm::{
+        allocator::slab::slab_init,
+        mmio_buddy::mmio_init,
+        page::{page_manager_init, page_reclaimer_init},
+    },
 };
 
 use super::MemoryManagementArch;
@@ -57,6 +61,8 @@ pub unsafe fn mm_init() {
     page_manager_init();
     // enable SHM_MANAGER
     shm_manager_init();
+    // enable PAGE_RECLAIMER
+    page_reclaimer_init();
 
     MM_INIT
         .compare_exchange(

+ 2 - 2
kernel/src/mm/kernel_mapper.rs

@@ -1,6 +1,6 @@
 use system_error::SystemError;
 
-use super::{page::PageFlags, PageTableKind, PhysAddr, VirtAddr};
+use super::{page::EntryFlags, PageTableKind, PhysAddr, VirtAddr};
 use crate::{
     arch::{
         mm::{LockedFrameAllocator, PageMapper},
@@ -104,7 +104,7 @@ impl KernelMapper {
         mut vaddr: VirtAddr,
         mut paddr: PhysAddr,
         size: usize,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
         flush: bool,
     ) -> Result<(), SystemError> {
         if self.readonly {

+ 1 - 1
kernel/src/mm/madvise.rs

@@ -12,7 +12,7 @@ impl LockedVMA {
         _flusher: impl Flusher<MMArch>,
     ) -> Result<(), SystemError> {
         //TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/madvise.c?fi=madvise#do_madvise
-        let mut vma = self.lock();
+        let mut vma = self.lock_irqsave();
         let mut new_flags = *vma.vm_flags();
         match behavior {
             MadvFlags::MADV_REMOVE => {

+ 3 - 3
kernel/src/mm/mmio_buddy.rs

@@ -12,7 +12,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
 use log::{debug, error, info, warn};
 use system_error::SystemError;
 
-use super::page::{PageFlags, PAGE_4K_SIZE};
+use super::page::{EntryFlags, PAGE_4K_SIZE};
 use super::{PhysAddr, VirtAddr};
 
 // 最大的伙伴块的幂
@@ -552,7 +552,7 @@ impl MmioBuddyMemPool {
             unsafe {
                 let x: Option<(
                     PhysAddr,
-                    PageFlags<MMArch>,
+                    EntryFlags<MMArch>,
                     crate::mm::page::PageFlush<MMArch>,
                 )> = kernel_mapper
                     .as_mut()
@@ -677,7 +677,7 @@ impl MMIOSpaceGuard {
             return Err(SystemError::EINVAL);
         }
 
-        let flags = PageFlags::mmio_flags();
+        let flags = EntryFlags::mmio_flags();
 
         let mut kernel_mapper = KernelMapper::lock();
         let r = kernel_mapper.map_phys_with_size(self.vaddr, paddr, length, flags, true);

+ 66 - 2
kernel/src/mm/mod.rs

@@ -1,4 +1,5 @@
 use alloc::sync::Arc;
+use page::EntryFlags;
 use system_error::SystemError;
 
 use crate::arch::MMArch;
@@ -40,7 +41,7 @@ static mut __IDLE_PROCESS_ADDRESS_SPACE: Option<Arc<AddressSpace>> = None;
 bitflags! {
     /// Virtual memory flags
     #[allow(clippy::bad_bit_mask)]
-    pub struct VmFlags:u64{
+    pub struct VmFlags:usize{
         const VM_NONE = 0x00000000;
 
         const VM_READ = 0x00000001;
@@ -93,6 +94,27 @@ bitflags! {
         const VM_FAULT_NEEDDSYNC = 0x002000;
         const VM_FAULT_COMPLETED = 0x004000;
         const VM_FAULT_HINDEX_MASK = 0x0f0000;
+        const VM_FAULT_ERROR = 0x000001 | 0x000002 | 0x000040 | 0x000010 | 0x000020 | 0x000800;
+    }
+
+    pub struct MsFlags:usize {
+        const MS_ASYNC = 1;
+        const MS_INVALIDATE = 2;
+        const MS_SYNC = 4;
+    }
+}
+
+impl core::ops::Index<VmFlags> for [usize] {
+    type Output = usize;
+
+    fn index(&self, index: VmFlags) -> &Self::Output {
+        &self[index.bits]
+    }
+}
+
+impl core::ops::IndexMut<VmFlags> for [usize] {
+    fn index_mut(&mut self, index: VmFlags) -> &mut Self::Output {
+        &mut self[index.bits]
     }
 }
 
@@ -599,7 +621,7 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
 
     /// 创建页表项
     ///
-    /// 这是一个低阶api,用于根据物理地址以及指定好的pageflags,创建页表项
+    /// 这是一个低阶api,用于根据物理地址以及指定好的EntryFlags,创建页表项
     ///
     /// ## 参数
     ///
@@ -631,6 +653,48 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
     ) -> bool {
         true
     }
+
+    const PAGE_NONE: usize;
+    const PAGE_SHARED: usize;
+    const PAGE_SHARED_EXEC: usize;
+    const PAGE_COPY_NOEXEC: usize;
+    const PAGE_COPY_EXEC: usize;
+    const PAGE_COPY: usize;
+    const PAGE_READONLY: usize;
+    const PAGE_READONLY_EXEC: usize;
+
+    const PAGE_READ: usize;
+    const PAGE_READ_EXEC: usize;
+    const PAGE_WRITE: usize;
+    const PAGE_WRITE_EXEC: usize;
+    const PAGE_EXEC: usize;
+
+    const PROTECTION_MAP: [EntryFlags<Self>; 16];
+
+    /// 页面保护标志转换函数
+    /// ## 参数
+    ///
+    /// - `vm_flags`: VmFlags标志
+    ///
+    /// ## 返回值
+    /// - EntryFlags: 页面的保护位
+    fn vm_get_page_prot(vm_flags: VmFlags) -> EntryFlags<Self> {
+        let map = Self::PROTECTION_MAP;
+        let mut ret = map[vm_flags
+            .intersection(
+                VmFlags::VM_READ | VmFlags::VM_WRITE | VmFlags::VM_EXEC | VmFlags::VM_SHARED,
+            )
+            .bits()];
+
+        #[cfg(target_arch = "x86_64")]
+        {
+            // 如果xd位被保留,那么将可执行性设置为true
+            if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
+                ret = ret.set_execute(true);
+            }
+        }
+        ret
+    }
 }
 
 /// @brief 虚拟地址范围

+ 4 - 4
kernel/src/mm/no_init.rs

@@ -19,7 +19,7 @@ use core::marker::PhantomData;
 
 use super::{
     allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
-    page::PageFlags,
+    page::EntryFlags,
     PageTableKind, VirtAddr,
 };
 
@@ -141,7 +141,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
 /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
 #[inline(never)]
 pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
-    let flags: PageFlags<MMArch> = PageFlags::new().set_write(true);
+    let flags: EntryFlags<MMArch> = EntryFlags::new().set_write(true);
 
     pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
 }
@@ -150,7 +150,7 @@ pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrame
 /// with READ_ONLY and EXECUTE flags.
 #[inline(never)]
 pub unsafe fn pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
-    let flags: PageFlags<MMArch> = PageFlags::new().set_write(false).set_execute(true);
+    let flags: EntryFlags<MMArch> = EntryFlags::new().set_write(false).set_execute(true);
 
     pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
 }
@@ -160,7 +160,7 @@ pub unsafe fn pseudo_map_phys_with_flags(
     vaddr: VirtAddr,
     paddr: PhysAddr,
     count: PageFrameCount,
-    flags: PageFlags<MMArch>,
+    flags: EntryFlags<MMArch>,
 ) {
     assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
     assert!(paddr.check_aligned(MMArch::PAGE_SIZE));

+ 360 - 44
kernel/src/mm/page.rs

@@ -1,3 +1,4 @@
+use alloc::string::ToString;
 use core::{
     fmt::{self, Debug, Error, Formatter},
     marker::PhantomData,
@@ -5,16 +6,26 @@ use core::{
     ops::Add,
     sync::atomic::{compiler_fence, Ordering},
 };
+use system_error::SystemError;
+use unified_init::macros::unified_init;
 
 use alloc::sync::Arc;
 use hashbrown::{HashMap, HashSet};
 use log::{error, info};
+use lru::LruCache;
 
 use crate::{
-    arch::{interrupt::ipi::send_ipi, MMArch},
+    arch::{interrupt::ipi::send_ipi, mm::LockedFrameAllocator, MMArch},
     exception::ipi::{IpiKind, IpiTarget},
+    filesystem::vfs::{file::PageCache, FilePrivateData},
+    init::initcall::INITCALL_CORE,
     ipc::shm::ShmId,
-    libs::spinlock::{SpinLock, SpinLockGuard},
+    libs::{
+        rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
+        spinlock::{SpinLock, SpinLockGuard},
+    },
+    process::{ProcessControlBlock, ProcessManager},
+    time::{sleep::usleep, PosixTimeSpec},
 };
 
 use super::{
@@ -53,7 +64,7 @@ pub fn page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager> {
 
 // 物理页管理器
 pub struct PageManager {
-    phys2page: HashMap<PhysAddr, Page>,
+    phys2page: HashMap<PhysAddr, Arc<Page>>,
 }
 
 impl PageManager {
@@ -67,18 +78,21 @@ impl PageManager {
         self.phys2page.contains_key(paddr)
     }
 
-    pub fn get(&self, paddr: &PhysAddr) -> Option<&Page> {
-        self.phys2page.get(paddr)
+    pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
+        page_reclaimer_lock_irqsave().get(paddr);
+        self.phys2page.get(paddr).cloned()
     }
 
-    pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page {
+    pub fn get_unwrap(&mut self, paddr: &PhysAddr) -> Arc<Page> {
+        page_reclaimer_lock_irqsave().get(paddr);
         self.phys2page
-            .get_mut(paddr)
-            .unwrap_or_else(|| panic!("{:?}", paddr))
+            .get(paddr)
+            .unwrap_or_else(|| panic!("Phys Page not found, {:?}", paddr))
+            .clone()
     }
 
-    pub fn insert(&mut self, paddr: PhysAddr, page: Page) {
-        self.phys2page.insert(paddr, page);
+    pub fn insert(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
+        self.phys2page.insert(paddr, page.clone());
     }
 
     pub fn remove_page(&mut self, paddr: &PhysAddr) {
@@ -86,8 +100,236 @@ impl PageManager {
     }
 }
 
-/// 物理页面信息
+pub static mut PAGE_RECLAIMER: Option<SpinLock<PageReclaimer>> = None;
+
+pub fn page_reclaimer_init() {
+    info!("page_reclaimer_init");
+    let page_reclaimer = SpinLock::new(PageReclaimer::new());
+
+    compiler_fence(Ordering::SeqCst);
+    unsafe { PAGE_RECLAIMER = Some(page_reclaimer) };
+    compiler_fence(Ordering::SeqCst);
+
+    info!("page_reclaimer_init done");
+}
+
+/// 页面回收线程
+static mut PAGE_RECLAIMER_THREAD: Option<Arc<ProcessControlBlock>> = None;
+
+/// 页面回收线程初始化函数
+#[unified_init(INITCALL_CORE)]
+fn page_reclaimer_thread_init() -> Result<(), SystemError> {
+    let closure = crate::process::kthread::KernelThreadClosure::StaticEmptyClosure((
+        &(page_reclaim_thread as fn() -> i32),
+        (),
+    ));
+    let pcb = crate::process::kthread::KernelThreadMechanism::create_and_run(
+        closure,
+        "page_reclaim".to_string(),
+    )
+    .ok_or("")
+    .expect("create tty_refresh thread failed");
+    unsafe {
+        PAGE_RECLAIMER_THREAD = Some(pcb);
+    }
+    Ok(())
+}
+
+/// 页面回收线程执行的函数
+fn page_reclaim_thread() -> i32 {
+    loop {
+        let usage = unsafe { LockedFrameAllocator.usage() };
+        // log::info!("usage{:?}", usage);
+
+        // 保留4096个页面,总计16MB的空闲空间
+        if usage.free().data() < 4096 {
+            let page_to_free = 4096;
+            page_reclaimer_lock_irqsave().shrink_list(PageFrameCount::new(page_to_free));
+        } else {
+            //TODO 暂时让页面回收线程负责脏页回写任务,后续需要分离
+            page_reclaimer_lock_irqsave().flush_dirty_pages();
+            // 休眠5秒
+            // log::info!("sleep");
+            let _ = usleep(PosixTimeSpec::new(5, 0));
+        }
+    }
+}
+
+/// 获取页面回收器
+pub fn page_reclaimer_lock_irqsave() -> SpinLockGuard<'static, PageReclaimer> {
+    unsafe { PAGE_RECLAIMER.as_ref().unwrap().lock_irqsave() }
+}
+
+/// 页面回收器
+pub struct PageReclaimer {
+    lru: LruCache<PhysAddr, Arc<Page>>,
+}
+
+impl PageReclaimer {
+    pub fn new() -> Self {
+        Self {
+            lru: LruCache::unbounded(),
+        }
+    }
+
+    pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
+        self.lru.get(paddr).cloned()
+    }
+
+    pub fn insert_page(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
+        self.lru.put(paddr, page.clone());
+    }
+
+    /// lru链表缩减
+    /// ## 参数
+    ///
+    /// - `count`: 需要缩减的页面数量
+    pub fn shrink_list(&mut self, count: PageFrameCount) {
+        for _ in 0..count.data() {
+            let (paddr, page) = self.lru.pop_lru().expect("pagecache is empty");
+            let page_cache = page.read_irqsave().page_cache().unwrap();
+            for vma in page.read_irqsave().anon_vma() {
+                let address_space = vma.lock_irqsave().address_space().unwrap();
+                let address_space = address_space.upgrade().unwrap();
+                let mut guard = address_space.write();
+                let mapper = &mut guard.user_mapper.utable;
+                let virt = vma.lock_irqsave().page_address(&page).unwrap();
+                unsafe {
+                    mapper.unmap(virt, false).unwrap().flush();
+                }
+            }
+            page_cache.remove_page(page.read_irqsave().index().unwrap());
+            page_manager_lock_irqsave().remove_page(&paddr);
+            if page.read_irqsave().flags.contains(PageFlags::PG_DIRTY) {
+                Self::page_writeback(&page, true);
+            }
+        }
+    }
+
+    /// 唤醒页面回收线程
+    pub fn wakeup_claim_thread() {
+        // log::info!("wakeup_claim_thread");
+        let _ = ProcessManager::wakeup(unsafe { PAGE_RECLAIMER_THREAD.as_ref().unwrap() });
+    }
+
+    /// 脏页回写函数
+    /// ## 参数
+    ///
+    /// - `page`: 需要回写的脏页
+    /// - `unmap`: 是否取消映射
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
+    pub fn page_writeback(page: &Arc<Page>, unmap: bool) {
+        if !unmap {
+            page.write_irqsave().remove_flags(PageFlags::PG_DIRTY);
+        }
+
+        for vma in page.read_irqsave().anon_vma() {
+            let address_space = vma.lock_irqsave().address_space().unwrap();
+            let address_space = address_space.upgrade().unwrap();
+            let mut guard = address_space.write();
+            let mapper = &mut guard.user_mapper.utable;
+            let virt = vma.lock_irqsave().page_address(page).unwrap();
+            if unmap {
+                unsafe {
+                    mapper.unmap(virt, false).unwrap().flush();
+                }
+            } else {
+                unsafe {
+                    // 保护位设为只读
+                    mapper.remap(
+                        virt,
+                        mapper.get_entry(virt, 0).unwrap().flags().set_write(false),
+                    )
+                };
+            }
+        }
+        let inode = page
+            .read_irqsave()
+            .page_cache
+            .clone()
+            .unwrap()
+            .inode()
+            .clone()
+            .unwrap()
+            .upgrade()
+            .unwrap();
+        inode
+            .write_at(
+                page.read_irqsave().index().unwrap(),
+                MMArch::PAGE_SIZE,
+                unsafe {
+                    core::slice::from_raw_parts(
+                        MMArch::phys_2_virt(page.read_irqsave().phys_addr)
+                            .unwrap()
+                            .data() as *mut u8,
+                        MMArch::PAGE_SIZE,
+                    )
+                },
+                SpinLock::new(FilePrivateData::Unused).lock(),
+            )
+            .unwrap();
+    }
+
+    /// lru脏页刷新
+    pub fn flush_dirty_pages(&self) {
+        // log::info!("flush_dirty_pages");
+        let iter = self.lru.iter();
+        for (_, page) in iter {
+            if page.read_irqsave().flags().contains(PageFlags::PG_DIRTY) {
+                Self::page_writeback(page, false);
+            }
+        }
+    }
+}
+
+bitflags! {
+    pub struct PageFlags: u64 {
+        const PG_LOCKED = 1 << 0;
+        const PG_WRITEBACK = 1 << 1;
+        const PG_REFERENCED = 1 << 2;
+        const PG_UPTODATE = 1 << 3;
+        const PG_DIRTY = 1 << 4;
+        const PG_LRU = 1 << 5;
+        const PG_HEAD = 1 << 6;
+        const PG_WAITERS = 1 << 7;
+        const PG_ACTIVE = 1 << 8;
+        const PG_WORKINGSET = 1 << 9;
+        const PG_ERROR = 1 << 10;
+        const PG_SLAB = 1 << 11;
+        const PG_RESERVED = 1 << 14;
+        const PG_PRIVATE = 1 << 15;
+        const PG_RECLAIM = 1 << 18;
+        const PG_SWAPBACKED = 1 << 19;
+    }
+}
+
+#[derive(Debug)]
 pub struct Page {
+    inner: RwLock<InnerPage>,
+}
+
+impl Page {
+    pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
+        let inner = InnerPage::new(shared, phys_addr);
+        Self {
+            inner: RwLock::new(inner),
+        }
+    }
+
+    pub fn read_irqsave(&self) -> RwLockReadGuard<InnerPage> {
+        self.inner.read_irqsave()
+    }
+
+    pub fn write_irqsave(&self) -> RwLockWriteGuard<InnerPage> {
+        self.inner.write_irqsave()
+    }
+}
+
+#[derive(Debug)]
+/// 物理页面信息
+pub struct InnerPage {
     /// 映射计数
     map_count: usize,
     /// 是否为共享页
@@ -98,10 +340,17 @@ pub struct Page {
     shm_id: Option<ShmId>,
     /// 映射到当前page的VMA
     anon_vma: HashSet<Arc<LockedVMA>>,
+    /// 标志
+    flags: PageFlags,
+    /// 页所在的物理页帧号
+    phys_addr: PhysAddr,
+    /// 在pagecache中的偏移
+    index: Option<usize>,
+    page_cache: Option<Arc<PageCache>>,
 }
 
-impl Page {
-    pub fn new(shared: bool) -> Self {
+impl InnerPage {
+    pub fn new(shared: bool, phys_addr: PhysAddr) -> Self {
         let dealloc_when_zero = !shared;
         Self {
             map_count: 0,
@@ -109,6 +358,10 @@ impl Page {
             free_when_zero: dealloc_when_zero,
             shm_id: None,
             anon_vma: HashSet::new(),
+            flags: PageFlags::empty(),
+            phys_addr,
+            index: None,
+            page_cache: None,
         }
     }
 
@@ -137,6 +390,31 @@ impl Page {
         self.shm_id
     }
 
+    pub fn index(&self) -> Option<usize> {
+        self.index
+    }
+
+    pub fn page_cache(&self) -> Option<Arc<PageCache>> {
+        self.page_cache.clone()
+    }
+
+    pub fn set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>) {
+        self.page_cache = page_cache;
+    }
+
+    pub fn set_index(&mut self, index: Option<usize>) {
+        self.index = index;
+    }
+
+    pub fn set_page_cache_index(
+        &mut self,
+        page_cache: Option<Arc<PageCache>>,
+        index: Option<usize>,
+    ) {
+        self.page_cache = page_cache;
+        self.index = index;
+    }
+
     pub fn set_shm_id(&mut self, shm_id: ShmId) {
         self.shm_id = Some(shm_id);
     }
@@ -154,6 +432,31 @@ impl Page {
     pub fn map_count(&self) -> usize {
         self.map_count
     }
+
+    #[inline(always)]
+    pub fn flags(&self) -> &PageFlags {
+        &self.flags
+    }
+
+    #[inline(always)]
+    pub fn set_flags(&mut self, flags: PageFlags) {
+        self.flags = flags
+    }
+
+    #[inline(always)]
+    pub fn add_flags(&mut self, flags: PageFlags) {
+        self.flags = self.flags.union(flags);
+    }
+
+    #[inline(always)]
+    pub fn remove_flags(&mut self, flags: PageFlags) {
+        self.flags = self.flags.difference(flags);
+    }
+
+    #[inline(always)]
+    pub fn phys_address(&self) -> PhysAddr {
+        self.phys_addr
+    }
 }
 
 #[derive(Debug)]
@@ -329,8 +632,19 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
                             new_table.set_entry(i, entry);
                         } else {
                             let phys = allocator.allocate_one()?;
-                            let mut anon_vma_guard = page_manager_lock_irqsave();
-                            anon_vma_guard.insert(phys, Page::new(false));
+                            let mut page_manager_guard = page_manager_lock_irqsave();
+                            let old_phys = entry.address().unwrap();
+                            let old_page = page_manager_guard.get_unwrap(&old_phys);
+                            let new_page =
+                                Arc::new(Page::new(old_page.read_irqsave().shared(), phys));
+                            if let Some(ref page_cache) = old_page.read_irqsave().page_cache() {
+                                new_page.write_irqsave().set_page_cache_index(
+                                    Some(page_cache.clone()),
+                                    old_page.read_irqsave().index(),
+                                );
+                            }
+
+                            page_manager_guard.insert(phys, &new_page);
                             let old_phys = entry.address().unwrap();
                             let frame = MMArch::phys_2_virt(phys).unwrap().data() as *mut u8;
                             frame.copy_from_nonoverlapping(
@@ -372,7 +686,7 @@ impl<Arch> Debug for PageEntry<Arch> {
 
 impl<Arch: MemoryManagementArch> PageEntry<Arch> {
     #[inline(always)]
-    pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self {
+    pub fn new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self {
         Self {
             data: MMArch::make_entry(paddr, flags.data()),
             phantom: PhantomData,
@@ -420,12 +734,12 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
     }
 
     #[inline(always)]
-    pub fn flags(&self) -> PageFlags<Arch> {
-        unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
+    pub fn flags(&self) -> EntryFlags<Arch> {
+        unsafe { EntryFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
     }
 
     #[inline(always)]
-    pub fn set_flags(&mut self, flags: PageFlags<Arch>) {
+    pub fn set_flags(&mut self, flags: EntryFlags<Arch>) {
         self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
     }
 
@@ -453,19 +767,19 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
 
 /// 页表项的标志位
 #[derive(Copy, Clone, Hash)]
-pub struct PageFlags<Arch> {
+pub struct EntryFlags<Arch> {
     data: usize,
     phantom: PhantomData<Arch>,
 }
 
-impl<Arch: MemoryManagementArch> Default for PageFlags<Arch> {
+impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> {
     fn default() -> Self {
         Self::new()
     }
 }
 
 #[allow(dead_code)]
-impl<Arch: MemoryManagementArch> PageFlags<Arch> {
+impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
     #[inline(always)]
     pub fn new() -> Self {
         let mut r = unsafe {
@@ -486,18 +800,19 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
         return r;
     }
 
-    /// 根据ProtFlags生成PageFlags
+    /// 根据ProtFlags生成EntryFlags
     ///
     /// ## 参数
     ///
     /// - prot_flags: 页的保护标志
     /// - user: 用户空间是否可访问
-    pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> {
-        let flags: PageFlags<Arch> = PageFlags::new()
-            .set_user(user)
-            .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
-            .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
-
+    pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self {
+        let vm_flags = super::VmFlags::from(prot_flags);
+        // let flags: EntryFlags<Arch> = EntryFlags::new()
+        //     .set_user(user)
+        //     .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
+        //     .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
+        let flags = Arch::vm_get_page_prot(vm_flags).set_user(user);
         return flags;
     }
 
@@ -763,9 +1078,9 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
     }
 }
 
-impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> {
+impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("PageFlags")
+        f.debug_struct("EntryFlags")
             .field("bits", &format_args!("{:#0x}", self.data))
             .field("present", &self.present())
             .field("has_write", &self.has_write())
@@ -861,7 +1176,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
     pub unsafe fn map(
         &mut self,
         virt: VirtAddr,
-        flags: PageFlags<Arch>,
+        flags: EntryFlags<Arch>,
     ) -> Option<PageFlush<Arch>> {
         compiler_fence(Ordering::SeqCst);
         let phys: PhysAddr = self.frame_allocator.allocate_one()?;
@@ -875,9 +1190,9 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         let mut page_manager_guard: SpinLockGuard<'static, PageManager> =
             page_manager_lock_irqsave();
         if !page_manager_guard.contains(&phys) {
-            page_manager_guard.insert(phys, Page::new(false))
+            page_manager_guard.insert(phys, &Arc::new(Page::new(false, phys)))
         }
-
+        drop(page_manager_guard);
         return self.map_phys(virt, phys, flags);
     }
 
@@ -886,7 +1201,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         &mut self,
         virt: VirtAddr,
         phys: PhysAddr,
-        flags: PageFlags<Arch>,
+        flags: EntryFlags<Arch>,
     ) -> Option<PageFlush<Arch>> {
         // 验证虚拟地址和物理地址是否对齐
         if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
@@ -926,8 +1241,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
                     // 清空这个页帧
                     MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
                     // 设置页表项的flags
-                    let flags: PageFlags<Arch> =
-                        PageFlags::new_page_table(virt.kind() == PageTableKind::User);
+                    let flags: EntryFlags<Arch> =
+                        EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
 
                     // 把新分配的页表映射到当前页表
                     table.set_entry(i, PageEntry::new(frame, flags));
@@ -943,7 +1258,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
     pub unsafe fn map_huge_page(
         &mut self,
         virt: VirtAddr,
-        flags: PageFlags<Arch>,
+        flags: EntryFlags<Arch>,
     ) -> Option<PageFlush<Arch>> {
         // 验证虚拟地址是否对齐
         if !(virt.check_aligned(Arch::PAGE_SIZE)) {
@@ -1009,7 +1324,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
 
         // 设置页表项的flags
-        let flags: PageFlags<Arch> = PageFlags::new_page_table(virt.kind() == PageTableKind::User);
+        let flags: EntryFlags<Arch> =
+            EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
 
         table.set_entry(i, PageEntry::new(frame, flags));
         table.next_level_table(i)
@@ -1111,7 +1427,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
     pub unsafe fn map_linearly(
         &mut self,
         phys: PhysAddr,
-        flags: PageFlags<Arch>,
+        flags: EntryFlags<Arch>,
     ) -> Option<(VirtAddr, PageFlush<Arch>)> {
         let virt: VirtAddr = Arch::phys_2_virt(phys)?;
         return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
@@ -1131,7 +1447,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
     pub unsafe fn remap(
         &mut self,
         virt: VirtAddr,
-        flags: PageFlags<Arch>,
+        flags: EntryFlags<Arch>,
     ) -> Option<PageFlush<Arch>> {
         return self
             .visit(virt, |p1, i| {
@@ -1153,7 +1469,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
     /// ## 返回值
     ///
     /// 如果查找成功,返回物理地址和页表项的flags,否则返回None
-    pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> {
+    pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> {
         let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
         let paddr = entry.address().ok()?;
         let flags = entry.flags();
@@ -1192,7 +1508,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
         &mut self,
         virt: VirtAddr,
         unmap_parents: bool,
-    ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> {
+    ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> {
         if !virt.check_aligned(Arch::PAGE_SIZE) {
             error!("Try to unmap unaligned page: virt={:?}", virt);
             return None;
@@ -1240,7 +1556,7 @@ unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
     table: &PageTable<Arch>,
     unmap_parents: bool,
     allocator: &mut impl FrameAllocator,
-) -> Option<(PhysAddr, PageFlags<Arch>)> {
+) -> Option<(PhysAddr, EntryFlags<Arch>)> {
     // 获取页表项的索引
     let i = table.index_of(vaddr)?;
 

+ 145 - 18
kernel/src/mm/syscall.rs

@@ -1,4 +1,4 @@
-use core::intrinsics::unlikely;
+use core::{intrinsics::unlikely, slice::from_raw_parts};
 
 use alloc::sync::Arc;
 use log::error;
@@ -6,6 +6,7 @@ use system_error::SystemError;
 
 use crate::{
     arch::MMArch,
+    driver::base::block::SeekFrom,
     ipc::shm::ShmFlags,
     libs::align::{check_aligned, page_align_up},
     mm::MemoryManagementArch,
@@ -15,7 +16,7 @@ use crate::{
 use super::{
     allocator::page_frame::{PageFrameCount, VirtPageFrame},
     ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
-    verify_area, VirtAddr, VmFlags,
+    verify_area, MsFlags, VirtAddr, VmFlags,
 };
 
 bitflags! {
@@ -154,6 +155,10 @@ impl From<MapFlags> for VmFlags {
             vm_flags |= VmFlags::VM_SYNC;
         }
 
+        if map_flags.contains(MapFlags::MAP_SHARED) {
+            vm_flags |= VmFlags::VM_SHARED;
+        }
+
         vm_flags
     }
 }
@@ -296,8 +301,8 @@ impl Syscall {
         len: usize,
         prot_flags: usize,
         map_flags: usize,
-        _fd: i32,
-        _offset: usize,
+        fd: i32,
+        offset: usize,
     ) -> Result<usize, SystemError> {
         let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
         let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
@@ -311,11 +316,6 @@ impl Syscall {
             );
             return Err(SystemError::EINVAL);
         }
-        // 暂时不支持除匿名页以外的映射
-        if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
-            error!("mmap: not support file mapping");
-            return Err(SystemError::ENOSYS);
-        }
 
         // 暂时不支持巨页映射
         if map_flags.contains(MapFlags::MAP_HUGETLB) {
@@ -323,14 +323,30 @@ impl Syscall {
             return Err(SystemError::ENOSYS);
         }
         let current_address_space = AddressSpace::current()?;
-        let start_page = current_address_space.write().map_anonymous(
-            start_vaddr,
-            len,
-            prot_flags,
-            map_flags,
-            true,
-            false,
-        )?;
+        let start_page = if map_flags.contains(MapFlags::MAP_ANONYMOUS) {
+            // 匿名映射
+            current_address_space.write().map_anonymous(
+                start_vaddr,
+                len,
+                prot_flags,
+                map_flags,
+                true,
+                false,
+            )?
+        } else {
+            // 文件映射
+            current_address_space.write().file_mapping(
+                start_vaddr,
+                len,
+                prot_flags,
+                map_flags,
+                fd,
+                offset,
+                true,
+                false,
+            )?
+        };
+
         return Ok(start_page.virt_address().data());
     }
 
@@ -390,7 +406,7 @@ impl Syscall {
             return Err(SystemError::EINVAL);
         }
         let vma = vma.unwrap();
-        let vm_flags = *vma.lock().vm_flags();
+        let vm_flags = *vma.lock_irqsave().vm_flags();
 
         // 暂时不支持巨页映射
         if vm_flags.contains(VmFlags::VM_HUGETLB) {
@@ -524,4 +540,115 @@ impl Syscall {
             .map_err(|_| SystemError::EINVAL)?;
         return Ok(0);
     }
+
+    /// ## msync系统调用
+    ///
+    /// ## 参数
+    ///
+    /// - `start`:起始地址(已经对齐到页)
+    /// - `len`:长度(已经对齐到页)
+    /// - `flags`:标志
+    pub fn msync(start: VirtAddr, len: usize, flags: usize) -> Result<usize, SystemError> {
+        if !start.check_aligned(MMArch::PAGE_SIZE) || !check_aligned(len, MMArch::PAGE_SIZE) {
+            return Err(SystemError::EINVAL);
+        }
+
+        if unlikely(verify_area(start, len).is_err()) {
+            return Err(SystemError::EINVAL);
+        }
+        if unlikely(len == 0) {
+            return Err(SystemError::EINVAL);
+        }
+
+        let mut start = start.data();
+        let end = start + len;
+        let flags = MsFlags::from_bits_truncate(flags);
+        let mut unmapped_error = Ok(0);
+
+        if !flags.intersects(MsFlags::MS_ASYNC | MsFlags::MS_INVALIDATE | MsFlags::MS_SYNC) {
+            return Err(SystemError::EINVAL);
+        }
+
+        if flags.contains(MsFlags::MS_ASYNC | MsFlags::MS_SYNC) {
+            return Err(SystemError::EINVAL);
+        }
+
+        if end < start {
+            return Err(SystemError::ENOMEM);
+        }
+
+        if start == end {
+            return Ok(0);
+        }
+
+        let current_address_space = AddressSpace::current()?;
+        let mut err = Err(SystemError::ENOMEM);
+        let mut next_vma = current_address_space
+            .read()
+            .mappings
+            .find_nearest(VirtAddr::new(start));
+        loop {
+            if let Some(vma) = next_vma.clone() {
+                let guard = vma.lock_irqsave();
+                let vm_start = guard.region().start().data();
+                let vm_end = guard.region().end().data();
+                if start < vm_start {
+                    if flags == MsFlags::MS_ASYNC {
+                        break;
+                    }
+                    start = vm_start;
+                    if start >= vm_end {
+                        break;
+                    }
+                    unmapped_error = Err(SystemError::ENOMEM);
+                }
+                let vm_flags = *guard.vm_flags();
+                if flags.contains(MsFlags::MS_INVALIDATE) && vm_flags.contains(VmFlags::VM_LOCKED) {
+                    err = Err(SystemError::EBUSY);
+                    break;
+                }
+                let file = guard.vm_file();
+                let fstart = (start - vm_start)
+                    + (guard.file_page_offset().unwrap_or(0) << MMArch::PAGE_SHIFT);
+                let fend = fstart + (core::cmp::min(end, vm_end) - start) - 1;
+                let old_start = start;
+                start = vm_end;
+                // log::info!("flags: {:?}", flags);
+                // log::info!("vm_flags: {:?}", vm_flags);
+                // log::info!("file: {:?}", file);
+                if flags.contains(MsFlags::MS_SYNC) && vm_flags.contains(VmFlags::VM_SHARED) {
+                    if let Some(file) = file {
+                        let old_pos = file.lseek(SeekFrom::SeekCurrent(0)).unwrap();
+                        file.lseek(SeekFrom::SeekSet(fstart as i64)).unwrap();
+                        err = file.write(len, unsafe {
+                            from_raw_parts(old_start as *mut u8, fend - fstart + 1)
+                        });
+                        file.lseek(SeekFrom::SeekSet(old_pos as i64)).unwrap();
+                        if err.is_err() {
+                            break;
+                        } else if start >= end {
+                            err = unmapped_error;
+                            break;
+                        }
+                        next_vma = current_address_space
+                            .read()
+                            .mappings
+                            .find_nearest(VirtAddr::new(start));
+                    }
+                } else {
+                    if start >= end {
+                        err = unmapped_error;
+                        break;
+                    }
+                    next_vma = current_address_space
+                        .read()
+                        .mappings
+                        .find_nearest(VirtAddr::new(vm_end));
+                }
+            } else {
+                return Err(SystemError::ENOMEM);
+            }
+        }
+        return err;
+    }
 }

+ 259 - 90
kernel/src/mm/ucontext.rs

@@ -20,6 +20,7 @@ use system_error::SystemError;
 use crate::{
     arch::{mm::PageMapper, CurrentIrqArch, MMArch},
     exception::InterruptArch,
+    filesystem::vfs::file::File,
     libs::{
         align::page_align_up,
         rwlock::RwLock,
@@ -34,7 +35,7 @@ use super::{
     allocator::page_frame::{
         deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
     },
-    page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll},
+    page::{EntryFlags, Flusher, InactiveFlusher, Page, PageFlushAll},
     syscall::{MadvFlags, MapFlags, MremapFlags, ProtFlags},
     MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, VmFlags,
 };
@@ -178,23 +179,23 @@ impl InnerAddressSpace {
         for vma in self.mappings.vmas.iter() {
             // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过
 
-            let vma_guard: SpinLockGuard<'_, VMA> = vma.lock();
+            let vma_guard: SpinLockGuard<'_, VMA> = vma.lock_irqsave();
 
             // 仅拷贝VMA信息并添加反向映射,因为UserMapper克隆时已经分配了新的物理页
             let new_vma = LockedVMA::new(vma_guard.clone_info_only());
             new_guard.mappings.vmas.insert(new_vma.clone());
             // debug!("new vma: {:x?}", new_vma);
-            let new_vma_guard = new_vma.lock();
+            let new_vma_guard = new_vma.lock_irqsave();
             let new_mapper = &new_guard.user_mapper.utable;
-            let mut anon_vma_guard = page_manager_lock_irqsave();
+            let mut page_manager_guard = page_manager_lock_irqsave();
             for page in new_vma_guard.pages().map(|p| p.virt_address()) {
                 if let Some((paddr, _)) = new_mapper.translate(page) {
-                    let page = anon_vma_guard.get_mut(&paddr);
-                    page.insert_vma(new_vma.clone());
+                    let page = page_manager_guard.get_unwrap(&paddr);
+                    page.write_irqsave().insert_vma(new_vma.clone());
                 }
             }
 
-            drop(anon_vma_guard);
+            drop(page_manager_guard);
             drop(vma_guard);
             drop(new_vma_guard);
         }
@@ -282,33 +283,135 @@ impl InnerAddressSpace {
 
         // debug!("map_anonymous: len = {}", len);
 
-        let start_page: VirtPageFrame = if allocate_at_once {
-            self.mmap(
-                round_hint_to_min(start_vaddr),
-                PageFrameCount::from_bytes(len).unwrap(),
-                prot_flags,
-                map_flags,
-                move |page, count, flags, mapper, flusher| {
-                    VMA::zeroed(page, count, vm_flags, flags, mapper, flusher)
-                },
-            )?
-        } else {
-            self.mmap(
-                round_hint_to_min(start_vaddr),
-                PageFrameCount::from_bytes(len).unwrap(),
-                prot_flags,
-                map_flags,
-                move |page, count, flags, _mapper, _flusher| {
+        let start_page: VirtPageFrame = self.mmap(
+            round_hint_to_min(start_vaddr),
+            PageFrameCount::from_bytes(len).unwrap(),
+            prot_flags,
+            map_flags,
+            move |page, count, flags, mapper, flusher| {
+                if allocate_at_once {
+                    VMA::zeroed(page, count, vm_flags, flags, mapper, flusher, None, None)
+                } else {
                     Ok(LockedVMA::new(VMA::new(
                         VirtRegion::new(page.virt_address(), count.data() * MMArch::PAGE_SIZE),
                         vm_flags,
                         flags,
+                        None,
+                        None,
                         false,
                     )))
-                },
-            )?
+                }
+            },
+        )?;
+
+        return Ok(start_page);
+    }
+
+    /// 进行文件页映射
+    ///
+    /// ## 参数
+    ///
+    /// - `start_vaddr`:映射的起始地址
+    /// - `len`:映射的长度
+    /// - `prot_flags`:保护标志
+    /// - `map_flags`:映射标志
+    /// - `fd`:文件描述符
+    /// - `offset`:映射偏移量
+    /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界
+    /// - `allocate_at_once`:是否立即分配物理空间
+    ///
+    /// ## 返回
+    ///
+    /// 返回映射的起始虚拟页帧
+    #[allow(clippy::too_many_arguments)]
+    pub fn file_mapping(
+        &mut self,
+        start_vaddr: VirtAddr,
+        len: usize,
+        prot_flags: ProtFlags,
+        map_flags: MapFlags,
+        fd: i32,
+        offset: usize,
+        round_to_min: bool,
+        allocate_at_once: bool,
+    ) -> Result<VirtPageFrame, SystemError> {
+        let allocate_at_once = if MMArch::PAGE_FAULT_ENABLED {
+            allocate_at_once
+        } else {
+            true
         };
+        // 用于对齐hint的函数
+        let round_hint_to_min = |hint: VirtAddr| {
+            // 先把hint向下对齐到页边界
+            let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK);
+            // debug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint);
+            // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR
+            if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) {
+                Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR)))
+            } else if addr == 0 {
+                None
+            } else {
+                Some(VirtAddr::new(addr))
+            }
+        };
+        // debug!("map_anonymous: start_vaddr = {:?}", start_vaddr);
+        // debug!("map_anonymous: len(no align) = {}", len);
 
+        let len = page_align_up(len);
+
+        let vm_flags = VmFlags::from(prot_flags)
+            | VmFlags::from(map_flags)
+            | VmFlags::VM_MAYREAD
+            | VmFlags::VM_MAYWRITE
+            | VmFlags::VM_MAYEXEC;
+
+        // debug!("map_anonymous: len = {}", len);
+
+        let binding = ProcessManager::current_pcb().fd_table();
+        let fd_table_guard = binding.read();
+
+        let file = fd_table_guard.get_file_by_fd(fd);
+        if file.is_none() {
+            return Err(SystemError::EBADF);
+        }
+        // drop guard 以避免无法调度的问题
+        drop(fd_table_guard);
+
+        // offset需要4K对齐
+        if !offset & (MMArch::PAGE_SIZE - 1) == 0 {
+            return Err(SystemError::EINVAL);
+        }
+        let pgoff = offset >> MMArch::PAGE_SHIFT;
+
+        let start_page: VirtPageFrame = self.mmap(
+            round_hint_to_min(start_vaddr),
+            PageFrameCount::from_bytes(len).unwrap(),
+            prot_flags,
+            map_flags,
+            move |page, count, flags, mapper, flusher| {
+                if allocate_at_once {
+                    VMA::zeroed(
+                        page,
+                        count,
+                        vm_flags,
+                        flags,
+                        mapper,
+                        flusher,
+                        file,
+                        Some(pgoff),
+                    )
+                } else {
+                    Ok(LockedVMA::new(VMA::new(
+                        VirtRegion::new(page.virt_address(), count.data() * MMArch::PAGE_SIZE),
+                        vm_flags,
+                        flags,
+                        file,
+                        Some(pgoff),
+                        false,
+                    )))
+                }
+            },
+        )?;
         return Ok(start_page);
     }
 
@@ -333,7 +436,7 @@ impl InnerAddressSpace {
         F: FnOnce(
             VirtPageFrame,
             PageFrameCount,
-            PageFlags<MMArch>,
+            EntryFlags<MMArch>,
             &mut PageMapper,
             &mut dyn Flusher<MMArch>,
         ) -> Result<Arc<LockedVMA>, SystemError>,
@@ -380,7 +483,7 @@ impl InnerAddressSpace {
         self.mappings.insert_vma(map_func(
             page,
             page_count,
-            PageFlags::from_prot_flags(prot_flags, true),
+            EntryFlags::from_prot_flags(prot_flags, true),
             &mut self.user_mapper.utable,
             flusher,
         )?);
@@ -479,9 +582,9 @@ impl InnerAddressSpace {
         let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>();
 
         for r in regions {
-            let r = r.lock().region;
+            let r = r.lock_irqsave().region;
             let r = self.mappings.remove_vma(&r).unwrap();
-            let intersection = r.lock().region().intersect(&to_unmap).unwrap();
+            let intersection = r.lock_irqsave().region().intersect(&to_unmap).unwrap();
             let split_result = r.extract(intersection, &self.user_mapper.utable).unwrap();
 
             // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
@@ -533,10 +636,10 @@ impl InnerAddressSpace {
 
         for r in regions {
             // debug!("mprotect: r: {:?}", r);
-            let r = *r.lock().region();
+            let r = *r.lock_irqsave().region();
             let r = self.mappings.remove_vma(&r).unwrap();
 
-            let intersection = r.lock().region().intersect(&region).unwrap();
+            let intersection = r.lock_irqsave().region().intersect(&region).unwrap();
             let split_result = r
                 .extract(intersection, mapper)
                 .expect("Failed to extract VMA");
@@ -548,17 +651,16 @@ impl InnerAddressSpace {
                 self.mappings.insert_vma(after);
             }
 
-            let mut r_guard = r.lock();
+            let mut r_guard = r.lock_irqsave();
             // 如果VMA的保护标志不允许指定的修改,则返回错误
             if !r_guard.can_have_flags(prot_flags) {
                 drop(r_guard);
                 self.mappings.insert_vma(r.clone());
                 return Err(SystemError::EACCES);
             }
-
             r_guard.set_vm_flags(VmFlags::from(prot_flags));
 
-            let new_flags: PageFlags<MMArch> = r_guard
+            let new_flags: EntryFlags<MMArch> = r_guard
                 .flags()
                 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
                 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
@@ -592,10 +694,10 @@ impl InnerAddressSpace {
         let regions = self.mappings.conflicts(region).collect::<Vec<_>>();
 
         for r in regions {
-            let r = *r.lock().region();
+            let r = *r.lock_irqsave().region();
             let r = self.mappings.remove_vma(&r).unwrap();
 
-            let intersection = r.lock().region().intersect(&region).unwrap();
+            let intersection = r.lock_irqsave().region().intersect(&region).unwrap();
             let split_result = r
                 .extract(intersection, mapper)
                 .expect("Failed to extract VMA");
@@ -768,7 +870,7 @@ impl UserMappings {
     #[allow(dead_code)]
     pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
         for v in self.vmas.iter() {
-            let guard = v.lock();
+            let guard = v.lock_irqsave();
             if guard.region.contains(vaddr) {
                 return Some(v.clone());
             }
@@ -788,13 +890,13 @@ impl UserMappings {
     pub fn find_nearest(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
         let mut nearest: Option<Arc<LockedVMA>> = None;
         for v in self.vmas.iter() {
-            let guard = v.lock();
+            let guard = v.lock_irqsave();
             if guard.region.contains(vaddr) {
                 return Some(v.clone());
             }
-            if guard.region.start > vaddr
+            if guard.region.start >= vaddr
                 && if let Some(ref nearest) = nearest {
-                    guard.region.start < nearest.lock().region.start
+                    guard.region.start < nearest.lock_irqsave().region.start
                 } else {
                     true
                 }
@@ -810,7 +912,7 @@ impl UserMappings {
         let r = self
             .vmas
             .iter()
-            .filter(move |v| v.lock().region.intersect(&request).is_some())
+            .filter(move |v| v.lock_irqsave().region.intersect(&request).is_some())
             .cloned();
         return r;
     }
@@ -932,7 +1034,7 @@ impl UserMappings {
 
     /// 在当前进程的映射关系中,插入一个新的VMA。
     pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
-        let region = vma.lock().region;
+        let region = vma.lock_irqsave().region;
         // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。
         assert!(self.conflicts(region).next().is_none());
         self.reserve_hole(&region);
@@ -952,7 +1054,7 @@ impl UserMappings {
         // 请注意,由于这里会对每个VMA加锁,因此性能很低
         let vma: Arc<LockedVMA> = self
             .vmas
-            .drain_filter(|vma| vma.lock().region == *region)
+            .drain_filter(|vma| vma.lock_irqsave().region == *region)
             .next()?;
         self.unreserve_hole(region);
 
@@ -1002,7 +1104,7 @@ impl LockedVMA {
             id: LOCKEDVMA_ID_ALLOCATOR.alloc().unwrap(),
             vma: SpinLock::new(vma),
         });
-        r.vma.lock().self_ref = Arc::downgrade(&r);
+        r.vma.lock_irqsave().self_ref = Arc::downgrade(&r);
         return r;
     }
 
@@ -1014,6 +1116,10 @@ impl LockedVMA {
         return self.vma.lock();
     }
 
+    pub fn lock_irqsave(&self) -> SpinLockGuard<VMA> {
+        return self.vma.lock_irqsave();
+    }
+
     /// 调整当前VMA的页面的标志位
     ///
     /// TODO:增加调整虚拟页映射的物理地址的功能
@@ -1024,11 +1130,11 @@ impl LockedVMA {
     ///
     pub fn remap(
         &self,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
         mapper: &mut PageMapper,
         mut flusher: impl Flusher<MMArch>,
     ) -> Result<(), SystemError> {
-        let mut guard = self.lock();
+        let mut guard = self.lock_irqsave();
         for page in guard.region.pages() {
             // 暂时要求所有的页帧都已经映射到页表
             // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
@@ -1046,7 +1152,7 @@ impl LockedVMA {
     pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) {
         // todo: 如果当前vma与文件相关,完善文件相关的逻辑
 
-        let mut guard = self.lock();
+        let mut guard = self.lock_irqsave();
 
         // 获取物理页的anon_vma的守卫
         let mut page_manager_guard: SpinLockGuard<'_, crate::mm::page::PageManager> =
@@ -1059,12 +1165,13 @@ impl LockedVMA {
                 .expect("Failed to unmap, beacuse of some page is not mapped");
 
             // 从anon_vma中删除当前VMA
-            let page = page_manager_guard.get_mut(&paddr);
-            page.remove_vma(self);
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write_irqsave().remove_vma(self);
 
             // 如果物理页的anon_vma链表长度为0并且不是共享页,则释放物理页.
-            if page.can_deallocate() {
+            if page.read_irqsave().can_deallocate() {
                 unsafe {
+                    drop(page);
                     deallocate_page_frames(
                         PhysPageFrame::new(paddr),
                         PageFrameCount::new(1),
@@ -1076,10 +1183,19 @@ impl LockedVMA {
             flusher.consume(flush);
         }
         guard.mapped = false;
+
+        // 当vma对应共享文件的写映射时,唤醒脏页回写线程
+        if guard.vm_file().is_some()
+            && guard
+                .vm_flags()
+                .contains(VmFlags::VM_SHARED | VmFlags::VM_WRITE)
+        {
+            crate::mm::page::PageReclaimer::wakeup_claim_thread();
+        }
     }
 
     pub fn mapped(&self) -> bool {
-        return self.vma.lock().mapped;
+        return self.vma.lock_irqsave().mapped;
     }
 
     /// 将当前VMA进行切分,切分成3个VMA,分别是:
@@ -1091,7 +1207,7 @@ impl LockedVMA {
         assert!(region.start().check_aligned(MMArch::PAGE_SIZE));
         assert!(region.end().check_aligned(MMArch::PAGE_SIZE));
 
-        let mut guard = self.lock();
+        let mut guard = self.lock_irqsave();
         {
             // 如果传入的region不在当前VMA的范围内,则直接返回None
             if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end())
@@ -1134,25 +1250,27 @@ impl LockedVMA {
         // 重新设置before、after这两个VMA里面的物理页的anon_vma
         let mut page_manager_guard = page_manager_lock_irqsave();
         if let Some(before) = before.clone() {
-            let virt_iter = before.lock().region.iter_pages();
+            let virt_iter = before.lock_irqsave().region.iter_pages();
             for frame in virt_iter {
                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
-                    let page = page_manager_guard.get_mut(&paddr);
-                    page.insert_vma(before.clone());
-                    page.remove_vma(self);
-                    before.lock().mapped = true;
+                    let page = page_manager_guard.get_unwrap(&paddr);
+                    let mut page_guard = page.write_irqsave();
+                    page_guard.insert_vma(before.clone());
+                    page_guard.remove_vma(self);
+                    before.lock_irqsave().mapped = true;
                 }
             }
         }
 
         if let Some(after) = after.clone() {
-            let virt_iter = after.lock().region.iter_pages();
+            let virt_iter = after.lock_irqsave().region.iter_pages();
             for frame in virt_iter {
                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
-                    let page = page_manager_guard.get_mut(&paddr);
-                    page.insert_vma(after.clone());
-                    page.remove_vma(self);
-                    after.lock().mapped = true;
+                    let page = page_manager_guard.get_unwrap(&paddr);
+                    let mut page_guard = page.write_irqsave();
+                    page_guard.insert_vma(after.clone());
+                    page_guard.remove_vma(self);
+                    after.lock_irqsave().mapped = true;
                 }
             }
         }
@@ -1168,7 +1286,7 @@ impl LockedVMA {
 
     /// 判断VMA是否为外部(非当前进程空间)的VMA
     pub fn is_foreign(&self) -> bool {
-        let guard = self.lock();
+        let guard = self.lock_irqsave();
         if let Some(space) = guard.user_address_space.clone() {
             if let Some(space) = space.upgrade() {
                 return AddressSpace::is_current(&space);
@@ -1182,15 +1300,15 @@ impl LockedVMA {
 
     /// 判断VMA是否可访问
     pub fn is_accessible(&self) -> bool {
-        let guard = self.lock();
+        let guard = self.lock_irqsave();
         let vm_access_flags: VmFlags = VmFlags::VM_READ | VmFlags::VM_WRITE | VmFlags::VM_EXEC;
         guard.vm_flags().intersects(vm_access_flags)
     }
 
     /// 判断VMA是否为匿名映射
     pub fn is_anonymous(&self) -> bool {
-        //TODO: 实现匿名映射判断逻辑,目前仅支持匿名映射
-        true
+        let guard = self.lock_irqsave();
+        guard.vm_file.is_none()
     }
 
     /// 判断VMA是否为大页映射
@@ -1236,13 +1354,17 @@ pub struct VMA {
     /// 虚拟内存区域标志
     vm_flags: VmFlags,
     /// VMA内的页帧的标志
-    flags: PageFlags<MMArch>,
+    flags: EntryFlags<MMArch>,
     /// VMA内的页帧是否已经映射到页表
     mapped: bool,
     /// VMA所属的用户地址空间
     user_address_space: Option<Weak<AddressSpace>>,
     self_ref: Weak<LockedVMA>,
 
+    vm_file: Option<Arc<File>>,
+    /// VMA映射的文件部分相对于整个文件的偏移页数
+    file_pgoff: Option<usize>,
+
     provider: Provider,
 }
 
@@ -1265,7 +1387,9 @@ impl VMA {
     pub fn new(
         region: VirtRegion,
         vm_flags: VmFlags,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
+        file: Option<Arc<File>>,
+        pgoff: Option<usize>,
         mapped: bool,
     ) -> Self {
         VMA {
@@ -1276,6 +1400,8 @@ impl VMA {
             user_address_space: None,
             self_ref: Weak::default(),
             provider: Provider::Allocated,
+            vm_file: file,
+            file_pgoff: pgoff,
         }
     }
 
@@ -1287,6 +1413,14 @@ impl VMA {
         return &self.vm_flags;
     }
 
+    pub fn vm_file(&self) -> Option<Arc<File>> {
+        return self.vm_file.clone();
+    }
+
+    pub fn address_space(&self) -> Option<Weak<AddressSpace>> {
+        return self.user_address_space.clone();
+    }
+
     pub fn set_vm_flags(&mut self, vm_flags: VmFlags) {
         self.vm_flags = vm_flags;
     }
@@ -1299,6 +1433,10 @@ impl VMA {
         self.mapped = mapped;
     }
 
+    pub fn set_flags(&mut self) {
+        self.flags = MMArch::vm_get_page_prot(self.vm_flags);
+    }
+
     /// # 拷贝当前VMA的内容
     ///
     /// ### 安全性
@@ -1313,6 +1451,8 @@ impl VMA {
             user_address_space: self.user_address_space.clone(),
             self_ref: self.self_ref.clone(),
             provider: Provider::Allocated,
+            file_pgoff: self.file_pgoff,
+            vm_file: self.vm_file.clone(),
         };
     }
 
@@ -1325,14 +1465,21 @@ impl VMA {
             user_address_space: None,
             self_ref: Weak::default(),
             provider: Provider::Allocated,
+            file_pgoff: self.file_pgoff,
+            vm_file: self.vm_file.clone(),
         };
     }
 
     #[inline(always)]
-    pub fn flags(&self) -> PageFlags<MMArch> {
+    pub fn flags(&self) -> EntryFlags<MMArch> {
         return self.flags;
     }
 
+    #[inline(always)]
+    pub fn file_page_offset(&self) -> Option<usize> {
+        return self.file_pgoff;
+    }
+
     pub fn pages(&self) -> VirtPageFrameIter {
         return VirtPageFrameIter::new(
             VirtPageFrame::new(self.region.start()),
@@ -1342,7 +1489,7 @@ impl VMA {
 
     pub fn remap(
         &mut self,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
         mapper: &mut PageMapper,
         mut flusher: impl Flusher<MMArch>,
     ) -> Result<(), SystemError> {
@@ -1395,7 +1542,7 @@ impl VMA {
         destination: VirtPageFrame,
         count: PageFrameCount,
         vm_flags: VmFlags,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
         mapper: &mut PageMapper,
         mut flusher: impl Flusher<MMArch>,
     ) -> Result<Arc<LockedVMA>, SystemError> {
@@ -1417,23 +1564,22 @@ impl VMA {
             cur_dest = cur_dest.next();
         }
 
-        let r: Arc<LockedVMA> = LockedVMA::new(VMA {
-            region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
+        let r: Arc<LockedVMA> = LockedVMA::new(VMA::new(
+            VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
             vm_flags,
             flags,
-            mapped: true,
-            user_address_space: None,
-            self_ref: Weak::default(),
-            provider: Provider::Allocated,
-        });
+            None,
+            None,
+            true,
+        ));
 
         // 将VMA加入到anon_vma中
         let mut page_manager_guard = page_manager_lock_irqsave();
         cur_phy = phys;
         for _ in 0..count.data() {
             let paddr = cur_phy.phys_address();
-            let page = page_manager_guard.get_mut(&paddr);
-            page.insert_vma(r.clone());
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write_irqsave().insert_vma(r.clone());
             cur_phy = cur_phy.next();
         }
 
@@ -1441,21 +1587,29 @@ impl VMA {
     }
 
     /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA
+    /// ## 参数
     ///
-    /// @param destination 要映射到的虚拟地址
-    /// @param count 要映射的页帧数量
-    /// @param flags 页面标志位
-    /// @param mapper 页表映射器
-    /// @param flusher 页表项刷新器
+    /// - `destination`: 要映射到的虚拟地址
+    /// - `page_count`: 要映射的页帧数量
+    /// - `vm_flags`: VMA标志位
+    /// - `flags`: 页面标志位
+    /// - `mapper`: 页表映射器
+    /// - `flusher`: 页表项刷新器
+    /// - `file`: 映射文件
+    /// - `pgoff`: 返回映射后的虚拟内存区域
     ///
-    /// @return 返回映射后的虚拟内存区域
+    /// ## 返回值
+    /// - 页面错误处理信息标志
+    #[allow(clippy::too_many_arguments)]
     pub fn zeroed(
         destination: VirtPageFrame,
         page_count: PageFrameCount,
         vm_flags: VmFlags,
-        flags: PageFlags<MMArch>,
+        flags: EntryFlags<MMArch>,
         mapper: &mut PageMapper,
         mut flusher: impl Flusher<MMArch>,
+        file: Option<Arc<File>>,
+        pgoff: Option<usize>,
     ) -> Result<Arc<LockedVMA>, SystemError> {
         let mut cur_dest: VirtPageFrame = destination;
         // debug!(
@@ -1482,6 +1636,8 @@ impl VMA {
             ),
             vm_flags,
             flags,
+            file,
+            pgoff,
             true,
         ));
         drop(flusher);
@@ -1495,12 +1651,25 @@ impl VMA {
             let paddr = mapper.translate(frame.virt_address()).unwrap().0;
 
             // 将VMA加入到anon_vma
-            let page = page_manager_guard.get_mut(&paddr);
-            page.insert_vma(r.clone());
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write_irqsave().insert_vma(r.clone());
         }
         // debug!("VMA::zeroed: done");
         return Ok(r);
     }
+
+    pub fn page_address(&self, page: &Arc<Page>) -> Result<VirtAddr, SystemError> {
+        let page_guard = page.read_irqsave();
+        let index = page_guard.index().unwrap();
+        if index >= self.file_pgoff.unwrap() {
+            let address =
+                self.region.start + ((index - self.file_pgoff.unwrap()) << MMArch::PAGE_SHIFT);
+            if address <= self.region.end() {
+                return Ok(address);
+            }
+        }
+        return Err(SystemError::EFAULT);
+    }
 }
 
 impl Drop for VMA {

+ 1 - 0
kernel/src/sched/mod.rs

@@ -112,6 +112,7 @@ pub trait Scheduler {
     );
 
     /// ## 选择接下来最适合运行的任务
+    #[allow(dead_code)]
     fn pick_task(rq: &mut CpuRunQueue) -> Option<Arc<ProcessControlBlock>>;
 
     /// ## 选择接下来最适合运行的任务

+ 6 - 0
kernel/src/syscall/mod.rs

@@ -1104,6 +1104,12 @@ impl Syscall {
 
                 Self::shmctl(id, cmd, user_buf, from_user)
             }
+            SYS_MSYNC => {
+                let start = page_align_up(args[0]);
+                let len = page_align_up(args[1]);
+                let flags = args[2];
+                Self::msync(VirtAddr::new(start), len, flags)
+            }
             SYS_UTIMENSAT => Self::sys_utimensat(
                 args[0] as i32,
                 args[1] as *const u8,

+ 2 - 2
kernel/src/virt/kvm/host_mem.rs

@@ -2,7 +2,7 @@ use log::debug;
 use system_error::SystemError;
 
 use super::{vcpu::Vcpu, vm};
-use crate::mm::{kernel_mapper::KernelMapper, page::PageFlags, VirtAddr};
+use crate::mm::{kernel_mapper::KernelMapper, page::EntryFlags, VirtAddr};
 
 /*
  * Address types:
@@ -152,7 +152,7 @@ fn hva_to_pfn(addr: u64, _atomic: bool, _writable: &mut bool) -> Result<u64, Sys
         return Ok(hpa.data() as u64 >> PAGE_SHIFT);
     }
     unsafe {
-        mapper.map(hva, PageFlags::mmio_flags());
+        mapper.map(hva, EntryFlags::mmio_flags());
     }
     let (hpa, _) = mapper.translate(hva).unwrap();
     return Ok(hpa.data() as u64 >> PAGE_SHIFT);

+ 1 - 0
user/apps/test_filemap/.gitignore

@@ -0,0 +1 @@
+test_filemap

+ 20 - 0
user/apps/test_filemap/Makefile

@@ -0,0 +1,20 @@
+ifeq ($(ARCH), x86_64)
+	CROSS_COMPILE=x86_64-linux-musl-
+else ifeq ($(ARCH), riscv64)
+	CROSS_COMPILE=riscv64-linux-musl-
+endif
+
+CC=$(CROSS_COMPILE)gcc
+
+.PHONY: all
+all: main.c
+	$(CC) -static -o test_filemap main.c
+
+.PHONY: install clean
+install: all
+	mv test_filemap $(DADK_CURRENT_BUILD_DIR)/test_filemap
+
+clean:
+	rm test_filemap *.o
+
+fmt:

+ 61 - 0
user/apps/test_filemap/main.c

@@ -0,0 +1,61 @@
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main()
+{
+    // 打开文件
+    int fd = open("example.txt", O_RDWR | O_CREAT | O_TRUNC, 0777);
+
+    if (fd == -1)
+    {
+        perror("open");
+        exit(EXIT_FAILURE);
+    }
+
+    write(fd, "HelloWorld!", 11);
+    char buf[12];
+    buf[11] = '\0';
+    close(fd);
+
+    fd = open("example.txt", O_RDWR);
+    read(fd, buf, 11);
+    printf("File content: %s\n", buf);
+
+    // 将文件映射到内存
+    void *map = mmap(NULL, 11, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if (map == MAP_FAILED)
+    {
+        perror("mmap");
+        close(fd);
+        exit(EXIT_FAILURE);
+    }
+    printf("mmap address: %p\n", map);
+
+    // 关闭文件描述符
+    // close(fd);
+
+    // 访问和修改文件内容
+    char *fileContent = (char *)map;
+    printf("change 'H' to 'G'\n");
+    fileContent[0] = 'G'; // 修改第一个字符为 'G'
+    printf("mmap content: %s\n", fileContent);
+
+    // 解除映射
+    printf("unmap\n");
+    if (munmap(map, 11) == -1)
+    {
+        perror("munmap");
+        exit(EXIT_FAILURE);
+    }
+
+    fd = open("example.txt", O_RDWR);
+    read(fd, buf, 11);
+    printf("File content: %s\n", buf);
+
+    return 0;
+}

+ 23 - 0
user/dadk/config/test_filemap-0.1.0.dadk

@@ -0,0 +1,23 @@
+{
+  "name": "test_filemap",
+  "version": "0.1.0",
+  "description": "测试filemap",
+  "task_type": {
+    "BuildFromSource": {
+      "Local": {
+        "path": "apps/test_filemap"
+      }
+    }
+  },
+  "depends": [],
+  "build": {
+    "build_command": "make install"
+  },
+  "clean": {
+    "clean_command": "make clean"
+  },
+  "install": {
+    "in_dragonos_path": "/bin"
+  },
+  "target_arch": ["x86_64"]
+}