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