1 pub mod barrier; 2 pub mod bump; 3 mod c_adapter; 4 5 use alloc::vec::Vec; 6 use hashbrown::HashSet; 7 use x86::time::rdtsc; 8 use x86_64::registers::model_specific::EferFlags; 9 10 use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port; 11 use crate::filesystem::procfs::kmsg::kmsg_init; 12 use crate::include::bindings::bindings::{ 13 multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t, 14 multiboot_tag_load_base_addr_t, 15 }; 16 use crate::libs::align::page_align_up; 17 use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window; 18 use crate::libs::printk::PrintkWriter; 19 use crate::libs::spinlock::SpinLock; 20 21 use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; 22 use crate::mm::memblock::mem_block_manager; 23 use crate::mm::mmio_buddy::mmio_init; 24 use crate::{ 25 arch::MMArch, 26 mm::allocator::{buddy::BuddyAllocator, bump::BumpAllocator}, 27 }; 28 29 use crate::mm::kernel_mapper::KernelMapper; 30 use crate::mm::page::{PageEntry, PageFlags}; 31 use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr}; 32 use crate::{kdebug, kinfo, kwarn}; 33 use system_error::SystemError; 34 35 use core::arch::asm; 36 use core::ffi::c_void; 37 use core::fmt::{Debug, Write}; 38 use core::mem::{self}; 39 40 use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; 41 42 use super::kvm::vmx::vmcs::VmcsFields; 43 use super::kvm::vmx::vmx_asm_wrapper::vmx_vmread; 44 45 pub type PageMapper = 46 crate::mm::page::PageMapper<crate::arch::x86_64::mm::X86_64MMArch, LockedFrameAllocator>; 47 48 /// 初始的CR3寄存器的值,用于内存管理初始化时,创建的第一个内核页表的位置 49 static mut INITIAL_CR3_VALUE: PhysAddr = PhysAddr::new(0); 50 51 /// 内核的第一个页表在pml4中的索引 52 /// 顶级页表的[256, 512)项是内核的页表 53 static KERNEL_PML4E_NO: usize = (X86_64MMArch::PHYS_OFFSET & ((1 << 48) - 1)) >> 39; 54 55 static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None); 56 57 #[derive(Clone, Copy, Debug)] 58 pub struct X86_64MMBootstrapInfo { 59 kernel_load_base_paddr: usize, 60 kernel_code_start: usize, 61 kernel_code_end: usize, 62 kernel_data_end: usize, 63 kernel_rodata_end: usize, 64 start_brk: usize, 65 } 66 67 pub(super) static mut BOOTSTRAP_MM_INFO: Option<X86_64MMBootstrapInfo> = None; 68 69 /// @brief X86_64的内存管理架构结构体 70 #[derive(Debug, Clone, Copy, Hash)] 71 pub struct X86_64MMArch; 72 73 /// XD标志位是否被保留 74 static XD_RESERVED: AtomicBool = AtomicBool::new(false); 75 76 impl MemoryManagementArch for X86_64MMArch { 77 /// 4K页 78 const PAGE_SHIFT: usize = 12; 79 80 /// 每个页表项占8字节,总共有512个页表项 81 const PAGE_ENTRY_SHIFT: usize = 9; 82 83 /// 四级页表(PML4T、PDPT、PDT、PT) 84 const PAGE_LEVELS: usize = 4; 85 86 /// 页表项的有效位的index。在x86_64中,页表项的第[0, 47]位表示地址和flag, 87 /// 第[48, 51]位表示保留。因此,有效位的index为52。 88 /// 请注意,第63位是XD位,表示是否允许执行。 89 const ENTRY_ADDRESS_SHIFT: usize = 52; 90 91 const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT; 92 93 const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT; 94 95 const ENTRY_FLAG_PRESENT: usize = 1 << 0; 96 97 const ENTRY_FLAG_READONLY: usize = 0; 98 99 const ENTRY_FLAG_READWRITE: usize = 1 << 1; 100 101 const ENTRY_FLAG_USER: usize = 1 << 2; 102 103 const ENTRY_FLAG_WRITE_THROUGH: usize = 1 << 3; 104 105 const ENTRY_FLAG_CACHE_DISABLE: usize = 1 << 4; 106 107 const ENTRY_FLAG_NO_EXEC: usize = 1 << 63; 108 /// x86_64不存在EXEC标志位,只有NO_EXEC(XD)标志位 109 const ENTRY_FLAG_EXEC: usize = 0; 110 111 /// 物理地址与虚拟地址的偏移量 112 /// 0xffff_8000_0000_0000 113 const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1); 114 115 const USER_END_VADDR: VirtAddr = VirtAddr::new(0x0000_7eff_ffff_ffff); 116 const USER_BRK_START: VirtAddr = VirtAddr::new(0x700000000000); 117 const USER_STACK_START: VirtAddr = VirtAddr::new(0x6ffff0a00000); 118 119 const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffffb00000000000); 120 /// 设置FIXMAP区域大小为1M 121 const FIXMAP_SIZE: usize = 256 * 4096; 122 123 /// @brief 获取物理内存区域 124 unsafe fn init() { 125 extern "C" { 126 fn _text(); 127 fn _etext(); 128 fn _edata(); 129 fn _erodata(); 130 fn _end(); 131 } 132 133 Self::init_xd_rsvd(); 134 let load_base_paddr = Self::get_load_base_paddr(); 135 136 let bootstrap_info = X86_64MMBootstrapInfo { 137 kernel_load_base_paddr: load_base_paddr.data(), 138 kernel_code_start: _text as usize, 139 kernel_code_end: _etext as usize, 140 kernel_data_end: _edata as usize, 141 kernel_rodata_end: _erodata as usize, 142 start_brk: _end as usize, 143 }; 144 145 unsafe { 146 BOOTSTRAP_MM_INFO = Some(bootstrap_info); 147 } 148 149 // 初始化物理内存区域(从multiboot2中获取) 150 Self::init_memory_area_from_multiboot2().expect("init memory area failed"); 151 152 send_to_default_serial8250_port("x86 64 init end\n\0".as_bytes()); 153 } 154 155 /// @brief 刷新TLB中,关于指定虚拟地址的条目 156 unsafe fn invalidate_page(address: VirtAddr) { 157 compiler_fence(Ordering::SeqCst); 158 asm!("invlpg [{0}]", in(reg) address.data(), options(nostack, preserves_flags)); 159 compiler_fence(Ordering::SeqCst); 160 } 161 162 /// @brief 刷新TLB中,所有的条目 163 unsafe fn invalidate_all() { 164 compiler_fence(Ordering::SeqCst); 165 // 通过设置cr3寄存器,来刷新整个TLB 166 Self::set_table(PageTableKind::User, Self::table(PageTableKind::User)); 167 compiler_fence(Ordering::SeqCst); 168 } 169 170 /// @brief 获取顶级页表的物理地址 171 unsafe fn table(table_kind: PageTableKind) -> PhysAddr { 172 match table_kind { 173 PageTableKind::Kernel | PageTableKind::User => { 174 let paddr: usize; 175 compiler_fence(Ordering::SeqCst); 176 asm!("mov {}, cr3", out(reg) paddr, options(nomem, nostack, preserves_flags)); 177 compiler_fence(Ordering::SeqCst); 178 return PhysAddr::new(paddr); 179 } 180 PageTableKind::EPT => { 181 let eptp = 182 vmx_vmread(VmcsFields::CTRL_EPTP_PTR as u32).expect("Failed to read eptp"); 183 return PhysAddr::new(eptp as usize); 184 } 185 } 186 } 187 188 /// @brief 设置顶级页表的物理地址到处理器中 189 unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { 190 compiler_fence(Ordering::SeqCst); 191 asm!("mov cr3, {}", in(reg) table.data(), options(nostack, preserves_flags)); 192 compiler_fence(Ordering::SeqCst); 193 } 194 195 /// @brief 判断虚拟地址是否合法 196 fn virt_is_valid(virt: VirtAddr) -> bool { 197 return virt.is_canonical(); 198 } 199 200 /// 获取内存管理初始化时,创建的第一个内核页表的地址 201 fn initial_page_table() -> PhysAddr { 202 unsafe { 203 return INITIAL_CR3_VALUE; 204 } 205 } 206 207 /// @brief 创建新的顶层页表 208 /// 209 /// 该函数会创建页表并复制内核的映射到新的页表中 210 /// 211 /// @return 新的页表 212 fn setup_new_usermapper() -> Result<crate::mm::ucontext::UserMapper, SystemError> { 213 let new_umapper: crate::mm::page::PageMapper<X86_64MMArch, LockedFrameAllocator> = unsafe { 214 PageMapper::create(PageTableKind::User, LockedFrameAllocator) 215 .ok_or(SystemError::ENOMEM)? 216 }; 217 218 let current_ktable: KernelMapper = KernelMapper::lock(); 219 let copy_mapping = |pml4_entry_no| unsafe { 220 let entry: PageEntry<X86_64MMArch> = current_ktable 221 .table() 222 .entry(pml4_entry_no) 223 .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no)); 224 new_umapper.table().set_entry(pml4_entry_no, entry) 225 }; 226 227 // 复制内核的映射 228 for pml4_entry_no in KERNEL_PML4E_NO..512 { 229 copy_mapping(pml4_entry_no); 230 } 231 232 return Ok(crate::mm::ucontext::UserMapper::new(new_umapper)); 233 } 234 235 const PAGE_SIZE: usize = 1 << Self::PAGE_SHIFT; 236 237 const PAGE_OFFSET_MASK: usize = Self::PAGE_SIZE - 1; 238 239 const PAGE_MASK: usize = !(Self::PAGE_OFFSET_MASK); 240 241 const PAGE_ADDRESS_SHIFT: usize = Self::PAGE_LEVELS * Self::PAGE_ENTRY_SHIFT + Self::PAGE_SHIFT; 242 243 const PAGE_ADDRESS_SIZE: usize = 1 << Self::PAGE_ADDRESS_SHIFT; 244 245 const PAGE_ADDRESS_MASK: usize = Self::PAGE_ADDRESS_SIZE - Self::PAGE_SIZE; 246 247 const PAGE_ENTRY_SIZE: usize = 1 << (Self::PAGE_SHIFT - Self::PAGE_ENTRY_SHIFT); 248 249 const PAGE_ENTRY_NUM: usize = 1 << Self::PAGE_ENTRY_SHIFT; 250 251 const PAGE_ENTRY_MASK: usize = Self::PAGE_ENTRY_NUM - 1; 252 253 const PAGE_NEGATIVE_MASK: usize = !((Self::PAGE_ADDRESS_SIZE) - 1); 254 255 const ENTRY_ADDRESS_SIZE: usize = 1 << Self::ENTRY_ADDRESS_SHIFT; 256 257 const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - Self::PAGE_SIZE; 258 259 const ENTRY_FLAGS_MASK: usize = !Self::ENTRY_ADDRESS_MASK; 260 261 unsafe fn read<T>(address: VirtAddr) -> T { 262 return core::ptr::read(address.data() as *const T); 263 } 264 265 unsafe fn write<T>(address: VirtAddr, value: T) { 266 core::ptr::write(address.data() as *mut T, value); 267 } 268 269 unsafe fn write_bytes(address: VirtAddr, value: u8, count: usize) { 270 core::ptr::write_bytes(address.data() as *mut u8, value, count); 271 } 272 273 unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> { 274 if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { 275 return Some(VirtAddr::new(vaddr)); 276 } else { 277 return None; 278 } 279 } 280 281 unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> { 282 if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { 283 return Some(PhysAddr::new(paddr)); 284 } else { 285 return None; 286 } 287 } 288 289 #[inline(always)] 290 fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { 291 return paddr.data() | page_flags; 292 } 293 } 294 295 impl X86_64MMArch { 296 unsafe fn get_load_base_paddr() -> PhysAddr { 297 let mut mb2_lb_info: [multiboot_tag_load_base_addr_t; 512] = mem::zeroed(); 298 send_to_default_serial8250_port("get_load_base_paddr begin\n\0".as_bytes()); 299 300 let mut mb2_count: u32 = 0; 301 multiboot2_iter( 302 Some(multiboot2_get_load_base), 303 &mut mb2_lb_info as *mut [multiboot_tag_load_base_addr_t; 512] as usize as *mut c_void, 304 &mut mb2_count, 305 ); 306 307 if mb2_count == 0 { 308 send_to_default_serial8250_port( 309 "get_load_base_paddr mb2_count == 0, default to 1MB\n\0".as_bytes(), 310 ); 311 return PhysAddr::new(0x100000); 312 } 313 314 let phys = mb2_lb_info[0].load_base_addr as usize; 315 316 return PhysAddr::new(phys); 317 } 318 unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> { 319 // 这个数组用来存放内存区域的信息(从C获取) 320 let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed(); 321 send_to_default_serial8250_port("init_memory_area_from_multiboot2 begin\n\0".as_bytes()); 322 323 let mut mb2_count: u32 = 0; 324 multiboot2_iter( 325 Some(multiboot2_get_memory), 326 &mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void, 327 &mut mb2_count, 328 ); 329 send_to_default_serial8250_port("init_memory_area_from_multiboot2 2\n\0".as_bytes()); 330 331 let mb2_count = mb2_count as usize; 332 let mut areas_count = 0usize; 333 let mut total_mem_size = 0usize; 334 for i in 0..mb2_count { 335 // Only use the memory area if its type is 1 (RAM) 336 if mb2_mem_info[i].type_ == 1 { 337 // Skip the memory area if its len is 0 338 if mb2_mem_info[i].len == 0 { 339 continue; 340 } 341 342 total_mem_size += mb2_mem_info[i].len as usize; 343 344 mem_block_manager() 345 .add_block( 346 PhysAddr::new(mb2_mem_info[i].addr as usize), 347 mb2_mem_info[i].len as usize, 348 ) 349 .unwrap_or_else(|e| { 350 kwarn!( 351 "Failed to add memory block: base={:#x}, size={:#x}, error={:?}", 352 mb2_mem_info[i].addr, 353 mb2_mem_info[i].len, 354 e 355 ); 356 }); 357 areas_count += 1; 358 } 359 } 360 send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes()); 361 kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024); 362 return Ok(areas_count); 363 } 364 365 fn init_xd_rsvd() { 366 // 读取ia32-EFER寄存器的值 367 let efer: EferFlags = x86_64::registers::model_specific::Efer::read(); 368 if !efer.contains(EferFlags::NO_EXECUTE_ENABLE) { 369 // NO_EXECUTE_ENABLE是false,那么就设置xd_reserved为true 370 kdebug!("NO_EXECUTE_ENABLE is false, set XD_RESERVED to true"); 371 XD_RESERVED.store(true, Ordering::Relaxed); 372 } 373 compiler_fence(Ordering::SeqCst); 374 } 375 376 /// 判断XD标志位是否被保留 377 pub fn is_xd_reserved() -> bool { 378 // return XD_RESERVED.load(Ordering::Relaxed); 379 380 // 由于暂时不支持execute disable,因此直接返回true 381 // 不支持的原因是,目前好像没有能正确的设置page-level的xd位,会触发page fault 382 return true; 383 } 384 } 385 386 impl VirtAddr { 387 /// @brief 判断虚拟地址是否合法 388 #[inline(always)] 389 pub fn is_canonical(self) -> bool { 390 let x = self.data() & X86_64MMArch::PHYS_OFFSET; 391 // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 392 // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 393 return x == 0 || x == X86_64MMArch::PHYS_OFFSET; 394 } 395 } 396 397 /// @brief 初始化内存管理模块 398 pub fn mm_init() { 399 send_to_default_serial8250_port("mm_init\n\0".as_bytes()); 400 PrintkWriter 401 .write_fmt(format_args!("mm_init() called\n")) 402 .unwrap(); 403 // printk_color!(GREEN, BLACK, "mm_init() called\n"); 404 static _CALL_ONCE: AtomicBool = AtomicBool::new(false); 405 if _CALL_ONCE 406 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) 407 .is_err() 408 { 409 send_to_default_serial8250_port("mm_init err\n\0".as_bytes()); 410 panic!("mm_init() can only be called once"); 411 } 412 413 unsafe { X86_64MMArch::init() }; 414 kdebug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO }); 415 kdebug!("phys[0]=virt[0x{:x}]", unsafe { 416 MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data() 417 }); 418 419 // 初始化内存管理器 420 unsafe { allocator_init() }; 421 // enable mmio 422 mmio_init(); 423 // enable KMSG 424 kmsg_init(); 425 } 426 427 unsafe fn allocator_init() { 428 let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk; 429 let phy_offset = 430 unsafe { MMArch::virt_2_phys(VirtAddr::new(page_align_up(virt_offset))) }.unwrap(); 431 432 let mut bump_allocator = BumpAllocator::<X86_64MMArch>::new(phy_offset.data()); 433 kdebug!( 434 "BumpAllocator created, offset={:?}", 435 bump_allocator.offset() 436 ); 437 438 // 暂存初始在head.S中指定的页表的地址,后面再考虑是否需要把它加到buddy的可用空间里面! 439 // 现在不加的原因是,我担心会有安全漏洞问题:这些初始的页表,位于内核的数据段。如果归还到buddy, 440 // 可能会产生一定的安全风险(有的代码可能根据虚拟地址来进行安全校验) 441 let _old_page_table = MMArch::table(PageTableKind::Kernel); 442 443 let new_page_table: PhysAddr; 444 // 使用bump分配器,把所有的内存页都映射到页表 445 { 446 // 用bump allocator创建新的页表 447 let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> = 448 crate::mm::page::PageMapper::<MMArch, _>::create( 449 PageTableKind::Kernel, 450 &mut bump_allocator, 451 ) 452 .expect("Failed to create page mapper"); 453 new_page_table = mapper.table().phys(); 454 kdebug!("PageMapper created"); 455 456 // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB) 457 { 458 let table = mapper.table(); 459 let empty_entry = PageEntry::<MMArch>::from_usize(0); 460 for i in 0..MMArch::PAGE_ENTRY_NUM { 461 table 462 .set_entry(i, empty_entry) 463 .expect("Failed to empty page table entry"); 464 } 465 } 466 kdebug!("Successfully emptied page table"); 467 468 let total_num = mem_block_manager().total_initial_memory_regions(); 469 for i in 0..total_num { 470 let area = mem_block_manager().get_initial_memory_region(i).unwrap(); 471 // kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size); 472 for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) { 473 let paddr = area.base.add(i * MMArch::PAGE_SIZE); 474 let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap(); 475 let flags = kernel_page_flags::<MMArch>(vaddr); 476 477 let flusher = mapper 478 .map_phys(vaddr, paddr, flags) 479 .expect("Failed to map frame"); 480 // 暂时不刷新TLB 481 flusher.ignore(); 482 } 483 } 484 485 // 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射) 486 LowAddressRemapping::remap_at_low_address(&mut mapper); 487 } 488 489 unsafe { 490 INITIAL_CR3_VALUE = new_page_table; 491 } 492 kdebug!( 493 "After mapping all physical memory, DragonOS used: {} KB", 494 bump_allocator.offset() / 1024 495 ); 496 497 // 初始化buddy_allocator 498 let buddy_allocator = unsafe { BuddyAllocator::<X86_64MMArch>::new(bump_allocator).unwrap() }; 499 // 设置全局的页帧分配器 500 unsafe { set_inner_allocator(buddy_allocator) }; 501 kinfo!("Successfully initialized buddy allocator"); 502 // 关闭显示输出 503 scm_disable_put_to_window(); 504 505 // make the new page table current 506 { 507 let mut binding = INNER_ALLOCATOR.lock(); 508 let mut allocator_guard = binding.as_mut().unwrap(); 509 kdebug!("To enable new page table."); 510 compiler_fence(Ordering::SeqCst); 511 let mapper = crate::mm::page::PageMapper::<MMArch, _>::new( 512 PageTableKind::Kernel, 513 new_page_table, 514 &mut allocator_guard, 515 ); 516 compiler_fence(Ordering::SeqCst); 517 mapper.make_current(); 518 compiler_fence(Ordering::SeqCst); 519 kdebug!("New page table enabled"); 520 } 521 kdebug!("Successfully enabled new page table"); 522 } 523 524 #[no_mangle] 525 pub extern "C" fn rs_test_buddy() { 526 test_buddy(); 527 } 528 pub fn test_buddy() { 529 // 申请内存然后写入数据然后free掉 530 // 总共申请200MB内存 531 const TOTAL_SIZE: usize = 200 * 1024 * 1024; 532 533 for i in 0..10 { 534 kdebug!("Test buddy, round: {i}"); 535 // 存放申请的内存块 536 let mut v: Vec<(PhysAddr, PageFrameCount)> = Vec::with_capacity(60 * 1024); 537 // 存放已经申请的内存块的地址(用于检查重复) 538 let mut addr_set: HashSet<PhysAddr> = HashSet::new(); 539 540 let mut allocated = 0usize; 541 542 let mut free_count = 0usize; 543 544 while allocated < TOTAL_SIZE { 545 let mut random_size = 0u64; 546 unsafe { x86::random::rdrand64(&mut random_size) }; 547 // 一次最多申请4M 548 random_size = random_size % (1024 * 4096); 549 if random_size == 0 { 550 continue; 551 } 552 let random_size = 553 core::cmp::min(page_align_up(random_size as usize), TOTAL_SIZE - allocated); 554 let random_size = PageFrameCount::from_bytes(random_size.next_power_of_two()).unwrap(); 555 // 获取帧 556 let (paddr, allocated_frame_count) = 557 unsafe { LockedFrameAllocator.allocate(random_size).unwrap() }; 558 assert!(allocated_frame_count.data().is_power_of_two()); 559 assert!(paddr.data() % MMArch::PAGE_SIZE == 0); 560 unsafe { 561 assert!(MMArch::phys_2_virt(paddr) 562 .as_ref() 563 .unwrap() 564 .check_aligned(allocated_frame_count.data() * MMArch::PAGE_SIZE)); 565 } 566 allocated += allocated_frame_count.data() * MMArch::PAGE_SIZE; 567 v.push((paddr, allocated_frame_count)); 568 assert!(addr_set.insert(paddr), "duplicate address: {:?}", paddr); 569 570 // 写入数据 571 let vaddr = unsafe { MMArch::phys_2_virt(paddr).unwrap() }; 572 let slice = unsafe { 573 core::slice::from_raw_parts_mut( 574 vaddr.data() as *mut u8, 575 allocated_frame_count.data() * MMArch::PAGE_SIZE, 576 ) 577 }; 578 for i in 0..slice.len() { 579 slice[i] = ((i + unsafe { rdtsc() } as usize) % 256) as u8; 580 } 581 582 // 随机释放一个内存块 583 if v.len() > 0 { 584 let mut random_index = 0u64; 585 unsafe { x86::random::rdrand64(&mut random_index) }; 586 // 70%概率释放 587 if random_index % 10 > 7 { 588 continue; 589 } 590 random_index = random_index % v.len() as u64; 591 let random_index = random_index as usize; 592 let (paddr, allocated_frame_count) = v.remove(random_index); 593 assert!(addr_set.remove(&paddr)); 594 unsafe { LockedFrameAllocator.free(paddr, allocated_frame_count) }; 595 free_count += allocated_frame_count.data() * MMArch::PAGE_SIZE; 596 } 597 } 598 599 kdebug!( 600 "Allocated {} MB memory, release: {} MB, no release: {} bytes", 601 allocated / 1024 / 1024, 602 free_count / 1024 / 1024, 603 (allocated - free_count) 604 ); 605 606 kdebug!("Now, to release buddy memory"); 607 // 释放所有的内存 608 for (paddr, allocated_frame_count) in v { 609 unsafe { LockedFrameAllocator.free(paddr, allocated_frame_count) }; 610 assert!(addr_set.remove(&paddr)); 611 free_count += allocated_frame_count.data() * MMArch::PAGE_SIZE; 612 } 613 614 kdebug!("release done!, allocated: {allocated}, free_count: {free_count}"); 615 } 616 } 617 618 /// 全局的页帧分配器 619 #[derive(Debug, Clone, Copy, Hash)] 620 pub struct LockedFrameAllocator; 621 622 impl FrameAllocator for LockedFrameAllocator { 623 unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 624 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 625 return allocator.allocate(count); 626 } else { 627 return None; 628 } 629 } 630 631 unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { 632 assert!(count.data().is_power_of_two()); 633 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 634 return allocator.free(address, count); 635 } 636 } 637 638 unsafe fn usage(&self) -> PageFrameUsage { 639 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 640 return allocator.usage(); 641 } else { 642 panic!("usage error"); 643 } 644 } 645 } 646 647 /// 获取内核地址默认的页面标志 648 pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> { 649 let info: X86_64MMBootstrapInfo = BOOTSTRAP_MM_INFO.clone().unwrap(); 650 651 if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end { 652 // Remap kernel code execute 653 return PageFlags::new().set_execute(true).set_write(true); 654 } else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end { 655 // Remap kernel rodata read only 656 return PageFlags::new().set_execute(true); 657 } else { 658 return PageFlags::new().set_write(true).set_execute(true); 659 } 660 } 661 662 unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) { 663 static FLAG: AtomicBool = AtomicBool::new(false); 664 if FLAG 665 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) 666 .is_err() 667 { 668 panic!("Cannot set inner allocator twice!"); 669 } 670 *INNER_ALLOCATOR.lock() = Some(allocator); 671 } 672 673 /// 低地址重映射的管理器 674 /// 675 /// 低地址重映射的管理器,在smp初始化完成之前,需要使用低地址的映射,因此需要在smp初始化完成之后,取消这一段映射 676 pub struct LowAddressRemapping; 677 678 impl LowAddressRemapping { 679 // 映射32M 680 const REMAP_SIZE: usize = 32 * 1024 * 1024; 681 682 pub unsafe fn remap_at_low_address( 683 mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>, 684 ) { 685 for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) { 686 let paddr = PhysAddr::new(i * MMArch::PAGE_SIZE); 687 let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE); 688 let flags = kernel_page_flags::<MMArch>(vaddr); 689 690 let flusher = mapper 691 .map_phys(vaddr, paddr, flags) 692 .expect("Failed to map frame"); 693 // 暂时不刷新TLB 694 flusher.ignore(); 695 } 696 } 697 698 /// 取消低地址的映射 699 pub unsafe fn unmap_at_low_address(flush: bool) { 700 let mut mapper = KernelMapper::lock(); 701 assert!(mapper.as_mut().is_some()); 702 for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) { 703 let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE); 704 let (_, _, flusher) = mapper 705 .as_mut() 706 .unwrap() 707 .unmap_phys(vaddr, true) 708 .expect("Failed to unmap frame"); 709 if flush == false { 710 flusher.ignore(); 711 } 712 } 713 } 714 } 715 #[no_mangle] 716 pub extern "C" fn rs_mm_init() { 717 mm_init(); 718 } 719