xref: /DragonOS/kernel/src/mm/syscall.rs (revision 6fc066ac11d2f9a3ac629d57487a6144fda1ac63)
140fe15e0SLoGin use core::intrinsics::unlikely;
240fe15e0SLoGin 
340fe15e0SLoGin use alloc::sync::Arc;
491e9d4abSLoGin use system_error::SystemError;
540fe15e0SLoGin 
6ab5c8ca4Slogin use crate::{
740fe15e0SLoGin     arch::MMArch,
8*6fc066acSJomo     ipc::shm::ShmFlags,
940fe15e0SLoGin     kerror,
1040fe15e0SLoGin     libs::align::{check_aligned, page_align_up},
1140fe15e0SLoGin     mm::MemoryManagementArch,
1291e9d4abSLoGin     syscall::Syscall,
13ab5c8ca4Slogin };
14ab5c8ca4Slogin 
1540fe15e0SLoGin use super::{
1640fe15e0SLoGin     allocator::page_frame::{PageFrameCount, VirtPageFrame},
1740fe15e0SLoGin     ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
184cfa009bSJomo     verify_area, VirtAddr, VmFlags,
1940fe15e0SLoGin };
2040fe15e0SLoGin 
2140fe15e0SLoGin bitflags! {
2240fe15e0SLoGin     /// Memory protection flags
2340fe15e0SLoGin     pub struct ProtFlags: u64 {
2440fe15e0SLoGin         const PROT_NONE = 0x0;
2540fe15e0SLoGin         const PROT_READ = 0x1;
2640fe15e0SLoGin         const PROT_WRITE = 0x2;
2740fe15e0SLoGin         const PROT_EXEC = 0x4;
28ab5c8ca4Slogin     }
2940fe15e0SLoGin 
3040fe15e0SLoGin     /// Memory mapping flags
3140fe15e0SLoGin     pub struct MapFlags: u64 {
3240fe15e0SLoGin         const MAP_NONE = 0x0;
3340fe15e0SLoGin         /// share changes
3440fe15e0SLoGin         const MAP_SHARED = 0x1;
3540fe15e0SLoGin         /// changes are private
3640fe15e0SLoGin         const MAP_PRIVATE = 0x2;
3740fe15e0SLoGin         /// Interpret addr exactly
3840fe15e0SLoGin         const MAP_FIXED = 0x10;
3940fe15e0SLoGin         /// don't use a file
4040fe15e0SLoGin         const MAP_ANONYMOUS = 0x20;
4140fe15e0SLoGin         // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
4240fe15e0SLoGin         /// stack-like segment
4340fe15e0SLoGin         const MAP_GROWSDOWN = 0x100;
4440fe15e0SLoGin         /// ETXTBSY
4540fe15e0SLoGin         const MAP_DENYWRITE = 0x800;
4640fe15e0SLoGin         /// Mark it as an executable
4740fe15e0SLoGin         const MAP_EXECUTABLE = 0x1000;
4840fe15e0SLoGin         /// Pages are locked
4940fe15e0SLoGin         const MAP_LOCKED = 0x2000;
5040fe15e0SLoGin         /// don't check for reservations
5140fe15e0SLoGin         const MAP_NORESERVE = 0x4000;
5240fe15e0SLoGin         /// populate (prefault) pagetables
5340fe15e0SLoGin         const MAP_POPULATE = 0x8000;
5440fe15e0SLoGin         /// do not block on IO
5540fe15e0SLoGin         const MAP_NONBLOCK = 0x10000;
5640fe15e0SLoGin         /// give out an address that is best suited for process/thread stacks
5740fe15e0SLoGin         const MAP_STACK = 0x20000;
5840fe15e0SLoGin         /// create a huge page mapping
5940fe15e0SLoGin         const MAP_HUGETLB = 0x40000;
6040fe15e0SLoGin         /// perform synchronous page faults for the mapping
6140fe15e0SLoGin         const MAP_SYNC = 0x80000;
6240fe15e0SLoGin         /// MAP_FIXED which doesn't unmap underlying mapping
6340fe15e0SLoGin         const MAP_FIXED_NOREPLACE = 0x100000;
6440fe15e0SLoGin 
6540fe15e0SLoGin         /// For anonymous mmap, memory could be uninitialized
6640fe15e0SLoGin         const MAP_UNINITIALIZED = 0x4000000;
674cfa009bSJomo     }
6840fe15e0SLoGin 
694cfa009bSJomo     /// Memory mremapping flags
704cfa009bSJomo     pub struct MremapFlags: u8 {
714cfa009bSJomo         const MREMAP_MAYMOVE = 1;
724cfa009bSJomo         const MREMAP_FIXED = 2;
734cfa009bSJomo         const MREMAP_DONTUNMAP = 4;
744cfa009bSJomo     }
754cfa009bSJomo }
764cfa009bSJomo 
774cfa009bSJomo impl From<MapFlags> for VmFlags {
784cfa009bSJomo     fn from(map_flags: MapFlags) -> Self {
794cfa009bSJomo         let mut vm_flags = VmFlags::VM_NONE;
804cfa009bSJomo 
814cfa009bSJomo         if map_flags.contains(MapFlags::MAP_GROWSDOWN) {
824cfa009bSJomo             vm_flags |= VmFlags::VM_GROWSDOWN;
834cfa009bSJomo         }
844cfa009bSJomo 
854cfa009bSJomo         if map_flags.contains(MapFlags::MAP_LOCKED) {
864cfa009bSJomo             vm_flags |= VmFlags::VM_LOCKED;
874cfa009bSJomo         }
884cfa009bSJomo 
894cfa009bSJomo         if map_flags.contains(MapFlags::MAP_SYNC) {
904cfa009bSJomo             vm_flags |= VmFlags::VM_SYNC;
914cfa009bSJomo         }
924cfa009bSJomo 
934cfa009bSJomo         vm_flags
944cfa009bSJomo     }
954cfa009bSJomo }
964cfa009bSJomo 
974cfa009bSJomo impl From<ProtFlags> for VmFlags {
984cfa009bSJomo     fn from(prot_flags: ProtFlags) -> Self {
994cfa009bSJomo         let mut vm_flags = VmFlags::VM_NONE;
1004cfa009bSJomo 
1014cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_READ) {
1024cfa009bSJomo             vm_flags |= VmFlags::VM_READ;
1034cfa009bSJomo         }
1044cfa009bSJomo 
1054cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_WRITE) {
1064cfa009bSJomo             vm_flags |= VmFlags::VM_WRITE;
1074cfa009bSJomo         }
1084cfa009bSJomo 
1094cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_EXEC) {
1104cfa009bSJomo             vm_flags |= VmFlags::VM_EXEC;
1114cfa009bSJomo         }
1124cfa009bSJomo 
1134cfa009bSJomo         vm_flags
1144cfa009bSJomo     }
1154cfa009bSJomo }
1164cfa009bSJomo 
117*6fc066acSJomo impl From<ShmFlags> for VmFlags {
118*6fc066acSJomo     fn from(shm_flags: ShmFlags) -> Self {
119*6fc066acSJomo         let mut vm_flags = VmFlags::VM_NONE;
120*6fc066acSJomo 
121*6fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_RDONLY) {
122*6fc066acSJomo             vm_flags |= VmFlags::VM_READ;
123*6fc066acSJomo         } else {
124*6fc066acSJomo             vm_flags |= VmFlags::VM_READ | VmFlags::VM_WRITE;
125*6fc066acSJomo         }
126*6fc066acSJomo 
127*6fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_EXEC) {
128*6fc066acSJomo             vm_flags |= VmFlags::VM_EXEC;
129*6fc066acSJomo         }
130*6fc066acSJomo 
131*6fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_HUGETLB) {
132*6fc066acSJomo             vm_flags |= VmFlags::VM_HUGETLB;
133*6fc066acSJomo         }
134*6fc066acSJomo 
135*6fc066acSJomo         vm_flags
136*6fc066acSJomo     }
137*6fc066acSJomo }
138*6fc066acSJomo 
139b5b571e0SLoGin impl From<VmFlags> for MapFlags {
140b5b571e0SLoGin     fn from(value: VmFlags) -> Self {
1414cfa009bSJomo         let mut map_flags = MapFlags::MAP_NONE;
1424cfa009bSJomo 
143b5b571e0SLoGin         if value.contains(VmFlags::VM_GROWSDOWN) {
1444cfa009bSJomo             map_flags |= MapFlags::MAP_GROWSDOWN;
1454cfa009bSJomo         }
1464cfa009bSJomo 
147b5b571e0SLoGin         if value.contains(VmFlags::VM_LOCKED) {
1484cfa009bSJomo             map_flags |= MapFlags::MAP_LOCKED;
1494cfa009bSJomo         }
1504cfa009bSJomo 
151b5b571e0SLoGin         if value.contains(VmFlags::VM_SYNC) {
1524cfa009bSJomo             map_flags |= MapFlags::MAP_SYNC;
1534cfa009bSJomo         }
1544cfa009bSJomo 
155b5b571e0SLoGin         if value.contains(VmFlags::VM_MAYSHARE) {
1563055390cSJomo             map_flags |= MapFlags::MAP_SHARED;
1573055390cSJomo         }
1583055390cSJomo 
1594cfa009bSJomo         map_flags
1604cfa009bSJomo     }
1614cfa009bSJomo }
1624cfa009bSJomo 
163b5b571e0SLoGin impl From<VmFlags> for ProtFlags {
164b5b571e0SLoGin     fn from(value: VmFlags) -> Self {
1654cfa009bSJomo         let mut prot_flags = ProtFlags::PROT_NONE;
1664cfa009bSJomo 
167b5b571e0SLoGin         if value.contains(VmFlags::VM_READ) {
1684cfa009bSJomo             prot_flags |= ProtFlags::PROT_READ;
1694cfa009bSJomo         }
1704cfa009bSJomo 
171b5b571e0SLoGin         if value.contains(VmFlags::VM_WRITE) {
1724cfa009bSJomo             prot_flags |= ProtFlags::PROT_WRITE;
1734cfa009bSJomo         }
1744cfa009bSJomo 
175b5b571e0SLoGin         if value.contains(VmFlags::VM_EXEC) {
1764cfa009bSJomo             prot_flags |= ProtFlags::PROT_EXEC;
1774cfa009bSJomo         }
1784cfa009bSJomo 
1794cfa009bSJomo         prot_flags
18040fe15e0SLoGin     }
18140fe15e0SLoGin }
18240fe15e0SLoGin 
183ab5c8ca4Slogin impl Syscall {
18440fe15e0SLoGin     pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
18540fe15e0SLoGin         // kdebug!("brk: new_addr={:?}", new_addr);
18640fe15e0SLoGin         let address_space = AddressSpace::current()?;
18740fe15e0SLoGin         let mut address_space = address_space.write();
18840fe15e0SLoGin 
1896d81180bSLoGin         if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
1906d81180bSLoGin             return Ok(address_space.brk);
1916d81180bSLoGin         }
1926d81180bSLoGin         if new_addr == address_space.brk {
1936d81180bSLoGin             return Ok(address_space.brk);
1946d81180bSLoGin         }
1956d81180bSLoGin 
19640fe15e0SLoGin         unsafe {
19740fe15e0SLoGin             address_space
19840fe15e0SLoGin                 .set_brk(VirtAddr::new(page_align_up(new_addr.data())))
19940fe15e0SLoGin                 .ok();
20040fe15e0SLoGin 
20140fe15e0SLoGin             return Ok(address_space.sbrk(0).unwrap());
202ab5c8ca4Slogin         }
203d8ad0a5eSLoGin     }
204d8ad0a5eSLoGin 
20540fe15e0SLoGin     pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
20640fe15e0SLoGin         let address_space = AddressSpace::current()?;
2071496ba7bSLoGin         assert!(address_space.read().user_mapper.utable.is_current());
20840fe15e0SLoGin         let mut address_space = address_space.write();
20940fe15e0SLoGin         let r = unsafe { address_space.sbrk(incr) };
21040fe15e0SLoGin 
21140fe15e0SLoGin         return r;
212d8ad0a5eSLoGin     }
213d8ad0a5eSLoGin 
21440fe15e0SLoGin     /// ## mmap系统调用
215d8ad0a5eSLoGin     ///
21640fe15e0SLoGin     /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
21740fe15e0SLoGin     ///
21840fe15e0SLoGin     /// ## 参数
21940fe15e0SLoGin     ///
22040fe15e0SLoGin     /// - `start_vaddr`:映射的起始地址
22140fe15e0SLoGin     /// - `len`:映射的长度
22240fe15e0SLoGin     /// - `prot`:保护标志
22340fe15e0SLoGin     /// - `flags`:映射标志
22440fe15e0SLoGin     /// - `fd`:文件描述符(暂时不支持)
22540fe15e0SLoGin     /// - `offset`:文件偏移量 (暂时不支持)
22640fe15e0SLoGin     ///
22740fe15e0SLoGin     /// ## 返回值
22840fe15e0SLoGin     ///
22940fe15e0SLoGin     /// 成功时返回映射的起始地址,失败时返回错误码
23040fe15e0SLoGin     pub fn mmap(
23140fe15e0SLoGin         start_vaddr: VirtAddr,
23240fe15e0SLoGin         len: usize,
23340fe15e0SLoGin         prot_flags: usize,
23440fe15e0SLoGin         map_flags: usize,
23540fe15e0SLoGin         _fd: i32,
23640fe15e0SLoGin         _offset: usize,
23740fe15e0SLoGin     ) -> Result<usize, SystemError> {
23840fe15e0SLoGin         let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
23940fe15e0SLoGin         let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
24040fe15e0SLoGin 
24140fe15e0SLoGin         if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
24240fe15e0SLoGin             && map_flags.contains(MapFlags::MAP_FIXED)
24340fe15e0SLoGin         {
24440fe15e0SLoGin             kerror!(
24540fe15e0SLoGin                 "mmap: MAP_FIXED is not supported for address below {}",
24640fe15e0SLoGin                 DEFAULT_MMAP_MIN_ADDR
24740fe15e0SLoGin             );
24840fe15e0SLoGin             return Err(SystemError::EINVAL);
249d8ad0a5eSLoGin         }
25040fe15e0SLoGin         // 暂时不支持除匿名页以外的映射
25140fe15e0SLoGin         if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
25240fe15e0SLoGin             kerror!("mmap: not support file mapping");
25340fe15e0SLoGin             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
25440fe15e0SLoGin         }
25540fe15e0SLoGin 
25640fe15e0SLoGin         // 暂时不支持巨页映射
25740fe15e0SLoGin         if map_flags.contains(MapFlags::MAP_HUGETLB) {
25840fe15e0SLoGin             kerror!("mmap: not support huge page mapping");
25940fe15e0SLoGin             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
26040fe15e0SLoGin         }
26140fe15e0SLoGin         let current_address_space = AddressSpace::current()?;
26240fe15e0SLoGin         let start_page = current_address_space.write().map_anonymous(
26340fe15e0SLoGin             start_vaddr,
26440fe15e0SLoGin             len,
26540fe15e0SLoGin             prot_flags,
26640fe15e0SLoGin             map_flags,
26740fe15e0SLoGin             true,
26840fe15e0SLoGin         )?;
26940fe15e0SLoGin         return Ok(start_page.virt_address().data());
27040fe15e0SLoGin     }
27140fe15e0SLoGin 
2724cfa009bSJomo     /// ## mremap系统调用
2734cfa009bSJomo     ///
2744cfa009bSJomo     ///
2754cfa009bSJomo     /// ## 参数
2764cfa009bSJomo     ///
2774cfa009bSJomo     /// - `old_vaddr`:原映射的起始地址
2784cfa009bSJomo     /// - `old_len`:原映射的长度
2794cfa009bSJomo     /// - `new_len`:重新映射的长度
2804cfa009bSJomo     /// - `mremap_flags`:重映射标志
2814cfa009bSJomo     /// - `new_vaddr`:重新映射的起始地址
2824cfa009bSJomo     ///
2834cfa009bSJomo     /// ## 返回值
2844cfa009bSJomo     ///
2854cfa009bSJomo     /// 成功时返回重映射的起始地址,失败时返回错误码
2864cfa009bSJomo     pub fn mremap(
2874cfa009bSJomo         old_vaddr: VirtAddr,
2884cfa009bSJomo         old_len: usize,
2894cfa009bSJomo         new_len: usize,
2904cfa009bSJomo         mremap_flags: MremapFlags,
2914cfa009bSJomo         new_vaddr: VirtAddr,
2924cfa009bSJomo     ) -> Result<usize, SystemError> {
2934cfa009bSJomo         // 需要重映射到新内存区域的情况下,必须包含MREMAP_MAYMOVE并且指定新地址
2944cfa009bSJomo         if mremap_flags.contains(MremapFlags::MREMAP_FIXED)
2954cfa009bSJomo             && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE)
2964cfa009bSJomo                 || new_vaddr == VirtAddr::new(0))
2974cfa009bSJomo         {
2984cfa009bSJomo             return Err(SystemError::EINVAL);
2994cfa009bSJomo         }
3004cfa009bSJomo 
3014cfa009bSJomo         // 不取消旧映射的情况下,必须包含MREMAP_MAYMOVE并且新内存大小等于旧内存大小
3024cfa009bSJomo         if mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP)
3034cfa009bSJomo             && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) || old_len != new_len)
3044cfa009bSJomo         {
3054cfa009bSJomo             return Err(SystemError::EINVAL);
3064cfa009bSJomo         }
3074cfa009bSJomo 
3084cfa009bSJomo         // 旧内存地址必须对齐
3094cfa009bSJomo         if !old_vaddr.check_aligned(MMArch::PAGE_SIZE) {
3104cfa009bSJomo             return Err(SystemError::EINVAL);
3114cfa009bSJomo         }
3124cfa009bSJomo 
3134cfa009bSJomo         // 将old_len、new_len 对齐页面大小
3144cfa009bSJomo         let old_len = page_align_up(old_len);
3154cfa009bSJomo         let new_len = page_align_up(new_len);
3164cfa009bSJomo 
3174cfa009bSJomo         // 不允许重映射内存区域大小为0
3184cfa009bSJomo         if new_len == 0 {
3194cfa009bSJomo             return Err(SystemError::EINVAL);
3204cfa009bSJomo         }
3214cfa009bSJomo 
3224cfa009bSJomo         let current_address_space = AddressSpace::current()?;
3234cfa009bSJomo         let vma = current_address_space.read().mappings.contains(old_vaddr);
3244cfa009bSJomo         if vma.is_none() {
3254cfa009bSJomo             return Err(SystemError::EINVAL);
3264cfa009bSJomo         }
3274cfa009bSJomo         let vma = vma.unwrap();
328b5b571e0SLoGin         let vm_flags = *vma.lock().vm_flags();
3294cfa009bSJomo 
3304cfa009bSJomo         // 暂时不支持巨页映射
3314cfa009bSJomo         if vm_flags.contains(VmFlags::VM_HUGETLB) {
3324cfa009bSJomo             kerror!("mmap: not support huge page mapping");
3334cfa009bSJomo             return Err(SystemError::ENOSYS);
3344cfa009bSJomo         }
3354cfa009bSJomo 
3364cfa009bSJomo         // 缩小旧内存映射区域
3374cfa009bSJomo         if old_len > new_len {
3384cfa009bSJomo             Self::munmap(old_vaddr + new_len, old_len - new_len)?;
3394cfa009bSJomo             return Ok(old_vaddr.data());
3404cfa009bSJomo         }
3414cfa009bSJomo 
3424cfa009bSJomo         // 重映射到新内存区域
3434cfa009bSJomo         let r = current_address_space.write().mremap(
3444cfa009bSJomo             old_vaddr,
3454cfa009bSJomo             old_len,
3464cfa009bSJomo             new_len,
3474cfa009bSJomo             mremap_flags,
3484cfa009bSJomo             new_vaddr,
3494cfa009bSJomo             vm_flags,
3504cfa009bSJomo         )?;
3514cfa009bSJomo 
3524cfa009bSJomo         if !mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) {
3534cfa009bSJomo             Self::munmap(old_vaddr, old_len)?;
3544cfa009bSJomo         }
3554cfa009bSJomo 
3564cfa009bSJomo         return Ok(r.data());
3574cfa009bSJomo     }
3584cfa009bSJomo 
35940fe15e0SLoGin     /// ## munmap系统调用
36040fe15e0SLoGin     ///
36140fe15e0SLoGin     /// ## 参数
36240fe15e0SLoGin     ///
36340fe15e0SLoGin     /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
36440fe15e0SLoGin     /// - `len`:取消映射的字节数(已经对齐到页)
36540fe15e0SLoGin     ///
36640fe15e0SLoGin     /// ## 返回值
36740fe15e0SLoGin     ///
36840fe15e0SLoGin     /// 成功时返回0,失败时返回错误码
36940fe15e0SLoGin     pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
37040fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
37140fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
37240fe15e0SLoGin 
37340fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
37440fe15e0SLoGin             return Err(SystemError::EINVAL);
37540fe15e0SLoGin         }
37640fe15e0SLoGin         if unlikely(len == 0) {
37740fe15e0SLoGin             return Err(SystemError::EINVAL);
37840fe15e0SLoGin         }
37940fe15e0SLoGin 
38040fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
38140fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
38240fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
38340fe15e0SLoGin 
38440fe15e0SLoGin         current_address_space
38540fe15e0SLoGin             .write()
38640fe15e0SLoGin             .munmap(start_frame, page_count)
38740fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
3884cfa009bSJomo 
38940fe15e0SLoGin         return Ok(0);
39040fe15e0SLoGin     }
39140fe15e0SLoGin 
39240fe15e0SLoGin     /// ## mprotect系统调用
39340fe15e0SLoGin     ///
39440fe15e0SLoGin     /// ## 参数
39540fe15e0SLoGin     ///
39640fe15e0SLoGin     /// - `start_vaddr`:起始地址(已经对齐到页)
39740fe15e0SLoGin     /// - `len`:长度(已经对齐到页)
39840fe15e0SLoGin     /// - `prot_flags`:保护标志
39940fe15e0SLoGin     pub fn mprotect(
40040fe15e0SLoGin         start_vaddr: VirtAddr,
40140fe15e0SLoGin         len: usize,
40240fe15e0SLoGin         prot_flags: usize,
40340fe15e0SLoGin     ) -> Result<usize, SystemError> {
40440fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
40540fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
40640fe15e0SLoGin 
40740fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
40840fe15e0SLoGin             return Err(SystemError::EINVAL);
40940fe15e0SLoGin         }
41040fe15e0SLoGin         if unlikely(len == 0) {
41140fe15e0SLoGin             return Err(SystemError::EINVAL);
41240fe15e0SLoGin         }
41340fe15e0SLoGin 
41440fe15e0SLoGin         let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
41540fe15e0SLoGin 
41640fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
41740fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
41840fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
41940fe15e0SLoGin 
42040fe15e0SLoGin         current_address_space
42140fe15e0SLoGin             .write()
42240fe15e0SLoGin             .mprotect(start_frame, page_count, prot_flags)
42340fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
42440fe15e0SLoGin         return Ok(0);
425ab5c8ca4Slogin     }
426ab5c8ca4Slogin }
427