1*40fe15e0SLoGin use core::intrinsics::unlikely; 2*40fe15e0SLoGin 3*40fe15e0SLoGin use alloc::sync::Arc; 4*40fe15e0SLoGin 5ab5c8ca4Slogin use crate::{ 6*40fe15e0SLoGin arch::MMArch, 7*40fe15e0SLoGin kerror, 8*40fe15e0SLoGin libs::align::{check_aligned, page_align_up}, 9*40fe15e0SLoGin mm::MemoryManagementArch, 10ab5c8ca4Slogin syscall::{Syscall, SystemError}, 11ab5c8ca4Slogin }; 12ab5c8ca4Slogin 13*40fe15e0SLoGin use super::{ 14*40fe15e0SLoGin allocator::page_frame::{PageFrameCount, VirtPageFrame}, 15*40fe15e0SLoGin ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR}, 16*40fe15e0SLoGin verify_area, VirtAddr, 17*40fe15e0SLoGin }; 18*40fe15e0SLoGin 19*40fe15e0SLoGin bitflags! { 20*40fe15e0SLoGin /// Memory protection flags 21*40fe15e0SLoGin pub struct ProtFlags: u64 { 22*40fe15e0SLoGin const PROT_NONE = 0x0; 23*40fe15e0SLoGin const PROT_READ = 0x1; 24*40fe15e0SLoGin const PROT_WRITE = 0x2; 25*40fe15e0SLoGin const PROT_EXEC = 0x4; 26ab5c8ca4Slogin } 27*40fe15e0SLoGin 28*40fe15e0SLoGin /// Memory mapping flags 29*40fe15e0SLoGin pub struct MapFlags: u64 { 30*40fe15e0SLoGin const MAP_NONE = 0x0; 31*40fe15e0SLoGin /// share changes 32*40fe15e0SLoGin const MAP_SHARED = 0x1; 33*40fe15e0SLoGin /// changes are private 34*40fe15e0SLoGin const MAP_PRIVATE = 0x2; 35*40fe15e0SLoGin /// Interpret addr exactly 36*40fe15e0SLoGin const MAP_FIXED = 0x10; 37*40fe15e0SLoGin /// don't use a file 38*40fe15e0SLoGin const MAP_ANONYMOUS = 0x20; 39*40fe15e0SLoGin // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7 40*40fe15e0SLoGin /// stack-like segment 41*40fe15e0SLoGin const MAP_GROWSDOWN = 0x100; 42*40fe15e0SLoGin /// ETXTBSY 43*40fe15e0SLoGin const MAP_DENYWRITE = 0x800; 44*40fe15e0SLoGin /// Mark it as an executable 45*40fe15e0SLoGin const MAP_EXECUTABLE = 0x1000; 46*40fe15e0SLoGin /// Pages are locked 47*40fe15e0SLoGin const MAP_LOCKED = 0x2000; 48*40fe15e0SLoGin /// don't check for reservations 49*40fe15e0SLoGin const MAP_NORESERVE = 0x4000; 50*40fe15e0SLoGin /// populate (prefault) pagetables 51*40fe15e0SLoGin const MAP_POPULATE = 0x8000; 52*40fe15e0SLoGin /// do not block on IO 53*40fe15e0SLoGin const MAP_NONBLOCK = 0x10000; 54*40fe15e0SLoGin /// give out an address that is best suited for process/thread stacks 55*40fe15e0SLoGin const MAP_STACK = 0x20000; 56*40fe15e0SLoGin /// create a huge page mapping 57*40fe15e0SLoGin const MAP_HUGETLB = 0x40000; 58*40fe15e0SLoGin /// perform synchronous page faults for the mapping 59*40fe15e0SLoGin const MAP_SYNC = 0x80000; 60*40fe15e0SLoGin /// MAP_FIXED which doesn't unmap underlying mapping 61*40fe15e0SLoGin const MAP_FIXED_NOREPLACE = 0x100000; 62*40fe15e0SLoGin 63*40fe15e0SLoGin /// For anonymous mmap, memory could be uninitialized 64*40fe15e0SLoGin const MAP_UNINITIALIZED = 0x4000000; 65*40fe15e0SLoGin 66*40fe15e0SLoGin } 67*40fe15e0SLoGin } 68*40fe15e0SLoGin 69ab5c8ca4Slogin impl Syscall { 70*40fe15e0SLoGin pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> { 71*40fe15e0SLoGin // kdebug!("brk: new_addr={:?}", new_addr); 72*40fe15e0SLoGin let address_space = AddressSpace::current()?; 73*40fe15e0SLoGin let mut address_space = address_space.write(); 74*40fe15e0SLoGin 75*40fe15e0SLoGin unsafe { 76*40fe15e0SLoGin address_space 77*40fe15e0SLoGin .set_brk(VirtAddr::new(page_align_up(new_addr.data()))) 78*40fe15e0SLoGin .ok(); 79*40fe15e0SLoGin 80*40fe15e0SLoGin return Ok(address_space.sbrk(0).unwrap()); 81ab5c8ca4Slogin } 82d8ad0a5eSLoGin } 83d8ad0a5eSLoGin 84*40fe15e0SLoGin pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> { 85*40fe15e0SLoGin // kdebug!("pid:{}, sbrk: incr={}", current_pcb().pid, incr); 86*40fe15e0SLoGin 87*40fe15e0SLoGin let address_space = AddressSpace::current()?; 88*40fe15e0SLoGin let mut address_space = address_space.write(); 89*40fe15e0SLoGin let r = unsafe { address_space.sbrk(incr) }; 90*40fe15e0SLoGin 91*40fe15e0SLoGin // kdebug!("pid:{}, sbrk: r={:?}", current_pcb().pid, r); 92*40fe15e0SLoGin return r; 93d8ad0a5eSLoGin } 94d8ad0a5eSLoGin 95*40fe15e0SLoGin /// ## mmap系统调用 96d8ad0a5eSLoGin /// 97*40fe15e0SLoGin /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现 98*40fe15e0SLoGin /// 99*40fe15e0SLoGin /// ## 参数 100*40fe15e0SLoGin /// 101*40fe15e0SLoGin /// - `start_vaddr`:映射的起始地址 102*40fe15e0SLoGin /// - `len`:映射的长度 103*40fe15e0SLoGin /// - `prot`:保护标志 104*40fe15e0SLoGin /// - `flags`:映射标志 105*40fe15e0SLoGin /// - `fd`:文件描述符(暂时不支持) 106*40fe15e0SLoGin /// - `offset`:文件偏移量 (暂时不支持) 107*40fe15e0SLoGin /// 108*40fe15e0SLoGin /// ## 返回值 109*40fe15e0SLoGin /// 110*40fe15e0SLoGin /// 成功时返回映射的起始地址,失败时返回错误码 111*40fe15e0SLoGin pub fn mmap( 112*40fe15e0SLoGin start_vaddr: VirtAddr, 113*40fe15e0SLoGin len: usize, 114*40fe15e0SLoGin prot_flags: usize, 115*40fe15e0SLoGin map_flags: usize, 116*40fe15e0SLoGin _fd: i32, 117*40fe15e0SLoGin _offset: usize, 118*40fe15e0SLoGin ) -> Result<usize, SystemError> { 119*40fe15e0SLoGin let map_flags = MapFlags::from_bits_truncate(map_flags as u64); 120*40fe15e0SLoGin let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64); 121*40fe15e0SLoGin 122*40fe15e0SLoGin if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR) 123*40fe15e0SLoGin && map_flags.contains(MapFlags::MAP_FIXED) 124*40fe15e0SLoGin { 125*40fe15e0SLoGin kerror!( 126*40fe15e0SLoGin "mmap: MAP_FIXED is not supported for address below {}", 127*40fe15e0SLoGin DEFAULT_MMAP_MIN_ADDR 128*40fe15e0SLoGin ); 129*40fe15e0SLoGin return Err(SystemError::EINVAL); 130d8ad0a5eSLoGin } 131*40fe15e0SLoGin // 暂时不支持除匿名页以外的映射 132*40fe15e0SLoGin if !map_flags.contains(MapFlags::MAP_ANONYMOUS) { 133*40fe15e0SLoGin kerror!("mmap: not support file mapping"); 134*40fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 135*40fe15e0SLoGin } 136*40fe15e0SLoGin 137*40fe15e0SLoGin // 暂时不支持巨页映射 138*40fe15e0SLoGin if map_flags.contains(MapFlags::MAP_HUGETLB) { 139*40fe15e0SLoGin kerror!("mmap: not support huge page mapping"); 140*40fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 141*40fe15e0SLoGin } 142*40fe15e0SLoGin let current_address_space = AddressSpace::current()?; 143*40fe15e0SLoGin let start_page = current_address_space.write().map_anonymous( 144*40fe15e0SLoGin start_vaddr, 145*40fe15e0SLoGin len, 146*40fe15e0SLoGin prot_flags, 147*40fe15e0SLoGin map_flags, 148*40fe15e0SLoGin true, 149*40fe15e0SLoGin )?; 150*40fe15e0SLoGin return Ok(start_page.virt_address().data()); 151*40fe15e0SLoGin } 152*40fe15e0SLoGin 153*40fe15e0SLoGin /// ## munmap系统调用 154*40fe15e0SLoGin /// 155*40fe15e0SLoGin /// ## 参数 156*40fe15e0SLoGin /// 157*40fe15e0SLoGin /// - `start_vaddr`:取消映射的起始地址(已经对齐到页) 158*40fe15e0SLoGin /// - `len`:取消映射的字节数(已经对齐到页) 159*40fe15e0SLoGin /// 160*40fe15e0SLoGin /// ## 返回值 161*40fe15e0SLoGin /// 162*40fe15e0SLoGin /// 成功时返回0,失败时返回错误码 163*40fe15e0SLoGin pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> { 164*40fe15e0SLoGin assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 165*40fe15e0SLoGin assert!(check_aligned(len, MMArch::PAGE_SIZE)); 166*40fe15e0SLoGin 167*40fe15e0SLoGin if unlikely(verify_area(start_vaddr, len).is_err()) { 168*40fe15e0SLoGin return Err(SystemError::EINVAL); 169*40fe15e0SLoGin } 170*40fe15e0SLoGin if unlikely(len == 0) { 171*40fe15e0SLoGin return Err(SystemError::EINVAL); 172*40fe15e0SLoGin } 173*40fe15e0SLoGin 174*40fe15e0SLoGin let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 175*40fe15e0SLoGin let start_frame = VirtPageFrame::new(start_vaddr); 176*40fe15e0SLoGin let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 177*40fe15e0SLoGin 178*40fe15e0SLoGin current_address_space 179*40fe15e0SLoGin .write() 180*40fe15e0SLoGin .munmap(start_frame, page_count) 181*40fe15e0SLoGin .map_err(|_| SystemError::EINVAL)?; 182*40fe15e0SLoGin return Ok(0); 183*40fe15e0SLoGin } 184*40fe15e0SLoGin 185*40fe15e0SLoGin /// ## mprotect系统调用 186*40fe15e0SLoGin /// 187*40fe15e0SLoGin /// ## 参数 188*40fe15e0SLoGin /// 189*40fe15e0SLoGin /// - `start_vaddr`:起始地址(已经对齐到页) 190*40fe15e0SLoGin /// - `len`:长度(已经对齐到页) 191*40fe15e0SLoGin /// - `prot_flags`:保护标志 192*40fe15e0SLoGin pub fn mprotect( 193*40fe15e0SLoGin start_vaddr: VirtAddr, 194*40fe15e0SLoGin len: usize, 195*40fe15e0SLoGin prot_flags: usize, 196*40fe15e0SLoGin ) -> Result<usize, SystemError> { 197*40fe15e0SLoGin assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 198*40fe15e0SLoGin assert!(check_aligned(len, MMArch::PAGE_SIZE)); 199*40fe15e0SLoGin 200*40fe15e0SLoGin if unlikely(verify_area(start_vaddr, len).is_err()) { 201*40fe15e0SLoGin return Err(SystemError::EINVAL); 202*40fe15e0SLoGin } 203*40fe15e0SLoGin if unlikely(len == 0) { 204*40fe15e0SLoGin return Err(SystemError::EINVAL); 205*40fe15e0SLoGin } 206*40fe15e0SLoGin 207*40fe15e0SLoGin let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?; 208*40fe15e0SLoGin 209*40fe15e0SLoGin let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 210*40fe15e0SLoGin let start_frame = VirtPageFrame::new(start_vaddr); 211*40fe15e0SLoGin let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 212*40fe15e0SLoGin 213*40fe15e0SLoGin current_address_space 214*40fe15e0SLoGin .write() 215*40fe15e0SLoGin .mprotect(start_frame, page_count, prot_flags) 216*40fe15e0SLoGin .map_err(|_| SystemError::EINVAL)?; 217*40fe15e0SLoGin return Ok(0); 218ab5c8ca4Slogin } 219ab5c8ca4Slogin } 220