140fe15e0SLoGin use core::intrinsics::unlikely; 240fe15e0SLoGin 340fe15e0SLoGin use alloc::sync::Arc; 491e9d4abSLoGin use system_error::SystemError; 540fe15e0SLoGin 6ab5c8ca4Slogin use crate::{ 740fe15e0SLoGin arch::MMArch, 840fe15e0SLoGin kerror, 940fe15e0SLoGin libs::align::{check_aligned, page_align_up}, 1040fe15e0SLoGin mm::MemoryManagementArch, 1191e9d4abSLoGin syscall::Syscall, 12ab5c8ca4Slogin }; 13ab5c8ca4Slogin 1440fe15e0SLoGin use super::{ 1540fe15e0SLoGin allocator::page_frame::{PageFrameCount, VirtPageFrame}, 1640fe15e0SLoGin ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR}, 17*4cfa009bSJomo verify_area, VirtAddr, VmFlags, 1840fe15e0SLoGin }; 1940fe15e0SLoGin 2040fe15e0SLoGin bitflags! { 2140fe15e0SLoGin /// Memory protection flags 2240fe15e0SLoGin pub struct ProtFlags: u64 { 2340fe15e0SLoGin const PROT_NONE = 0x0; 2440fe15e0SLoGin const PROT_READ = 0x1; 2540fe15e0SLoGin const PROT_WRITE = 0x2; 2640fe15e0SLoGin const PROT_EXEC = 0x4; 27ab5c8ca4Slogin } 2840fe15e0SLoGin 2940fe15e0SLoGin /// Memory mapping flags 3040fe15e0SLoGin pub struct MapFlags: u64 { 3140fe15e0SLoGin const MAP_NONE = 0x0; 3240fe15e0SLoGin /// share changes 3340fe15e0SLoGin const MAP_SHARED = 0x1; 3440fe15e0SLoGin /// changes are private 3540fe15e0SLoGin const MAP_PRIVATE = 0x2; 3640fe15e0SLoGin /// Interpret addr exactly 3740fe15e0SLoGin const MAP_FIXED = 0x10; 3840fe15e0SLoGin /// don't use a file 3940fe15e0SLoGin const MAP_ANONYMOUS = 0x20; 4040fe15e0SLoGin // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7 4140fe15e0SLoGin /// stack-like segment 4240fe15e0SLoGin const MAP_GROWSDOWN = 0x100; 4340fe15e0SLoGin /// ETXTBSY 4440fe15e0SLoGin const MAP_DENYWRITE = 0x800; 4540fe15e0SLoGin /// Mark it as an executable 4640fe15e0SLoGin const MAP_EXECUTABLE = 0x1000; 4740fe15e0SLoGin /// Pages are locked 4840fe15e0SLoGin const MAP_LOCKED = 0x2000; 4940fe15e0SLoGin /// don't check for reservations 5040fe15e0SLoGin const MAP_NORESERVE = 0x4000; 5140fe15e0SLoGin /// populate (prefault) pagetables 5240fe15e0SLoGin const MAP_POPULATE = 0x8000; 5340fe15e0SLoGin /// do not block on IO 5440fe15e0SLoGin const MAP_NONBLOCK = 0x10000; 5540fe15e0SLoGin /// give out an address that is best suited for process/thread stacks 5640fe15e0SLoGin const MAP_STACK = 0x20000; 5740fe15e0SLoGin /// create a huge page mapping 5840fe15e0SLoGin const MAP_HUGETLB = 0x40000; 5940fe15e0SLoGin /// perform synchronous page faults for the mapping 6040fe15e0SLoGin const MAP_SYNC = 0x80000; 6140fe15e0SLoGin /// MAP_FIXED which doesn't unmap underlying mapping 6240fe15e0SLoGin const MAP_FIXED_NOREPLACE = 0x100000; 6340fe15e0SLoGin 6440fe15e0SLoGin /// For anonymous mmap, memory could be uninitialized 6540fe15e0SLoGin const MAP_UNINITIALIZED = 0x4000000; 66*4cfa009bSJomo } 6740fe15e0SLoGin 68*4cfa009bSJomo /// Memory mremapping flags 69*4cfa009bSJomo pub struct MremapFlags: u8 { 70*4cfa009bSJomo const MREMAP_MAYMOVE = 1; 71*4cfa009bSJomo const MREMAP_FIXED = 2; 72*4cfa009bSJomo const MREMAP_DONTUNMAP = 4; 73*4cfa009bSJomo } 74*4cfa009bSJomo } 75*4cfa009bSJomo 76*4cfa009bSJomo impl From<MapFlags> for VmFlags { 77*4cfa009bSJomo fn from(map_flags: MapFlags) -> Self { 78*4cfa009bSJomo let mut vm_flags = VmFlags::VM_NONE; 79*4cfa009bSJomo 80*4cfa009bSJomo if map_flags.contains(MapFlags::MAP_GROWSDOWN) { 81*4cfa009bSJomo vm_flags |= VmFlags::VM_GROWSDOWN; 82*4cfa009bSJomo } 83*4cfa009bSJomo 84*4cfa009bSJomo if map_flags.contains(MapFlags::MAP_LOCKED) { 85*4cfa009bSJomo vm_flags |= VmFlags::VM_LOCKED; 86*4cfa009bSJomo } 87*4cfa009bSJomo 88*4cfa009bSJomo if map_flags.contains(MapFlags::MAP_SYNC) { 89*4cfa009bSJomo vm_flags |= VmFlags::VM_SYNC; 90*4cfa009bSJomo } 91*4cfa009bSJomo 92*4cfa009bSJomo vm_flags 93*4cfa009bSJomo } 94*4cfa009bSJomo } 95*4cfa009bSJomo 96*4cfa009bSJomo impl From<ProtFlags> for VmFlags { 97*4cfa009bSJomo fn from(prot_flags: ProtFlags) -> Self { 98*4cfa009bSJomo let mut vm_flags = VmFlags::VM_NONE; 99*4cfa009bSJomo 100*4cfa009bSJomo if prot_flags.contains(ProtFlags::PROT_READ) { 101*4cfa009bSJomo vm_flags |= VmFlags::VM_READ; 102*4cfa009bSJomo } 103*4cfa009bSJomo 104*4cfa009bSJomo if prot_flags.contains(ProtFlags::PROT_WRITE) { 105*4cfa009bSJomo vm_flags |= VmFlags::VM_WRITE; 106*4cfa009bSJomo } 107*4cfa009bSJomo 108*4cfa009bSJomo if prot_flags.contains(ProtFlags::PROT_EXEC) { 109*4cfa009bSJomo vm_flags |= VmFlags::VM_EXEC; 110*4cfa009bSJomo } 111*4cfa009bSJomo 112*4cfa009bSJomo vm_flags 113*4cfa009bSJomo } 114*4cfa009bSJomo } 115*4cfa009bSJomo 116*4cfa009bSJomo impl Into<MapFlags> for VmFlags { 117*4cfa009bSJomo fn into(self) -> MapFlags { 118*4cfa009bSJomo let mut map_flags = MapFlags::MAP_NONE; 119*4cfa009bSJomo 120*4cfa009bSJomo if self.contains(VmFlags::VM_GROWSDOWN) { 121*4cfa009bSJomo map_flags |= MapFlags::MAP_GROWSDOWN; 122*4cfa009bSJomo } 123*4cfa009bSJomo 124*4cfa009bSJomo if self.contains(VmFlags::VM_LOCKED) { 125*4cfa009bSJomo map_flags |= MapFlags::MAP_LOCKED; 126*4cfa009bSJomo } 127*4cfa009bSJomo 128*4cfa009bSJomo if self.contains(VmFlags::VM_SYNC) { 129*4cfa009bSJomo map_flags |= MapFlags::MAP_SYNC; 130*4cfa009bSJomo } 131*4cfa009bSJomo 132*4cfa009bSJomo map_flags 133*4cfa009bSJomo } 134*4cfa009bSJomo } 135*4cfa009bSJomo 136*4cfa009bSJomo impl Into<ProtFlags> for VmFlags { 137*4cfa009bSJomo fn into(self) -> ProtFlags { 138*4cfa009bSJomo let mut prot_flags = ProtFlags::PROT_NONE; 139*4cfa009bSJomo 140*4cfa009bSJomo if self.contains(VmFlags::VM_READ) { 141*4cfa009bSJomo prot_flags |= ProtFlags::PROT_READ; 142*4cfa009bSJomo } 143*4cfa009bSJomo 144*4cfa009bSJomo if self.contains(VmFlags::VM_WRITE) { 145*4cfa009bSJomo prot_flags |= ProtFlags::PROT_WRITE; 146*4cfa009bSJomo } 147*4cfa009bSJomo 148*4cfa009bSJomo if self.contains(VmFlags::VM_EXEC) { 149*4cfa009bSJomo prot_flags |= ProtFlags::PROT_EXEC; 150*4cfa009bSJomo } 151*4cfa009bSJomo 152*4cfa009bSJomo prot_flags 15340fe15e0SLoGin } 15440fe15e0SLoGin } 15540fe15e0SLoGin 156ab5c8ca4Slogin impl Syscall { 15740fe15e0SLoGin pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> { 15840fe15e0SLoGin // kdebug!("brk: new_addr={:?}", new_addr); 15940fe15e0SLoGin let address_space = AddressSpace::current()?; 16040fe15e0SLoGin let mut address_space = address_space.write(); 16140fe15e0SLoGin 1626d81180bSLoGin if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR { 1636d81180bSLoGin return Ok(address_space.brk); 1646d81180bSLoGin } 1656d81180bSLoGin if new_addr == address_space.brk { 1666d81180bSLoGin return Ok(address_space.brk); 1676d81180bSLoGin } 1686d81180bSLoGin 16940fe15e0SLoGin unsafe { 17040fe15e0SLoGin address_space 17140fe15e0SLoGin .set_brk(VirtAddr::new(page_align_up(new_addr.data()))) 17240fe15e0SLoGin .ok(); 17340fe15e0SLoGin 17440fe15e0SLoGin return Ok(address_space.sbrk(0).unwrap()); 175ab5c8ca4Slogin } 176d8ad0a5eSLoGin } 177d8ad0a5eSLoGin 17840fe15e0SLoGin pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> { 17940fe15e0SLoGin let address_space = AddressSpace::current()?; 1801496ba7bSLoGin assert!(address_space.read().user_mapper.utable.is_current()); 18140fe15e0SLoGin let mut address_space = address_space.write(); 18240fe15e0SLoGin let r = unsafe { address_space.sbrk(incr) }; 18340fe15e0SLoGin 18440fe15e0SLoGin return r; 185d8ad0a5eSLoGin } 186d8ad0a5eSLoGin 18740fe15e0SLoGin /// ## mmap系统调用 188d8ad0a5eSLoGin /// 18940fe15e0SLoGin /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现 19040fe15e0SLoGin /// 19140fe15e0SLoGin /// ## 参数 19240fe15e0SLoGin /// 19340fe15e0SLoGin /// - `start_vaddr`:映射的起始地址 19440fe15e0SLoGin /// - `len`:映射的长度 19540fe15e0SLoGin /// - `prot`:保护标志 19640fe15e0SLoGin /// - `flags`:映射标志 19740fe15e0SLoGin /// - `fd`:文件描述符(暂时不支持) 19840fe15e0SLoGin /// - `offset`:文件偏移量 (暂时不支持) 19940fe15e0SLoGin /// 20040fe15e0SLoGin /// ## 返回值 20140fe15e0SLoGin /// 20240fe15e0SLoGin /// 成功时返回映射的起始地址,失败时返回错误码 20340fe15e0SLoGin pub fn mmap( 20440fe15e0SLoGin start_vaddr: VirtAddr, 20540fe15e0SLoGin len: usize, 20640fe15e0SLoGin prot_flags: usize, 20740fe15e0SLoGin map_flags: usize, 20840fe15e0SLoGin _fd: i32, 20940fe15e0SLoGin _offset: usize, 21040fe15e0SLoGin ) -> Result<usize, SystemError> { 21140fe15e0SLoGin let map_flags = MapFlags::from_bits_truncate(map_flags as u64); 21240fe15e0SLoGin let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64); 21340fe15e0SLoGin 21440fe15e0SLoGin if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR) 21540fe15e0SLoGin && map_flags.contains(MapFlags::MAP_FIXED) 21640fe15e0SLoGin { 21740fe15e0SLoGin kerror!( 21840fe15e0SLoGin "mmap: MAP_FIXED is not supported for address below {}", 21940fe15e0SLoGin DEFAULT_MMAP_MIN_ADDR 22040fe15e0SLoGin ); 22140fe15e0SLoGin return Err(SystemError::EINVAL); 222d8ad0a5eSLoGin } 22340fe15e0SLoGin // 暂时不支持除匿名页以外的映射 22440fe15e0SLoGin if !map_flags.contains(MapFlags::MAP_ANONYMOUS) { 22540fe15e0SLoGin kerror!("mmap: not support file mapping"); 22640fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 22740fe15e0SLoGin } 22840fe15e0SLoGin 22940fe15e0SLoGin // 暂时不支持巨页映射 23040fe15e0SLoGin if map_flags.contains(MapFlags::MAP_HUGETLB) { 23140fe15e0SLoGin kerror!("mmap: not support huge page mapping"); 23240fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 23340fe15e0SLoGin } 23440fe15e0SLoGin let current_address_space = AddressSpace::current()?; 23540fe15e0SLoGin let start_page = current_address_space.write().map_anonymous( 23640fe15e0SLoGin start_vaddr, 23740fe15e0SLoGin len, 23840fe15e0SLoGin prot_flags, 23940fe15e0SLoGin map_flags, 24040fe15e0SLoGin true, 24140fe15e0SLoGin )?; 24240fe15e0SLoGin return Ok(start_page.virt_address().data()); 24340fe15e0SLoGin } 24440fe15e0SLoGin 245*4cfa009bSJomo /// ## mremap系统调用 246*4cfa009bSJomo /// 247*4cfa009bSJomo /// 248*4cfa009bSJomo /// ## 参数 249*4cfa009bSJomo /// 250*4cfa009bSJomo /// - `old_vaddr`:原映射的起始地址 251*4cfa009bSJomo /// - `old_len`:原映射的长度 252*4cfa009bSJomo /// - `new_len`:重新映射的长度 253*4cfa009bSJomo /// - `mremap_flags`:重映射标志 254*4cfa009bSJomo /// - `new_vaddr`:重新映射的起始地址 255*4cfa009bSJomo /// 256*4cfa009bSJomo /// ## 返回值 257*4cfa009bSJomo /// 258*4cfa009bSJomo /// 成功时返回重映射的起始地址,失败时返回错误码 259*4cfa009bSJomo pub fn mremap( 260*4cfa009bSJomo old_vaddr: VirtAddr, 261*4cfa009bSJomo old_len: usize, 262*4cfa009bSJomo new_len: usize, 263*4cfa009bSJomo mremap_flags: MremapFlags, 264*4cfa009bSJomo new_vaddr: VirtAddr, 265*4cfa009bSJomo ) -> Result<usize, SystemError> { 266*4cfa009bSJomo // 需要重映射到新内存区域的情况下,必须包含MREMAP_MAYMOVE并且指定新地址 267*4cfa009bSJomo if mremap_flags.contains(MremapFlags::MREMAP_FIXED) 268*4cfa009bSJomo && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) 269*4cfa009bSJomo || new_vaddr == VirtAddr::new(0)) 270*4cfa009bSJomo { 271*4cfa009bSJomo return Err(SystemError::EINVAL); 272*4cfa009bSJomo } 273*4cfa009bSJomo 274*4cfa009bSJomo // 不取消旧映射的情况下,必须包含MREMAP_MAYMOVE并且新内存大小等于旧内存大小 275*4cfa009bSJomo if mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) 276*4cfa009bSJomo && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) || old_len != new_len) 277*4cfa009bSJomo { 278*4cfa009bSJomo return Err(SystemError::EINVAL); 279*4cfa009bSJomo } 280*4cfa009bSJomo 281*4cfa009bSJomo // 旧内存地址必须对齐 282*4cfa009bSJomo if !old_vaddr.check_aligned(MMArch::PAGE_SIZE) { 283*4cfa009bSJomo return Err(SystemError::EINVAL); 284*4cfa009bSJomo } 285*4cfa009bSJomo 286*4cfa009bSJomo // 将old_len、new_len 对齐页面大小 287*4cfa009bSJomo let old_len = page_align_up(old_len); 288*4cfa009bSJomo let new_len = page_align_up(new_len); 289*4cfa009bSJomo 290*4cfa009bSJomo // 不允许重映射内存区域大小为0 291*4cfa009bSJomo if new_len == 0 { 292*4cfa009bSJomo return Err(SystemError::EINVAL); 293*4cfa009bSJomo } 294*4cfa009bSJomo 295*4cfa009bSJomo let current_address_space = AddressSpace::current()?; 296*4cfa009bSJomo let vma = current_address_space.read().mappings.contains(old_vaddr); 297*4cfa009bSJomo if vma.is_none() { 298*4cfa009bSJomo return Err(SystemError::EINVAL); 299*4cfa009bSJomo } 300*4cfa009bSJomo let vma = vma.unwrap(); 301*4cfa009bSJomo let vm_flags = vma.lock().vm_flags().clone(); 302*4cfa009bSJomo 303*4cfa009bSJomo // 暂时不支持巨页映射 304*4cfa009bSJomo if vm_flags.contains(VmFlags::VM_HUGETLB) { 305*4cfa009bSJomo kerror!("mmap: not support huge page mapping"); 306*4cfa009bSJomo return Err(SystemError::ENOSYS); 307*4cfa009bSJomo } 308*4cfa009bSJomo 309*4cfa009bSJomo // 缩小旧内存映射区域 310*4cfa009bSJomo if old_len > new_len { 311*4cfa009bSJomo Self::munmap(old_vaddr + new_len, old_len - new_len)?; 312*4cfa009bSJomo return Ok(old_vaddr.data()); 313*4cfa009bSJomo } 314*4cfa009bSJomo 315*4cfa009bSJomo // 重映射到新内存区域 316*4cfa009bSJomo let r = current_address_space.write().mremap( 317*4cfa009bSJomo old_vaddr, 318*4cfa009bSJomo old_len, 319*4cfa009bSJomo new_len, 320*4cfa009bSJomo mremap_flags, 321*4cfa009bSJomo new_vaddr, 322*4cfa009bSJomo vm_flags, 323*4cfa009bSJomo )?; 324*4cfa009bSJomo 325*4cfa009bSJomo if !mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) { 326*4cfa009bSJomo Self::munmap(old_vaddr, old_len)?; 327*4cfa009bSJomo } 328*4cfa009bSJomo 329*4cfa009bSJomo return Ok(r.data()); 330*4cfa009bSJomo } 331*4cfa009bSJomo 33240fe15e0SLoGin /// ## munmap系统调用 33340fe15e0SLoGin /// 33440fe15e0SLoGin /// ## 参数 33540fe15e0SLoGin /// 33640fe15e0SLoGin /// - `start_vaddr`:取消映射的起始地址(已经对齐到页) 33740fe15e0SLoGin /// - `len`:取消映射的字节数(已经对齐到页) 33840fe15e0SLoGin /// 33940fe15e0SLoGin /// ## 返回值 34040fe15e0SLoGin /// 34140fe15e0SLoGin /// 成功时返回0,失败时返回错误码 34240fe15e0SLoGin pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> { 34340fe15e0SLoGin assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 34440fe15e0SLoGin assert!(check_aligned(len, MMArch::PAGE_SIZE)); 34540fe15e0SLoGin 34640fe15e0SLoGin if unlikely(verify_area(start_vaddr, len).is_err()) { 34740fe15e0SLoGin return Err(SystemError::EINVAL); 34840fe15e0SLoGin } 34940fe15e0SLoGin if unlikely(len == 0) { 35040fe15e0SLoGin return Err(SystemError::EINVAL); 35140fe15e0SLoGin } 35240fe15e0SLoGin 35340fe15e0SLoGin let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 35440fe15e0SLoGin let start_frame = VirtPageFrame::new(start_vaddr); 35540fe15e0SLoGin let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 35640fe15e0SLoGin 35740fe15e0SLoGin current_address_space 35840fe15e0SLoGin .write() 35940fe15e0SLoGin .munmap(start_frame, page_count) 36040fe15e0SLoGin .map_err(|_| SystemError::EINVAL)?; 361*4cfa009bSJomo 36240fe15e0SLoGin return Ok(0); 36340fe15e0SLoGin } 36440fe15e0SLoGin 36540fe15e0SLoGin /// ## mprotect系统调用 36640fe15e0SLoGin /// 36740fe15e0SLoGin /// ## 参数 36840fe15e0SLoGin /// 36940fe15e0SLoGin /// - `start_vaddr`:起始地址(已经对齐到页) 37040fe15e0SLoGin /// - `len`:长度(已经对齐到页) 37140fe15e0SLoGin /// - `prot_flags`:保护标志 37240fe15e0SLoGin pub fn mprotect( 37340fe15e0SLoGin start_vaddr: VirtAddr, 37440fe15e0SLoGin len: usize, 37540fe15e0SLoGin prot_flags: usize, 37640fe15e0SLoGin ) -> Result<usize, SystemError> { 37740fe15e0SLoGin assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 37840fe15e0SLoGin assert!(check_aligned(len, MMArch::PAGE_SIZE)); 37940fe15e0SLoGin 38040fe15e0SLoGin if unlikely(verify_area(start_vaddr, len).is_err()) { 38140fe15e0SLoGin return Err(SystemError::EINVAL); 38240fe15e0SLoGin } 38340fe15e0SLoGin if unlikely(len == 0) { 38440fe15e0SLoGin return Err(SystemError::EINVAL); 38540fe15e0SLoGin } 38640fe15e0SLoGin 38740fe15e0SLoGin let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?; 38840fe15e0SLoGin 38940fe15e0SLoGin let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 39040fe15e0SLoGin let start_frame = VirtPageFrame::new(start_vaddr); 39140fe15e0SLoGin let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 39240fe15e0SLoGin 39340fe15e0SLoGin current_address_space 39440fe15e0SLoGin .write() 39540fe15e0SLoGin .mprotect(start_frame, page_count, prot_flags) 39640fe15e0SLoGin .map_err(|_| SystemError::EINVAL)?; 39740fe15e0SLoGin return Ok(0); 398ab5c8ca4Slogin } 399ab5c8ca4Slogin } 400