xref: /DragonOS/kernel/src/mm/mod.rs (revision cc5feaf67b914ecf701abcba70c01da149755491)
1 use alloc::sync::Arc;
2 
3 use crate::{arch::MMArch, include::bindings::bindings::PAGE_OFFSET, syscall::SystemError};
4 
5 use core::{
6     cmp,
7     fmt::Debug,
8     intrinsics::unlikely,
9     ops::{Add, AddAssign, Sub, SubAssign},
10     ptr,
11     sync::atomic::{AtomicBool, Ordering},
12 };
13 
14 use self::{
15     allocator::page_frame::{VirtPageFrame, VirtPageFrameIter},
16     page::round_up_to_page_size,
17     ucontext::{AddressSpace, UserMapper},
18 };
19 
20 pub mod allocator;
21 pub mod c_adapter;
22 pub mod kernel_mapper;
23 pub mod mmio_buddy;
24 pub mod no_init;
25 pub mod page;
26 pub mod percpu;
27 pub mod syscall;
28 pub mod ucontext;
29 
30 /// 内核INIT进程的用户地址空间结构体(仅在process_init中初始化)
31 static mut __INITIAL_PROCESS_ADDRESS_SPACE: Option<Arc<AddressSpace>> = None;
32 
33 /// 获取内核INIT进程的用户地址空间结构体
34 #[allow(non_snake_case)]
35 #[inline(always)]
36 pub fn INITIAL_PROCESS_ADDRESS_SPACE() -> Arc<AddressSpace> {
37     unsafe {
38         return __INITIAL_PROCESS_ADDRESS_SPACE
39             .as_ref()
40             .expect("INITIAL_PROCESS_ADDRESS_SPACE is null")
41             .clone();
42     }
43 }
44 
45 /// 设置内核INIT进程的用户地址空间结构体全局变量
46 #[allow(non_snake_case)]
47 pub unsafe fn set_INITIAL_PROCESS_ADDRESS_SPACE(address_space: Arc<AddressSpace>) {
48     static INITIALIZED: AtomicBool = AtomicBool::new(false);
49     if INITIALIZED
50         .compare_exchange(false, true, Ordering::SeqCst, Ordering::Acquire)
51         .is_err()
52     {
53         panic!("INITIAL_PROCESS_ADDRESS_SPACE is already initialized");
54     }
55     __INITIAL_PROCESS_ADDRESS_SPACE = Some(address_space);
56 }
57 
58 /// @brief 将内核空间的虚拟地址转换为物理地址
59 #[inline(always)]
60 pub fn virt_2_phys(addr: usize) -> usize {
61     addr - PAGE_OFFSET as usize
62 }
63 
64 /// @brief 将物理地址转换为内核空间的虚拟地址
65 #[inline(always)]
66 pub fn phys_2_virt(addr: usize) -> usize {
67     addr + PAGE_OFFSET as usize
68 }
69 
70 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
71 pub enum PageTableKind {
72     /// 用户可访问的页表
73     User,
74     /// 内核页表
75     Kernel,
76     /// 内存虚拟化中使用的EPT
77     EPT,
78 }
79 
80 /// 物理内存地址
81 #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
82 #[repr(transparent)]
83 pub struct PhysAddr(usize);
84 
85 impl PhysAddr {
86     #[inline(always)]
87     pub const fn new(address: usize) -> Self {
88         Self(address)
89     }
90 
91     /// @brief 获取物理地址的值
92     #[inline(always)]
93     pub fn data(&self) -> usize {
94         self.0
95     }
96 
97     /// @brief 将物理地址加上一个偏移量
98     #[inline(always)]
99     pub fn add(self, offset: usize) -> Self {
100         Self(self.0 + offset)
101     }
102 
103     /// @brief 判断物理地址是否按照指定要求对齐
104     #[inline(always)]
105     pub fn check_aligned(&self, align: usize) -> bool {
106         return self.0 & (align - 1) == 0;
107     }
108 
109     #[inline(always)]
110     pub fn is_null(&self) -> bool {
111         return self.0 == 0;
112     }
113 }
114 
115 impl Debug for PhysAddr {
116     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117         write!(f, "PhysAddr({:#x})", self.0)
118     }
119 }
120 
121 impl core::ops::Add<usize> for PhysAddr {
122     type Output = Self;
123 
124     #[inline(always)]
125     fn add(self, rhs: usize) -> Self::Output {
126         return Self(self.0 + rhs);
127     }
128 }
129 
130 impl core::ops::AddAssign<usize> for PhysAddr {
131     #[inline(always)]
132     fn add_assign(&mut self, rhs: usize) {
133         self.0 += rhs;
134     }
135 }
136 
137 impl core::ops::Add<PhysAddr> for PhysAddr {
138     type Output = Self;
139 
140     #[inline(always)]
141     fn add(self, rhs: PhysAddr) -> Self::Output {
142         return Self(self.0 + rhs.0);
143     }
144 }
145 
146 impl core::ops::AddAssign<PhysAddr> for PhysAddr {
147     #[inline(always)]
148     fn add_assign(&mut self, rhs: PhysAddr) {
149         self.0 += rhs.0;
150     }
151 }
152 
153 impl core::ops::BitOrAssign<usize> for PhysAddr {
154     #[inline(always)]
155     fn bitor_assign(&mut self, rhs: usize) {
156         self.0 |= rhs;
157     }
158 }
159 
160 impl core::ops::BitOrAssign<PhysAddr> for PhysAddr {
161     #[inline(always)]
162     fn bitor_assign(&mut self, rhs: PhysAddr) {
163         self.0 |= rhs.0;
164     }
165 }
166 
167 impl core::ops::Sub<usize> for PhysAddr {
168     type Output = Self;
169 
170     #[inline(always)]
171     fn sub(self, rhs: usize) -> Self::Output {
172         return Self(self.0 - rhs);
173     }
174 }
175 
176 impl core::ops::SubAssign<usize> for PhysAddr {
177     #[inline(always)]
178     fn sub_assign(&mut self, rhs: usize) {
179         self.0 -= rhs;
180     }
181 }
182 
183 impl core::ops::Sub<PhysAddr> for PhysAddr {
184     type Output = usize;
185 
186     #[inline(always)]
187     fn sub(self, rhs: PhysAddr) -> Self::Output {
188         return self.0 - rhs.0;
189     }
190 }
191 
192 impl core::ops::SubAssign<PhysAddr> for PhysAddr {
193     #[inline(always)]
194     fn sub_assign(&mut self, rhs: PhysAddr) {
195         self.0 -= rhs.0;
196     }
197 }
198 
199 /// 虚拟内存地址
200 #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
201 #[repr(transparent)]
202 pub struct VirtAddr(usize);
203 
204 impl VirtAddr {
205     #[inline(always)]
206     pub const fn new(address: usize) -> Self {
207         return Self(address);
208     }
209 
210     /// @brief 获取虚拟地址的值
211     #[inline(always)]
212     pub fn data(&self) -> usize {
213         return self.0;
214     }
215 
216     /// @brief 判断虚拟地址的类型
217     #[inline(always)]
218     pub fn kind(&self) -> PageTableKind {
219         if self.check_user() {
220             return PageTableKind::User;
221         } else {
222             return PageTableKind::Kernel;
223         }
224     }
225 
226     /// @brief 判断虚拟地址是否按照指定要求对齐
227     #[inline(always)]
228     pub fn check_aligned(&self, align: usize) -> bool {
229         return self.0 & (align - 1) == 0;
230     }
231 
232     /// @brief 判断虚拟地址是否在用户空间
233     #[inline(always)]
234     pub fn check_user(&self) -> bool {
235         if self < &MMArch::USER_END_VADDR {
236             return true;
237         } else {
238             return false;
239         }
240     }
241 
242     #[inline(always)]
243     pub fn as_ptr<T>(self) -> *mut T {
244         return self.0 as *mut T;
245     }
246 
247     #[inline(always)]
248     pub fn is_null(&self) -> bool {
249         return self.0 == 0;
250     }
251 }
252 
253 impl Add<VirtAddr> for VirtAddr {
254     type Output = Self;
255 
256     #[inline(always)]
257     fn add(self, rhs: VirtAddr) -> Self::Output {
258         return Self(self.0 + rhs.0);
259     }
260 }
261 
262 impl Add<usize> for VirtAddr {
263     type Output = Self;
264 
265     #[inline(always)]
266     fn add(self, rhs: usize) -> Self::Output {
267         return Self(self.0 + rhs);
268     }
269 }
270 
271 impl Sub<VirtAddr> for VirtAddr {
272     type Output = usize;
273 
274     #[inline(always)]
275     fn sub(self, rhs: VirtAddr) -> Self::Output {
276         return self.0 - rhs.0;
277     }
278 }
279 
280 impl Sub<usize> for VirtAddr {
281     type Output = Self;
282 
283     #[inline(always)]
284     fn sub(self, rhs: usize) -> Self::Output {
285         return Self(self.0 - rhs);
286     }
287 }
288 
289 impl AddAssign<usize> for VirtAddr {
290     #[inline(always)]
291     fn add_assign(&mut self, rhs: usize) {
292         self.0 += rhs;
293     }
294 }
295 
296 impl AddAssign<VirtAddr> for VirtAddr {
297     #[inline(always)]
298     fn add_assign(&mut self, rhs: VirtAddr) {
299         self.0 += rhs.0;
300     }
301 }
302 
303 impl SubAssign<usize> for VirtAddr {
304     #[inline(always)]
305     fn sub_assign(&mut self, rhs: usize) {
306         self.0 -= rhs;
307     }
308 }
309 
310 impl SubAssign<VirtAddr> for VirtAddr {
311     #[inline(always)]
312     fn sub_assign(&mut self, rhs: VirtAddr) {
313         self.0 -= rhs.0;
314     }
315 }
316 
317 impl Debug for VirtAddr {
318     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
319         write!(f, "VirtAddr({:#x})", self.0)
320     }
321 }
322 
323 /// @brief 物理内存区域
324 #[derive(Clone, Copy, Debug)]
325 pub struct PhysMemoryArea {
326     /// 物理基地址
327     pub base: PhysAddr,
328     /// 该区域的物理内存大小
329     pub size: usize,
330 }
331 
332 impl PhysMemoryArea {
333     pub fn new(base: PhysAddr, size: usize) -> Self {
334         Self { base, size }
335     }
336 
337     /// 返回向上页面对齐的区域起始物理地址
338     pub fn area_base_aligned(&self) -> PhysAddr {
339         return PhysAddr::new(
340             (self.base.data() + (MMArch::PAGE_SIZE - 1)) & !(MMArch::PAGE_SIZE - 1),
341         );
342     }
343 
344     /// 返回向下页面对齐的区域截止物理地址
345     pub fn area_end_aligned(&self) -> PhysAddr {
346         return PhysAddr::new((self.base.data() + self.size) & !(MMArch::PAGE_SIZE - 1));
347     }
348 }
349 
350 impl Default for PhysMemoryArea {
351     fn default() -> Self {
352         Self {
353             base: PhysAddr::new(0),
354             size: 0,
355         }
356     }
357 }
358 
359 pub trait MemoryManagementArch: Clone + Copy + Debug {
360     /// 页面大小的shift(假如页面4K,那么这个值就是12,因为2^12=4096)
361     const PAGE_SHIFT: usize;
362     /// 每个页表的页表项数目。(以2^n次幂来表示)假如有512个页表项,那么这个值就是9
363     const PAGE_ENTRY_SHIFT: usize;
364     /// 页表层级数量
365     const PAGE_LEVELS: usize;
366 
367     /// 页表项的有效位的index(假如页表项的第0-51位有效,那么这个值就是52)
368     const ENTRY_ADDRESS_SHIFT: usize;
369     /// 页面的页表项的默认值
370     const ENTRY_FLAG_DEFAULT_PAGE: usize;
371     /// 页表的页表项的默认值
372     const ENTRY_FLAG_DEFAULT_TABLE: usize;
373     /// 页表项的present位被置位之后的值
374     const ENTRY_FLAG_PRESENT: usize;
375     /// 页表项为read only时的值
376     const ENTRY_FLAG_READONLY: usize;
377     /// 页表项为可读写状态的值
378     const ENTRY_FLAG_READWRITE: usize;
379     /// 页面项标记页面为user page的值
380     const ENTRY_FLAG_USER: usize;
381     /// 页面项标记页面为write through的值
382     const ENTRY_FLAG_WRITE_THROUGH: usize;
383     /// 页面项标记页面为cache disable的值
384     const ENTRY_FLAG_CACHE_DISABLE: usize;
385     /// 标记当前页面不可执行的标志位(Execute disable)(也就是说,不能从这段内存里面获取处理器指令)
386     const ENTRY_FLAG_NO_EXEC: usize;
387     /// 标记当前页面可执行的标志位(Execute enable)
388     const ENTRY_FLAG_EXEC: usize;
389 
390     /// 虚拟地址与物理地址的偏移量
391     const PHYS_OFFSET: usize;
392 
393     /// 每个页面的大小
394     const PAGE_SIZE: usize = 1 << Self::PAGE_SHIFT;
395     /// 通过这个mask,获取地址的页内偏移量
396     const PAGE_OFFSET_MASK: usize = Self::PAGE_SIZE - 1;
397     /// 通过这个mask,获取页的首地址
398     const PAGE_MASK: usize = !(Self::PAGE_OFFSET_MASK);
399     /// 页表项的地址、数据部分的shift。
400     /// 打个比方,如果这个值为52,那么意味着页表项的[0, 52)位,用于表示地址以及其他的标志位
401     const PAGE_ADDRESS_SHIFT: usize = Self::PAGE_LEVELS * Self::PAGE_ENTRY_SHIFT + Self::PAGE_SHIFT;
402     /// 最大的虚拟地址(对于不同的架构,由于上述PAGE_ADDRESS_SHIFT可能包括了reserved bits, 事实上能表示的虚拟地址应该比这个值要小)
403     const PAGE_ADDRESS_SIZE: usize = 1 << Self::PAGE_ADDRESS_SHIFT;
404     /// 页表项的值与这个常量进行与运算,得到的结果是所填写的物理地址
405     const PAGE_ADDRESS_MASK: usize = Self::PAGE_ADDRESS_SIZE - Self::PAGE_SIZE;
406     /// 每个页表项的大小
407     const PAGE_ENTRY_SIZE: usize = 1 << (Self::PAGE_SHIFT - Self::PAGE_ENTRY_SHIFT);
408     /// 每个页表的页表项数目
409     const PAGE_ENTRY_NUM: usize = 1 << Self::PAGE_ENTRY_SHIFT;
410     /// 该字段用于根据虚拟地址,获取该虚拟地址在对应的页表中是第几个页表项
411     const PAGE_ENTRY_MASK: usize = Self::PAGE_ENTRY_NUM - 1;
412 
413     const PAGE_NEGATIVE_MASK: usize = !((Self::PAGE_ADDRESS_SIZE) - 1);
414 
415     const ENTRY_ADDRESS_SIZE: usize = 1 << Self::ENTRY_ADDRESS_SHIFT;
416     /// 该mask用于获取页表项中地址字段
417     const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - Self::PAGE_SIZE;
418     /// 这个mask用于获取页表项中的flags
419     const ENTRY_FLAGS_MASK: usize = !Self::ENTRY_ADDRESS_MASK;
420 
421     /// 用户空间的最高地址
422     const USER_END_VADDR: VirtAddr;
423     /// 用户堆的起始地址
424     const USER_BRK_START: VirtAddr;
425     /// 用户栈起始地址(向下生长,不包含该值)
426     const USER_STACK_START: VirtAddr;
427 
428     /// @brief 用于初始化内存管理模块与架构相关的信息。
429     /// 该函数应调用其他模块的接口,生成内存区域结构体,提供给BumpAllocator使用
430     unsafe fn init() -> &'static [PhysMemoryArea];
431 
432     /// @brief 读取指定虚拟地址的值,并假设它是类型T的指针
433     #[inline(always)]
434     unsafe fn read<T>(address: VirtAddr) -> T {
435         return ptr::read(address.data() as *const T);
436     }
437 
438     /// @brief 将value写入到指定的虚拟地址
439     #[inline(always)]
440     unsafe fn write<T>(address: VirtAddr, value: T) {
441         ptr::write(address.data() as *mut T, value);
442     }
443 
444     #[inline(always)]
445     unsafe fn write_bytes(address: VirtAddr, value: u8, count: usize) {
446         ptr::write_bytes(address.data() as *mut u8, value, count);
447     }
448 
449     /// @brief 刷新TLB中,关于指定虚拟地址的条目
450     unsafe fn invalidate_page(address: VirtAddr);
451 
452     /// @brief 刷新TLB中,所有的条目
453     unsafe fn invalidate_all();
454 
455     /// @brief 获取顶级页表的物理地址
456     unsafe fn table(table_kind: PageTableKind) -> PhysAddr;
457 
458     /// @brief 设置顶级页表的物理地址到处理器中
459     unsafe fn set_table(table_kind: PageTableKind, table: PhysAddr);
460 
461     /// @brief 将物理地址转换为虚拟地址.
462     ///
463     /// @param phys 物理地址
464     ///
465     /// @return 转换后的虚拟地址。如果转换失败,返回None
466     #[inline(always)]
467     unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
468         if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) {
469             return Some(VirtAddr::new(vaddr));
470         } else {
471             return None;
472         }
473     }
474 
475     /// 将虚拟地址转换为物理地址
476     ///
477     /// ## 参数
478     ///
479     /// - `virt` 虚拟地址
480     ///
481     /// ## 返回值
482     ///
483     /// 转换后的物理地址。如果转换失败,返回None
484     #[inline(always)]
485     unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
486         if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
487             return Some(PhysAddr::new(paddr));
488         } else {
489             return None;
490         }
491     }
492 
493     /// @brief 判断指定的虚拟地址是否正确(符合规范)
494     fn virt_is_valid(virt: VirtAddr) -> bool;
495 
496     /// 获取内存管理初始化时,创建的第一个内核页表的地址
497     fn initial_page_table() -> PhysAddr;
498 
499     /// 初始化新的usermapper,为用户进程创建页表
500     fn setup_new_usermapper() -> Result<UserMapper, SystemError>;
501 }
502 
503 /// @brief 虚拟地址范围
504 /// 该结构体用于表示一个虚拟地址范围,包括起始地址与大小
505 ///
506 /// 请注意与VMA进行区分,该结构体被VMA所包含
507 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
508 pub struct VirtRegion {
509     start: VirtAddr,
510     size: usize,
511 }
512 
513 #[allow(dead_code)]
514 impl VirtRegion {
515     /// # 创建一个新的虚拟地址范围
516     pub fn new(start: VirtAddr, size: usize) -> Self {
517         VirtRegion { start, size }
518     }
519 
520     /// 获取虚拟地址范围的起始地址
521     #[inline(always)]
522     pub fn start(&self) -> VirtAddr {
523         self.start
524     }
525 
526     /// 获取虚拟地址范围的截止地址(不包括返回的地址)
527     #[inline(always)]
528     pub fn end(&self) -> VirtAddr {
529         return self.start().add(self.size);
530     }
531 
532     /// # Create a new VirtRegion from a range [start, end)
533     ///
534     /// If end <= start, return None
535     pub fn between(start: VirtAddr, end: VirtAddr) -> Option<Self> {
536         if unlikely(end.data() <= start.data()) {
537             return None;
538         }
539         let size = end.data() - start.data();
540         return Some(VirtRegion::new(start, size));
541     }
542 
543     /// # 取两个虚拟地址范围的交集
544     ///
545     /// 如果两个虚拟地址范围没有交集,返回None
546     pub fn intersect(&self, other: &VirtRegion) -> Option<VirtRegion> {
547         let start = self.start.max(other.start);
548         let end = self.end().min(other.end());
549         return VirtRegion::between(start, end);
550     }
551 
552     /// 设置虚拟地址范围的起始地址
553     #[inline(always)]
554     pub fn set_start(&mut self, start: VirtAddr) {
555         self.start = start;
556     }
557 
558     #[inline(always)]
559     pub fn size(&self) -> usize {
560         self.size
561     }
562 
563     /// 设置虚拟地址范围的大小
564     #[inline(always)]
565     pub fn set_size(&mut self, size: usize) {
566         self.size = size;
567     }
568 
569     /// 判断虚拟地址范围是否为空
570     #[inline(always)]
571     pub fn is_empty(&self) -> bool {
572         self.size == 0
573     }
574 
575     /// 将虚拟地址区域的大小向上对齐到页大小
576     #[inline(always)]
577     pub fn round_up_size_to_page(self) -> Self {
578         return VirtRegion::new(self.start, round_up_to_page_size(self.size));
579     }
580 
581     /// 判断两个虚拟地址范围是否由于具有交集而导致冲突
582     #[inline(always)]
583     pub fn collide(&self, other: &VirtRegion) -> bool {
584         return self.intersect(other).is_some();
585     }
586 
587     pub fn iter_pages(&self) -> VirtPageFrameIter {
588         return VirtPageFrame::iter_range(
589             VirtPageFrame::new(self.start),
590             VirtPageFrame::new(self.end()),
591         );
592     }
593 
594     /// 获取[self.start(), region.start())的虚拟地址范围
595     ///
596     /// 如果self.start() >= region.start(),返回None
597     pub fn before(self, region: &VirtRegion) -> Option<Self> {
598         return Self::between(self.start(), region.start());
599     }
600 
601     /// 获取[region.end(),self.end())的虚拟地址范围
602     ///
603     /// 如果 self.end() >= region.end() ,返回None
604     pub fn after(self, region: &VirtRegion) -> Option<Self> {
605         // if self.end() > region.end() none
606         return Self::between(region.end(), self.end());
607     }
608 
609     /// 把当前虚拟地址范围内的某个虚拟地址,转换为另一个虚拟地址范围内的虚拟地址
610     ///
611     /// 如果vaddr不在当前虚拟地址范围内,返回None
612     ///
613     /// 如果vaddr在当前虚拟地址范围内,返回vaddr在new_base中的虚拟地址
614     pub fn rebase(self, vaddr: VirtAddr, new_base: &VirtRegion) -> Option<VirtAddr> {
615         if !self.contains(vaddr) {
616             return None;
617         }
618         let offset = vaddr.data() - self.start().data();
619         let new_start = new_base.start().data() + offset;
620         return Some(VirtAddr::new(new_start));
621     }
622 
623     /// 判断虚拟地址范围是否包含指定的虚拟地址
624     pub fn contains(&self, addr: VirtAddr) -> bool {
625         return self.start() <= addr && addr < self.end();
626     }
627 
628     /// 创建当前虚拟地址范围的页面迭代器
629     pub fn pages(&self) -> VirtPageFrameIter {
630         return VirtPageFrame::iter_range(
631             VirtPageFrame::new(self.start()),
632             VirtPageFrame::new(self.end()),
633         );
634     }
635 }
636 
637 impl PartialOrd for VirtRegion {
638     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
639         return self.start.partial_cmp(&other.start);
640     }
641 }
642 
643 impl Ord for VirtRegion {
644     fn cmp(&self, other: &Self) -> cmp::Ordering {
645         return self.start.cmp(&other.start);
646     }
647 }
648 
649 /// ## 判断虚拟地址是否超出了用户空间
650 ///
651 /// 如果虚拟地址超出了用户空间,返回Err(SystemError::EFAULT).
652 /// 如果end < start,返回Err(SystemError::EOVERFLOW)
653 ///
654 /// 否则返回Ok(())
655 pub fn verify_area(addr: VirtAddr, size: usize) -> Result<(), SystemError> {
656     let end = addr.add(size);
657     if unlikely(end.data() < addr.data()) {
658         return Err(SystemError::EOVERFLOW);
659     }
660 
661     if !addr.check_user() || !end.check_user() {
662         return Err(SystemError::EFAULT);
663     }
664 
665     return Ok(());
666 }
667