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