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