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 // 开启S-mode User Memory Access,允许内核访问用户空间 73 riscv::register::sstatus::set_sum(); 74 75 let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0); 76 let _old_page_table = MMArch::table(PageTableKind::Kernel); 77 let new_page_table: PhysAddr; 78 79 // 使用bump分配器,把所有的内存页都映射到页表 80 { 81 // kdebug!("to create new page table"); 82 // 用bump allocator创建新的页表 83 let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> = 84 crate::mm::page::PageMapper::<MMArch, _>::create( 85 PageTableKind::Kernel, 86 &mut bump_allocator, 87 ) 88 .expect("Failed to create page mapper"); 89 new_page_table = mapper.table().phys(); 90 // kdebug!("PageMapper created"); 91 92 // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB) 93 { 94 let table = mapper.table(); 95 let empty_entry = PageEntry::<MMArch>::from_usize(0); 96 for i in 0..MMArch::PAGE_ENTRY_NUM { 97 table 98 .set_entry(i, empty_entry) 99 .expect("Failed to empty page table entry"); 100 } 101 } 102 kdebug!("Successfully emptied page table"); 103 104 let total_num = mem_block_manager().total_initial_memory_regions(); 105 for i in 0..total_num { 106 let area = mem_block_manager().get_initial_memory_region(i).unwrap(); 107 // kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size); 108 for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) { 109 let paddr = area.base.add(i * MMArch::PAGE_SIZE); 110 let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap(); 111 let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true); 112 113 let flusher = mapper 114 .map_phys(vaddr, paddr, flags) 115 .expect("Failed to map frame"); 116 // 暂时不刷新TLB 117 flusher.ignore(); 118 } 119 } 120 121 // 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射) 122 LowAddressRemapping::remap_at_low_address(&mut mapper); 123 } 124 125 unsafe { 126 INITIAL_PGTABLE_VALUE = new_page_table; 127 } 128 kdebug!( 129 "After mapping all physical memory, DragonOS used: {} KB", 130 bump_allocator.usage().used().bytes() / 1024 131 ); 132 133 // 初始化buddy_allocator 134 let buddy_allocator = unsafe { BuddyAllocator::<MMArch>::new(bump_allocator).unwrap() }; 135 // 设置全局的页帧分配器 136 unsafe { set_inner_allocator(buddy_allocator) }; 137 kinfo!("Successfully initialized buddy allocator"); 138 // 关闭显示输出 139 scm_disable_put_to_window(); 140 141 // make the new page table current 142 { 143 let mut binding = INNER_ALLOCATOR.lock(); 144 let mut allocator_guard = binding.as_mut().unwrap(); 145 kdebug!("To enable new page table."); 146 compiler_fence(Ordering::SeqCst); 147 let mapper = crate::mm::page::PageMapper::<MMArch, _>::new( 148 PageTableKind::Kernel, 149 new_page_table, 150 &mut allocator_guard, 151 ); 152 compiler_fence(Ordering::SeqCst); 153 mapper.make_current(); 154 compiler_fence(Ordering::SeqCst); 155 // kdebug!("New page table enabled"); 156 } 157 kdebug!("Successfully enabled new page table"); 158 kinfo!("riscv mm init done"); 159 160 return Ok(()); 161 } 162 163 unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) { 164 static FLAG: AtomicBool = AtomicBool::new(false); 165 if FLAG 166 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) 167 .is_err() 168 { 169 panic!("Cannot set inner allocator twice!"); 170 } 171 *INNER_ALLOCATOR.lock() = Some(allocator); 172 } 173 174 /// 低地址重映射的管理器 175 /// 176 /// 低地址重映射的管理器,在smp初始化完成之前,需要使用低地址的映射,因此需要在smp初始化完成之后,取消这一段映射 177 pub struct LowAddressRemapping; 178 179 impl LowAddressRemapping { 180 pub unsafe fn remap_at_low_address( 181 mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>, 182 ) { 183 let info = efi_manager().kernel_load_info().unwrap(); 184 let base = PhysAddr::new(info.paddr as usize); 185 let size = info.size as usize; 186 187 for i in 0..(size / MMArch::PAGE_SIZE) { 188 let paddr = PhysAddr::new(base.data() + i * MMArch::PAGE_SIZE); 189 let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE); 190 let flags = kernel_page_flags::<MMArch>(vaddr).set_execute(true); 191 192 let flusher = mapper 193 .map_phys(vaddr, paddr, flags) 194 .expect("Failed to map frame"); 195 // 暂时不刷新TLB 196 flusher.ignore(); 197 } 198 } 199 200 /// 取消低地址的映射 201 pub unsafe fn unmap_at_low_address(flush: bool) { 202 let mut mapper = KernelMapper::lock(); 203 assert!(mapper.as_mut().is_some()); 204 205 let info = efi_manager().kernel_load_info().unwrap(); 206 let base = PhysAddr::new(info.paddr as usize); 207 let size = info.size as usize; 208 209 for i in 0..(size / MMArch::PAGE_SIZE) { 210 let vaddr = VirtAddr::new(base.data() + i * MMArch::PAGE_SIZE); 211 let (_, _, flusher) = mapper 212 .as_mut() 213 .unwrap() 214 .unmap_phys(vaddr, true) 215 .expect("Failed to unmap frame"); 216 if flush == false { 217 flusher.ignore(); 218 } 219 } 220 } 221 } 222