xref: /DragonOS/kernel/src/arch/riscv64/mm/init.rs (revision b8ed38251dc255b0c525801b5dbf37d3b0d0d61e)
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