xref: /DragonOS/kernel/src/arch/riscv64/mm/mod.rs (revision 70f159a3988eab656ea1d2b204fde87948526ecf)
1 use acpi::address;
2 use riscv::register::satp;
3 use sbi_rt::{HartMask, SbiRet};
4 use system_error::SystemError;
5 
6 use crate::{
7     arch::MMArch,
8     kdebug,
9     libs::spinlock::SpinLock,
10     mm::{
11         allocator::{
12             buddy::BuddyAllocator,
13             page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
14         },
15         kernel_mapper::KernelMapper,
16         page::{PageEntry, PageFlags},
17         ucontext::UserMapper,
18         MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
19     },
20     smp::cpu::ProcessorId,
21 };
22 
23 use self::init::riscv_mm_init;
24 
25 pub mod bump;
26 pub(super) mod init;
27 
28 pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>;
29 
30 /// 内核起始物理地址
31 pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0);
32 /// 内核结束的物理地址
33 pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0);
34 /// 内核起始虚拟地址
35 pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0);
36 /// 内核结束虚拟地址
37 pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
38 
39 pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
40 
41 /// RiscV64的内存管理架构结构体(sv39)
42 #[derive(Debug, Clone, Copy, Hash)]
43 pub struct RiscV64MMArch;
44 
45 impl RiscV64MMArch {
46     pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
47 
48     /// 使远程cpu的TLB中,指定地址范围的页失效
49     pub fn remote_invalidate_page(
50         cpu: ProcessorId,
51         address: VirtAddr,
52         size: usize,
53     ) -> Result<(), SbiRet> {
54         let r = sbi_rt::remote_sfence_vma(Into::into(cpu), address.data(), size);
55         if r.is_ok() {
56             return Ok(());
57         } else {
58             return Err(r);
59         }
60     }
61 
62     /// 使指定远程cpu的TLB中,所有范围的页失效
63     pub fn remote_invalidate_all(cpu: ProcessorId) -> Result<(), SbiRet> {
64         let r = Self::remote_invalidate_page(
65             cpu,
66             VirtAddr::new(0),
67             1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT,
68         );
69 
70         return r;
71     }
72 
73     pub fn remote_invalidate_all_with_mask(mask: HartMask) -> Result<(), SbiRet> {
74         let r = sbi_rt::remote_sfence_vma(mask, 0, 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT);
75         if r.is_ok() {
76             return Ok(());
77         } else {
78             return Err(r);
79         }
80     }
81 }
82 
83 /// 内核空间起始地址在顶层页表中的索引
84 const KERNEL_TOP_PAGE_ENTRY_NO: usize = (RiscV64MMArch::PHYS_OFFSET
85     & ((1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT) - 1))
86     >> (RiscV64MMArch::ENTRY_ADDRESS_SHIFT - RiscV64MMArch::PAGE_ENTRY_SHIFT);
87 
88 impl MemoryManagementArch for RiscV64MMArch {
89     const PAGE_SHIFT: usize = 12;
90 
91     const PAGE_ENTRY_SHIFT: usize = 9;
92 
93     /// sv39分页只有三级
94     const PAGE_LEVELS: usize = 3;
95 
96     const ENTRY_ADDRESS_SHIFT: usize = 39;
97 
98     const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT
99         | Self::ENTRY_FLAG_READWRITE
100         | Self::ENTRY_FLAG_DIRTY
101         | Self::ENTRY_FLAG_ACCESSED
102         | Self::ENTRY_FLAG_GLOBAL;
103 
104     const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
105 
106     const ENTRY_FLAG_PRESENT: usize = 1 << 0;
107 
108     const ENTRY_FLAG_READONLY: usize = 0;
109 
110     const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
111 
112     const ENTRY_FLAG_USER: usize = (1 << 4);
113 
114     const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61);
115 
116     const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61);
117 
118     const ENTRY_FLAG_NO_EXEC: usize = 0;
119 
120     const ENTRY_FLAG_EXEC: usize = (1 << 3);
121     const ENTRY_FLAG_ACCESSED: usize = (1 << 6);
122     const ENTRY_FLAG_DIRTY: usize = (1 << 7);
123 
124     const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
125     const KERNEL_LINK_OFFSET: usize = 0x1000000;
126 
127     const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff);
128 
129     const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff);
130 
131     const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000);
132 
133     /// 在距离sv39的顶端还有1G的位置,设置为FIXMAP的起始地址
134     const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000);
135     /// 设置1MB的fixmap空间
136     const FIXMAP_SIZE: usize = 256 * 4096;
137 
138     #[inline(never)]
139     unsafe fn init() {
140         riscv_mm_init().expect("init kernel memory management architecture failed");
141     }
142 
143     unsafe fn invalidate_page(address: VirtAddr) {
144         riscv::asm::sfence_vma(0, address.data());
145     }
146 
147     unsafe fn invalidate_all() {
148         riscv::asm::sfence_vma_all();
149     }
150 
151     unsafe fn table(_table_kind: PageTableKind) -> PhysAddr {
152         // phys page number
153         let ppn = riscv::register::satp::read().ppn();
154 
155         let paddr = PhysPageFrame::from_ppn(ppn).phys_address();
156 
157         return paddr;
158     }
159 
160     unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
161         let ppn = PhysPageFrame::new(table).ppn();
162         riscv::asm::sfence_vma_all();
163         satp::set(satp::Mode::Sv39, 0, ppn);
164     }
165 
166     fn virt_is_valid(virt: VirtAddr) -> bool {
167         virt.is_canonical()
168     }
169 
170     fn initial_page_table() -> PhysAddr {
171         todo!()
172     }
173 
174     fn setup_new_usermapper() -> Result<UserMapper, SystemError> {
175         let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe {
176             PageMapper::create(PageTableKind::User, LockedFrameAllocator)
177                 .ok_or(SystemError::ENOMEM)?
178         };
179 
180         let current_ktable: KernelMapper = KernelMapper::lock();
181         let copy_mapping = |pml4_entry_no| unsafe {
182             let entry: PageEntry<RiscV64MMArch> = current_ktable
183                 .table()
184                 .entry(pml4_entry_no)
185                 .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no));
186             new_umapper.table().set_entry(pml4_entry_no, entry)
187         };
188 
189         // 复制内核的映射
190         for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 {
191             copy_mapping(pml4_entry_no);
192         }
193 
194         return Ok(crate::mm::ucontext::UserMapper::new(new_umapper));
195     }
196 
197     unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
198         // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系
199         // 因此这里需要特殊处理
200         if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA {
201             let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA);
202             return Some(r);
203         }
204 
205         if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) {
206             return Some(VirtAddr::new(vaddr));
207         } else {
208             return None;
209         }
210     }
211 
212     unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
213         if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA {
214             let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA);
215             return Some(r);
216         }
217 
218         if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
219             let r = PhysAddr::new(paddr);
220             return Some(r);
221         } else {
222             return None;
223         }
224     }
225 
226     fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
227         let ppn = PhysPageFrame::new(paddr).ppn();
228         let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags;
229         return r;
230     }
231 }
232 
233 impl VirtAddr {
234     /// 判断虚拟地址是否合法
235     #[inline(always)]
236     pub fn is_canonical(self) -> bool {
237         let x = self.data() & RiscV64MMArch::PHYS_OFFSET;
238         // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址
239         // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址
240         return x == 0 || x == RiscV64MMArch::PHYS_OFFSET;
241     }
242 }
243 
244 /// 获取内核地址默认的页面标志
245 pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
246     PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
247         .set_user(false)
248         .set_execute(true)
249 }
250 
251 /// 全局的页帧分配器
252 #[derive(Debug, Clone, Copy, Hash)]
253 pub struct LockedFrameAllocator;
254 
255 impl FrameAllocator for LockedFrameAllocator {
256     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
257         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
258             return allocator.allocate(count);
259         } else {
260             return None;
261         }
262     }
263 
264     unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
265         assert!(count.data().is_power_of_two());
266         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
267             return allocator.free(address, count);
268         }
269     }
270 
271     unsafe fn usage(&self) -> PageFrameUsage {
272         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
273             return allocator.usage();
274         } else {
275             panic!("usage error");
276         }
277     }
278 }
279