1 // 进程的用户空间内存管理 2 3 use core::{ 4 cmp, 5 hash::Hasher, 6 intrinsics::unlikely, 7 ops::Add, 8 sync::atomic::{compiler_fence, Ordering}, 9 }; 10 11 use alloc::{ 12 collections::BTreeMap, 13 sync::{Arc, Weak}, 14 vec::Vec, 15 }; 16 use hashbrown::HashSet; 17 18 use crate::{ 19 arch::{mm::PageMapper, CurrentIrqArch, MMArch}, 20 exception::InterruptArch, 21 libs::{ 22 align::page_align_up, 23 rwlock::{RwLock, RwLockWriteGuard}, 24 spinlock::{SpinLock, SpinLockGuard}, 25 }, 26 process::ProcessManager, 27 syscall::SystemError, 28 }; 29 30 use super::{ 31 allocator::page_frame::{ 32 deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter, 33 }, 34 page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll}, 35 syscall::{MapFlags, ProtFlags}, 36 MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, 37 }; 38 39 /// MMAP_MIN_ADDR的默认值 40 /// 以下内容来自linux-5.19: 41 /// This is the portion of low virtual memory which should be protected 42 // from userspace allocation. Keeping a user from writing to low pages 43 // can help reduce the impact of kernel NULL pointer bugs. 44 // For most ia64, ppc64 and x86 users with lots of address space 45 // a value of 65536 is reasonable and should cause no problems. 46 // On arm and other archs it should not be higher than 32768. 47 // Programs which use vm86 functionality or have some need to map 48 // this low address space will need CAP_SYS_RAWIO or disable this 49 // protection by setting the value to 0. 50 pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536; 51 52 #[derive(Debug)] 53 pub struct AddressSpace { 54 inner: RwLock<InnerAddressSpace>, 55 } 56 57 impl AddressSpace { 58 pub fn new(create_stack: bool) -> Result<Arc<Self>, SystemError> { 59 let inner = InnerAddressSpace::new(create_stack)?; 60 let result = Self { 61 inner: RwLock::new(inner), 62 }; 63 return Ok(Arc::new(result)); 64 } 65 66 /// 从pcb中获取当前进程的地址空间结构体的Arc指针 67 pub fn current() -> Result<Arc<AddressSpace>, SystemError> { 68 let vm = ProcessManager::current_pcb() 69 .basic() 70 .user_vm() 71 .expect("Current process has no address space"); 72 73 return Ok(vm); 74 } 75 76 /// 判断某个地址空间是否为当前进程的地址空间 77 pub fn is_current(self: &Arc<Self>) -> bool { 78 let current = Self::current(); 79 if let Ok(current) = current { 80 return Arc::ptr_eq(¤t, self); 81 } 82 return false; 83 } 84 } 85 86 impl core::ops::Deref for AddressSpace { 87 type Target = RwLock<InnerAddressSpace>; 88 89 fn deref(&self) -> &Self::Target { 90 &self.inner 91 } 92 } 93 94 impl core::ops::DerefMut for AddressSpace { 95 fn deref_mut(&mut self) -> &mut Self::Target { 96 &mut self.inner 97 } 98 } 99 100 /// @brief 用户地址空间结构体(每个进程都有一个) 101 #[derive(Debug)] 102 pub struct InnerAddressSpace { 103 pub user_mapper: UserMapper, 104 pub mappings: UserMappings, 105 pub mmap_min: VirtAddr, 106 /// 用户栈信息结构体 107 pub user_stack: Option<UserStack>, 108 109 pub elf_brk_start: VirtAddr, 110 pub elf_brk: VirtAddr, 111 112 /// 当前进程的堆空间的起始地址 113 pub brk_start: VirtAddr, 114 /// 当前进程的堆空间的结束地址(不包含) 115 pub brk: VirtAddr, 116 117 pub start_code: VirtAddr, 118 pub end_code: VirtAddr, 119 pub start_data: VirtAddr, 120 pub end_data: VirtAddr, 121 } 122 123 impl InnerAddressSpace { 124 pub fn new(create_stack: bool) -> Result<Self, SystemError> { 125 let mut result = Self { 126 user_mapper: MMArch::setup_new_usermapper()?, 127 mappings: UserMappings::new(), 128 mmap_min: VirtAddr(DEFAULT_MMAP_MIN_ADDR), 129 elf_brk_start: VirtAddr::new(0), 130 elf_brk: VirtAddr::new(0), 131 brk_start: MMArch::USER_BRK_START, 132 brk: MMArch::USER_BRK_START, 133 user_stack: None, 134 start_code: VirtAddr(0), 135 end_code: VirtAddr(0), 136 start_data: VirtAddr(0), 137 end_data: VirtAddr(0), 138 }; 139 if create_stack { 140 // kdebug!("to create user stack."); 141 result.new_user_stack(UserStack::DEFAULT_USER_STACK_SIZE)?; 142 } 143 144 return Ok(result); 145 } 146 147 /// 尝试克隆当前进程的地址空间,包括这些映射都会被克隆 148 /// 149 /// # Returns 150 /// 151 /// 返回克隆后的,新的地址空间的Arc指针 152 pub fn try_clone(&mut self) -> Result<Arc<AddressSpace>, SystemError> { 153 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 154 let new_addr_space = AddressSpace::new(false)?; 155 let mut new_guard = new_addr_space.write(); 156 157 // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容) 158 unsafe { 159 new_guard.user_stack = Some(self.user_stack.as_ref().unwrap().clone_info_only()); 160 } 161 let _current_stack_size = self.user_stack.as_ref().unwrap().stack_size(); 162 163 let current_mapper = &mut self.user_mapper.utable; 164 165 for vma in self.mappings.vmas.iter() { 166 // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过 167 168 let vma_guard: SpinLockGuard<'_, VMA> = vma.lock(); 169 let old_flags = vma_guard.flags(); 170 let tmp_flags: PageFlags<MMArch> = PageFlags::new().set_write(true); 171 172 // 分配内存页并创建新的VMA 173 let new_vma = VMA::zeroed( 174 VirtPageFrame::new(vma_guard.region.start()), 175 PageFrameCount::new(vma_guard.region.size() / MMArch::PAGE_SIZE), 176 tmp_flags, 177 &mut new_guard.user_mapper.utable, 178 (), 179 )?; 180 new_guard.mappings.vmas.insert(new_vma.clone()); 181 // kdebug!("new vma: {:x?}", new_vma); 182 let mut new_vma_guard = new_vma.lock(); 183 for page in new_vma_guard.pages().map(|p| p.virt_address()) { 184 // kdebug!("page: {:x?}", page); 185 let current_frame = unsafe { 186 MMArch::phys_2_virt( 187 current_mapper 188 .translate(page) 189 .expect("VMA page not mapped") 190 .0, 191 ) 192 } 193 .expect("Phys2Virt: vaddr overflow.") 194 .data() as *mut u8; 195 196 let new_frame = unsafe { 197 MMArch::phys_2_virt( 198 new_guard 199 .user_mapper 200 .utable 201 .translate(page) 202 .expect("VMA page not mapped") 203 .0, 204 ) 205 } 206 .expect("Phys2Virt: vaddr overflow.") 207 .data() as *mut u8; 208 209 unsafe { 210 // 拷贝数据 211 new_frame.copy_from_nonoverlapping(current_frame, MMArch::PAGE_SIZE); 212 } 213 } 214 drop(vma_guard); 215 216 new_vma_guard.remap(old_flags, &mut new_guard.user_mapper.utable, ())?; 217 drop(new_vma_guard); 218 } 219 drop(new_guard); 220 drop(irq_guard); 221 return Ok(new_addr_space); 222 } 223 224 /// 判断当前的地址空间是否是当前进程的地址空间 225 #[inline] 226 pub fn is_current(&self) -> bool { 227 return self.user_mapper.utable.is_current(); 228 } 229 230 /// 进行匿名页映射 231 /// 232 /// ## 参数 233 /// 234 /// - `start_vaddr`:映射的起始地址 235 /// - `len`:映射的长度 236 /// - `prot_flags`:保护标志 237 /// - `map_flags`:映射标志 238 /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界 239 /// 240 /// ## 返回 241 /// 242 /// 返回映射的起始虚拟页帧 243 pub fn map_anonymous( 244 &mut self, 245 start_vaddr: VirtAddr, 246 len: usize, 247 prot_flags: ProtFlags, 248 map_flags: MapFlags, 249 round_to_min: bool, 250 ) -> Result<VirtPageFrame, SystemError> { 251 // 用于对齐hint的函数 252 let round_hint_to_min = |hint: VirtAddr| { 253 // 先把hint向下对齐到页边界 254 let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK); 255 // kdebug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint); 256 // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR 257 if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) { 258 Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR))) 259 } else if addr == 0 { 260 None 261 } else { 262 Some(VirtAddr::new(addr)) 263 } 264 }; 265 // kdebug!("map_anonymous: start_vaddr = {:?}", start_vaddr); 266 // kdebug!("map_anonymous: len(no align) = {}", len); 267 268 let len = page_align_up(len); 269 270 // kdebug!("map_anonymous: len = {}", len); 271 272 let start_page: VirtPageFrame = self.mmap( 273 round_hint_to_min(start_vaddr), 274 PageFrameCount::from_bytes(len).unwrap(), 275 prot_flags, 276 map_flags, 277 move |page, count, flags, mapper, flusher| { 278 Ok(VMA::zeroed(page, count, flags, mapper, flusher)?) 279 }, 280 )?; 281 282 return Ok(start_page); 283 } 284 285 /// 向进程的地址空间映射页面 286 /// 287 /// # 参数 288 /// 289 /// - `addr`:映射的起始地址,如果为`None`,则由内核自动分配 290 /// - `page_count`:映射的页面数量 291 /// - `prot_flags`:保护标志 292 /// - `map_flags`:映射标志 293 /// - `map_func`:映射函数,用于创建VMA 294 /// 295 /// # Returns 296 /// 297 /// 返回映射的起始虚拟页帧 298 /// 299 /// # Errors 300 /// 301 /// - `EINVAL`:参数错误 302 pub fn mmap< 303 F: FnOnce( 304 VirtPageFrame, 305 PageFrameCount, 306 PageFlags<MMArch>, 307 &mut PageMapper, 308 &mut dyn Flusher<MMArch>, 309 ) -> Result<Arc<LockedVMA>, SystemError>, 310 >( 311 &mut self, 312 addr: Option<VirtAddr>, 313 page_count: PageFrameCount, 314 prot_flags: ProtFlags, 315 map_flags: MapFlags, 316 map_func: F, 317 ) -> Result<VirtPageFrame, SystemError> { 318 if page_count == PageFrameCount::new(0) { 319 return Err(SystemError::EINVAL); 320 } 321 // kdebug!("mmap: addr: {addr:?}, page_count: {page_count:?}, prot_flags: {prot_flags:?}, map_flags: {map_flags:?}"); 322 323 // 找到未使用的区域 324 let region = match addr { 325 Some(vaddr) => { 326 self.mappings 327 .find_free_at(self.mmap_min, vaddr, page_count.bytes(), map_flags)? 328 } 329 None => self 330 .mappings 331 .find_free(self.mmap_min, page_count.bytes()) 332 .ok_or(SystemError::ENOMEM)?, 333 }; 334 335 let page = VirtPageFrame::new(region.start()); 336 337 // kdebug!("mmap: page: {:?}, region={region:?}", page.virt_address()); 338 339 compiler_fence(Ordering::SeqCst); 340 let (mut active, mut inactive); 341 let flusher = if self.is_current() { 342 active = PageFlushAll::new(); 343 &mut active as &mut dyn Flusher<MMArch> 344 } else { 345 inactive = InactiveFlusher::new(); 346 &mut inactive as &mut dyn Flusher<MMArch> 347 }; 348 compiler_fence(Ordering::SeqCst); 349 // 映射页面,并将VMA插入到地址空间的VMA列表中 350 self.mappings.insert_vma(map_func( 351 page, 352 page_count, 353 PageFlags::from_prot_flags(prot_flags, true), 354 &mut self.user_mapper.utable, 355 flusher, 356 )?); 357 358 return Ok(page); 359 } 360 361 /// 取消进程的地址空间中的映射 362 /// 363 /// # 参数 364 /// 365 /// - `start_page`:起始页帧 366 /// - `page_count`:取消映射的页帧数量 367 /// 368 /// # Errors 369 /// 370 /// - `EINVAL`:参数错误 371 /// - `ENOMEM`:内存不足 372 pub fn munmap( 373 &mut self, 374 start_page: VirtPageFrame, 375 page_count: PageFrameCount, 376 ) -> Result<(), SystemError> { 377 let to_unmap = VirtRegion::new(start_page.virt_address(), page_count.bytes()); 378 let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 379 380 let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>(); 381 382 for r in regions { 383 let r = r.lock().region; 384 let r = self.mappings.remove_vma(&r).unwrap(); 385 let intersection = r.lock().region().intersect(&to_unmap).unwrap(); 386 let (before, r, after) = r.extract(intersection).unwrap(); 387 388 // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑 389 390 if let Some(before) = before { 391 // 如果前面有VMA,则需要将前面的VMA重新插入到地址空间的VMA列表中 392 self.mappings.insert_vma(before); 393 } 394 395 if let Some(after) = after { 396 // 如果后面有VMA,则需要将后面的VMA重新插入到地址空间的VMA列表中 397 self.mappings.insert_vma(after); 398 } 399 400 r.unmap(&mut self.user_mapper.utable, &mut flusher); 401 } 402 403 // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑 404 405 return Ok(()); 406 } 407 408 pub fn mprotect( 409 &mut self, 410 start_page: VirtPageFrame, 411 page_count: PageFrameCount, 412 prot_flags: ProtFlags, 413 ) -> Result<(), SystemError> { 414 // kdebug!( 415 // "mprotect: start_page: {:?}, page_count: {:?}, prot_flags:{prot_flags:?}", 416 // start_page, 417 // page_count 418 // ); 419 let (mut active, mut inactive); 420 let mut flusher = if self.is_current() { 421 active = PageFlushAll::new(); 422 &mut active as &mut dyn Flusher<MMArch> 423 } else { 424 inactive = InactiveFlusher::new(); 425 &mut inactive as &mut dyn Flusher<MMArch> 426 }; 427 428 let mapper = &mut self.user_mapper.utable; 429 let region = VirtRegion::new(start_page.virt_address(), page_count.bytes()); 430 // kdebug!("mprotect: region: {:?}", region); 431 432 let regions = self.mappings.conflicts(region).collect::<Vec<_>>(); 433 // kdebug!("mprotect: regions: {:?}", regions); 434 435 for r in regions { 436 // kdebug!("mprotect: r: {:?}", r); 437 let r = r.lock().region().clone(); 438 let r = self.mappings.remove_vma(&r).unwrap(); 439 440 let intersection = r.lock().region().intersect(®ion).unwrap(); 441 let (before, r, after) = r.extract(intersection).expect("Failed to extract VMA"); 442 443 if let Some(before) = before { 444 self.mappings.insert_vma(before); 445 } 446 if let Some(after) = after { 447 self.mappings.insert_vma(after); 448 } 449 450 let mut r_guard = r.lock(); 451 // 如果VMA的保护标志不允许指定的修改,则返回错误 452 if !r_guard.can_have_flags(prot_flags) { 453 drop(r_guard); 454 self.mappings.insert_vma(r.clone()); 455 return Err(SystemError::EACCES); 456 } 457 458 let new_flags: PageFlags<MMArch> = r_guard 459 .flags() 460 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 461 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 462 463 r_guard.remap(new_flags, mapper, &mut flusher)?; 464 drop(r_guard); 465 self.mappings.insert_vma(r); 466 } 467 468 return Ok(()); 469 } 470 471 /// 创建新的用户栈 472 /// 473 /// ## 参数 474 /// 475 /// - `size`:栈的大小 476 pub fn new_user_stack(&mut self, size: usize) -> Result<(), SystemError> { 477 assert!(self.user_stack.is_none(), "User stack already exists"); 478 let stack = UserStack::new(self, None, size)?; 479 self.user_stack = Some(stack); 480 return Ok(()); 481 } 482 483 #[inline(always)] 484 pub fn user_stack_mut(&mut self) -> Option<&mut UserStack> { 485 return self.user_stack.as_mut(); 486 } 487 488 /// 取消用户空间内的所有映射 489 pub unsafe fn unmap_all(&mut self) { 490 let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 491 for vma in self.mappings.iter_vmas() { 492 vma.unmap(&mut self.user_mapper.utable, &mut flusher); 493 } 494 } 495 496 /// 设置进程的堆的内存空间 497 /// 498 /// ## 参数 499 /// 500 /// - `new_brk`:新的堆的结束地址。需要满足页对齐要求,并且是用户空间地址,且大于等于当前的堆的起始地址 501 /// 502 /// ## 返回值 503 /// 504 /// 返回旧的堆的结束地址 505 pub unsafe fn set_brk(&mut self, new_brk: VirtAddr) -> Result<VirtAddr, SystemError> { 506 assert!(new_brk.check_aligned(MMArch::PAGE_SIZE)); 507 508 if !new_brk.check_user() || new_brk < self.brk_start { 509 return Err(SystemError::EFAULT); 510 } 511 512 let old_brk = self.brk; 513 514 if new_brk > self.brk { 515 let len = new_brk - self.brk; 516 let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 517 let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED; 518 self.map_anonymous(old_brk, len, prot_flags, map_flags, true)?; 519 520 self.brk = new_brk; 521 return Ok(old_brk); 522 } else { 523 let unmap_len = self.brk - new_brk; 524 let unmap_start = new_brk; 525 if unmap_len == 0 { 526 return Ok(old_brk); 527 } 528 self.munmap( 529 VirtPageFrame::new(unmap_start), 530 PageFrameCount::from_bytes(unmap_len).unwrap(), 531 )?; 532 self.brk = new_brk; 533 return Ok(old_brk); 534 } 535 } 536 537 pub unsafe fn sbrk(&mut self, incr: isize) -> Result<VirtAddr, SystemError> { 538 if incr == 0 { 539 return Ok(self.brk); 540 } 541 542 let new_brk = if incr > 0 { 543 self.brk + incr as usize 544 } else { 545 self.brk - (incr.abs() as usize) 546 }; 547 548 let new_brk = VirtAddr::new(page_align_up(new_brk.data())); 549 550 return self.set_brk(new_brk); 551 } 552 } 553 554 impl Drop for InnerAddressSpace { 555 fn drop(&mut self) { 556 unsafe { 557 self.unmap_all(); 558 } 559 } 560 } 561 562 #[derive(Debug, Hash)] 563 pub struct UserMapper { 564 pub utable: PageMapper, 565 } 566 567 impl UserMapper { 568 pub fn new(utable: PageMapper) -> Self { 569 return Self { utable }; 570 } 571 } 572 573 impl Drop for UserMapper { 574 fn drop(&mut self) { 575 if self.utable.is_current() { 576 // 如果当前要被销毁的用户空间的页表是当前进程的页表,那么就切换回初始内核页表 577 unsafe { MMArch::set_table(PageTableKind::User, MMArch::initial_page_table()) } 578 } 579 // 释放用户空间顶层页表占用的页帧 580 // 请注意,在释放这个页帧之前,用户页表应该已经被完全释放,否则会产生内存泄露 581 unsafe { 582 deallocate_page_frames( 583 PhysPageFrame::new(self.utable.table().phys()), 584 PageFrameCount::new(1), 585 ) 586 }; 587 } 588 } 589 590 /// 用户空间映射信息 591 #[derive(Debug)] 592 pub struct UserMappings { 593 /// 当前用户空间的虚拟内存区域 594 vmas: HashSet<Arc<LockedVMA>>, 595 /// 当前用户空间的VMA空洞 596 vm_holes: BTreeMap<VirtAddr, usize>, 597 } 598 599 impl UserMappings { 600 pub fn new() -> Self { 601 return Self { 602 vmas: HashSet::new(), 603 vm_holes: core::iter::once((VirtAddr::new(0), MMArch::USER_END_VADDR.data())) 604 .collect::<BTreeMap<_, _>>(), 605 }; 606 } 607 608 /// 判断当前进程的VMA内,是否有包含指定的虚拟地址的VMA。 609 /// 610 /// 如果有,返回包含指定虚拟地址的VMA的Arc指针,否则返回None。 611 #[allow(dead_code)] 612 pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> { 613 for v in self.vmas.iter() { 614 let guard = v.lock(); 615 if guard.region.contains(vaddr) { 616 return Some(v.clone()); 617 } 618 } 619 return None; 620 } 621 622 /// 获取当前进程的地址空间中,与给定虚拟地址范围有重叠的VMA的迭代器。 623 pub fn conflicts(&self, request: VirtRegion) -> impl Iterator<Item = Arc<LockedVMA>> + '_ { 624 let r = self 625 .vmas 626 .iter() 627 .filter(move |v| !v.lock().region.intersect(&request).is_none()) 628 .cloned(); 629 return r; 630 } 631 632 /// 在当前进程的地址空间中,寻找第一个符合条件的空闲的虚拟内存范围。 633 /// 634 /// @param min_vaddr 最小的起始地址 635 /// @param size 请求的大小 636 /// 637 /// @return 如果找到了,返回虚拟内存范围,否则返回None 638 pub fn find_free(&self, min_vaddr: VirtAddr, size: usize) -> Option<VirtRegion> { 639 let _vaddr = min_vaddr; 640 let mut iter = self 641 .vm_holes 642 .iter() 643 .skip_while(|(hole_vaddr, hole_size)| hole_vaddr.add(**hole_size) <= min_vaddr); 644 645 let (hole_vaddr, size) = iter.find(|(hole_vaddr, hole_size)| { 646 // 计算当前空洞的可用大小 647 let available_size: usize = 648 if hole_vaddr <= &&min_vaddr && min_vaddr <= hole_vaddr.add(**hole_size) { 649 **hole_size - (min_vaddr - **hole_vaddr) 650 } else { 651 **hole_size 652 }; 653 654 size <= available_size 655 })?; 656 657 // 创建一个新的虚拟内存范围。 658 let region = VirtRegion::new(cmp::max(*hole_vaddr, min_vaddr), *size); 659 return Some(region); 660 } 661 662 pub fn find_free_at( 663 &self, 664 min_vaddr: VirtAddr, 665 vaddr: VirtAddr, 666 size: usize, 667 flags: MapFlags, 668 ) -> Result<VirtRegion, SystemError> { 669 // 如果没有指定地址,那么就在当前进程的地址空间中寻找一个空闲的虚拟内存范围。 670 if vaddr == VirtAddr::new(0) { 671 return self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM); 672 } 673 674 // 如果指定了地址,那么就检查指定的地址是否可用。 675 676 let requested = VirtRegion::new(vaddr, size); 677 678 if requested.end() >= MMArch::USER_END_VADDR || !vaddr.check_aligned(MMArch::PAGE_SIZE) { 679 return Err(SystemError::EINVAL); 680 } 681 682 if let Some(_x) = self.conflicts(requested).next() { 683 if flags.contains(MapFlags::MAP_FIXED_NOREPLACE) { 684 // 如果指定了 MAP_FIXED_NOREPLACE 标志,由于所指定的地址无法成功建立映射,则放弃映射,不对地址做修正 685 return Err(SystemError::EEXIST); 686 } 687 688 if flags.contains(MapFlags::MAP_FIXED) { 689 // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖 690 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 691 } 692 693 // 如果没有指定MAP_FIXED标志,那么就对地址做修正 694 let requested = self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM)?; 695 return Ok(requested); 696 } 697 698 return Ok(requested); 699 } 700 701 /// 在当前进程的地址空间中,保留一个指定大小的区域,使得该区域不在空洞中。 702 /// 该函数会修改vm_holes中的空洞信息。 703 /// 704 /// @param region 要保留的区域 705 /// 706 /// 请注意,在调用本函数之前,必须先确定region所在范围内没有VMA。 707 fn reserve_hole(&mut self, region: &VirtRegion) { 708 let prev_hole: Option<(&VirtAddr, &mut usize)> = 709 self.vm_holes.range_mut(..region.start()).next_back(); 710 711 if let Some((prev_hole_vaddr, prev_hole_size)) = prev_hole { 712 let prev_hole_end = prev_hole_vaddr.add(*prev_hole_size); 713 714 if prev_hole_end > region.start() { 715 // 如果前一个空洞的结束地址大于当前空洞的起始地址,那么就需要调整前一个空洞的大小。 716 *prev_hole_size = region.start().data() - prev_hole_vaddr.data(); 717 } 718 719 if prev_hole_end > region.end() { 720 // 如果前一个空洞的结束地址大于当前空洞的结束地址,那么就需要增加一个新的空洞。 721 self.vm_holes 722 .insert(region.end(), prev_hole_end - region.end()); 723 } 724 } 725 } 726 727 /// 在当前进程的地址空间中,释放一个指定大小的区域,使得该区域成为一个空洞。 728 /// 该函数会修改vm_holes中的空洞信息。 729 fn unreserve_hole(&mut self, region: &VirtRegion) { 730 // 如果将要插入的空洞与后一个空洞相邻,那么就需要合并。 731 let next_hole_size: Option<usize> = self.vm_holes.remove(®ion.end()); 732 733 if let Some((_prev_hole_vaddr, prev_hole_size)) = self 734 .vm_holes 735 .range_mut(..region.start()) 736 .next_back() 737 .filter(|(offset, size)| offset.data() + **size == region.start().data()) 738 { 739 *prev_hole_size += region.size() + next_hole_size.unwrap_or(0); 740 } else { 741 self.vm_holes 742 .insert(region.start(), region.size() + next_hole_size.unwrap_or(0)); 743 } 744 } 745 746 /// 在当前进程的映射关系中,插入一个新的VMA。 747 pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { 748 let region = vma.lock().region.clone(); 749 // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。 750 assert!(self.conflicts(region).next().is_none()); 751 self.reserve_hole(®ion); 752 753 self.vmas.insert(vma); 754 } 755 756 /// @brief 删除一个VMA,并把对应的地址空间加入空洞中。 757 /// 758 /// 这里不会取消VMA对应的地址的映射 759 /// 760 /// @param region 要删除的VMA所在的地址范围 761 /// 762 /// @return 如果成功删除了VMA,则返回被删除的VMA,否则返回None 763 /// 如果没有可以删除的VMA,则不会执行删除操作,并报告失败。 764 pub fn remove_vma(&mut self, region: &VirtRegion) -> Option<Arc<LockedVMA>> { 765 // 请注意,由于这里会对每个VMA加锁,因此性能很低 766 let vma: Arc<LockedVMA> = self 767 .vmas 768 .drain_filter(|vma| vma.lock().region == *region) 769 .next()?; 770 self.unreserve_hole(region); 771 772 return Some(vma); 773 } 774 775 /// @brief Get the iterator of all VMAs in this process. 776 pub fn iter_vmas(&self) -> hashbrown::hash_set::Iter<Arc<LockedVMA>> { 777 return self.vmas.iter(); 778 } 779 } 780 781 impl Default for UserMappings { 782 fn default() -> Self { 783 return Self::new(); 784 } 785 } 786 787 /// 加了锁的VMA 788 /// 789 /// 备注:进行性能测试,看看SpinLock和RwLock哪个更快。 790 #[derive(Debug)] 791 pub struct LockedVMA(SpinLock<VMA>); 792 793 impl core::hash::Hash for LockedVMA { 794 fn hash<H: Hasher>(&self, state: &mut H) { 795 self.0.lock().hash(state); 796 } 797 } 798 799 impl PartialEq for LockedVMA { 800 fn eq(&self, other: &Self) -> bool { 801 self.0.lock().eq(&other.0.lock()) 802 } 803 } 804 805 impl Eq for LockedVMA {} 806 807 #[allow(dead_code)] 808 impl LockedVMA { 809 pub fn new(vma: VMA) -> Arc<Self> { 810 let r = Arc::new(Self(SpinLock::new(vma))); 811 r.0.lock().self_ref = Arc::downgrade(&r); 812 return r; 813 } 814 815 pub fn lock(&self) -> SpinLockGuard<VMA> { 816 return self.0.lock(); 817 } 818 819 /// 调整当前VMA的页面的标志位 820 /// 821 /// TODO:增加调整虚拟页映射的物理地址的功能 822 /// 823 /// @param flags 新的标志位 824 /// @param mapper 页表映射器 825 /// @param flusher 页表项刷新器 826 /// 827 pub fn remap( 828 &self, 829 flags: PageFlags<MMArch>, 830 mapper: &mut PageMapper, 831 mut flusher: impl Flusher<MMArch>, 832 ) -> Result<(), SystemError> { 833 let mut guard = self.lock(); 834 assert!(guard.mapped); 835 for page in guard.region.pages() { 836 // 暂时要求所有的页帧都已经映射到页表 837 // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了 838 let r = unsafe { 839 mapper 840 .remap(page.virt_address(), flags) 841 .expect("Failed to remap, beacuse of some page is not mapped") 842 }; 843 flusher.consume(r); 844 } 845 guard.flags = flags; 846 return Ok(()); 847 } 848 849 pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) { 850 // todo: 如果当前vma与文件相关,完善文件相关的逻辑 851 852 let mut guard = self.lock(); 853 assert!(guard.mapped); 854 for page in guard.region.pages() { 855 let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) } 856 .expect("Failed to unmap, beacuse of some page is not mapped"); 857 858 // todo: 获取物理页的anon_vma的守卫 859 860 // todo: 从anon_vma中删除当前VMA 861 862 // todo: 如果物理页的anon_vma链表长度为0,则释放物理页. 863 864 // 目前由于还没有实现共享页,所以直接释放物理页也没问题。 865 // 但是在实现共享页之后,就不能直接释放物理页了,需要在anon_vma链表长度为0的时候才能释放物理页 866 unsafe { deallocate_page_frames(PhysPageFrame::new(paddr), PageFrameCount::new(1)) }; 867 868 flusher.consume(flush); 869 } 870 guard.mapped = false; 871 } 872 873 pub fn mapped(&self) -> bool { 874 return self.0.lock().mapped; 875 } 876 877 /// 将当前VMA进行切分,切分成3个VMA,分别是: 878 /// 879 /// 1. 前面的VMA,如果没有则为None 880 /// 2. 中间的VMA,也就是传入的Region 881 /// 3. 后面的VMA,如果没有则为None 882 pub fn extract( 883 &self, 884 region: VirtRegion, 885 ) -> Option<( 886 Option<Arc<LockedVMA>>, 887 Arc<LockedVMA>, 888 Option<Arc<LockedVMA>>, 889 )> { 890 assert!(region.start().check_aligned(MMArch::PAGE_SIZE)); 891 assert!(region.end().check_aligned(MMArch::PAGE_SIZE)); 892 893 let mut guard = self.lock(); 894 { 895 // 如果传入的region不在当前VMA的范围内,则直接返回None 896 if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end()) 897 { 898 return None; 899 } 900 901 let intersect: Option<VirtRegion> = guard.region.intersect(®ion); 902 // 如果当前VMA不包含region,则直接返回None 903 if unlikely(intersect.is_none()) { 904 return None; 905 } 906 let intersect: VirtRegion = intersect.unwrap(); 907 if unlikely(intersect == guard.region) { 908 // 如果当前VMA完全包含region,则直接返回当前VMA 909 return Some((None, guard.self_ref.upgrade().unwrap(), None)); 910 } 911 } 912 913 let before: Option<Arc<LockedVMA>> = guard.region.before(®ion).map(|virt_region| { 914 let mut vma: VMA = unsafe { guard.clone() }; 915 vma.region = virt_region; 916 917 let vma: Arc<LockedVMA> = LockedVMA::new(vma); 918 vma 919 }); 920 921 let after: Option<Arc<LockedVMA>> = guard.region.after(®ion).map(|virt_region| { 922 let mut vma: VMA = unsafe { guard.clone() }; 923 vma.region = virt_region; 924 925 let vma: Arc<LockedVMA> = LockedVMA::new(vma); 926 vma 927 }); 928 929 guard.region = region; 930 931 // TODO: 重新设置before、after这两个VMA里面的物理页的anon_vma 932 933 return Some((before, guard.self_ref.upgrade().unwrap(), after)); 934 } 935 } 936 937 /// @brief 虚拟内存区域 938 #[derive(Debug)] 939 pub struct VMA { 940 /// 虚拟内存区域对应的虚拟地址范围 941 region: VirtRegion, 942 /// VMA内的页帧的标志 943 flags: PageFlags<MMArch>, 944 /// VMA内的页帧是否已经映射到页表 945 mapped: bool, 946 /// VMA所属的用户地址空间 947 user_address_space: Option<Weak<AddressSpace>>, 948 self_ref: Weak<LockedVMA>, 949 } 950 951 impl core::hash::Hash for VMA { 952 fn hash<H: Hasher>(&self, state: &mut H) { 953 self.region.hash(state); 954 self.flags.hash(state); 955 self.mapped.hash(state); 956 } 957 } 958 959 #[allow(dead_code)] 960 impl VMA { 961 pub fn region(&self) -> &VirtRegion { 962 return &self.region; 963 } 964 965 /// # 拷贝当前VMA的内容 966 /// 967 /// ### 安全性 968 /// 969 /// 由于这样操作可能由于错误的拷贝,导致内存泄露、内存重复释放等问题,所以需要小心使用。 970 pub unsafe fn clone(&self) -> Self { 971 return Self { 972 region: self.region, 973 flags: self.flags, 974 mapped: self.mapped, 975 user_address_space: self.user_address_space.clone(), 976 self_ref: self.self_ref.clone(), 977 }; 978 } 979 980 #[inline(always)] 981 pub fn flags(&self) -> PageFlags<MMArch> { 982 return self.flags; 983 } 984 985 pub fn pages(&self) -> VirtPageFrameIter { 986 return VirtPageFrameIter::new( 987 VirtPageFrame::new(self.region.start()), 988 VirtPageFrame::new(self.region.end()), 989 ); 990 } 991 992 pub fn remap( 993 &mut self, 994 flags: PageFlags<MMArch>, 995 mapper: &mut PageMapper, 996 mut flusher: impl Flusher<MMArch>, 997 ) -> Result<(), SystemError> { 998 assert!(self.mapped); 999 for page in self.region.pages() { 1000 // kdebug!("remap page {:?}", page.virt_address()); 1001 // 暂时要求所有的页帧都已经映射到页表 1002 // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了 1003 let r = unsafe { 1004 mapper 1005 .remap(page.virt_address(), flags) 1006 .expect("Failed to remap, beacuse of some page is not mapped") 1007 }; 1008 // kdebug!("consume page {:?}", page.virt_address()); 1009 flusher.consume(r); 1010 // kdebug!("remap page {:?} done", page.virt_address()); 1011 } 1012 self.flags = flags; 1013 return Ok(()); 1014 } 1015 1016 /// 检查当前VMA是否可以拥有指定的标志位 1017 /// 1018 /// ## 参数 1019 /// 1020 /// - `prot_flags` 要检查的标志位 1021 pub fn can_have_flags(&self, prot_flags: ProtFlags) -> bool { 1022 return (self.flags.has_write() || !prot_flags.contains(ProtFlags::PROT_WRITE)) 1023 && (self.flags.has_execute() || !prot_flags.contains(ProtFlags::PROT_EXEC)); 1024 } 1025 1026 /// 把物理地址映射到虚拟地址 1027 /// 1028 /// @param phys 要映射的物理地址 1029 /// @param destination 要映射到的虚拟地址 1030 /// @param count 要映射的页帧数量 1031 /// @param flags 页面标志位 1032 /// @param mapper 页表映射器 1033 /// @param flusher 页表项刷新器 1034 /// 1035 /// @return 返回映射后的虚拟内存区域 1036 pub fn physmap( 1037 phys: PhysPageFrame, 1038 destination: VirtPageFrame, 1039 count: PageFrameCount, 1040 flags: PageFlags<MMArch>, 1041 mapper: &mut PageMapper, 1042 mut flusher: impl Flusher<MMArch>, 1043 ) -> Result<Arc<LockedVMA>, SystemError> { 1044 { 1045 let mut cur_phy = phys; 1046 let mut cur_dest = destination; 1047 1048 for _ in 0..count.data() { 1049 // 将物理页帧映射到虚拟页帧 1050 let r = unsafe { 1051 mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags) 1052 } 1053 .expect("Failed to map phys, may be OOM error"); 1054 1055 // todo: 增加OOM处理 1056 1057 // todo: 将VMA加入到anon_vma中 1058 1059 // 刷新TLB 1060 flusher.consume(r); 1061 1062 cur_phy = cur_phy.next(); 1063 cur_dest = cur_dest.next(); 1064 } 1065 } 1066 1067 let r: Arc<LockedVMA> = LockedVMA::new(VMA { 1068 region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE), 1069 flags, 1070 mapped: true, 1071 user_address_space: None, 1072 self_ref: Weak::default(), 1073 }); 1074 return Ok(r); 1075 } 1076 1077 /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA 1078 /// 1079 /// @param destination 要映射到的虚拟地址 1080 /// @param count 要映射的页帧数量 1081 /// @param flags 页面标志位 1082 /// @param mapper 页表映射器 1083 /// @param flusher 页表项刷新器 1084 /// 1085 /// @return 返回映射后的虚拟内存区域 1086 pub fn zeroed( 1087 destination: VirtPageFrame, 1088 page_count: PageFrameCount, 1089 flags: PageFlags<MMArch>, 1090 mapper: &mut PageMapper, 1091 mut flusher: impl Flusher<MMArch>, 1092 ) -> Result<Arc<LockedVMA>, SystemError> { 1093 let mut cur_dest: VirtPageFrame = destination; 1094 // kdebug!( 1095 // "VMA::zeroed: page_count = {:?}, destination={destination:?}", 1096 // page_count 1097 // ); 1098 for _ in 0..page_count.data() { 1099 // kdebug!( 1100 // "VMA::zeroed: cur_dest={cur_dest:?}, vaddr = {:?}", 1101 // cur_dest.virt_address() 1102 // ); 1103 let r = unsafe { mapper.map(cur_dest.virt_address(), flags) } 1104 .expect("Failed to map zero, may be OOM error"); 1105 // todo: 将VMA加入到anon_vma中 1106 // todo: 增加OOM处理 1107 1108 // 稍后再刷新TLB,这里取消刷新 1109 flusher.consume(r); 1110 cur_dest = cur_dest.next(); 1111 } 1112 let r = LockedVMA::new(VMA { 1113 region: VirtRegion::new( 1114 destination.virt_address(), 1115 page_count.data() * MMArch::PAGE_SIZE, 1116 ), 1117 flags, 1118 mapped: true, 1119 user_address_space: None, 1120 self_ref: Weak::default(), 1121 }); 1122 drop(flusher); 1123 // kdebug!("VMA::zeroed: flusher dropped"); 1124 1125 // 清空这些内存 1126 let virt_iter: VirtPageFrameIter = 1127 VirtPageFrameIter::new(destination, destination.add(page_count)); 1128 for frame in virt_iter { 1129 let paddr = mapper.translate(frame.virt_address()).unwrap().0; 1130 1131 unsafe { 1132 let vaddr = MMArch::phys_2_virt(paddr).unwrap(); 1133 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 1134 } 1135 } 1136 // kdebug!("VMA::zeroed: done"); 1137 return Ok(r); 1138 } 1139 } 1140 1141 impl Drop for VMA { 1142 fn drop(&mut self) { 1143 // 当VMA被释放时,需要确保它已经被从页表中解除映射 1144 assert!(!self.mapped, "VMA is still mapped"); 1145 } 1146 } 1147 1148 impl PartialEq for VMA { 1149 fn eq(&self, other: &Self) -> bool { 1150 return self.region == other.region; 1151 } 1152 } 1153 1154 impl Eq for VMA {} 1155 1156 impl PartialOrd for VMA { 1157 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 1158 return self.region.partial_cmp(&other.region); 1159 } 1160 } 1161 1162 impl Ord for VMA { 1163 fn cmp(&self, other: &Self) -> cmp::Ordering { 1164 return self.region.cmp(&other.region); 1165 } 1166 } 1167 1168 #[derive(Debug)] 1169 pub struct UserStack { 1170 // 栈底地址 1171 stack_bottom: VirtAddr, 1172 // 当前已映射的大小 1173 mapped_size: usize, 1174 /// 栈顶地址(这个值需要仔细确定!因为它可能不会实时与用户栈的真实栈顶保持一致!要小心!) 1175 current_sp: VirtAddr, 1176 } 1177 1178 impl UserStack { 1179 /// 默认的用户栈底地址 1180 pub const DEFAULT_USER_STACK_BOTTOM: VirtAddr = MMArch::USER_STACK_START; 1181 /// 默认的用户栈大小为8MB 1182 pub const DEFAULT_USER_STACK_SIZE: usize = 8 * 1024 * 1024; 1183 /// 用户栈的保护页数量 1184 pub const GUARD_PAGES_NUM: usize = 4; 1185 1186 /// 创建一个用户栈 1187 pub fn new( 1188 vm: &mut InnerAddressSpace, 1189 stack_bottom: Option<VirtAddr>, 1190 stack_size: usize, 1191 ) -> Result<Self, SystemError> { 1192 let stack_bottom = stack_bottom.unwrap_or(Self::DEFAULT_USER_STACK_BOTTOM); 1193 assert!(stack_bottom.check_aligned(MMArch::PAGE_SIZE)); 1194 1195 // 分配用户栈的保护页 1196 let guard_size = Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE; 1197 let actual_stack_bottom = stack_bottom - guard_size; 1198 1199 let mut prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE; 1200 let map_flags = 1201 MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE; 1202 // kdebug!( 1203 // "map anonymous stack: {:?} {}", 1204 // actual_stack_bottom, 1205 // guard_size 1206 // ); 1207 vm.map_anonymous( 1208 actual_stack_bottom, 1209 guard_size, 1210 prot_flags, 1211 map_flags, 1212 false, 1213 )?; 1214 // test_buddy(); 1215 // 设置保护页只读 1216 prot_flags.remove(ProtFlags::PROT_WRITE); 1217 // kdebug!( 1218 // "to mprotect stack guard pages: {:?} {}", 1219 // actual_stack_bottom, 1220 // guard_size 1221 // ); 1222 vm.mprotect( 1223 VirtPageFrame::new(actual_stack_bottom), 1224 PageFrameCount::new(Self::GUARD_PAGES_NUM), 1225 prot_flags, 1226 )?; 1227 1228 // kdebug!( 1229 // "mprotect stack guard pages done: {:?} {}", 1230 // actual_stack_bottom, 1231 // guard_size 1232 // ); 1233 1234 let mut user_stack = UserStack { 1235 stack_bottom: actual_stack_bottom, 1236 mapped_size: guard_size, 1237 current_sp: actual_stack_bottom - guard_size, 1238 }; 1239 1240 // kdebug!("extend user stack: {:?} {}", stack_bottom, stack_size); 1241 // 分配用户栈 1242 user_stack.initial_extend(vm, stack_size)?; 1243 // kdebug!("user stack created: {:?} {}", stack_bottom, stack_size); 1244 return Ok(user_stack); 1245 } 1246 1247 fn initial_extend( 1248 &mut self, 1249 vm: &mut InnerAddressSpace, 1250 mut bytes: usize, 1251 ) -> Result<(), SystemError> { 1252 let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 1253 let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS; 1254 1255 bytes = page_align_up(bytes); 1256 self.mapped_size += bytes; 1257 1258 vm.map_anonymous( 1259 self.stack_bottom - self.mapped_size, 1260 bytes, 1261 prot_flags, 1262 map_flags, 1263 false, 1264 )?; 1265 1266 return Ok(()); 1267 } 1268 1269 /// 扩展用户栈 1270 /// 1271 /// ## 参数 1272 /// 1273 /// - `vm` 用户地址空间结构体 1274 /// - `bytes` 要扩展的字节数 1275 /// 1276 /// ## 返回值 1277 /// 1278 /// - **Ok(())** 扩展成功 1279 /// - **Err(SystemError)** 扩展失败 1280 #[allow(dead_code)] 1281 pub fn extend( 1282 &mut self, 1283 vm: &mut RwLockWriteGuard<InnerAddressSpace>, 1284 mut bytes: usize, 1285 ) -> Result<(), SystemError> { 1286 let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 1287 let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS; 1288 1289 bytes = page_align_up(bytes); 1290 self.mapped_size += bytes; 1291 1292 vm.map_anonymous( 1293 self.stack_bottom - self.mapped_size, 1294 bytes, 1295 prot_flags, 1296 map_flags, 1297 false, 1298 )?; 1299 1300 return Ok(()); 1301 } 1302 1303 /// 获取栈顶地址 1304 /// 1305 /// 请注意,如果用户栈的栈顶地址发生变化,这个值可能不会实时更新! 1306 pub fn sp(&self) -> VirtAddr { 1307 return self.current_sp; 1308 } 1309 1310 pub unsafe fn set_sp(&mut self, sp: VirtAddr) { 1311 self.current_sp = sp; 1312 } 1313 1314 /// 仅仅克隆用户栈的信息,不会克隆用户栈的内容/映射 1315 pub unsafe fn clone_info_only(&self) -> Self { 1316 return Self { 1317 stack_bottom: self.stack_bottom, 1318 mapped_size: self.mapped_size, 1319 current_sp: self.current_sp, 1320 }; 1321 } 1322 1323 /// 获取当前用户栈的大小(不包括保护页) 1324 pub fn stack_size(&self) -> usize { 1325 return self.mapped_size - Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE; 1326 } 1327 } 1328