1 use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
2
3 use log::{debug, info};
4 use system_error::SystemError;
5
6 use crate::{
7 arch::{
8 mm::{
9 kernel_page_flags, INNER_ALLOCATOR, KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA,
10 KERNEL_END_VA,
11 },
12 MMArch,
13 },
14 driver::firmware::efi::efi_manager,
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)]
mm_early_init()30 pub fn mm_early_init() {
31 unsafe { init_kernel_addr() };
32 }
33
init_kernel_addr()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 debug!(
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
riscv_mm_init() -> Result<(), SystemError>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 // debug!("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 // debug!("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 debug!("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 // debug!("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 debug!(
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 info!("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 debug!("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 // debug!("New page table enabled");
156 }
157 debug!("Successfully enabled new page table");
158 info!("riscv mm init done");
159
160 return Ok(());
161 }
162
set_inner_allocator(allocator: BuddyAllocator<MMArch>)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 {
remap_at_low_address( mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>, )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 /// 取消低地址的映射
unmap_at_low_address(flush: bool)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