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