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