1*453452ccSLoGin use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; 2*453452ccSLoGin 3*453452ccSLoGin use system_error::SystemError; 4*453452ccSLoGin 57a29d4fcSLoGin use crate::{ 6*453452ccSLoGin arch::{ 7*453452ccSLoGin mm::{ 8*453452ccSLoGin kernel_page_flags, INNER_ALLOCATOR, KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, 9*453452ccSLoGin KERNEL_END_VA, 10*453452ccSLoGin }, 11*453452ccSLoGin MMArch, 12*453452ccSLoGin }, 13*453452ccSLoGin driver::firmware::efi::efi_manager, 14*453452ccSLoGin kdebug, kinfo, 15*453452ccSLoGin libs::lib_ui::screen_manager::scm_disable_put_to_window, 16*453452ccSLoGin mm::{ 17*453452ccSLoGin allocator::{buddy::BuddyAllocator, bump::BumpAllocator, page_frame::FrameAllocator}, 18*453452ccSLoGin kernel_mapper::KernelMapper, 19*453452ccSLoGin memblock::mem_block_manager, 20*453452ccSLoGin page::PageEntry, 21*453452ccSLoGin MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 22*453452ccSLoGin }, 237a29d4fcSLoGin }; 247a29d4fcSLoGin 25*453452ccSLoGin use super::RiscV64MMArch; 26*453452ccSLoGin 27*453452ccSLoGin pub(super) static mut INITIAL_PGTABLE_VALUE: PhysAddr = PhysAddr::new(0); 28*453452ccSLoGin 297a29d4fcSLoGin #[inline(never)] 307a29d4fcSLoGin pub fn mm_early_init() { 317a29d4fcSLoGin unsafe { init_kernel_addr() }; 327a29d4fcSLoGin } 337a29d4fcSLoGin 347a29d4fcSLoGin unsafe fn init_kernel_addr() { 357a29d4fcSLoGin extern "C" { 367a29d4fcSLoGin /// 内核起始label 377a29d4fcSLoGin fn boot_text_start_pa(); 387a29d4fcSLoGin /// 内核结束位置的label 397a29d4fcSLoGin fn _end(); 407a29d4fcSLoGin 417a29d4fcSLoGin fn _start(); 427a29d4fcSLoGin 437a29d4fcSLoGin /// 内核start标签被加载到的物理地址 447a29d4fcSLoGin fn __initial_start_load_paddr(); 457a29d4fcSLoGin } 467a29d4fcSLoGin let initial_start_load_pa = *(__initial_start_load_paddr as usize as *const usize); 477a29d4fcSLoGin let offset = _start as usize - boot_text_start_pa as usize; 487a29d4fcSLoGin let start_pa = initial_start_load_pa - offset; 497a29d4fcSLoGin 507a29d4fcSLoGin let offset2 = _end as usize - boot_text_start_pa as usize; 517a29d4fcSLoGin let end_pa = start_pa + offset2; 527a29d4fcSLoGin 537a29d4fcSLoGin KERNEL_BEGIN_PA = PhysAddr::new(start_pa); 547a29d4fcSLoGin KERNEL_END_PA = PhysAddr::new(end_pa); 557a29d4fcSLoGin 567a29d4fcSLoGin KERNEL_BEGIN_VA = VirtAddr::new(boot_text_start_pa as usize); 577a29d4fcSLoGin KERNEL_END_VA = VirtAddr::new(_end as usize); 587a29d4fcSLoGin 597a29d4fcSLoGin kdebug!( 607a29d4fcSLoGin "init_kernel_addr: \n\tKERNEL_BEGIN_PA: {KERNEL_BEGIN_PA:?} 617a29d4fcSLoGin \tKERNEL_END_PA: {KERNEL_END_PA:?} 627a29d4fcSLoGin \tKERNEL_BEGIN_VA: {KERNEL_BEGIN_VA:?} 637a29d4fcSLoGin \tKERNEL_END_VA: {KERNEL_END_VA:?} 647a29d4fcSLoGin " 657a29d4fcSLoGin ); 667a29d4fcSLoGin } 67*453452ccSLoGin 68*453452ccSLoGin pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> { 69*453452ccSLoGin mem_block_manager() 70*453452ccSLoGin .reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA) 71*453452ccSLoGin .expect("Failed to reserve kernel memory"); 72*453452ccSLoGin 73*453452ccSLoGin let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0); 74*453452ccSLoGin let _old_page_table = MMArch::table(PageTableKind::Kernel); 75*453452ccSLoGin let new_page_table: PhysAddr; 76*453452ccSLoGin 77*453452ccSLoGin // 使用bump分配器,把所有的内存页都映射到页表 78*453452ccSLoGin { 79*453452ccSLoGin kdebug!("to create new page table"); 80*453452ccSLoGin // 用bump allocator创建新的页表 81*453452ccSLoGin let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> = 82*453452ccSLoGin crate::mm::page::PageMapper::<MMArch, _>::create( 83*453452ccSLoGin PageTableKind::Kernel, 84*453452ccSLoGin &mut bump_allocator, 85*453452ccSLoGin ) 86*453452ccSLoGin .expect("Failed to create page mapper"); 87*453452ccSLoGin new_page_table = mapper.table().phys(); 88*453452ccSLoGin kdebug!("PageMapper created"); 89*453452ccSLoGin 90*453452ccSLoGin // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB) 91*453452ccSLoGin { 92*453452ccSLoGin let table = mapper.table(); 93*453452ccSLoGin let empty_entry = PageEntry::<MMArch>::from_usize(0); 94*453452ccSLoGin for i in 0..MMArch::PAGE_ENTRY_NUM { 95*453452ccSLoGin table 96*453452ccSLoGin .set_entry(i, empty_entry) 97*453452ccSLoGin .expect("Failed to empty page table entry"); 98*453452ccSLoGin } 99*453452ccSLoGin } 100*453452ccSLoGin kdebug!("Successfully emptied page table"); 101*453452ccSLoGin 102*453452ccSLoGin let total_num = mem_block_manager().total_initial_memory_regions(); 103*453452ccSLoGin for i in 0..total_num { 104*453452ccSLoGin let area = mem_block_manager().get_initial_memory_region(i).unwrap(); 105*453452ccSLoGin // kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size); 106*453452ccSLoGin for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) { 107*453452ccSLoGin let paddr = area.base.add(i * MMArch::PAGE_SIZE); 108*453452ccSLoGin let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap(); 109*453452ccSLoGin let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true); 110*453452ccSLoGin 111*453452ccSLoGin let flusher = mapper 112*453452ccSLoGin .map_phys(vaddr, paddr, flags) 113*453452ccSLoGin .expect("Failed to map frame"); 114*453452ccSLoGin // 暂时不刷新TLB 115*453452ccSLoGin flusher.ignore(); 116*453452ccSLoGin } 117*453452ccSLoGin } 118*453452ccSLoGin 119*453452ccSLoGin // 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射) 120*453452ccSLoGin LowAddressRemapping::remap_at_low_address(&mut mapper); 121*453452ccSLoGin } 122*453452ccSLoGin 123*453452ccSLoGin unsafe { 124*453452ccSLoGin INITIAL_PGTABLE_VALUE = new_page_table; 125*453452ccSLoGin } 126*453452ccSLoGin kdebug!( 127*453452ccSLoGin "After mapping all physical memory, DragonOS used: {} KB", 128*453452ccSLoGin bump_allocator.usage().used().bytes() / 1024 129*453452ccSLoGin ); 130*453452ccSLoGin 131*453452ccSLoGin // 初始化buddy_allocator 132*453452ccSLoGin let buddy_allocator = unsafe { BuddyAllocator::<MMArch>::new(bump_allocator).unwrap() }; 133*453452ccSLoGin // 设置全局的页帧分配器 134*453452ccSLoGin unsafe { set_inner_allocator(buddy_allocator) }; 135*453452ccSLoGin kinfo!("Successfully initialized buddy allocator"); 136*453452ccSLoGin // 关闭显示输出 137*453452ccSLoGin scm_disable_put_to_window(); 138*453452ccSLoGin 139*453452ccSLoGin // make the new page table current 140*453452ccSLoGin { 141*453452ccSLoGin let mut binding = INNER_ALLOCATOR.lock(); 142*453452ccSLoGin let mut allocator_guard = binding.as_mut().unwrap(); 143*453452ccSLoGin kdebug!("To enable new page table."); 144*453452ccSLoGin compiler_fence(Ordering::SeqCst); 145*453452ccSLoGin let mapper = crate::mm::page::PageMapper::<MMArch, _>::new( 146*453452ccSLoGin PageTableKind::Kernel, 147*453452ccSLoGin new_page_table, 148*453452ccSLoGin &mut allocator_guard, 149*453452ccSLoGin ); 150*453452ccSLoGin compiler_fence(Ordering::SeqCst); 151*453452ccSLoGin mapper.make_current(); 152*453452ccSLoGin compiler_fence(Ordering::SeqCst); 153*453452ccSLoGin // kdebug!("New page table enabled"); 154*453452ccSLoGin } 155*453452ccSLoGin kdebug!("Successfully enabled new page table"); 156*453452ccSLoGin kinfo!("riscv mm init done"); 157*453452ccSLoGin 158*453452ccSLoGin return Ok(()); 159*453452ccSLoGin } 160*453452ccSLoGin 161*453452ccSLoGin unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) { 162*453452ccSLoGin static FLAG: AtomicBool = AtomicBool::new(false); 163*453452ccSLoGin if FLAG 164*453452ccSLoGin .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) 165*453452ccSLoGin .is_err() 166*453452ccSLoGin { 167*453452ccSLoGin panic!("Cannot set inner allocator twice!"); 168*453452ccSLoGin } 169*453452ccSLoGin *INNER_ALLOCATOR.lock() = Some(allocator); 170*453452ccSLoGin } 171*453452ccSLoGin 172*453452ccSLoGin /// 低地址重映射的管理器 173*453452ccSLoGin /// 174*453452ccSLoGin /// 低地址重映射的管理器,在smp初始化完成之前,需要使用低地址的映射,因此需要在smp初始化完成之后,取消这一段映射 175*453452ccSLoGin pub struct LowAddressRemapping; 176*453452ccSLoGin 177*453452ccSLoGin impl LowAddressRemapping { 178*453452ccSLoGin pub unsafe fn remap_at_low_address( 179*453452ccSLoGin mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>, 180*453452ccSLoGin ) { 181*453452ccSLoGin let info = efi_manager().kernel_load_info().unwrap(); 182*453452ccSLoGin let base = PhysAddr::new(info.paddr as usize); 183*453452ccSLoGin let size = info.size as usize; 184*453452ccSLoGin 185*453452ccSLoGin for i in 0..(size / MMArch::PAGE_SIZE) { 186*453452ccSLoGin let paddr = PhysAddr::new(base.data() + i * MMArch::PAGE_SIZE); 187*453452ccSLoGin let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE); 188*453452ccSLoGin let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true); 189*453452ccSLoGin 190*453452ccSLoGin let flusher = mapper 191*453452ccSLoGin .map_phys(vaddr, paddr, flags) 192*453452ccSLoGin .expect("Failed to map frame"); 193*453452ccSLoGin // 暂时不刷新TLB 194*453452ccSLoGin flusher.ignore(); 195*453452ccSLoGin } 196*453452ccSLoGin } 197*453452ccSLoGin 198*453452ccSLoGin /// 取消低地址的映射 199*453452ccSLoGin pub unsafe fn unmap_at_low_address(flush: bool) { 200*453452ccSLoGin let mut mapper = KernelMapper::lock(); 201*453452ccSLoGin assert!(mapper.as_mut().is_some()); 202*453452ccSLoGin 203*453452ccSLoGin let info = efi_manager().kernel_load_info().unwrap(); 204*453452ccSLoGin let base = PhysAddr::new(info.paddr as usize); 205*453452ccSLoGin let size = info.size as usize; 206*453452ccSLoGin 207*453452ccSLoGin for i in 0..(size / MMArch::PAGE_SIZE) { 208*453452ccSLoGin let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE); 209*453452ccSLoGin let (_, _, flusher) = mapper 210*453452ccSLoGin .as_mut() 211*453452ccSLoGin .unwrap() 212*453452ccSLoGin .unmap_phys(vaddr, true) 213*453452ccSLoGin .expect("Failed to unmap frame"); 214*453452ccSLoGin if flush == false { 215*453452ccSLoGin flusher.ignore(); 216*453452ccSLoGin } 217*453452ccSLoGin } 218*453452ccSLoGin } 219*453452ccSLoGin } 220