140fe15e0SLoGin use core::intrinsics::unlikely; 240fe15e0SLoGin 340fe15e0SLoGin use alloc::sync::Arc; 440fe15e0SLoGin 5ab5c8ca4Slogin use crate::{ 640fe15e0SLoGin arch::MMArch, 740fe15e0SLoGin kerror, 840fe15e0SLoGin libs::align::{check_aligned, page_align_up}, 940fe15e0SLoGin mm::MemoryManagementArch, 10ab5c8ca4Slogin syscall::{Syscall, SystemError}, 11ab5c8ca4Slogin }; 12ab5c8ca4Slogin 1340fe15e0SLoGin use super::{ 1440fe15e0SLoGin allocator::page_frame::{PageFrameCount, VirtPageFrame}, 1540fe15e0SLoGin ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR}, 1640fe15e0SLoGin verify_area, VirtAddr, 1740fe15e0SLoGin }; 1840fe15e0SLoGin 1940fe15e0SLoGin bitflags! { 2040fe15e0SLoGin /// Memory protection flags 2140fe15e0SLoGin pub struct ProtFlags: u64 { 2240fe15e0SLoGin const PROT_NONE = 0x0; 2340fe15e0SLoGin const PROT_READ = 0x1; 2440fe15e0SLoGin const PROT_WRITE = 0x2; 2540fe15e0SLoGin const PROT_EXEC = 0x4; 26ab5c8ca4Slogin } 2740fe15e0SLoGin 2840fe15e0SLoGin /// Memory mapping flags 2940fe15e0SLoGin pub struct MapFlags: u64 { 3040fe15e0SLoGin const MAP_NONE = 0x0; 3140fe15e0SLoGin /// share changes 3240fe15e0SLoGin const MAP_SHARED = 0x1; 3340fe15e0SLoGin /// changes are private 3440fe15e0SLoGin const MAP_PRIVATE = 0x2; 3540fe15e0SLoGin /// Interpret addr exactly 3640fe15e0SLoGin const MAP_FIXED = 0x10; 3740fe15e0SLoGin /// don't use a file 3840fe15e0SLoGin const MAP_ANONYMOUS = 0x20; 3940fe15e0SLoGin // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7 4040fe15e0SLoGin /// stack-like segment 4140fe15e0SLoGin const MAP_GROWSDOWN = 0x100; 4240fe15e0SLoGin /// ETXTBSY 4340fe15e0SLoGin const MAP_DENYWRITE = 0x800; 4440fe15e0SLoGin /// Mark it as an executable 4540fe15e0SLoGin const MAP_EXECUTABLE = 0x1000; 4640fe15e0SLoGin /// Pages are locked 4740fe15e0SLoGin const MAP_LOCKED = 0x2000; 4840fe15e0SLoGin /// don't check for reservations 4940fe15e0SLoGin const MAP_NORESERVE = 0x4000; 5040fe15e0SLoGin /// populate (prefault) pagetables 5140fe15e0SLoGin const MAP_POPULATE = 0x8000; 5240fe15e0SLoGin /// do not block on IO 5340fe15e0SLoGin const MAP_NONBLOCK = 0x10000; 5440fe15e0SLoGin /// give out an address that is best suited for process/thread stacks 5540fe15e0SLoGin const MAP_STACK = 0x20000; 5640fe15e0SLoGin /// create a huge page mapping 5740fe15e0SLoGin const MAP_HUGETLB = 0x40000; 5840fe15e0SLoGin /// perform synchronous page faults for the mapping 5940fe15e0SLoGin const MAP_SYNC = 0x80000; 6040fe15e0SLoGin /// MAP_FIXED which doesn't unmap underlying mapping 6140fe15e0SLoGin const MAP_FIXED_NOREPLACE = 0x100000; 6240fe15e0SLoGin 6340fe15e0SLoGin /// For anonymous mmap, memory could be uninitialized 6440fe15e0SLoGin const MAP_UNINITIALIZED = 0x4000000; 6540fe15e0SLoGin 6640fe15e0SLoGin } 6740fe15e0SLoGin } 6840fe15e0SLoGin 69ab5c8ca4Slogin impl Syscall { 7040fe15e0SLoGin pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> { 7140fe15e0SLoGin // kdebug!("brk: new_addr={:?}", new_addr); 7240fe15e0SLoGin let address_space = AddressSpace::current()?; 7340fe15e0SLoGin let mut address_space = address_space.write(); 7440fe15e0SLoGin 75*6d81180bSLoGin if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR { 76*6d81180bSLoGin return Ok(address_space.brk); 77*6d81180bSLoGin } 78*6d81180bSLoGin if new_addr == address_space.brk { 79*6d81180bSLoGin return Ok(address_space.brk); 80*6d81180bSLoGin } 81*6d81180bSLoGin 8240fe15e0SLoGin unsafe { 8340fe15e0SLoGin address_space 8440fe15e0SLoGin .set_brk(VirtAddr::new(page_align_up(new_addr.data()))) 8540fe15e0SLoGin .ok(); 8640fe15e0SLoGin 8740fe15e0SLoGin return Ok(address_space.sbrk(0).unwrap()); 88ab5c8ca4Slogin } 89d8ad0a5eSLoGin } 90d8ad0a5eSLoGin 9140fe15e0SLoGin pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> { 9240fe15e0SLoGin // kdebug!("pid:{}, sbrk: incr={}", current_pcb().pid, incr); 9340fe15e0SLoGin 9440fe15e0SLoGin let address_space = AddressSpace::current()?; 9540fe15e0SLoGin let mut address_space = address_space.write(); 9640fe15e0SLoGin let r = unsafe { address_space.sbrk(incr) }; 9740fe15e0SLoGin 9840fe15e0SLoGin // kdebug!("pid:{}, sbrk: r={:?}", current_pcb().pid, r); 9940fe15e0SLoGin return r; 100d8ad0a5eSLoGin } 101d8ad0a5eSLoGin 10240fe15e0SLoGin /// ## mmap系统调用 103d8ad0a5eSLoGin /// 10440fe15e0SLoGin /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现 10540fe15e0SLoGin /// 10640fe15e0SLoGin /// ## 参数 10740fe15e0SLoGin /// 10840fe15e0SLoGin /// - `start_vaddr`:映射的起始地址 10940fe15e0SLoGin /// - `len`:映射的长度 11040fe15e0SLoGin /// - `prot`:保护标志 11140fe15e0SLoGin /// - `flags`:映射标志 11240fe15e0SLoGin /// - `fd`:文件描述符(暂时不支持) 11340fe15e0SLoGin /// - `offset`:文件偏移量 (暂时不支持) 11440fe15e0SLoGin /// 11540fe15e0SLoGin /// ## 返回值 11640fe15e0SLoGin /// 11740fe15e0SLoGin /// 成功时返回映射的起始地址,失败时返回错误码 11840fe15e0SLoGin pub fn mmap( 11940fe15e0SLoGin start_vaddr: VirtAddr, 12040fe15e0SLoGin len: usize, 12140fe15e0SLoGin prot_flags: usize, 12240fe15e0SLoGin map_flags: usize, 12340fe15e0SLoGin _fd: i32, 12440fe15e0SLoGin _offset: usize, 12540fe15e0SLoGin ) -> Result<usize, SystemError> { 12640fe15e0SLoGin let map_flags = MapFlags::from_bits_truncate(map_flags as u64); 12740fe15e0SLoGin let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64); 12840fe15e0SLoGin 12940fe15e0SLoGin if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR) 13040fe15e0SLoGin && map_flags.contains(MapFlags::MAP_FIXED) 13140fe15e0SLoGin { 13240fe15e0SLoGin kerror!( 13340fe15e0SLoGin "mmap: MAP_FIXED is not supported for address below {}", 13440fe15e0SLoGin DEFAULT_MMAP_MIN_ADDR 13540fe15e0SLoGin ); 13640fe15e0SLoGin return Err(SystemError::EINVAL); 137d8ad0a5eSLoGin } 13840fe15e0SLoGin // 暂时不支持除匿名页以外的映射 13940fe15e0SLoGin if !map_flags.contains(MapFlags::MAP_ANONYMOUS) { 14040fe15e0SLoGin kerror!("mmap: not support file mapping"); 14140fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 14240fe15e0SLoGin } 14340fe15e0SLoGin 14440fe15e0SLoGin // 暂时不支持巨页映射 14540fe15e0SLoGin if map_flags.contains(MapFlags::MAP_HUGETLB) { 14640fe15e0SLoGin kerror!("mmap: not support huge page mapping"); 14740fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 14840fe15e0SLoGin } 14940fe15e0SLoGin let current_address_space = AddressSpace::current()?; 15040fe15e0SLoGin let start_page = current_address_space.write().map_anonymous( 15140fe15e0SLoGin start_vaddr, 15240fe15e0SLoGin len, 15340fe15e0SLoGin prot_flags, 15440fe15e0SLoGin map_flags, 15540fe15e0SLoGin true, 15640fe15e0SLoGin )?; 15740fe15e0SLoGin return Ok(start_page.virt_address().data()); 15840fe15e0SLoGin } 15940fe15e0SLoGin 16040fe15e0SLoGin /// ## munmap系统调用 16140fe15e0SLoGin /// 16240fe15e0SLoGin /// ## 参数 16340fe15e0SLoGin /// 16440fe15e0SLoGin /// - `start_vaddr`:取消映射的起始地址(已经对齐到页) 16540fe15e0SLoGin /// - `len`:取消映射的字节数(已经对齐到页) 16640fe15e0SLoGin /// 16740fe15e0SLoGin /// ## 返回值 16840fe15e0SLoGin /// 16940fe15e0SLoGin /// 成功时返回0,失败时返回错误码 17040fe15e0SLoGin pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> { 17140fe15e0SLoGin assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 17240fe15e0SLoGin assert!(check_aligned(len, MMArch::PAGE_SIZE)); 17340fe15e0SLoGin 17440fe15e0SLoGin if unlikely(verify_area(start_vaddr, len).is_err()) { 17540fe15e0SLoGin return Err(SystemError::EINVAL); 17640fe15e0SLoGin } 17740fe15e0SLoGin if unlikely(len == 0) { 17840fe15e0SLoGin return Err(SystemError::EINVAL); 17940fe15e0SLoGin } 18040fe15e0SLoGin 18140fe15e0SLoGin let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 18240fe15e0SLoGin let start_frame = VirtPageFrame::new(start_vaddr); 18340fe15e0SLoGin let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 18440fe15e0SLoGin 18540fe15e0SLoGin current_address_space 18640fe15e0SLoGin .write() 18740fe15e0SLoGin .munmap(start_frame, page_count) 18840fe15e0SLoGin .map_err(|_| SystemError::EINVAL)?; 18940fe15e0SLoGin return Ok(0); 19040fe15e0SLoGin } 19140fe15e0SLoGin 19240fe15e0SLoGin /// ## mprotect系统调用 19340fe15e0SLoGin /// 19440fe15e0SLoGin /// ## 参数 19540fe15e0SLoGin /// 19640fe15e0SLoGin /// - `start_vaddr`:起始地址(已经对齐到页) 19740fe15e0SLoGin /// - `len`:长度(已经对齐到页) 19840fe15e0SLoGin /// - `prot_flags`:保护标志 19940fe15e0SLoGin pub fn mprotect( 20040fe15e0SLoGin start_vaddr: VirtAddr, 20140fe15e0SLoGin len: usize, 20240fe15e0SLoGin prot_flags: usize, 20340fe15e0SLoGin ) -> Result<usize, SystemError> { 20440fe15e0SLoGin assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 20540fe15e0SLoGin assert!(check_aligned(len, MMArch::PAGE_SIZE)); 20640fe15e0SLoGin 20740fe15e0SLoGin if unlikely(verify_area(start_vaddr, len).is_err()) { 20840fe15e0SLoGin return Err(SystemError::EINVAL); 20940fe15e0SLoGin } 21040fe15e0SLoGin if unlikely(len == 0) { 21140fe15e0SLoGin return Err(SystemError::EINVAL); 21240fe15e0SLoGin } 21340fe15e0SLoGin 21440fe15e0SLoGin let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?; 21540fe15e0SLoGin 21640fe15e0SLoGin let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 21740fe15e0SLoGin let start_frame = VirtPageFrame::new(start_vaddr); 21840fe15e0SLoGin let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 21940fe15e0SLoGin 22040fe15e0SLoGin current_address_space 22140fe15e0SLoGin .write() 22240fe15e0SLoGin .mprotect(start_frame, page_count, prot_flags) 22340fe15e0SLoGin .map_err(|_| SystemError::EINVAL)?; 22440fe15e0SLoGin return Ok(0); 225ab5c8ca4Slogin } 226ab5c8ca4Slogin } 227