xref: /DragonOS/kernel/src/mm/syscall.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
140fe15e0SLoGin use core::intrinsics::unlikely;
240fe15e0SLoGin 
340fe15e0SLoGin use alloc::sync::Arc;
4*2eab6dd7S曾俊 use log::error;
591e9d4abSLoGin use system_error::SystemError;
640fe15e0SLoGin 
7ab5c8ca4Slogin use crate::{
840fe15e0SLoGin     arch::MMArch,
96fc066acSJomo     ipc::shm::ShmFlags,
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     }
75a17651b1SMemoryShore 
76a17651b1SMemoryShore 
77a17651b1SMemoryShore     pub struct MadvFlags: u64 {
78a17651b1SMemoryShore         /// 默认行为,系统会进行一定的预读和预写,适用于一般读取场景
79a17651b1SMemoryShore         const MADV_NORMAL = 0;
80a17651b1SMemoryShore         /// 随机访问模式,系统会尽量最小化数据读取量,适用于随机访问的场景
81a17651b1SMemoryShore         const MADV_RANDOM = 1;
82a17651b1SMemoryShore         /// 顺序访问模式,系统会进行积极的预读,访问后的页面可以尽快释放,适用于顺序读取场景
83a17651b1SMemoryShore         const MADV_SEQUENTIAL = 2;
84a17651b1SMemoryShore         /// 通知系统预读某些页面,用于应用程序提前准备数据
85a17651b1SMemoryShore         const MADV_WILLNEED = 3;
86a17651b1SMemoryShore         /// 通知系统应用程序不再需要某些页面,内核可以释放相关资源
87a17651b1SMemoryShore         const MADV_DONTNEED = 4;
88a17651b1SMemoryShore 
89a17651b1SMemoryShore         /// 将指定范围的页面标记为延迟释放,真正的释放会延迟至内存压力发生时
90a17651b1SMemoryShore         const MADV_FREE = 8;
91a17651b1SMemoryShore         /// 应用程序请求释放指定范围的页面和相关的后备存储
92a17651b1SMemoryShore         const MADV_REMOVE = 9;
93a17651b1SMemoryShore         /// 在 fork 时排除指定区域
94a17651b1SMemoryShore         const MADV_DONTFORK = 10;
95a17651b1SMemoryShore         /// 取消 MADV_DONTFORK 的效果,不再在 fork 时排除指定区域
96a17651b1SMemoryShore         const MADV_DOFORK = 11;
97a17651b1SMemoryShore         /// 模拟内存硬件错误,触发内存错误处理器处理
98a17651b1SMemoryShore         const MADV_HWPOISON = 100;
99a17651b1SMemoryShore         /// 尝试软下线指定的内存范围
100a17651b1SMemoryShore         const MADV_SOFT_OFFLINE = 101;
101a17651b1SMemoryShore 
102a17651b1SMemoryShore         /// 应用程序建议内核尝试合并指定范围内内容相同的页面
103a17651b1SMemoryShore         const MADV_MERGEABLE = 12;
104a17651b1SMemoryShore         /// 取消 MADV_MERGEABLE 的效果,不再合并页面
105a17651b1SMemoryShore         const MADV_UNMERGEABLE = 13;
106a17651b1SMemoryShore 
107a17651b1SMemoryShore         /// 应用程序希望将指定范围以透明大页方式支持
108a17651b1SMemoryShore         const MADV_HUGEPAGE = 14;
109a17651b1SMemoryShore         /// 将指定范围标记为不值得用透明大页支持
110a17651b1SMemoryShore         const MADV_NOHUGEPAGE = 15;
111a17651b1SMemoryShore 
112a17651b1SMemoryShore         /// 应用程序请求在核心转储时排除指定范围内的页面
113a17651b1SMemoryShore         const MADV_DONTDUMP = 16;
114a17651b1SMemoryShore         /// 取消 MADV_DONTDUMP 的效果,不再排除核心转储时的页面
115a17651b1SMemoryShore         const MADV_DODUMP = 17;
116a17651b1SMemoryShore 
117a17651b1SMemoryShore         /// 在 fork 时将子进程的该区域内存填充为零
118a17651b1SMemoryShore         const MADV_WIPEONFORK = 18;
119a17651b1SMemoryShore         /// 取消 `MADV_WIPEONFORK` 的效果,不再在 fork 时填充子进程的内存
120a17651b1SMemoryShore         const MADV_KEEPONFORK = 19;
121a17651b1SMemoryShore 
122a17651b1SMemoryShore         /// 应用程序不会立刻使用这些内存,内核将页面设置为非活动状态以便在内存压力发生时轻松回收
123a17651b1SMemoryShore         const MADV_COLD = 20;
124a17651b1SMemoryShore         /// 应用程序不会立刻使用这些内存,内核立即将这些页面换出
125a17651b1SMemoryShore         const MADV_PAGEOUT = 21;
126a17651b1SMemoryShore 
127a17651b1SMemoryShore         /// 预先填充页面表,可读,通过触发读取故障
128a17651b1SMemoryShore         const MADV_POPULATE_READ = 22;
129a17651b1SMemoryShore         /// 预先填充页面表,可写,通过触发写入故障
130a17651b1SMemoryShore         const MADV_POPULATE_WRITE = 23;
131a17651b1SMemoryShore 
132a17651b1SMemoryShore         /// 与 `MADV_DONTNEED` 类似,会将被锁定的页面释放
133a17651b1SMemoryShore         const MADV_DONTNEED_LOCKED = 24;
134a17651b1SMemoryShore 
135a17651b1SMemoryShore         /// 同步将页面合并为新的透明大页
136a17651b1SMemoryShore         const MADV_COLLAPSE = 25;
137a17651b1SMemoryShore 
138a17651b1SMemoryShore     }
1394cfa009bSJomo }
1404cfa009bSJomo 
1414cfa009bSJomo impl From<MapFlags> for VmFlags {
1424cfa009bSJomo     fn from(map_flags: MapFlags) -> Self {
1434cfa009bSJomo         let mut vm_flags = VmFlags::VM_NONE;
1444cfa009bSJomo 
1454cfa009bSJomo         if map_flags.contains(MapFlags::MAP_GROWSDOWN) {
1464cfa009bSJomo             vm_flags |= VmFlags::VM_GROWSDOWN;
1474cfa009bSJomo         }
1484cfa009bSJomo 
1494cfa009bSJomo         if map_flags.contains(MapFlags::MAP_LOCKED) {
1504cfa009bSJomo             vm_flags |= VmFlags::VM_LOCKED;
1514cfa009bSJomo         }
1524cfa009bSJomo 
1534cfa009bSJomo         if map_flags.contains(MapFlags::MAP_SYNC) {
1544cfa009bSJomo             vm_flags |= VmFlags::VM_SYNC;
1554cfa009bSJomo         }
1564cfa009bSJomo 
1574cfa009bSJomo         vm_flags
1584cfa009bSJomo     }
1594cfa009bSJomo }
1604cfa009bSJomo 
1614cfa009bSJomo impl From<ProtFlags> for VmFlags {
1624cfa009bSJomo     fn from(prot_flags: ProtFlags) -> Self {
1634cfa009bSJomo         let mut vm_flags = VmFlags::VM_NONE;
1644cfa009bSJomo 
1654cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_READ) {
1664cfa009bSJomo             vm_flags |= VmFlags::VM_READ;
1674cfa009bSJomo         }
1684cfa009bSJomo 
1694cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_WRITE) {
1704cfa009bSJomo             vm_flags |= VmFlags::VM_WRITE;
1714cfa009bSJomo         }
1724cfa009bSJomo 
1734cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_EXEC) {
1744cfa009bSJomo             vm_flags |= VmFlags::VM_EXEC;
1754cfa009bSJomo         }
1764cfa009bSJomo 
1774cfa009bSJomo         vm_flags
1784cfa009bSJomo     }
1794cfa009bSJomo }
1804cfa009bSJomo 
1816fc066acSJomo impl From<ShmFlags> for VmFlags {
1826fc066acSJomo     fn from(shm_flags: ShmFlags) -> Self {
1836fc066acSJomo         let mut vm_flags = VmFlags::VM_NONE;
1846fc066acSJomo 
1856fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_RDONLY) {
1866fc066acSJomo             vm_flags |= VmFlags::VM_READ;
1876fc066acSJomo         } else {
1886fc066acSJomo             vm_flags |= VmFlags::VM_READ | VmFlags::VM_WRITE;
1896fc066acSJomo         }
1906fc066acSJomo 
1916fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_EXEC) {
1926fc066acSJomo             vm_flags |= VmFlags::VM_EXEC;
1936fc066acSJomo         }
1946fc066acSJomo 
1956fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_HUGETLB) {
1966fc066acSJomo             vm_flags |= VmFlags::VM_HUGETLB;
1976fc066acSJomo         }
1986fc066acSJomo 
1996fc066acSJomo         vm_flags
2006fc066acSJomo     }
2016fc066acSJomo }
2026fc066acSJomo 
203b5b571e0SLoGin impl From<VmFlags> for MapFlags {
204b5b571e0SLoGin     fn from(value: VmFlags) -> Self {
2054cfa009bSJomo         let mut map_flags = MapFlags::MAP_NONE;
2064cfa009bSJomo 
207b5b571e0SLoGin         if value.contains(VmFlags::VM_GROWSDOWN) {
2084cfa009bSJomo             map_flags |= MapFlags::MAP_GROWSDOWN;
2094cfa009bSJomo         }
2104cfa009bSJomo 
211b5b571e0SLoGin         if value.contains(VmFlags::VM_LOCKED) {
2124cfa009bSJomo             map_flags |= MapFlags::MAP_LOCKED;
2134cfa009bSJomo         }
2144cfa009bSJomo 
215b5b571e0SLoGin         if value.contains(VmFlags::VM_SYNC) {
2164cfa009bSJomo             map_flags |= MapFlags::MAP_SYNC;
2174cfa009bSJomo         }
2184cfa009bSJomo 
219b5b571e0SLoGin         if value.contains(VmFlags::VM_MAYSHARE) {
2203055390cSJomo             map_flags |= MapFlags::MAP_SHARED;
2213055390cSJomo         }
2223055390cSJomo 
2234cfa009bSJomo         map_flags
2244cfa009bSJomo     }
2254cfa009bSJomo }
2264cfa009bSJomo 
227b5b571e0SLoGin impl From<VmFlags> for ProtFlags {
228b5b571e0SLoGin     fn from(value: VmFlags) -> Self {
2294cfa009bSJomo         let mut prot_flags = ProtFlags::PROT_NONE;
2304cfa009bSJomo 
231b5b571e0SLoGin         if value.contains(VmFlags::VM_READ) {
2324cfa009bSJomo             prot_flags |= ProtFlags::PROT_READ;
2334cfa009bSJomo         }
2344cfa009bSJomo 
235b5b571e0SLoGin         if value.contains(VmFlags::VM_WRITE) {
2364cfa009bSJomo             prot_flags |= ProtFlags::PROT_WRITE;
2374cfa009bSJomo         }
2384cfa009bSJomo 
239b5b571e0SLoGin         if value.contains(VmFlags::VM_EXEC) {
2404cfa009bSJomo             prot_flags |= ProtFlags::PROT_EXEC;
2414cfa009bSJomo         }
2424cfa009bSJomo 
2434cfa009bSJomo         prot_flags
24440fe15e0SLoGin     }
24540fe15e0SLoGin }
24640fe15e0SLoGin 
247ab5c8ca4Slogin impl Syscall {
24840fe15e0SLoGin     pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
249*2eab6dd7S曾俊         // debug!("brk: new_addr={:?}", new_addr);
25040fe15e0SLoGin         let address_space = AddressSpace::current()?;
25140fe15e0SLoGin         let mut address_space = address_space.write();
25240fe15e0SLoGin 
2536d81180bSLoGin         if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
2546d81180bSLoGin             return Ok(address_space.brk);
2556d81180bSLoGin         }
2566d81180bSLoGin         if new_addr == address_space.brk {
2576d81180bSLoGin             return Ok(address_space.brk);
2586d81180bSLoGin         }
2596d81180bSLoGin 
26040fe15e0SLoGin         unsafe {
26140fe15e0SLoGin             address_space
26240fe15e0SLoGin                 .set_brk(VirtAddr::new(page_align_up(new_addr.data())))
26340fe15e0SLoGin                 .ok();
26440fe15e0SLoGin 
26540fe15e0SLoGin             return Ok(address_space.sbrk(0).unwrap());
266ab5c8ca4Slogin         }
267d8ad0a5eSLoGin     }
268d8ad0a5eSLoGin 
26940fe15e0SLoGin     pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
27040fe15e0SLoGin         let address_space = AddressSpace::current()?;
2711496ba7bSLoGin         assert!(address_space.read().user_mapper.utable.is_current());
27240fe15e0SLoGin         let mut address_space = address_space.write();
27340fe15e0SLoGin         let r = unsafe { address_space.sbrk(incr) };
27440fe15e0SLoGin 
27540fe15e0SLoGin         return r;
276d8ad0a5eSLoGin     }
277d8ad0a5eSLoGin 
27840fe15e0SLoGin     /// ## mmap系统调用
279d8ad0a5eSLoGin     ///
28040fe15e0SLoGin     /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
28140fe15e0SLoGin     ///
28240fe15e0SLoGin     /// ## 参数
28340fe15e0SLoGin     ///
28440fe15e0SLoGin     /// - `start_vaddr`:映射的起始地址
28540fe15e0SLoGin     /// - `len`:映射的长度
28640fe15e0SLoGin     /// - `prot`:保护标志
28740fe15e0SLoGin     /// - `flags`:映射标志
28840fe15e0SLoGin     /// - `fd`:文件描述符(暂时不支持)
28940fe15e0SLoGin     /// - `offset`:文件偏移量 (暂时不支持)
29040fe15e0SLoGin     ///
29140fe15e0SLoGin     /// ## 返回值
29240fe15e0SLoGin     ///
29340fe15e0SLoGin     /// 成功时返回映射的起始地址,失败时返回错误码
29440fe15e0SLoGin     pub fn mmap(
29540fe15e0SLoGin         start_vaddr: VirtAddr,
29640fe15e0SLoGin         len: usize,
29740fe15e0SLoGin         prot_flags: usize,
29840fe15e0SLoGin         map_flags: usize,
29940fe15e0SLoGin         _fd: i32,
30040fe15e0SLoGin         _offset: usize,
30140fe15e0SLoGin     ) -> Result<usize, SystemError> {
30240fe15e0SLoGin         let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
30340fe15e0SLoGin         let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
30440fe15e0SLoGin 
30540fe15e0SLoGin         if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
30640fe15e0SLoGin             && map_flags.contains(MapFlags::MAP_FIXED)
30740fe15e0SLoGin         {
308*2eab6dd7S曾俊             error!(
30940fe15e0SLoGin                 "mmap: MAP_FIXED is not supported for address below {}",
31040fe15e0SLoGin                 DEFAULT_MMAP_MIN_ADDR
31140fe15e0SLoGin             );
31240fe15e0SLoGin             return Err(SystemError::EINVAL);
313d8ad0a5eSLoGin         }
31440fe15e0SLoGin         // 暂时不支持除匿名页以外的映射
31540fe15e0SLoGin         if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
316*2eab6dd7S曾俊             error!("mmap: not support file mapping");
3171074eb34SSamuel Dai             return Err(SystemError::ENOSYS);
31840fe15e0SLoGin         }
31940fe15e0SLoGin 
32040fe15e0SLoGin         // 暂时不支持巨页映射
32140fe15e0SLoGin         if map_flags.contains(MapFlags::MAP_HUGETLB) {
322*2eab6dd7S曾俊             error!("mmap: not support huge page mapping");
3231074eb34SSamuel Dai             return Err(SystemError::ENOSYS);
32440fe15e0SLoGin         }
32540fe15e0SLoGin         let current_address_space = AddressSpace::current()?;
32640fe15e0SLoGin         let start_page = current_address_space.write().map_anonymous(
32740fe15e0SLoGin             start_vaddr,
32840fe15e0SLoGin             len,
32940fe15e0SLoGin             prot_flags,
33040fe15e0SLoGin             map_flags,
33140fe15e0SLoGin             true,
332a17651b1SMemoryShore             true,
33340fe15e0SLoGin         )?;
33440fe15e0SLoGin         return Ok(start_page.virt_address().data());
33540fe15e0SLoGin     }
33640fe15e0SLoGin 
3374cfa009bSJomo     /// ## mremap系统调用
3384cfa009bSJomo     ///
3394cfa009bSJomo     ///
3404cfa009bSJomo     /// ## 参数
3414cfa009bSJomo     ///
3424cfa009bSJomo     /// - `old_vaddr`:原映射的起始地址
3434cfa009bSJomo     /// - `old_len`:原映射的长度
3444cfa009bSJomo     /// - `new_len`:重新映射的长度
3454cfa009bSJomo     /// - `mremap_flags`:重映射标志
3464cfa009bSJomo     /// - `new_vaddr`:重新映射的起始地址
3474cfa009bSJomo     ///
3484cfa009bSJomo     /// ## 返回值
3494cfa009bSJomo     ///
3504cfa009bSJomo     /// 成功时返回重映射的起始地址,失败时返回错误码
3514cfa009bSJomo     pub fn mremap(
3524cfa009bSJomo         old_vaddr: VirtAddr,
3534cfa009bSJomo         old_len: usize,
3544cfa009bSJomo         new_len: usize,
3554cfa009bSJomo         mremap_flags: MremapFlags,
3564cfa009bSJomo         new_vaddr: VirtAddr,
3574cfa009bSJomo     ) -> Result<usize, SystemError> {
3584cfa009bSJomo         // 需要重映射到新内存区域的情况下,必须包含MREMAP_MAYMOVE并且指定新地址
3594cfa009bSJomo         if mremap_flags.contains(MremapFlags::MREMAP_FIXED)
3604cfa009bSJomo             && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE)
3614cfa009bSJomo                 || new_vaddr == VirtAddr::new(0))
3624cfa009bSJomo         {
3634cfa009bSJomo             return Err(SystemError::EINVAL);
3644cfa009bSJomo         }
3654cfa009bSJomo 
3664cfa009bSJomo         // 不取消旧映射的情况下,必须包含MREMAP_MAYMOVE并且新内存大小等于旧内存大小
3674cfa009bSJomo         if mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP)
3684cfa009bSJomo             && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) || old_len != new_len)
3694cfa009bSJomo         {
3704cfa009bSJomo             return Err(SystemError::EINVAL);
3714cfa009bSJomo         }
3724cfa009bSJomo 
3734cfa009bSJomo         // 旧内存地址必须对齐
3744cfa009bSJomo         if !old_vaddr.check_aligned(MMArch::PAGE_SIZE) {
3754cfa009bSJomo             return Err(SystemError::EINVAL);
3764cfa009bSJomo         }
3774cfa009bSJomo 
3784cfa009bSJomo         // 将old_len、new_len 对齐页面大小
3794cfa009bSJomo         let old_len = page_align_up(old_len);
3804cfa009bSJomo         let new_len = page_align_up(new_len);
3814cfa009bSJomo 
3824cfa009bSJomo         // 不允许重映射内存区域大小为0
3834cfa009bSJomo         if new_len == 0 {
3844cfa009bSJomo             return Err(SystemError::EINVAL);
3854cfa009bSJomo         }
3864cfa009bSJomo 
3874cfa009bSJomo         let current_address_space = AddressSpace::current()?;
3884cfa009bSJomo         let vma = current_address_space.read().mappings.contains(old_vaddr);
3894cfa009bSJomo         if vma.is_none() {
3904cfa009bSJomo             return Err(SystemError::EINVAL);
3914cfa009bSJomo         }
3924cfa009bSJomo         let vma = vma.unwrap();
393b5b571e0SLoGin         let vm_flags = *vma.lock().vm_flags();
3944cfa009bSJomo 
3954cfa009bSJomo         // 暂时不支持巨页映射
3964cfa009bSJomo         if vm_flags.contains(VmFlags::VM_HUGETLB) {
397*2eab6dd7S曾俊             error!("mmap: not support huge page mapping");
3984cfa009bSJomo             return Err(SystemError::ENOSYS);
3994cfa009bSJomo         }
4004cfa009bSJomo 
4014cfa009bSJomo         // 缩小旧内存映射区域
4024cfa009bSJomo         if old_len > new_len {
4034cfa009bSJomo             Self::munmap(old_vaddr + new_len, old_len - new_len)?;
4044cfa009bSJomo             return Ok(old_vaddr.data());
4054cfa009bSJomo         }
4064cfa009bSJomo 
4074cfa009bSJomo         // 重映射到新内存区域
4084cfa009bSJomo         let r = current_address_space.write().mremap(
4094cfa009bSJomo             old_vaddr,
4104cfa009bSJomo             old_len,
4114cfa009bSJomo             new_len,
4124cfa009bSJomo             mremap_flags,
4134cfa009bSJomo             new_vaddr,
4144cfa009bSJomo             vm_flags,
4154cfa009bSJomo         )?;
4164cfa009bSJomo 
4174cfa009bSJomo         if !mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) {
4184cfa009bSJomo             Self::munmap(old_vaddr, old_len)?;
4194cfa009bSJomo         }
4204cfa009bSJomo 
4214cfa009bSJomo         return Ok(r.data());
4224cfa009bSJomo     }
4234cfa009bSJomo 
42440fe15e0SLoGin     /// ## munmap系统调用
42540fe15e0SLoGin     ///
42640fe15e0SLoGin     /// ## 参数
42740fe15e0SLoGin     ///
42840fe15e0SLoGin     /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
42940fe15e0SLoGin     /// - `len`:取消映射的字节数(已经对齐到页)
43040fe15e0SLoGin     ///
43140fe15e0SLoGin     /// ## 返回值
43240fe15e0SLoGin     ///
43340fe15e0SLoGin     /// 成功时返回0,失败时返回错误码
43440fe15e0SLoGin     pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
43540fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
43640fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
43740fe15e0SLoGin 
43840fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
43940fe15e0SLoGin             return Err(SystemError::EINVAL);
44040fe15e0SLoGin         }
44140fe15e0SLoGin         if unlikely(len == 0) {
44240fe15e0SLoGin             return Err(SystemError::EINVAL);
44340fe15e0SLoGin         }
44440fe15e0SLoGin 
44540fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
44640fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
44740fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
44840fe15e0SLoGin 
44940fe15e0SLoGin         current_address_space
45040fe15e0SLoGin             .write()
45140fe15e0SLoGin             .munmap(start_frame, page_count)
45240fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
4534cfa009bSJomo 
45440fe15e0SLoGin         return Ok(0);
45540fe15e0SLoGin     }
45640fe15e0SLoGin 
45740fe15e0SLoGin     /// ## mprotect系统调用
45840fe15e0SLoGin     ///
45940fe15e0SLoGin     /// ## 参数
46040fe15e0SLoGin     ///
46140fe15e0SLoGin     /// - `start_vaddr`:起始地址(已经对齐到页)
46240fe15e0SLoGin     /// - `len`:长度(已经对齐到页)
46340fe15e0SLoGin     /// - `prot_flags`:保护标志
46440fe15e0SLoGin     pub fn mprotect(
46540fe15e0SLoGin         start_vaddr: VirtAddr,
46640fe15e0SLoGin         len: usize,
46740fe15e0SLoGin         prot_flags: usize,
46840fe15e0SLoGin     ) -> Result<usize, SystemError> {
46940fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
47040fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
47140fe15e0SLoGin 
47240fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
47340fe15e0SLoGin             return Err(SystemError::EINVAL);
47440fe15e0SLoGin         }
47540fe15e0SLoGin         if unlikely(len == 0) {
47640fe15e0SLoGin             return Err(SystemError::EINVAL);
47740fe15e0SLoGin         }
47840fe15e0SLoGin 
47940fe15e0SLoGin         let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
48040fe15e0SLoGin 
48140fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
48240fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
48340fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
48440fe15e0SLoGin 
48540fe15e0SLoGin         current_address_space
48640fe15e0SLoGin             .write()
48740fe15e0SLoGin             .mprotect(start_frame, page_count, prot_flags)
48840fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
48940fe15e0SLoGin         return Ok(0);
490ab5c8ca4Slogin     }
491a17651b1SMemoryShore 
492a17651b1SMemoryShore     /// ## madvise系统调用
493a17651b1SMemoryShore     ///
494a17651b1SMemoryShore     /// ## 参数
495a17651b1SMemoryShore     ///
496a17651b1SMemoryShore     /// - `start_vaddr`:起始地址(已经对齐到页)
497a17651b1SMemoryShore     /// - `len`:长度(已经对齐到页)
498a17651b1SMemoryShore     /// - `madv_flags`:建议标志
499a17651b1SMemoryShore     pub fn madvise(
500a17651b1SMemoryShore         start_vaddr: VirtAddr,
501a17651b1SMemoryShore         len: usize,
502a17651b1SMemoryShore         madv_flags: usize,
503a17651b1SMemoryShore     ) -> Result<usize, SystemError> {
504a17651b1SMemoryShore         if !start_vaddr.check_aligned(MMArch::PAGE_SIZE) || !check_aligned(len, MMArch::PAGE_SIZE) {
505a17651b1SMemoryShore             return Err(SystemError::EINVAL);
506a17651b1SMemoryShore         }
507a17651b1SMemoryShore 
508a17651b1SMemoryShore         if unlikely(verify_area(start_vaddr, len).is_err()) {
509a17651b1SMemoryShore             return Err(SystemError::EINVAL);
510a17651b1SMemoryShore         }
511a17651b1SMemoryShore         if unlikely(len == 0) {
512a17651b1SMemoryShore             return Err(SystemError::EINVAL);
513a17651b1SMemoryShore         }
514a17651b1SMemoryShore 
515a17651b1SMemoryShore         let madv_flags = MadvFlags::from_bits(madv_flags as u64).ok_or(SystemError::EINVAL)?;
516a17651b1SMemoryShore 
517a17651b1SMemoryShore         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
518a17651b1SMemoryShore         let start_frame = VirtPageFrame::new(start_vaddr);
519a17651b1SMemoryShore         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
520a17651b1SMemoryShore 
521a17651b1SMemoryShore         current_address_space
522a17651b1SMemoryShore             .write()
523a17651b1SMemoryShore             .madvise(start_frame, page_count, madv_flags)
524a17651b1SMemoryShore             .map_err(|_| SystemError::EINVAL)?;
525a17651b1SMemoryShore         return Ok(0);
526a17651b1SMemoryShore     }
527ab5c8ca4Slogin }
528