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