xref: /DragonOS/kernel/src/mm/syscall.rs (revision cf7f801e1d50ee5b04cb728e4251a57f4183bfbc)
1*cf7f801eSMemoryShore use core::{intrinsics::unlikely, slice::from_raw_parts};
240fe15e0SLoGin 
340fe15e0SLoGin use alloc::sync::Arc;
42eab6dd7S曾俊 use log::error;
591e9d4abSLoGin use system_error::SystemError;
640fe15e0SLoGin 
7ab5c8ca4Slogin use crate::{
840fe15e0SLoGin     arch::MMArch,
9*cf7f801eSMemoryShore     driver::base::block::SeekFrom,
106fc066acSJomo     ipc::shm::ShmFlags,
1140fe15e0SLoGin     libs::align::{check_aligned, page_align_up},
1240fe15e0SLoGin     mm::MemoryManagementArch,
1391e9d4abSLoGin     syscall::Syscall,
14ab5c8ca4Slogin };
15ab5c8ca4Slogin 
1640fe15e0SLoGin use super::{
1740fe15e0SLoGin     allocator::page_frame::{PageFrameCount, VirtPageFrame},
1840fe15e0SLoGin     ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
19*cf7f801eSMemoryShore     verify_area, MsFlags, VirtAddr, VmFlags,
2040fe15e0SLoGin };
2140fe15e0SLoGin 
2240fe15e0SLoGin bitflags! {
2340fe15e0SLoGin     /// Memory protection flags
2440fe15e0SLoGin     pub struct ProtFlags: u64 {
2540fe15e0SLoGin         const PROT_NONE = 0x0;
2640fe15e0SLoGin         const PROT_READ = 0x1;
2740fe15e0SLoGin         const PROT_WRITE = 0x2;
2840fe15e0SLoGin         const PROT_EXEC = 0x4;
29ab5c8ca4Slogin     }
3040fe15e0SLoGin 
3140fe15e0SLoGin     /// Memory mapping flags
3240fe15e0SLoGin     pub struct MapFlags: u64 {
3340fe15e0SLoGin         const MAP_NONE = 0x0;
3440fe15e0SLoGin         /// share changes
3540fe15e0SLoGin         const MAP_SHARED = 0x1;
3640fe15e0SLoGin         /// changes are private
3740fe15e0SLoGin         const MAP_PRIVATE = 0x2;
3840fe15e0SLoGin         /// Interpret addr exactly
3940fe15e0SLoGin         const MAP_FIXED = 0x10;
4040fe15e0SLoGin         /// don't use a file
4140fe15e0SLoGin         const MAP_ANONYMOUS = 0x20;
4240fe15e0SLoGin         // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
4340fe15e0SLoGin         /// stack-like segment
4440fe15e0SLoGin         const MAP_GROWSDOWN = 0x100;
4540fe15e0SLoGin         /// ETXTBSY
4640fe15e0SLoGin         const MAP_DENYWRITE = 0x800;
4740fe15e0SLoGin         /// Mark it as an executable
4840fe15e0SLoGin         const MAP_EXECUTABLE = 0x1000;
4940fe15e0SLoGin         /// Pages are locked
5040fe15e0SLoGin         const MAP_LOCKED = 0x2000;
5140fe15e0SLoGin         /// don't check for reservations
5240fe15e0SLoGin         const MAP_NORESERVE = 0x4000;
5340fe15e0SLoGin         /// populate (prefault) pagetables
5440fe15e0SLoGin         const MAP_POPULATE = 0x8000;
5540fe15e0SLoGin         /// do not block on IO
5640fe15e0SLoGin         const MAP_NONBLOCK = 0x10000;
5740fe15e0SLoGin         /// give out an address that is best suited for process/thread stacks
5840fe15e0SLoGin         const MAP_STACK = 0x20000;
5940fe15e0SLoGin         /// create a huge page mapping
6040fe15e0SLoGin         const MAP_HUGETLB = 0x40000;
6140fe15e0SLoGin         /// perform synchronous page faults for the mapping
6240fe15e0SLoGin         const MAP_SYNC = 0x80000;
6340fe15e0SLoGin         /// MAP_FIXED which doesn't unmap underlying mapping
6440fe15e0SLoGin         const MAP_FIXED_NOREPLACE = 0x100000;
6540fe15e0SLoGin 
6640fe15e0SLoGin         /// For anonymous mmap, memory could be uninitialized
6740fe15e0SLoGin         const MAP_UNINITIALIZED = 0x4000000;
684cfa009bSJomo     }
6940fe15e0SLoGin 
704cfa009bSJomo     /// Memory mremapping flags
714cfa009bSJomo     pub struct MremapFlags: u8 {
724cfa009bSJomo         const MREMAP_MAYMOVE = 1;
734cfa009bSJomo         const MREMAP_FIXED = 2;
744cfa009bSJomo         const MREMAP_DONTUNMAP = 4;
754cfa009bSJomo     }
76a17651b1SMemoryShore 
77a17651b1SMemoryShore 
78a17651b1SMemoryShore     pub struct MadvFlags: u64 {
79a17651b1SMemoryShore         /// 默认行为,系统会进行一定的预读和预写,适用于一般读取场景
80a17651b1SMemoryShore         const MADV_NORMAL = 0;
81a17651b1SMemoryShore         /// 随机访问模式,系统会尽量最小化数据读取量,适用于随机访问的场景
82a17651b1SMemoryShore         const MADV_RANDOM = 1;
83a17651b1SMemoryShore         /// 顺序访问模式,系统会进行积极的预读,访问后的页面可以尽快释放,适用于顺序读取场景
84a17651b1SMemoryShore         const MADV_SEQUENTIAL = 2;
85a17651b1SMemoryShore         /// 通知系统预读某些页面,用于应用程序提前准备数据
86a17651b1SMemoryShore         const MADV_WILLNEED = 3;
87a17651b1SMemoryShore         /// 通知系统应用程序不再需要某些页面,内核可以释放相关资源
88a17651b1SMemoryShore         const MADV_DONTNEED = 4;
89a17651b1SMemoryShore 
90a17651b1SMemoryShore         /// 将指定范围的页面标记为延迟释放,真正的释放会延迟至内存压力发生时
91a17651b1SMemoryShore         const MADV_FREE = 8;
92a17651b1SMemoryShore         /// 应用程序请求释放指定范围的页面和相关的后备存储
93a17651b1SMemoryShore         const MADV_REMOVE = 9;
94a17651b1SMemoryShore         /// 在 fork 时排除指定区域
95a17651b1SMemoryShore         const MADV_DONTFORK = 10;
96a17651b1SMemoryShore         /// 取消 MADV_DONTFORK 的效果,不再在 fork 时排除指定区域
97a17651b1SMemoryShore         const MADV_DOFORK = 11;
98a17651b1SMemoryShore         /// 模拟内存硬件错误,触发内存错误处理器处理
99a17651b1SMemoryShore         const MADV_HWPOISON = 100;
100a17651b1SMemoryShore         /// 尝试软下线指定的内存范围
101a17651b1SMemoryShore         const MADV_SOFT_OFFLINE = 101;
102a17651b1SMemoryShore 
103a17651b1SMemoryShore         /// 应用程序建议内核尝试合并指定范围内内容相同的页面
104a17651b1SMemoryShore         const MADV_MERGEABLE = 12;
105a17651b1SMemoryShore         /// 取消 MADV_MERGEABLE 的效果,不再合并页面
106a17651b1SMemoryShore         const MADV_UNMERGEABLE = 13;
107a17651b1SMemoryShore 
108a17651b1SMemoryShore         /// 应用程序希望将指定范围以透明大页方式支持
109a17651b1SMemoryShore         const MADV_HUGEPAGE = 14;
110a17651b1SMemoryShore         /// 将指定范围标记为不值得用透明大页支持
111a17651b1SMemoryShore         const MADV_NOHUGEPAGE = 15;
112a17651b1SMemoryShore 
113a17651b1SMemoryShore         /// 应用程序请求在核心转储时排除指定范围内的页面
114a17651b1SMemoryShore         const MADV_DONTDUMP = 16;
115a17651b1SMemoryShore         /// 取消 MADV_DONTDUMP 的效果,不再排除核心转储时的页面
116a17651b1SMemoryShore         const MADV_DODUMP = 17;
117a17651b1SMemoryShore 
118a17651b1SMemoryShore         /// 在 fork 时将子进程的该区域内存填充为零
119a17651b1SMemoryShore         const MADV_WIPEONFORK = 18;
120a17651b1SMemoryShore         /// 取消 `MADV_WIPEONFORK` 的效果,不再在 fork 时填充子进程的内存
121a17651b1SMemoryShore         const MADV_KEEPONFORK = 19;
122a17651b1SMemoryShore 
123a17651b1SMemoryShore         /// 应用程序不会立刻使用这些内存,内核将页面设置为非活动状态以便在内存压力发生时轻松回收
124a17651b1SMemoryShore         const MADV_COLD = 20;
125a17651b1SMemoryShore         /// 应用程序不会立刻使用这些内存,内核立即将这些页面换出
126a17651b1SMemoryShore         const MADV_PAGEOUT = 21;
127a17651b1SMemoryShore 
128a17651b1SMemoryShore         /// 预先填充页面表,可读,通过触发读取故障
129a17651b1SMemoryShore         const MADV_POPULATE_READ = 22;
130a17651b1SMemoryShore         /// 预先填充页面表,可写,通过触发写入故障
131a17651b1SMemoryShore         const MADV_POPULATE_WRITE = 23;
132a17651b1SMemoryShore 
133a17651b1SMemoryShore         /// 与 `MADV_DONTNEED` 类似,会将被锁定的页面释放
134a17651b1SMemoryShore         const MADV_DONTNEED_LOCKED = 24;
135a17651b1SMemoryShore 
136a17651b1SMemoryShore         /// 同步将页面合并为新的透明大页
137a17651b1SMemoryShore         const MADV_COLLAPSE = 25;
138a17651b1SMemoryShore 
139a17651b1SMemoryShore     }
1404cfa009bSJomo }
1414cfa009bSJomo 
1424cfa009bSJomo impl From<MapFlags> for VmFlags {
from(map_flags: MapFlags) -> Self1434cfa009bSJomo     fn from(map_flags: MapFlags) -> Self {
1444cfa009bSJomo         let mut vm_flags = VmFlags::VM_NONE;
1454cfa009bSJomo 
1464cfa009bSJomo         if map_flags.contains(MapFlags::MAP_GROWSDOWN) {
1474cfa009bSJomo             vm_flags |= VmFlags::VM_GROWSDOWN;
1484cfa009bSJomo         }
1494cfa009bSJomo 
1504cfa009bSJomo         if map_flags.contains(MapFlags::MAP_LOCKED) {
1514cfa009bSJomo             vm_flags |= VmFlags::VM_LOCKED;
1524cfa009bSJomo         }
1534cfa009bSJomo 
1544cfa009bSJomo         if map_flags.contains(MapFlags::MAP_SYNC) {
1554cfa009bSJomo             vm_flags |= VmFlags::VM_SYNC;
1564cfa009bSJomo         }
1574cfa009bSJomo 
158*cf7f801eSMemoryShore         if map_flags.contains(MapFlags::MAP_SHARED) {
159*cf7f801eSMemoryShore             vm_flags |= VmFlags::VM_SHARED;
160*cf7f801eSMemoryShore         }
161*cf7f801eSMemoryShore 
1624cfa009bSJomo         vm_flags
1634cfa009bSJomo     }
1644cfa009bSJomo }
1654cfa009bSJomo 
1664cfa009bSJomo impl From<ProtFlags> for VmFlags {
from(prot_flags: ProtFlags) -> Self1674cfa009bSJomo     fn from(prot_flags: ProtFlags) -> Self {
1684cfa009bSJomo         let mut vm_flags = VmFlags::VM_NONE;
1694cfa009bSJomo 
1704cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_READ) {
1714cfa009bSJomo             vm_flags |= VmFlags::VM_READ;
1724cfa009bSJomo         }
1734cfa009bSJomo 
1744cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_WRITE) {
1754cfa009bSJomo             vm_flags |= VmFlags::VM_WRITE;
1764cfa009bSJomo         }
1774cfa009bSJomo 
1784cfa009bSJomo         if prot_flags.contains(ProtFlags::PROT_EXEC) {
1794cfa009bSJomo             vm_flags |= VmFlags::VM_EXEC;
1804cfa009bSJomo         }
1814cfa009bSJomo 
1824cfa009bSJomo         vm_flags
1834cfa009bSJomo     }
1844cfa009bSJomo }
1854cfa009bSJomo 
1866fc066acSJomo impl From<ShmFlags> for VmFlags {
from(shm_flags: ShmFlags) -> Self1876fc066acSJomo     fn from(shm_flags: ShmFlags) -> Self {
1886fc066acSJomo         let mut vm_flags = VmFlags::VM_NONE;
1896fc066acSJomo 
1906fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_RDONLY) {
1916fc066acSJomo             vm_flags |= VmFlags::VM_READ;
1926fc066acSJomo         } else {
1936fc066acSJomo             vm_flags |= VmFlags::VM_READ | VmFlags::VM_WRITE;
1946fc066acSJomo         }
1956fc066acSJomo 
1966fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_EXEC) {
1976fc066acSJomo             vm_flags |= VmFlags::VM_EXEC;
1986fc066acSJomo         }
1996fc066acSJomo 
2006fc066acSJomo         if shm_flags.contains(ShmFlags::SHM_HUGETLB) {
2016fc066acSJomo             vm_flags |= VmFlags::VM_HUGETLB;
2026fc066acSJomo         }
2036fc066acSJomo 
2046fc066acSJomo         vm_flags
2056fc066acSJomo     }
2066fc066acSJomo }
2076fc066acSJomo 
208b5b571e0SLoGin impl From<VmFlags> for MapFlags {
from(value: VmFlags) -> Self209b5b571e0SLoGin     fn from(value: VmFlags) -> Self {
2104cfa009bSJomo         let mut map_flags = MapFlags::MAP_NONE;
2114cfa009bSJomo 
212b5b571e0SLoGin         if value.contains(VmFlags::VM_GROWSDOWN) {
2134cfa009bSJomo             map_flags |= MapFlags::MAP_GROWSDOWN;
2144cfa009bSJomo         }
2154cfa009bSJomo 
216b5b571e0SLoGin         if value.contains(VmFlags::VM_LOCKED) {
2174cfa009bSJomo             map_flags |= MapFlags::MAP_LOCKED;
2184cfa009bSJomo         }
2194cfa009bSJomo 
220b5b571e0SLoGin         if value.contains(VmFlags::VM_SYNC) {
2214cfa009bSJomo             map_flags |= MapFlags::MAP_SYNC;
2224cfa009bSJomo         }
2234cfa009bSJomo 
224b5b571e0SLoGin         if value.contains(VmFlags::VM_MAYSHARE) {
2253055390cSJomo             map_flags |= MapFlags::MAP_SHARED;
2263055390cSJomo         }
2273055390cSJomo 
2284cfa009bSJomo         map_flags
2294cfa009bSJomo     }
2304cfa009bSJomo }
2314cfa009bSJomo 
232b5b571e0SLoGin impl From<VmFlags> for ProtFlags {
from(value: VmFlags) -> Self233b5b571e0SLoGin     fn from(value: VmFlags) -> Self {
2344cfa009bSJomo         let mut prot_flags = ProtFlags::PROT_NONE;
2354cfa009bSJomo 
236b5b571e0SLoGin         if value.contains(VmFlags::VM_READ) {
2374cfa009bSJomo             prot_flags |= ProtFlags::PROT_READ;
2384cfa009bSJomo         }
2394cfa009bSJomo 
240b5b571e0SLoGin         if value.contains(VmFlags::VM_WRITE) {
2414cfa009bSJomo             prot_flags |= ProtFlags::PROT_WRITE;
2424cfa009bSJomo         }
2434cfa009bSJomo 
244b5b571e0SLoGin         if value.contains(VmFlags::VM_EXEC) {
2454cfa009bSJomo             prot_flags |= ProtFlags::PROT_EXEC;
2464cfa009bSJomo         }
2474cfa009bSJomo 
2484cfa009bSJomo         prot_flags
24940fe15e0SLoGin     }
25040fe15e0SLoGin }
25140fe15e0SLoGin 
252ab5c8ca4Slogin impl Syscall {
brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError>25340fe15e0SLoGin     pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
2542eab6dd7S曾俊         // debug!("brk: new_addr={:?}", new_addr);
25540fe15e0SLoGin         let address_space = AddressSpace::current()?;
25640fe15e0SLoGin         let mut address_space = address_space.write();
25740fe15e0SLoGin 
2586d81180bSLoGin         if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
2596d81180bSLoGin             return Ok(address_space.brk);
2606d81180bSLoGin         }
2616d81180bSLoGin         if new_addr == address_space.brk {
2626d81180bSLoGin             return Ok(address_space.brk);
2636d81180bSLoGin         }
2646d81180bSLoGin 
26540fe15e0SLoGin         unsafe {
26640fe15e0SLoGin             address_space
26740fe15e0SLoGin                 .set_brk(VirtAddr::new(page_align_up(new_addr.data())))
26840fe15e0SLoGin                 .ok();
26940fe15e0SLoGin 
27040fe15e0SLoGin             return Ok(address_space.sbrk(0).unwrap());
271ab5c8ca4Slogin         }
272d8ad0a5eSLoGin     }
273d8ad0a5eSLoGin 
sbrk(incr: isize) -> Result<VirtAddr, SystemError>27440fe15e0SLoGin     pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
27540fe15e0SLoGin         let address_space = AddressSpace::current()?;
2761496ba7bSLoGin         assert!(address_space.read().user_mapper.utable.is_current());
27740fe15e0SLoGin         let mut address_space = address_space.write();
27840fe15e0SLoGin         let r = unsafe { address_space.sbrk(incr) };
27940fe15e0SLoGin 
28040fe15e0SLoGin         return r;
281d8ad0a5eSLoGin     }
282d8ad0a5eSLoGin 
28340fe15e0SLoGin     /// ## mmap系统调用
284d8ad0a5eSLoGin     ///
28540fe15e0SLoGin     /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
28640fe15e0SLoGin     ///
28740fe15e0SLoGin     /// ## 参数
28840fe15e0SLoGin     ///
28940fe15e0SLoGin     /// - `start_vaddr`:映射的起始地址
29040fe15e0SLoGin     /// - `len`:映射的长度
29140fe15e0SLoGin     /// - `prot`:保护标志
29240fe15e0SLoGin     /// - `flags`:映射标志
29340fe15e0SLoGin     /// - `fd`:文件描述符(暂时不支持)
29440fe15e0SLoGin     /// - `offset`:文件偏移量 (暂时不支持)
29540fe15e0SLoGin     ///
29640fe15e0SLoGin     /// ## 返回值
29740fe15e0SLoGin     ///
29840fe15e0SLoGin     /// 成功时返回映射的起始地址,失败时返回错误码
mmap( start_vaddr: VirtAddr, len: usize, prot_flags: usize, map_flags: usize, fd: i32, offset: usize, ) -> Result<usize, SystemError>29940fe15e0SLoGin     pub fn mmap(
30040fe15e0SLoGin         start_vaddr: VirtAddr,
30140fe15e0SLoGin         len: usize,
30240fe15e0SLoGin         prot_flags: usize,
30340fe15e0SLoGin         map_flags: usize,
304*cf7f801eSMemoryShore         fd: i32,
305*cf7f801eSMemoryShore         offset: usize,
30640fe15e0SLoGin     ) -> Result<usize, SystemError> {
30740fe15e0SLoGin         let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
30840fe15e0SLoGin         let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
30940fe15e0SLoGin 
31040fe15e0SLoGin         if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
31140fe15e0SLoGin             && map_flags.contains(MapFlags::MAP_FIXED)
31240fe15e0SLoGin         {
3132eab6dd7S曾俊             error!(
31440fe15e0SLoGin                 "mmap: MAP_FIXED is not supported for address below {}",
31540fe15e0SLoGin                 DEFAULT_MMAP_MIN_ADDR
31640fe15e0SLoGin             );
31740fe15e0SLoGin             return Err(SystemError::EINVAL);
318d8ad0a5eSLoGin         }
31940fe15e0SLoGin 
32040fe15e0SLoGin         // 暂时不支持巨页映射
32140fe15e0SLoGin         if map_flags.contains(MapFlags::MAP_HUGETLB) {
3222eab6dd7S曾俊             error!("mmap: not support huge page mapping");
3231074eb34SSamuel Dai             return Err(SystemError::ENOSYS);
32440fe15e0SLoGin         }
32540fe15e0SLoGin         let current_address_space = AddressSpace::current()?;
326*cf7f801eSMemoryShore         let start_page = if map_flags.contains(MapFlags::MAP_ANONYMOUS) {
327*cf7f801eSMemoryShore             // 匿名映射
328*cf7f801eSMemoryShore             current_address_space.write().map_anonymous(
32940fe15e0SLoGin                 start_vaddr,
33040fe15e0SLoGin                 len,
33140fe15e0SLoGin                 prot_flags,
33240fe15e0SLoGin                 map_flags,
33340fe15e0SLoGin                 true,
334de199e3cSMemoryShore                 false,
335*cf7f801eSMemoryShore             )?
336*cf7f801eSMemoryShore         } else {
337*cf7f801eSMemoryShore             // 文件映射
338*cf7f801eSMemoryShore             current_address_space.write().file_mapping(
339*cf7f801eSMemoryShore                 start_vaddr,
340*cf7f801eSMemoryShore                 len,
341*cf7f801eSMemoryShore                 prot_flags,
342*cf7f801eSMemoryShore                 map_flags,
343*cf7f801eSMemoryShore                 fd,
344*cf7f801eSMemoryShore                 offset,
345*cf7f801eSMemoryShore                 true,
346*cf7f801eSMemoryShore                 false,
347*cf7f801eSMemoryShore             )?
348*cf7f801eSMemoryShore         };
349*cf7f801eSMemoryShore 
35040fe15e0SLoGin         return Ok(start_page.virt_address().data());
35140fe15e0SLoGin     }
35240fe15e0SLoGin 
3534cfa009bSJomo     /// ## mremap系统调用
3544cfa009bSJomo     ///
3554cfa009bSJomo     ///
3564cfa009bSJomo     /// ## 参数
3574cfa009bSJomo     ///
3584cfa009bSJomo     /// - `old_vaddr`:原映射的起始地址
3594cfa009bSJomo     /// - `old_len`:原映射的长度
3604cfa009bSJomo     /// - `new_len`:重新映射的长度
3614cfa009bSJomo     /// - `mremap_flags`:重映射标志
3624cfa009bSJomo     /// - `new_vaddr`:重新映射的起始地址
3634cfa009bSJomo     ///
3644cfa009bSJomo     /// ## 返回值
3654cfa009bSJomo     ///
3664cfa009bSJomo     /// 成功时返回重映射的起始地址,失败时返回错误码
mremap( old_vaddr: VirtAddr, old_len: usize, new_len: usize, mremap_flags: MremapFlags, new_vaddr: VirtAddr, ) -> Result<usize, SystemError>3674cfa009bSJomo     pub fn mremap(
3684cfa009bSJomo         old_vaddr: VirtAddr,
3694cfa009bSJomo         old_len: usize,
3704cfa009bSJomo         new_len: usize,
3714cfa009bSJomo         mremap_flags: MremapFlags,
3724cfa009bSJomo         new_vaddr: VirtAddr,
3734cfa009bSJomo     ) -> Result<usize, SystemError> {
3744cfa009bSJomo         // 需要重映射到新内存区域的情况下,必须包含MREMAP_MAYMOVE并且指定新地址
3754cfa009bSJomo         if mremap_flags.contains(MremapFlags::MREMAP_FIXED)
3764cfa009bSJomo             && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE)
3774cfa009bSJomo                 || new_vaddr == VirtAddr::new(0))
3784cfa009bSJomo         {
3794cfa009bSJomo             return Err(SystemError::EINVAL);
3804cfa009bSJomo         }
3814cfa009bSJomo 
3824cfa009bSJomo         // 不取消旧映射的情况下,必须包含MREMAP_MAYMOVE并且新内存大小等于旧内存大小
3834cfa009bSJomo         if mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP)
3844cfa009bSJomo             && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) || old_len != new_len)
3854cfa009bSJomo         {
3864cfa009bSJomo             return Err(SystemError::EINVAL);
3874cfa009bSJomo         }
3884cfa009bSJomo 
3894cfa009bSJomo         // 旧内存地址必须对齐
3904cfa009bSJomo         if !old_vaddr.check_aligned(MMArch::PAGE_SIZE) {
3914cfa009bSJomo             return Err(SystemError::EINVAL);
3924cfa009bSJomo         }
3934cfa009bSJomo 
3944cfa009bSJomo         // 将old_len、new_len 对齐页面大小
3954cfa009bSJomo         let old_len = page_align_up(old_len);
3964cfa009bSJomo         let new_len = page_align_up(new_len);
3974cfa009bSJomo 
3984cfa009bSJomo         // 不允许重映射内存区域大小为0
3994cfa009bSJomo         if new_len == 0 {
4004cfa009bSJomo             return Err(SystemError::EINVAL);
4014cfa009bSJomo         }
4024cfa009bSJomo 
4034cfa009bSJomo         let current_address_space = AddressSpace::current()?;
4044cfa009bSJomo         let vma = current_address_space.read().mappings.contains(old_vaddr);
4054cfa009bSJomo         if vma.is_none() {
4064cfa009bSJomo             return Err(SystemError::EINVAL);
4074cfa009bSJomo         }
4084cfa009bSJomo         let vma = vma.unwrap();
409*cf7f801eSMemoryShore         let vm_flags = *vma.lock_irqsave().vm_flags();
4104cfa009bSJomo 
4114cfa009bSJomo         // 暂时不支持巨页映射
4124cfa009bSJomo         if vm_flags.contains(VmFlags::VM_HUGETLB) {
4132eab6dd7S曾俊             error!("mmap: not support huge page mapping");
4144cfa009bSJomo             return Err(SystemError::ENOSYS);
4154cfa009bSJomo         }
4164cfa009bSJomo 
4174cfa009bSJomo         // 缩小旧内存映射区域
4184cfa009bSJomo         if old_len > new_len {
4194cfa009bSJomo             Self::munmap(old_vaddr + new_len, old_len - new_len)?;
4204cfa009bSJomo             return Ok(old_vaddr.data());
4214cfa009bSJomo         }
4224cfa009bSJomo 
4234cfa009bSJomo         // 重映射到新内存区域
4244cfa009bSJomo         let r = current_address_space.write().mremap(
4254cfa009bSJomo             old_vaddr,
4264cfa009bSJomo             old_len,
4274cfa009bSJomo             new_len,
4284cfa009bSJomo             mremap_flags,
4294cfa009bSJomo             new_vaddr,
4304cfa009bSJomo             vm_flags,
4314cfa009bSJomo         )?;
4324cfa009bSJomo 
4334cfa009bSJomo         if !mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) {
4344cfa009bSJomo             Self::munmap(old_vaddr, old_len)?;
4354cfa009bSJomo         }
4364cfa009bSJomo 
4374cfa009bSJomo         return Ok(r.data());
4384cfa009bSJomo     }
4394cfa009bSJomo 
44040fe15e0SLoGin     /// ## munmap系统调用
44140fe15e0SLoGin     ///
44240fe15e0SLoGin     /// ## 参数
44340fe15e0SLoGin     ///
44440fe15e0SLoGin     /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
44540fe15e0SLoGin     /// - `len`:取消映射的字节数(已经对齐到页)
44640fe15e0SLoGin     ///
44740fe15e0SLoGin     /// ## 返回值
44840fe15e0SLoGin     ///
44940fe15e0SLoGin     /// 成功时返回0,失败时返回错误码
munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError>45040fe15e0SLoGin     pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
45140fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
45240fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
45340fe15e0SLoGin 
45440fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
45540fe15e0SLoGin             return Err(SystemError::EINVAL);
45640fe15e0SLoGin         }
45740fe15e0SLoGin         if unlikely(len == 0) {
45840fe15e0SLoGin             return Err(SystemError::EINVAL);
45940fe15e0SLoGin         }
46040fe15e0SLoGin 
46140fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
46240fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
46340fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
46440fe15e0SLoGin 
46540fe15e0SLoGin         current_address_space
46640fe15e0SLoGin             .write()
46740fe15e0SLoGin             .munmap(start_frame, page_count)
46840fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
4694cfa009bSJomo 
47040fe15e0SLoGin         return Ok(0);
47140fe15e0SLoGin     }
47240fe15e0SLoGin 
47340fe15e0SLoGin     /// ## mprotect系统调用
47440fe15e0SLoGin     ///
47540fe15e0SLoGin     /// ## 参数
47640fe15e0SLoGin     ///
47740fe15e0SLoGin     /// - `start_vaddr`:起始地址(已经对齐到页)
47840fe15e0SLoGin     /// - `len`:长度(已经对齐到页)
47940fe15e0SLoGin     /// - `prot_flags`:保护标志
mprotect( start_vaddr: VirtAddr, len: usize, prot_flags: usize, ) -> Result<usize, SystemError>48040fe15e0SLoGin     pub fn mprotect(
48140fe15e0SLoGin         start_vaddr: VirtAddr,
48240fe15e0SLoGin         len: usize,
48340fe15e0SLoGin         prot_flags: usize,
48440fe15e0SLoGin     ) -> Result<usize, SystemError> {
48540fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
48640fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
48740fe15e0SLoGin 
48840fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
48940fe15e0SLoGin             return Err(SystemError::EINVAL);
49040fe15e0SLoGin         }
49140fe15e0SLoGin         if unlikely(len == 0) {
49240fe15e0SLoGin             return Err(SystemError::EINVAL);
49340fe15e0SLoGin         }
49440fe15e0SLoGin 
49540fe15e0SLoGin         let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
49640fe15e0SLoGin 
49740fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
49840fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
49940fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
50040fe15e0SLoGin 
50140fe15e0SLoGin         current_address_space
50240fe15e0SLoGin             .write()
50340fe15e0SLoGin             .mprotect(start_frame, page_count, prot_flags)
50440fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
50540fe15e0SLoGin         return Ok(0);
506ab5c8ca4Slogin     }
507a17651b1SMemoryShore 
508a17651b1SMemoryShore     /// ## madvise系统调用
509a17651b1SMemoryShore     ///
510a17651b1SMemoryShore     /// ## 参数
511a17651b1SMemoryShore     ///
512a17651b1SMemoryShore     /// - `start_vaddr`:起始地址(已经对齐到页)
513a17651b1SMemoryShore     /// - `len`:长度(已经对齐到页)
514a17651b1SMemoryShore     /// - `madv_flags`:建议标志
madvise( start_vaddr: VirtAddr, len: usize, madv_flags: usize, ) -> Result<usize, SystemError>515a17651b1SMemoryShore     pub fn madvise(
516a17651b1SMemoryShore         start_vaddr: VirtAddr,
517a17651b1SMemoryShore         len: usize,
518a17651b1SMemoryShore         madv_flags: usize,
519a17651b1SMemoryShore     ) -> Result<usize, SystemError> {
520a17651b1SMemoryShore         if !start_vaddr.check_aligned(MMArch::PAGE_SIZE) || !check_aligned(len, MMArch::PAGE_SIZE) {
521a17651b1SMemoryShore             return Err(SystemError::EINVAL);
522a17651b1SMemoryShore         }
523a17651b1SMemoryShore 
524a17651b1SMemoryShore         if unlikely(verify_area(start_vaddr, len).is_err()) {
525a17651b1SMemoryShore             return Err(SystemError::EINVAL);
526a17651b1SMemoryShore         }
527a17651b1SMemoryShore         if unlikely(len == 0) {
528a17651b1SMemoryShore             return Err(SystemError::EINVAL);
529a17651b1SMemoryShore         }
530a17651b1SMemoryShore 
531a17651b1SMemoryShore         let madv_flags = MadvFlags::from_bits(madv_flags as u64).ok_or(SystemError::EINVAL)?;
532a17651b1SMemoryShore 
533a17651b1SMemoryShore         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
534a17651b1SMemoryShore         let start_frame = VirtPageFrame::new(start_vaddr);
535a17651b1SMemoryShore         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
536a17651b1SMemoryShore 
537a17651b1SMemoryShore         current_address_space
538a17651b1SMemoryShore             .write()
539a17651b1SMemoryShore             .madvise(start_frame, page_count, madv_flags)
540a17651b1SMemoryShore             .map_err(|_| SystemError::EINVAL)?;
541a17651b1SMemoryShore         return Ok(0);
542a17651b1SMemoryShore     }
543*cf7f801eSMemoryShore 
544*cf7f801eSMemoryShore     /// ## msync系统调用
545*cf7f801eSMemoryShore     ///
546*cf7f801eSMemoryShore     /// ## 参数
547*cf7f801eSMemoryShore     ///
548*cf7f801eSMemoryShore     /// - `start`:起始地址(已经对齐到页)
549*cf7f801eSMemoryShore     /// - `len`:长度(已经对齐到页)
550*cf7f801eSMemoryShore     /// - `flags`:标志
msync(start: VirtAddr, len: usize, flags: usize) -> Result<usize, SystemError>551*cf7f801eSMemoryShore     pub fn msync(start: VirtAddr, len: usize, flags: usize) -> Result<usize, SystemError> {
552*cf7f801eSMemoryShore         if !start.check_aligned(MMArch::PAGE_SIZE) || !check_aligned(len, MMArch::PAGE_SIZE) {
553*cf7f801eSMemoryShore             return Err(SystemError::EINVAL);
554*cf7f801eSMemoryShore         }
555*cf7f801eSMemoryShore 
556*cf7f801eSMemoryShore         if unlikely(verify_area(start, len).is_err()) {
557*cf7f801eSMemoryShore             return Err(SystemError::EINVAL);
558*cf7f801eSMemoryShore         }
559*cf7f801eSMemoryShore         if unlikely(len == 0) {
560*cf7f801eSMemoryShore             return Err(SystemError::EINVAL);
561*cf7f801eSMemoryShore         }
562*cf7f801eSMemoryShore 
563*cf7f801eSMemoryShore         let mut start = start.data();
564*cf7f801eSMemoryShore         let end = start + len;
565*cf7f801eSMemoryShore         let flags = MsFlags::from_bits_truncate(flags);
566*cf7f801eSMemoryShore         let mut unmapped_error = Ok(0);
567*cf7f801eSMemoryShore 
568*cf7f801eSMemoryShore         if !flags.intersects(MsFlags::MS_ASYNC | MsFlags::MS_INVALIDATE | MsFlags::MS_SYNC) {
569*cf7f801eSMemoryShore             return Err(SystemError::EINVAL);
570*cf7f801eSMemoryShore         }
571*cf7f801eSMemoryShore 
572*cf7f801eSMemoryShore         if flags.contains(MsFlags::MS_ASYNC | MsFlags::MS_SYNC) {
573*cf7f801eSMemoryShore             return Err(SystemError::EINVAL);
574*cf7f801eSMemoryShore         }
575*cf7f801eSMemoryShore 
576*cf7f801eSMemoryShore         if end < start {
577*cf7f801eSMemoryShore             return Err(SystemError::ENOMEM);
578*cf7f801eSMemoryShore         }
579*cf7f801eSMemoryShore 
580*cf7f801eSMemoryShore         if start == end {
581*cf7f801eSMemoryShore             return Ok(0);
582*cf7f801eSMemoryShore         }
583*cf7f801eSMemoryShore 
584*cf7f801eSMemoryShore         let current_address_space = AddressSpace::current()?;
585*cf7f801eSMemoryShore         let mut err = Err(SystemError::ENOMEM);
586*cf7f801eSMemoryShore         let mut next_vma = current_address_space
587*cf7f801eSMemoryShore             .read()
588*cf7f801eSMemoryShore             .mappings
589*cf7f801eSMemoryShore             .find_nearest(VirtAddr::new(start));
590*cf7f801eSMemoryShore         loop {
591*cf7f801eSMemoryShore             if let Some(vma) = next_vma.clone() {
592*cf7f801eSMemoryShore                 let guard = vma.lock_irqsave();
593*cf7f801eSMemoryShore                 let vm_start = guard.region().start().data();
594*cf7f801eSMemoryShore                 let vm_end = guard.region().end().data();
595*cf7f801eSMemoryShore                 if start < vm_start {
596*cf7f801eSMemoryShore                     if flags == MsFlags::MS_ASYNC {
597*cf7f801eSMemoryShore                         break;
598*cf7f801eSMemoryShore                     }
599*cf7f801eSMemoryShore                     start = vm_start;
600*cf7f801eSMemoryShore                     if start >= vm_end {
601*cf7f801eSMemoryShore                         break;
602*cf7f801eSMemoryShore                     }
603*cf7f801eSMemoryShore                     unmapped_error = Err(SystemError::ENOMEM);
604*cf7f801eSMemoryShore                 }
605*cf7f801eSMemoryShore                 let vm_flags = *guard.vm_flags();
606*cf7f801eSMemoryShore                 if flags.contains(MsFlags::MS_INVALIDATE) && vm_flags.contains(VmFlags::VM_LOCKED) {
607*cf7f801eSMemoryShore                     err = Err(SystemError::EBUSY);
608*cf7f801eSMemoryShore                     break;
609*cf7f801eSMemoryShore                 }
610*cf7f801eSMemoryShore                 let file = guard.vm_file();
611*cf7f801eSMemoryShore                 let fstart = (start - vm_start)
612*cf7f801eSMemoryShore                     + (guard.file_page_offset().unwrap_or(0) << MMArch::PAGE_SHIFT);
613*cf7f801eSMemoryShore                 let fend = fstart + (core::cmp::min(end, vm_end) - start) - 1;
614*cf7f801eSMemoryShore                 let old_start = start;
615*cf7f801eSMemoryShore                 start = vm_end;
616*cf7f801eSMemoryShore                 // log::info!("flags: {:?}", flags);
617*cf7f801eSMemoryShore                 // log::info!("vm_flags: {:?}", vm_flags);
618*cf7f801eSMemoryShore                 // log::info!("file: {:?}", file);
619*cf7f801eSMemoryShore                 if flags.contains(MsFlags::MS_SYNC) && vm_flags.contains(VmFlags::VM_SHARED) {
620*cf7f801eSMemoryShore                     if let Some(file) = file {
621*cf7f801eSMemoryShore                         let old_pos = file.lseek(SeekFrom::SeekCurrent(0)).unwrap();
622*cf7f801eSMemoryShore                         file.lseek(SeekFrom::SeekSet(fstart as i64)).unwrap();
623*cf7f801eSMemoryShore                         err = file.write(len, unsafe {
624*cf7f801eSMemoryShore                             from_raw_parts(old_start as *mut u8, fend - fstart + 1)
625*cf7f801eSMemoryShore                         });
626*cf7f801eSMemoryShore                         file.lseek(SeekFrom::SeekSet(old_pos as i64)).unwrap();
627*cf7f801eSMemoryShore                         if err.is_err() {
628*cf7f801eSMemoryShore                             break;
629*cf7f801eSMemoryShore                         } else if start >= end {
630*cf7f801eSMemoryShore                             err = unmapped_error;
631*cf7f801eSMemoryShore                             break;
632*cf7f801eSMemoryShore                         }
633*cf7f801eSMemoryShore                         next_vma = current_address_space
634*cf7f801eSMemoryShore                             .read()
635*cf7f801eSMemoryShore                             .mappings
636*cf7f801eSMemoryShore                             .find_nearest(VirtAddr::new(start));
637*cf7f801eSMemoryShore                     }
638*cf7f801eSMemoryShore                 } else {
639*cf7f801eSMemoryShore                     if start >= end {
640*cf7f801eSMemoryShore                         err = unmapped_error;
641*cf7f801eSMemoryShore                         break;
642*cf7f801eSMemoryShore                     }
643*cf7f801eSMemoryShore                     next_vma = current_address_space
644*cf7f801eSMemoryShore                         .read()
645*cf7f801eSMemoryShore                         .mappings
646*cf7f801eSMemoryShore                         .find_nearest(VirtAddr::new(vm_end));
647*cf7f801eSMemoryShore                 }
648*cf7f801eSMemoryShore             } else {
649*cf7f801eSMemoryShore                 return Err(SystemError::ENOMEM);
650*cf7f801eSMemoryShore             }
651*cf7f801eSMemoryShore         }
652*cf7f801eSMemoryShore         return err;
653*cf7f801eSMemoryShore     }
654ab5c8ca4Slogin }
655