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