1 use core::intrinsics::unlikely; 2 3 use alloc::sync::Arc; 4 use system_error::SystemError; 5 6 use crate::{ 7 arch::MMArch, 8 ipc::shm::ShmFlags, 9 kerror, 10 libs::align::{check_aligned, page_align_up}, 11 mm::MemoryManagementArch, 12 syscall::Syscall, 13 }; 14 15 use super::{ 16 allocator::page_frame::{PageFrameCount, VirtPageFrame}, 17 ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR}, 18 verify_area, VirtAddr, VmFlags, 19 }; 20 21 bitflags! { 22 /// Memory protection flags 23 pub struct ProtFlags: u64 { 24 const PROT_NONE = 0x0; 25 const PROT_READ = 0x1; 26 const PROT_WRITE = 0x2; 27 const PROT_EXEC = 0x4; 28 } 29 30 /// Memory mapping flags 31 pub struct MapFlags: u64 { 32 const MAP_NONE = 0x0; 33 /// share changes 34 const MAP_SHARED = 0x1; 35 /// changes are private 36 const MAP_PRIVATE = 0x2; 37 /// Interpret addr exactly 38 const MAP_FIXED = 0x10; 39 /// don't use a file 40 const MAP_ANONYMOUS = 0x20; 41 // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7 42 /// stack-like segment 43 const MAP_GROWSDOWN = 0x100; 44 /// ETXTBSY 45 const MAP_DENYWRITE = 0x800; 46 /// Mark it as an executable 47 const MAP_EXECUTABLE = 0x1000; 48 /// Pages are locked 49 const MAP_LOCKED = 0x2000; 50 /// don't check for reservations 51 const MAP_NORESERVE = 0x4000; 52 /// populate (prefault) pagetables 53 const MAP_POPULATE = 0x8000; 54 /// do not block on IO 55 const MAP_NONBLOCK = 0x10000; 56 /// give out an address that is best suited for process/thread stacks 57 const MAP_STACK = 0x20000; 58 /// create a huge page mapping 59 const MAP_HUGETLB = 0x40000; 60 /// perform synchronous page faults for the mapping 61 const MAP_SYNC = 0x80000; 62 /// MAP_FIXED which doesn't unmap underlying mapping 63 const MAP_FIXED_NOREPLACE = 0x100000; 64 65 /// For anonymous mmap, memory could be uninitialized 66 const MAP_UNINITIALIZED = 0x4000000; 67 } 68 69 /// Memory mremapping flags 70 pub struct MremapFlags: u8 { 71 const MREMAP_MAYMOVE = 1; 72 const MREMAP_FIXED = 2; 73 const MREMAP_DONTUNMAP = 4; 74 } 75 } 76 77 impl From<MapFlags> for VmFlags { 78 fn from(map_flags: MapFlags) -> Self { 79 let mut vm_flags = VmFlags::VM_NONE; 80 81 if map_flags.contains(MapFlags::MAP_GROWSDOWN) { 82 vm_flags |= VmFlags::VM_GROWSDOWN; 83 } 84 85 if map_flags.contains(MapFlags::MAP_LOCKED) { 86 vm_flags |= VmFlags::VM_LOCKED; 87 } 88 89 if map_flags.contains(MapFlags::MAP_SYNC) { 90 vm_flags |= VmFlags::VM_SYNC; 91 } 92 93 vm_flags 94 } 95 } 96 97 impl From<ProtFlags> for VmFlags { 98 fn from(prot_flags: ProtFlags) -> Self { 99 let mut vm_flags = VmFlags::VM_NONE; 100 101 if prot_flags.contains(ProtFlags::PROT_READ) { 102 vm_flags |= VmFlags::VM_READ; 103 } 104 105 if prot_flags.contains(ProtFlags::PROT_WRITE) { 106 vm_flags |= VmFlags::VM_WRITE; 107 } 108 109 if prot_flags.contains(ProtFlags::PROT_EXEC) { 110 vm_flags |= VmFlags::VM_EXEC; 111 } 112 113 vm_flags 114 } 115 } 116 117 impl From<ShmFlags> for VmFlags { 118 fn from(shm_flags: ShmFlags) -> Self { 119 let mut vm_flags = VmFlags::VM_NONE; 120 121 if shm_flags.contains(ShmFlags::SHM_RDONLY) { 122 vm_flags |= VmFlags::VM_READ; 123 } else { 124 vm_flags |= VmFlags::VM_READ | VmFlags::VM_WRITE; 125 } 126 127 if shm_flags.contains(ShmFlags::SHM_EXEC) { 128 vm_flags |= VmFlags::VM_EXEC; 129 } 130 131 if shm_flags.contains(ShmFlags::SHM_HUGETLB) { 132 vm_flags |= VmFlags::VM_HUGETLB; 133 } 134 135 vm_flags 136 } 137 } 138 139 impl From<VmFlags> for MapFlags { 140 fn from(value: VmFlags) -> Self { 141 let mut map_flags = MapFlags::MAP_NONE; 142 143 if value.contains(VmFlags::VM_GROWSDOWN) { 144 map_flags |= MapFlags::MAP_GROWSDOWN; 145 } 146 147 if value.contains(VmFlags::VM_LOCKED) { 148 map_flags |= MapFlags::MAP_LOCKED; 149 } 150 151 if value.contains(VmFlags::VM_SYNC) { 152 map_flags |= MapFlags::MAP_SYNC; 153 } 154 155 if value.contains(VmFlags::VM_MAYSHARE) { 156 map_flags |= MapFlags::MAP_SHARED; 157 } 158 159 map_flags 160 } 161 } 162 163 impl From<VmFlags> for ProtFlags { 164 fn from(value: VmFlags) -> Self { 165 let mut prot_flags = ProtFlags::PROT_NONE; 166 167 if value.contains(VmFlags::VM_READ) { 168 prot_flags |= ProtFlags::PROT_READ; 169 } 170 171 if value.contains(VmFlags::VM_WRITE) { 172 prot_flags |= ProtFlags::PROT_WRITE; 173 } 174 175 if value.contains(VmFlags::VM_EXEC) { 176 prot_flags |= ProtFlags::PROT_EXEC; 177 } 178 179 prot_flags 180 } 181 } 182 183 impl Syscall { 184 pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> { 185 // kdebug!("brk: new_addr={:?}", new_addr); 186 let address_space = AddressSpace::current()?; 187 let mut address_space = address_space.write(); 188 189 if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR { 190 return Ok(address_space.brk); 191 } 192 if new_addr == address_space.brk { 193 return Ok(address_space.brk); 194 } 195 196 unsafe { 197 address_space 198 .set_brk(VirtAddr::new(page_align_up(new_addr.data()))) 199 .ok(); 200 201 return Ok(address_space.sbrk(0).unwrap()); 202 } 203 } 204 205 pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> { 206 let address_space = AddressSpace::current()?; 207 assert!(address_space.read().user_mapper.utable.is_current()); 208 let mut address_space = address_space.write(); 209 let r = unsafe { address_space.sbrk(incr) }; 210 211 return r; 212 } 213 214 /// ## mmap系统调用 215 /// 216 /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现 217 /// 218 /// ## 参数 219 /// 220 /// - `start_vaddr`:映射的起始地址 221 /// - `len`:映射的长度 222 /// - `prot`:保护标志 223 /// - `flags`:映射标志 224 /// - `fd`:文件描述符(暂时不支持) 225 /// - `offset`:文件偏移量 (暂时不支持) 226 /// 227 /// ## 返回值 228 /// 229 /// 成功时返回映射的起始地址,失败时返回错误码 230 pub fn mmap( 231 start_vaddr: VirtAddr, 232 len: usize, 233 prot_flags: usize, 234 map_flags: usize, 235 _fd: i32, 236 _offset: usize, 237 ) -> Result<usize, SystemError> { 238 let map_flags = MapFlags::from_bits_truncate(map_flags as u64); 239 let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64); 240 241 if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR) 242 && map_flags.contains(MapFlags::MAP_FIXED) 243 { 244 kerror!( 245 "mmap: MAP_FIXED is not supported for address below {}", 246 DEFAULT_MMAP_MIN_ADDR 247 ); 248 return Err(SystemError::EINVAL); 249 } 250 // 暂时不支持除匿名页以外的映射 251 if !map_flags.contains(MapFlags::MAP_ANONYMOUS) { 252 kerror!("mmap: not support file mapping"); 253 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 254 } 255 256 // 暂时不支持巨页映射 257 if map_flags.contains(MapFlags::MAP_HUGETLB) { 258 kerror!("mmap: not support huge page mapping"); 259 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 260 } 261 let current_address_space = AddressSpace::current()?; 262 let start_page = current_address_space.write().map_anonymous( 263 start_vaddr, 264 len, 265 prot_flags, 266 map_flags, 267 true, 268 )?; 269 return Ok(start_page.virt_address().data()); 270 } 271 272 /// ## mremap系统调用 273 /// 274 /// 275 /// ## 参数 276 /// 277 /// - `old_vaddr`:原映射的起始地址 278 /// - `old_len`:原映射的长度 279 /// - `new_len`:重新映射的长度 280 /// - `mremap_flags`:重映射标志 281 /// - `new_vaddr`:重新映射的起始地址 282 /// 283 /// ## 返回值 284 /// 285 /// 成功时返回重映射的起始地址,失败时返回错误码 286 pub fn mremap( 287 old_vaddr: VirtAddr, 288 old_len: usize, 289 new_len: usize, 290 mremap_flags: MremapFlags, 291 new_vaddr: VirtAddr, 292 ) -> Result<usize, SystemError> { 293 // 需要重映射到新内存区域的情况下,必须包含MREMAP_MAYMOVE并且指定新地址 294 if mremap_flags.contains(MremapFlags::MREMAP_FIXED) 295 && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) 296 || new_vaddr == VirtAddr::new(0)) 297 { 298 return Err(SystemError::EINVAL); 299 } 300 301 // 不取消旧映射的情况下,必须包含MREMAP_MAYMOVE并且新内存大小等于旧内存大小 302 if mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) 303 && (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) || old_len != new_len) 304 { 305 return Err(SystemError::EINVAL); 306 } 307 308 // 旧内存地址必须对齐 309 if !old_vaddr.check_aligned(MMArch::PAGE_SIZE) { 310 return Err(SystemError::EINVAL); 311 } 312 313 // 将old_len、new_len 对齐页面大小 314 let old_len = page_align_up(old_len); 315 let new_len = page_align_up(new_len); 316 317 // 不允许重映射内存区域大小为0 318 if new_len == 0 { 319 return Err(SystemError::EINVAL); 320 } 321 322 let current_address_space = AddressSpace::current()?; 323 let vma = current_address_space.read().mappings.contains(old_vaddr); 324 if vma.is_none() { 325 return Err(SystemError::EINVAL); 326 } 327 let vma = vma.unwrap(); 328 let vm_flags = *vma.lock().vm_flags(); 329 330 // 暂时不支持巨页映射 331 if vm_flags.contains(VmFlags::VM_HUGETLB) { 332 kerror!("mmap: not support huge page mapping"); 333 return Err(SystemError::ENOSYS); 334 } 335 336 // 缩小旧内存映射区域 337 if old_len > new_len { 338 Self::munmap(old_vaddr + new_len, old_len - new_len)?; 339 return Ok(old_vaddr.data()); 340 } 341 342 // 重映射到新内存区域 343 let r = current_address_space.write().mremap( 344 old_vaddr, 345 old_len, 346 new_len, 347 mremap_flags, 348 new_vaddr, 349 vm_flags, 350 )?; 351 352 if !mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) { 353 Self::munmap(old_vaddr, old_len)?; 354 } 355 356 return Ok(r.data()); 357 } 358 359 /// ## munmap系统调用 360 /// 361 /// ## 参数 362 /// 363 /// - `start_vaddr`:取消映射的起始地址(已经对齐到页) 364 /// - `len`:取消映射的字节数(已经对齐到页) 365 /// 366 /// ## 返回值 367 /// 368 /// 成功时返回0,失败时返回错误码 369 pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> { 370 assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 371 assert!(check_aligned(len, MMArch::PAGE_SIZE)); 372 373 if unlikely(verify_area(start_vaddr, len).is_err()) { 374 return Err(SystemError::EINVAL); 375 } 376 if unlikely(len == 0) { 377 return Err(SystemError::EINVAL); 378 } 379 380 let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 381 let start_frame = VirtPageFrame::new(start_vaddr); 382 let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 383 384 current_address_space 385 .write() 386 .munmap(start_frame, page_count) 387 .map_err(|_| SystemError::EINVAL)?; 388 389 return Ok(0); 390 } 391 392 /// ## mprotect系统调用 393 /// 394 /// ## 参数 395 /// 396 /// - `start_vaddr`:起始地址(已经对齐到页) 397 /// - `len`:长度(已经对齐到页) 398 /// - `prot_flags`:保护标志 399 pub fn mprotect( 400 start_vaddr: VirtAddr, 401 len: usize, 402 prot_flags: usize, 403 ) -> Result<usize, SystemError> { 404 assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE)); 405 assert!(check_aligned(len, MMArch::PAGE_SIZE)); 406 407 if unlikely(verify_area(start_vaddr, len).is_err()) { 408 return Err(SystemError::EINVAL); 409 } 410 if unlikely(len == 0) { 411 return Err(SystemError::EINVAL); 412 } 413 414 let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?; 415 416 let current_address_space: Arc<AddressSpace> = AddressSpace::current()?; 417 let start_frame = VirtPageFrame::new(start_vaddr); 418 let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE); 419 420 current_address_space 421 .write() 422 .mprotect(start_frame, page_count, prot_flags) 423 .map_err(|_| SystemError::EINVAL)?; 424 return Ok(0); 425 } 426 } 427