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