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