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}, 2240fe15e0SLoGin page::PageFlags, 2340fe15e0SLoGin PageTableKind, VirtAddr, 2440fe15e0SLoGin }; 2540fe15e0SLoGin 26c75ef4e2SLoGin /// 用于存储重映射页表的位图和页面 27*7a29d4fcSLoGin pub static EARLY_IOREMAP_PAGES: SpinLock<EarlyIoRemapPages> = 28*7a29d4fcSLoGin 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 /// 清空数据 40c75ef4e2SLoGin fn zero(&mut self) { 41c75ef4e2SLoGin self.data.fill(0); 42c75ef4e2SLoGin } 43c75ef4e2SLoGin } 44c75ef4e2SLoGin 45c75ef4e2SLoGin #[repr(C)] 46*7a29d4fcSLoGin 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; 54c75ef4e2SLoGin 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 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 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 { 89c75ef4e2SLoGin assert_eq!(self.bmp.get(index).unwrap(), true); 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> { 10140fe15e0SLoGin 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> { 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)?; 114*7a29d4fcSLoGin kdebug!("allocate page: vaddr={:?}, paddr={:?}", vaddr, paddr); 115c75ef4e2SLoGin return Some((paddr, count)); 11640fe15e0SLoGin } 11740fe15e0SLoGin 118c75ef4e2SLoGin unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) { 119c75ef4e2SLoGin assert_eq!(count.data(), 1); 120c75ef4e2SLoGin assert!(address.check_aligned(MMA::PAGE_SIZE)); 121*7a29d4fcSLoGin kdebug!("free page: paddr={:?}", address); 122c75ef4e2SLoGin let vaddr = MMA::phys_2_virt(address); 123c75ef4e2SLoGin if let Some(vaddr) = vaddr { 124c75ef4e2SLoGin EARLY_IOREMAP_PAGES.lock_irqsave().free_page(vaddr); 125c75ef4e2SLoGin } 12640fe15e0SLoGin } 12740fe15e0SLoGin /// @brief: 获取内存区域页帧的使用情况 12840fe15e0SLoGin /// @param self 12940fe15e0SLoGin /// @return 页帧的使用情况 13040fe15e0SLoGin unsafe fn usage(&self) -> PageFrameUsage { 131c75ef4e2SLoGin // 暂时不支持 13240fe15e0SLoGin panic!("NoInitAllocator can't get page frame usage"); 13340fe15e0SLoGin } 13440fe15e0SLoGin } 13540fe15e0SLoGin 13640fe15e0SLoGin /// Use pseudo mapper to map physical memory to virtual memory. 13740fe15e0SLoGin /// 13840fe15e0SLoGin /// ## Safety 13940fe15e0SLoGin /// 14040fe15e0SLoGin /// 调用该函数时,必须保证内存管理器尚未初始化。否则将导致未定义的行为 14140fe15e0SLoGin /// 14240fe15e0SLoGin /// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准) 14374ffde66SLoGin #[inline(never)] 14440fe15e0SLoGin pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) { 145*7a29d4fcSLoGin let flags: PageFlags<MMArch> = PageFlags::new().set_write(true).set_execute(true); 146*7a29d4fcSLoGin 147*7a29d4fcSLoGin pseudo_map_phys_with_flags(vaddr, paddr, count, flags); 148*7a29d4fcSLoGin } 149*7a29d4fcSLoGin 150*7a29d4fcSLoGin /// Use pseudo mapper to map physical memory to virtual memory 151*7a29d4fcSLoGin /// with READ_ONLY and EXECUTE flags. 152*7a29d4fcSLoGin #[inline(never)] 153*7a29d4fcSLoGin pub unsafe fn pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) { 154*7a29d4fcSLoGin let flags: PageFlags<MMArch> = PageFlags::new().set_write(false).set_execute(true); 155*7a29d4fcSLoGin 156*7a29d4fcSLoGin pseudo_map_phys_with_flags(vaddr, paddr, count, flags); 157*7a29d4fcSLoGin } 158*7a29d4fcSLoGin 159*7a29d4fcSLoGin #[inline(never)] 160*7a29d4fcSLoGin pub unsafe fn pseudo_map_phys_with_flags( 161*7a29d4fcSLoGin vaddr: VirtAddr, 162*7a29d4fcSLoGin paddr: PhysAddr, 163*7a29d4fcSLoGin count: PageFrameCount, 164*7a29d4fcSLoGin flags: PageFlags<MMArch>, 165*7a29d4fcSLoGin ) { 16640fe15e0SLoGin assert!(vaddr.check_aligned(MMArch::PAGE_SIZE)); 16740fe15e0SLoGin assert!(paddr.check_aligned(MMArch::PAGE_SIZE)); 16840fe15e0SLoGin 16940fe15e0SLoGin let mut pseudo_allocator = PseudoAllocator::<MMArch>::new(); 17040fe15e0SLoGin 17140fe15e0SLoGin let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new( 17240fe15e0SLoGin PageTableKind::Kernel, 17340fe15e0SLoGin MMArch::table(PageTableKind::Kernel), 17440fe15e0SLoGin &mut pseudo_allocator, 17540fe15e0SLoGin ); 17640fe15e0SLoGin 17740fe15e0SLoGin for i in 0..count.data() { 17840fe15e0SLoGin let vaddr = vaddr + i * MMArch::PAGE_SIZE; 17940fe15e0SLoGin let paddr = paddr + i * MMArch::PAGE_SIZE; 180*7a29d4fcSLoGin let flusher: crate::mm::page::PageFlush<MMArch> = 181*7a29d4fcSLoGin mapper.map_phys(vaddr, paddr, flags).unwrap(); 18240fe15e0SLoGin flusher.ignore(); 18340fe15e0SLoGin } 18440fe15e0SLoGin 18540fe15e0SLoGin mapper.make_current(); 18640fe15e0SLoGin } 18774ffde66SLoGin 18874ffde66SLoGin /// Unmap physical memory from virtual memory. 18974ffde66SLoGin /// 19074ffde66SLoGin /// ## 说明 19174ffde66SLoGin /// 19274ffde66SLoGin /// 该函数在系统启动早期,内存管理尚未初始化的时候使用 19374ffde66SLoGin #[inline(never)] 19474ffde66SLoGin pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) { 19574ffde66SLoGin assert!(vaddr.check_aligned(MMArch::PAGE_SIZE)); 19674ffde66SLoGin assert!(count.data() == 1); 19774ffde66SLoGin 19874ffde66SLoGin let mut pseudo_allocator = PseudoAllocator::<MMArch>::new(); 19974ffde66SLoGin 20074ffde66SLoGin let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new( 20174ffde66SLoGin PageTableKind::Kernel, 20274ffde66SLoGin MMArch::table(PageTableKind::Kernel), 20374ffde66SLoGin &mut pseudo_allocator, 20474ffde66SLoGin ); 20574ffde66SLoGin 20674ffde66SLoGin for i in 0..count.data() { 20774ffde66SLoGin let vaddr = vaddr + i * MMArch::PAGE_SIZE; 20874ffde66SLoGin mapper.unmap_phys(vaddr, true).map(|(_, _, flusher)| { 20974ffde66SLoGin flusher.ignore(); 21074ffde66SLoGin }); 21174ffde66SLoGin } 21274ffde66SLoGin 21374ffde66SLoGin mapper.make_current(); 21474ffde66SLoGin } 215