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