1 //! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能
2 //!
3 //! 这里假设在内核引导文件中,已经填写了前100M的内存映射关系,因此这里不需要任何动态分配。
4 //!
5 //! 映射关系为:
6 //!
7 //! 虚拟地址 0-100M与虚拟地址 0x8000_0000_0000 - 0x8000_0640_0000 之间具有重映射关系。
8 //! 也就是说,他们的第二级页表在最顶级页表中,占用了第0和第256个页表项。
9 //!
10 
11 use crate::mm::{MMArch, MemoryManagementArch, PhysAddr};
12 use core::marker::PhantomData;
13 
14 use super::{
15     allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
16     page::PageFlags,
17     PageTableKind, VirtAddr,
18 };
19 
20 /// 伪分配器
21 struct PseudoAllocator<MMA> {
22     phantom: PhantomData<MMA>,
23 }
24 
25 impl<MMA: MemoryManagementArch> PseudoAllocator<MMA> {
new() -> Self26     pub const fn new() -> Self {
27         Self {
28             phantom: PhantomData,
29         }
30     }
31 }
32 
33 /// 为NoInitAllocator实现FrameAllocator
34 impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
allocate(&mut self, _count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)>35     unsafe fn allocate(&mut self, _count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
36         panic!("NoInitAllocator can't allocate page frame");
37     }
38 
free(&mut self, _address: PhysAddr, _count: PageFrameCount)39     unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) {
40         panic!("NoInitAllocator can't free page frame");
41     }
42     /// @brief: 获取内存区域页帧的使用情况
43     /// @param  self
44     /// @return 页帧的使用情况
usage(&self) -> PageFrameUsage45     unsafe fn usage(&self) -> PageFrameUsage {
46         panic!("NoInitAllocator can't get page frame usage");
47     }
48 }
49 
50 /// Use pseudo mapper to map physical memory to virtual memory.
51 ///
52 /// ## Safety
53 ///
54 /// 调用该函数时,必须保证内存管理器尚未初始化。否则将导致未定义的行为
55 ///
56 /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount)57 pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
58     assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
59     assert!(paddr.check_aligned(MMArch::PAGE_SIZE));
60 
61     let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();
62 
63     let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
64         PageTableKind::Kernel,
65         MMArch::table(PageTableKind::Kernel),
66         &mut pseudo_allocator,
67     );
68 
69     let flags: PageFlags<MMArch> = PageFlags::new().set_write(true).set_execute(true);
70 
71     for i in 0..count.data() {
72         let vaddr = vaddr + i * MMArch::PAGE_SIZE;
73         let paddr = paddr + i * MMArch::PAGE_SIZE;
74         let flusher = mapper.map_phys(vaddr, paddr, flags).unwrap();
75         flusher.ignore();
76     }
77 
78     mapper.make_current();
79 }
80