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