xref: /DragonOS/kernel/src/mm/no_init.rs (revision cf7f801e1d50ee5b04cb728e4251a57f4183bfbc)
140fe15e0SLoGin //! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能
240fe15e0SLoGin //!
340fe15e0SLoGin //! 映射关系为:
440fe15e0SLoGin //!
540fe15e0SLoGin //! 虚拟地址 0-100M与虚拟地址 0x8000_0000_0000 - 0x8000_0640_0000 之间具有重映射关系。
640fe15e0SLoGin //! 也就是说,他们的第二级页表在最顶级页表中,占用了第0和第256个页表项。
740fe15e0SLoGin //!
8c75ef4e2SLoGin //! 对于x86:
9c75ef4e2SLoGin //! 这里假设在内核引导文件中,已经填写了前100M的页表,其中,前50M是真实映射到内存的,后面的仅仅创建了页表,表项全部为0。
1040fe15e0SLoGin 
11c75ef4e2SLoGin use bitmap::{traits::BitMapOps, StaticBitmap};
12c75ef4e2SLoGin 
13c75ef4e2SLoGin use crate::{
14c75ef4e2SLoGin     libs::spinlock::SpinLock,
15c75ef4e2SLoGin     mm::{MMArch, MemoryManagementArch, PhysAddr},
16c75ef4e2SLoGin };
17c75ef4e2SLoGin 
1840fe15e0SLoGin use core::marker::PhantomData;
1940fe15e0SLoGin 
2040fe15e0SLoGin use super::{
2140fe15e0SLoGin     allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
22*cf7f801eSMemoryShore     page::EntryFlags,
2340fe15e0SLoGin     PageTableKind, VirtAddr,
2440fe15e0SLoGin };
2540fe15e0SLoGin 
26c75ef4e2SLoGin /// 用于存储重映射页表的位图和页面
277a29d4fcSLoGin pub static EARLY_IOREMAP_PAGES: SpinLock<EarlyIoRemapPages> =
287a29d4fcSLoGin     SpinLock::new(EarlyIoRemapPages::new());
29c75ef4e2SLoGin 
30c75ef4e2SLoGin /// 早期重映射使用的页表
31c75ef4e2SLoGin #[repr(C)]
32c75ef4e2SLoGin #[repr(align(4096))]
33c75ef4e2SLoGin #[derive(Clone, Copy)]
34c75ef4e2SLoGin struct EarlyRemapPage {
35c75ef4e2SLoGin     data: [u64; MMArch::PAGE_SIZE],
36c75ef4e2SLoGin }
37c75ef4e2SLoGin 
38c75ef4e2SLoGin impl EarlyRemapPage {
39c75ef4e2SLoGin     /// 清空数据
zero(&mut self)40c75ef4e2SLoGin     fn zero(&mut self) {
41c75ef4e2SLoGin         self.data.fill(0);
42c75ef4e2SLoGin     }
43c75ef4e2SLoGin }
44c75ef4e2SLoGin 
45c75ef4e2SLoGin #[repr(C)]
467a29d4fcSLoGin pub struct EarlyIoRemapPages {
47c75ef4e2SLoGin     pages: [EarlyRemapPage; Self::EARLY_REMAP_PAGES_NUM],
48c75ef4e2SLoGin     bmp: StaticBitmap<{ Self::EARLY_REMAP_PAGES_NUM }>,
49c75ef4e2SLoGin }
50c75ef4e2SLoGin 
51c75ef4e2SLoGin impl EarlyIoRemapPages {
52c75ef4e2SLoGin     /// 预留的用于在内存管理初始化之前,映射内存所使用的页表数量
53c75ef4e2SLoGin     pub const EARLY_REMAP_PAGES_NUM: usize = 256;
new() -> Self54c75ef4e2SLoGin     pub const fn new() -> Self {
55c75ef4e2SLoGin         Self {
56c75ef4e2SLoGin             pages: [EarlyRemapPage {
57c75ef4e2SLoGin                 data: [0; MMArch::PAGE_SIZE],
58c75ef4e2SLoGin             }; Self::EARLY_REMAP_PAGES_NUM],
59c75ef4e2SLoGin             bmp: StaticBitmap::new(),
60c75ef4e2SLoGin         }
61c75ef4e2SLoGin     }
62c75ef4e2SLoGin 
63c75ef4e2SLoGin     /// 分配一个页面
64c75ef4e2SLoGin     ///
65c75ef4e2SLoGin     /// 如果成功,返回虚拟地址
66c75ef4e2SLoGin     ///
67c75ef4e2SLoGin     /// 如果失败,返回None
allocate_page(&mut self) -> Option<VirtAddr>68c75ef4e2SLoGin     pub fn allocate_page(&mut self) -> Option<VirtAddr> {
69c75ef4e2SLoGin         if let Some(index) = self.bmp.first_false_index() {
70c75ef4e2SLoGin             self.bmp.set(index, true);
71c75ef4e2SLoGin             // 清空数据
72c75ef4e2SLoGin             self.pages[index].zero();
73c75ef4e2SLoGin 
74c75ef4e2SLoGin             let p = &self.pages[index] as *const EarlyRemapPage as usize;
75c75ef4e2SLoGin             let vaddr = VirtAddr::new(p);
76c75ef4e2SLoGin             assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
77c75ef4e2SLoGin             return Some(vaddr);
78c75ef4e2SLoGin         } else {
79c75ef4e2SLoGin             return None;
80c75ef4e2SLoGin         }
81c75ef4e2SLoGin     }
82c75ef4e2SLoGin 
free_page(&mut self, addr: VirtAddr)83c75ef4e2SLoGin     pub fn free_page(&mut self, addr: VirtAddr) {
84c75ef4e2SLoGin         // 判断地址是否合法
85c75ef4e2SLoGin         let start_vaddr = &self.pages[0] as *const EarlyRemapPage as usize;
86c75ef4e2SLoGin         let offset = addr.data() - start_vaddr;
87c75ef4e2SLoGin         let index = offset / MMArch::PAGE_SIZE;
88c75ef4e2SLoGin         if index < Self::EARLY_REMAP_PAGES_NUM {
89b5b571e0SLoGin             assert!(self.bmp.get(index).unwrap());
90c75ef4e2SLoGin             self.bmp.set(index, false);
91c75ef4e2SLoGin         }
92c75ef4e2SLoGin     }
93c75ef4e2SLoGin }
94c75ef4e2SLoGin 
9540fe15e0SLoGin /// 伪分配器
9640fe15e0SLoGin struct PseudoAllocator<MMA> {
9740fe15e0SLoGin     phantom: PhantomData<MMA>,
9840fe15e0SLoGin }
9940fe15e0SLoGin 
10040fe15e0SLoGin impl<MMA: MemoryManagementArch> PseudoAllocator<MMA> {
new() -> Self10140fe15e0SLoGin     pub const fn new() -> Self {
10240fe15e0SLoGin         Self {
10340fe15e0SLoGin             phantom: PhantomData,
10440fe15e0SLoGin         }
10540fe15e0SLoGin     }
10640fe15e0SLoGin }
10740fe15e0SLoGin 
10840fe15e0SLoGin /// 为NoInitAllocator实现FrameAllocator
10940fe15e0SLoGin impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)>110c75ef4e2SLoGin     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
111c75ef4e2SLoGin         assert!(count.data() == 1);
112c75ef4e2SLoGin         let vaddr = EARLY_IOREMAP_PAGES.lock_irqsave().allocate_page()?;
113c75ef4e2SLoGin         let paddr = MMA::virt_2_phys(vaddr)?;
114c75ef4e2SLoGin         return Some((paddr, count));
11540fe15e0SLoGin     }
11640fe15e0SLoGin 
free(&mut self, address: PhysAddr, count: PageFrameCount)117c75ef4e2SLoGin     unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
118c75ef4e2SLoGin         assert_eq!(count.data(), 1);
119c75ef4e2SLoGin         assert!(address.check_aligned(MMA::PAGE_SIZE));
12092849878SLoGin 
121c75ef4e2SLoGin         let vaddr = MMA::phys_2_virt(address);
122c75ef4e2SLoGin         if let Some(vaddr) = vaddr {
123c75ef4e2SLoGin             EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr);
124c75ef4e2SLoGin         }
12540fe15e0SLoGin     }
12640fe15e0SLoGin     /// @brief: 获取内存区域页帧的使用情况
12740fe15e0SLoGin     /// @param  self
12840fe15e0SLoGin     /// @return 页帧的使用情况
usage(&self) -> PageFrameUsage12940fe15e0SLoGin     unsafe fn usage(&self) -> PageFrameUsage {
130c75ef4e2SLoGin         // 暂时不支持
13140fe15e0SLoGin         panic!("NoInitAllocator can't get page frame usage");
13240fe15e0SLoGin     }
13340fe15e0SLoGin }
13440fe15e0SLoGin 
13540fe15e0SLoGin /// Use pseudo mapper to map physical memory to virtual memory.
13640fe15e0SLoGin ///
13740fe15e0SLoGin /// ## Safety
13840fe15e0SLoGin ///
13940fe15e0SLoGin /// 调用该函数时,必须保证内存管理器尚未初始化。否则将导致未定义的行为
14040fe15e0SLoGin ///
14140fe15e0SLoGin /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
14274ffde66SLoGin #[inline(never)]
pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount)14340fe15e0SLoGin pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
144*cf7f801eSMemoryShore     let flags: EntryFlags<MMArch> = EntryFlags::new().set_write(true);
1457a29d4fcSLoGin 
1467a29d4fcSLoGin     pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
1477a29d4fcSLoGin }
1487a29d4fcSLoGin 
1497a29d4fcSLoGin /// Use pseudo mapper to map physical memory to virtual memory
1507a29d4fcSLoGin /// with READ_ONLY and EXECUTE flags.
1517a29d4fcSLoGin #[inline(never)]
pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount)1527a29d4fcSLoGin pub unsafe fn pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
153*cf7f801eSMemoryShore     let flags: EntryFlags<MMArch> = EntryFlags::new().set_write(false).set_execute(true);
1547a29d4fcSLoGin 
1557a29d4fcSLoGin     pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
1567a29d4fcSLoGin }
1577a29d4fcSLoGin 
1587a29d4fcSLoGin #[inline(never)]
pseudo_map_phys_with_flags( vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount, flags: EntryFlags<MMArch>, )1597a29d4fcSLoGin pub unsafe fn pseudo_map_phys_with_flags(
1607a29d4fcSLoGin     vaddr: VirtAddr,
1617a29d4fcSLoGin     paddr: PhysAddr,
1627a29d4fcSLoGin     count: PageFrameCount,
163*cf7f801eSMemoryShore     flags: EntryFlags<MMArch>,
1647a29d4fcSLoGin ) {
16540fe15e0SLoGin     assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
16640fe15e0SLoGin     assert!(paddr.check_aligned(MMArch::PAGE_SIZE));
16740fe15e0SLoGin 
16840fe15e0SLoGin     let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();
16940fe15e0SLoGin 
17040fe15e0SLoGin     let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
17140fe15e0SLoGin         PageTableKind::Kernel,
17240fe15e0SLoGin         MMArch::table(PageTableKind::Kernel),
17340fe15e0SLoGin         &mut pseudo_allocator,
17440fe15e0SLoGin     );
17540fe15e0SLoGin 
17640fe15e0SLoGin     for i in 0..count.data() {
17740fe15e0SLoGin         let vaddr = vaddr + i * MMArch::PAGE_SIZE;
17840fe15e0SLoGin         let paddr = paddr + i * MMArch::PAGE_SIZE;
1797a29d4fcSLoGin         let flusher: crate::mm::page::PageFlush<MMArch> =
1807a29d4fcSLoGin             mapper.map_phys(vaddr, paddr, flags).unwrap();
18140fe15e0SLoGin         flusher.ignore();
18240fe15e0SLoGin     }
18340fe15e0SLoGin 
18440fe15e0SLoGin     mapper.make_current();
18540fe15e0SLoGin }
18674ffde66SLoGin 
18774ffde66SLoGin /// Unmap physical memory from virtual memory.
18874ffde66SLoGin ///
18974ffde66SLoGin /// ## 说明
19074ffde66SLoGin ///
19174ffde66SLoGin /// 该函数在系统启动早期,内存管理尚未初始化的时候使用
19274ffde66SLoGin #[inline(never)]
pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount)19374ffde66SLoGin pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) {
19474ffde66SLoGin     assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
19574ffde66SLoGin 
19674ffde66SLoGin     let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();
19774ffde66SLoGin 
19874ffde66SLoGin     let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
19974ffde66SLoGin         PageTableKind::Kernel,
20074ffde66SLoGin         MMArch::table(PageTableKind::Kernel),
20174ffde66SLoGin         &mut pseudo_allocator,
20274ffde66SLoGin     );
20374ffde66SLoGin 
20474ffde66SLoGin     for i in 0..count.data() {
20574ffde66SLoGin         let vaddr = vaddr + i * MMArch::PAGE_SIZE;
206b5b571e0SLoGin         if let Some((_, _, flusher)) = mapper.unmap_phys(vaddr, true) {
20774ffde66SLoGin             flusher.ignore();
208b5b571e0SLoGin         };
20974ffde66SLoGin     }
21074ffde66SLoGin 
21174ffde66SLoGin     mapper.make_current();
21274ffde66SLoGin }
213