Browse Source

重写页面保护标志的构造逻辑

MemoryShore 10 months ago
parent
commit
3ac055a7b0

+ 35 - 0
kernel/src/arch/x86_64/mm/mod.rs

@@ -326,6 +326,41 @@ impl MemoryManagementArch for X86_64MMArch {
         }
         pkru::pkru_allows_pkey(pkru::vma_pkey(vma), write)
     }
+
+    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;
 }
 
 impl X86_64MMArch {

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

@@ -17,7 +17,7 @@ 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
+    ((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

+ 45 - 9
kernel/src/mm/fault.rs

@@ -307,14 +307,20 @@ 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()
-        );
+        // panic!(
+        //     "do_cow_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_cow_fault
+
+        let mut ret = Self::filemap_fault(pfm.clone(), mapper);
+
+        ret = ret.union(Self::finish_fault(pfm, mapper));
+
+        ret
     }
 
     /// 处理文件映射页的缺页异常
@@ -344,7 +350,7 @@ impl PageFaultHandler {
         ret = Self::filemap_fault(pfm.clone(), mapper);
 
         ret = ret.union(Self::finish_fault(pfm, mapper));
-        
+
         ret
     }
 
@@ -456,6 +462,14 @@ impl PageFaultHandler {
         }
     }
 
+    /// 缺页附近页预读
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
     pub unsafe fn do_fault_around(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
         log::info!("do_fault_around");
         if mapper.get_table(*pfm.address(), 0).is_none() {
@@ -518,6 +532,14 @@ impl PageFaultHandler {
         VmFaultReason::empty()
     }
 
+    /// 通用的VMA文件映射页面映射函数
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
     pub unsafe fn filemap_map_pages(
         pfm: PageFaultMessage,
         mapper: &mut PageMapper,
@@ -559,6 +581,14 @@ impl PageFaultHandler {
         VmFaultReason::empty()
     }
 
+    /// 通用的VMA文件映射错误处理函数
+    /// ## 参数
+    ///
+    /// - `pfm`: 缺页异常信息
+    /// - `mapper`: 页表映射器
+    ///
+    /// ## 返回值
+    /// - VmFaultReason: 页面错误处理信息标志
     pub unsafe fn filemap_fault(
         mut pfm: PageFaultMessage,
         mapper: &mut PageMapper,
@@ -626,7 +656,13 @@ impl PageFaultHandler {
         {
             // 私有文件映射的写时复制场景
             // 分配空白页并映射到缺页地址
-            mapper.map(pfm.address, vma_guard.flags()).unwrap().flush();
+            mapper
+                .map(
+                    pfm.address,
+                    vma_guard.flags().set_write(true).set_dirty(true),
+                )
+                .unwrap()
+                .flush();
 
             //复制PageCache内容到新的页内
             let new_frame = phys_2_virt(mapper.translate(pfm.address).unwrap().0.data());

+ 59 - 1
kernel/src/mm/mod.rs

@@ -1,4 +1,5 @@
 use alloc::sync::Arc;
+use page::EntryFlags;
 use system_error::SystemError;
 
 use crate::{arch::MMArch, include::bindings::bindings::PAGE_OFFSET};
@@ -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;
@@ -96,6 +97,20 @@ bitflags! {
     }
 }
 
+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]
+    }
+}
+
 /// 获取内核IDLE进程的用户地址空间结构体
 #[allow(non_snake_case)]
 #[inline(always)]
@@ -642,6 +657,49 @@ 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;
+
+    fn protection_map() -> [usize; 16] {
+        let mut map = [0; 16];
+        map[VmFlags::VM_NONE] = Self::PAGE_NONE;
+        map[VmFlags::VM_READ] = Self::PAGE_READONLY;
+        map[VmFlags::VM_WRITE] = Self::PAGE_COPY;
+        map[VmFlags::VM_WRITE | VmFlags::VM_READ] = Self::PAGE_COPY;
+        map[VmFlags::VM_EXEC] = Self::PAGE_READONLY_EXEC;
+        map[VmFlags::VM_EXEC | VmFlags::VM_READ] = Self::PAGE_READONLY_EXEC;
+        map[VmFlags::VM_EXEC | VmFlags::VM_WRITE] = Self::PAGE_COPY_EXEC;
+        map[VmFlags::VM_EXEC | VmFlags::VM_WRITE | VmFlags::VM_READ] = Self::PAGE_COPY_EXEC;
+        map[VmFlags::VM_SHARED] = Self::PAGE_NONE;
+        map[VmFlags::VM_SHARED | VmFlags::VM_READ] = Self::PAGE_READONLY;
+        map[VmFlags::VM_SHARED | VmFlags::VM_WRITE] = Self::PAGE_SHARED;
+        map[VmFlags::VM_SHARED | VmFlags::VM_WRITE | VmFlags::VM_READ] = Self::PAGE_SHARED;
+        map[VmFlags::VM_SHARED | VmFlags::VM_EXEC] = Self::PAGE_READONLY_EXEC;
+        map[VmFlags::VM_SHARED | VmFlags::VM_EXEC | VmFlags::VM_READ] = Self::PAGE_READONLY_EXEC;
+        map[VmFlags::VM_SHARED | VmFlags::VM_EXEC | VmFlags::VM_WRITE] = Self::PAGE_SHARED_EXEC;
+        map[VmFlags::VM_SHARED | VmFlags::VM_EXEC | VmFlags::VM_WRITE | VmFlags::VM_READ] =
+            Self::PAGE_SHARED_EXEC;
+        map
+    }
+
+    /// 页面保护标志转换函数
+    /// ## 参数
+    ///
+    /// - `vm_flags`: VmFlags标志
+    ///
+    /// ## 返回值
+    /// - EntryFlags: 页面的保护位
+    fn vm_get_page_prot(vm_flags: VmFlags) -> EntryFlags<Self> {
+        let map = Self::protection_map();
+        unsafe { EntryFlags::from_data(map[vm_flags]) }
+    }
 }
 
 /// @brief 虚拟地址范围

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

@@ -530,11 +530,12 @@ impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
     /// - prot_flags: 页的保护标志
     /// - user: 用户空间是否可访问
     pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> EntryFlags<Arch> {
-        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 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;
     }
 

+ 4 - 0
kernel/src/mm/ucontext.rs

@@ -1425,6 +1425,10 @@ impl VMA {
         self.mapped = mapped;
     }
 
+    pub fn set_flags(&mut self) {
+        self.flags = MMArch::vm_get_page_prot(self.vm_flags);
+    }
+
     /// # 拷贝当前VMA的内容
     ///
     /// ### 安全性