Pārlūkot izejas kodu

新的内存管理模块 (#303)

  实现了具有优秀架构设计的新的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。

  内存管理模块主要由以下类型的组件组成:

- **硬件抽象层(MemoryManagementArch)** - 提供对具体处理器架构的抽象,使得内存管理模块可以在不同的处理器架构上运行
- **页面映射器(PageMapper)**- 提供对虚拟地址和物理地址的映射,以及页表的创建、填写、销毁、权限管理等操作。分为两种类型:内核页表映射器(KernelMapper)和用户页表映射器(位于具体的用户地址空间结构中)
- **页面刷新器(PageFlusher)** - 提供对页表的刷新操作(整表刷新、单页刷新、跨核心刷新)
- **页帧分配器(FrameAllocator)** - 提供对页帧的分配、释放、管理等操作。具体来说,包括BumpAllocator、BuddyAllocator
- **小对象分配器** - 提供对小内存对象的分配、释放、管理等操作。指的是内核里面的SlabAllocator (SlabAllocator的实现目前还没有完成)
- **MMIO空间管理器** - 提供对MMIO地址空间的分配、管理操作。(目前这个模块待进一步重构)
- **用户地址空间管理机制** - 提供对用户地址空间的管理。
    - VMA机制 - 提供对用户地址空间的管理,包括VMA的创建、销毁、权限管理等操作
    - 用户映射管理 - 与VMA机制共同作用,管理用户地址空间的映射
- **系统调用层** - 提供对用户空间的内存管理系统调用,包括mmap、munmap、mprotect、mremap等
- **C接口兼容层** - 提供对原有的C代码的接口,是的C代码能够正常运行。


除上面的新增内容以外,其它的更改内容:
- 新增二进制加载器,以及elf的解析器
- 解决由于local_irq_save、local_irq_restore函数的汇编不规范导致影响栈行为的bug。
- 解决local_irq_save未关中断的错误。
- 修复sys_gettimeofday对timezone参数的处理的bug

---------

Co-authored-by: kong <[email protected]>
LoGin 1 gadu atpakaļ
vecāks
revīzija
40fe15e095
100 mainītis faili ar 7905 papildinājumiem un 4857 dzēšanām
  1. 2 1
      .vscode/settings.json
  2. 11 1
      Makefile
  3. 10 5
      README.md
  4. 4 4
      README_EN.md
  5. BIN
      docs/Multiboot2 Specification version 2.0.pdf
  6. 39 1
      docs/community/contact/index.rst
  7. 4 1
      docs/introduction/build_system.md
  8. 18 6
      docs/introduction/features.md
  9. 3 1
      docs/introduction/index.rst
  10. 0 15
      docs/kernel/core_api/allocate-memory.md
  11. 0 13
      docs/kernel/core_api/index.rst
  12. 0 267
      docs/kernel/core_api/mm-api.md
  13. 29 0
      docs/kernel/memory_management/allocate-memory.md
  14. 4 4
      docs/kernel/memory_management/index.rst
  15. 20 0
      docs/kernel/memory_management/intro.md
  16. 2 1
      docs/kernel/process_management/index.rst
  17. 15 0
      docs/kernel/process_management/load_binary.md
  18. 7 0
      kernel/Cargo.toml
  19. 3 2
      kernel/src/Makefile
  20. 2 2
      kernel/src/arch/mod.rs
  21. 3 2
      kernel/src/arch/x86_64/asm/irqflags.rs
  22. 8 0
      kernel/src/arch/x86_64/context.rs
  23. 1 1
      kernel/src/arch/x86_64/fpu.rs
  24. 3 3
      kernel/src/arch/x86_64/interrupt/mod.rs
  25. 1 0
      kernel/src/arch/x86_64/libs/mod.rs
  26. 618 19
      kernel/src/arch/x86_64/mm/mod.rs
  27. 6 0
      kernel/src/arch/x86_64/mod.rs
  28. 1 1
      kernel/src/arch/x86_64/msi.rs
  29. 176 22
      kernel/src/arch/x86_64/syscall.rs
  30. 8 0
      kernel/src/common/atomic.h
  31. 20 14
      kernel/src/driver/acpi/acpi.c
  32. 5 5
      kernel/src/driver/base/char/mod.rs
  33. 2 1
      kernel/src/driver/base/device/mod.rs
  34. 1 1
      kernel/src/driver/disk/ahci/ahci.c
  35. 6 4
      kernel/src/driver/interrupt/apic/apic.c
  36. 1 1
      kernel/src/driver/pci/msi.c
  37. 44 20
      kernel/src/driver/pci/pci.rs
  38. 4 6
      kernel/src/driver/pci/pci_irq.rs
  39. 1 1
      kernel/src/driver/uart/uart.rs
  40. 6 11
      kernel/src/driver/video/video.c
  41. 69 27
      kernel/src/driver/virtio/virtio_impl.rs
  42. 3 3
      kernel/src/exception/mod.rs
  43. 1 0
      kernel/src/exception/softirq.rs
  44. 9 6
      kernel/src/filesystem/procfs/mod.rs
  45. 15 29
      kernel/src/filesystem/sysfs/bus.rs
  46. 1 1
      kernel/src/filesystem/vfs/VFS.h
  47. 1 1
      kernel/src/filesystem/vfs/file.rs
  48. 53 64
      kernel/src/head.S
  49. 2 1
      kernel/src/include/bindings/wrapper.h
  50. 4 4
      kernel/src/ipc/signal.rs
  51. 10 5
      kernel/src/lib.rs
  52. 27 1
      kernel/src/libs/align.rs
  53. 785 0
      kernel/src/libs/elf.rs
  54. 33 5
      kernel/src/libs/libUI/screen_manager.c
  55. 3 1
      kernel/src/libs/libUI/screen_manager.h
  56. 25 1
      kernel/src/libs/libUI/textui.c
  57. 5 1
      kernel/src/libs/libUI/textui.h
  58. 1 0
      kernel/src/libs/mod.rs
  59. 4 0
      kernel/src/libs/printk.c
  60. 92 10
      kernel/src/libs/printk.rs
  61. 43 5
      kernel/src/libs/rwlock.rs
  62. 16 16
      kernel/src/libs/spinlock.rs
  63. 28 22
      kernel/src/main.c
  64. 0 27
      kernel/src/mm/Makefile
  65. 0 55
      kernel/src/mm/allocator.rs
  66. 667 0
      kernel/src/mm/allocator/buddy.rs
  67. 112 0
      kernel/src/mm/allocator/bump.rs
  68. 101 0
      kernel/src/mm/allocator/kernel_allocator.rs
  69. 5 0
      kernel/src/mm/allocator/mod.rs
  70. 338 0
      kernel/src/mm/allocator/page_frame.rs
  71. 123 0
      kernel/src/mm/allocator/slab.rs
  72. 135 0
      kernel/src/mm/c_adapter.rs
  73. 0 79
      kernel/src/mm/internal.h
  74. 145 0
      kernel/src/mm/kernel_mapper.rs
  75. 0 196
      kernel/src/mm/mm-stat.c
  76. 0 175
      kernel/src/mm/mm-types.h
  77. 0 686
      kernel/src/mm/mm.c
  78. 14 365
      kernel/src/mm/mm.h
  79. 0 582
      kernel/src/mm/mmap.c
  80. 0 9
      kernel/src/mm/mmio.c
  81. 1 3
      kernel/src/mm/mmio.h
  82. 160 219
      kernel/src/mm/mmio_buddy.rs
  83. 609 4
      kernel/src/mm/mod.rs
  84. 79 0
      kernel/src/mm/no_init.rs
  85. 924 0
      kernel/src/mm/page.rs
  86. 0 713
      kernel/src/mm/slab.c
  87. 4 109
      kernel/src/mm/slab.h
  88. 202 26
      kernel/src/mm/syscall.rs
  89. 1319 0
      kernel/src/mm/ucontext.rs
  90. 0 109
      kernel/src/mm/utils.c
  91. 0 275
      kernel/src/mm/vma.c
  92. 86 0
      kernel/src/process/abi.rs
  93. 115 0
      kernel/src/process/c_adapter.rs
  94. 288 0
      kernel/src/process/exec.rs
  95. 5 83
      kernel/src/process/fork.c
  96. 38 2
      kernel/src/process/fork.rs
  97. 32 0
      kernel/src/process/mod.rs
  98. 15 14
      kernel/src/process/proc-types.h
  99. 38 445
      kernel/src/process/process.c
  100. 32 42
      kernel/src/process/process.h

+ 2 - 1
.vscode/settings.json

@@ -174,7 +174,8 @@
         "sleep.h": "c",
         "net.h": "c",
         "lz4.h": "c",
-        "cmd_test.h": "c"
+        "cmd_test.h": "c",
+        "cmpxchg.h": "c"
     },
     "C_Cpp.errorSquiggles": "enabled",
     "esbonio.sphinx.confDir": "",

+ 11 - 1
Makefile

@@ -61,14 +61,24 @@ clean:
 		cd .. ;\
 	done
 
+.PHONY: ECHO
+ECHO:
+	@echo "$@"
+
 cppcheck-xml: 
 	cppcheck kernel user --platform=unix64 --std=c11 -I user/libs/ -I=kernel/ --force -j $(NPROCS) --xml 2> cppcheck.xml
 
 cppcheck:
 	cppcheck kernel user --platform=unix64 --std=c11 -I user/libs/ -I=kernel/ --force -j $(NPROCS)
 
+docs: ECHO
+	bash -c "cd docs && make html && cd .."
+
+clean-docs:
+	bash -c "cd docs && make clean && cd .."
+
 gdb:
-	gdb -n -x tools/.gdbinit
+	rust-gdb -n -x tools/.gdbinit
 
 # 写入磁盘镜像
 write_diskimage:

+ 10 - 5
README.md

@@ -1,5 +1,9 @@
 # DragonOS
 
+## 打造完全自主可控的数字化未来!
+
+--- 
+
 **Languages** 中文|[English](README_EN.md)
 
 &nbsp;
@@ -18,6 +22,8 @@
 
 - 项目文档  **[docs.DragonOS.org](https://docs.dragonos.org)**
 
+- **了解开发动态、开发任务,请访问DragonOS的zulip社群**: [https://DragonOS.zulipchat.com](https://DragonOS.zulipchat.com)
+
 - 开源论坛  **[bbs.DragonOS.org](https://bbs.dragonos.org)**
 
 - 软件镜像站 **[mirrors.DragonOS.org](https://mirrors.DragonOS.org)**
@@ -42,9 +48,9 @@
 
 ## 如何加入?
 
-&emsp;&emsp;如果你愿意加入我们,你可以查看GitHub仓库的Project面板,选择近期已规划的功能,对他们进行完善。
+&emsp;&emsp;如果你愿意加入我们,你可以访问DragonOS的zulip社群,了解开发动态、开发任务: [https://DragonOS.zulipchat.com](https://DragonOS.zulipchat.com)
 
-&emsp;&emsp;或者,你也可以带着你的创意与想法,和社区的小伙伴一起讨论,为DragonOS创造一些新的功能。
+&emsp;&emsp;你也可以带着你的创意与想法,和社区的小伙伴一起讨论,为DragonOS创造一些新的功能。
 
 ## 如何与社区建立联系?
 
@@ -52,9 +58,8 @@
 
 &emsp;&emsp;或者是加入我们的开发交流QQ群:**115763565**
 
-&emsp;&emsp;对于正式问题的讨论,我们建议在论坛[bbs.DragonOS.org](https://bbs.dragonos.org/)上的对应板块,使用正式的语言发帖讨论。亦或者是在本仓库的issue下提出问题。
+&emsp;&emsp;对于正式问题的讨论,我们建议在 **[DragonOS的zulip社群](https://DragonOS.zulipchat.com)** 上的对应板块,使用正式的语言发帖讨论。亦或者是在本仓库的issue下提出问题。
 
-&emsp;&emsp;在发帖的同时,可以把帖子转发到交流QQ群,这样能使得问题的交流更加高效,也便于问题的归档。
 
 ## 贡献者名单
 
@@ -68,7 +73,7 @@
 
 ## 赞助
 
-&emsp;&emsp;DragonOS是一个公益性质的开源项目,但是它的发展离不开资金的支持,如果您愿意的话,可以通过 ** [赞助 - DragonOS](https://dragonos.org/?page_id=37) ** ,从而促进这个项目的发展。所有的赞助者的名单都会被公示。您的每一分赞助,都会为DragonOS的发展作出贡献!
+&emsp;&emsp;DragonOS是一个公益性质的开源项目,但是它的发展离不开资金的支持,如果您愿意的话,可以通过 **[赞助 - DragonOS](https://dragonos.org/?page_id=37)** ,从而促进这个项目的发展。所有的赞助者的名单都会被公示。您的每一分赞助,都会为DragonOS的发展作出贡献!
 
 ### 赞助的资金都会被用到哪里?
 

+ 4 - 4
README_EN.md

@@ -12,6 +12,7 @@
 
 - Home Page  **[DragonOS.org](https://dragonos.org)**
 - Documentation  **[docs.DragonOS.org](https://docs.dragonos.org)**
+- **To learn about development dynamics and development tasks, please visit DragonOS's zulip community:** [https://DragonOS.zulipchat.com](https://DragonOS.zulipchat.com)
 - BBS  **[bbs.DragonOS.org](https://bbs.dragonos.org)**
 - Software mirror website **[mirrors.DragonOS.org](https://mirrors.DragonOS.org)**
 - QQ group **115763565**
@@ -31,7 +32,7 @@
 
 ## How to join DragonOS ?
 
-&emsp;&emsp;If you are willing to join us, you can check the project panel of the GitHub repo, select the recently planned functions, and improve them.
+&emsp;&emsp;If you are willing to join us, you can visit DragonOS's zulip community, learn about development dynamics and development tasks: [https://DragonOS.zulipchat.com](https://DragonOS.zulipchat.com)
 
 &emsp;&emsp;Or, you can also bring your ideas, discuss with community members, and create some new functions for DragonOS.
 
@@ -41,9 +42,8 @@
 
 &emsp;&emsp;Or join our development exchange QQ group: **115763565**
 
-&emsp;&emsp;For the discussion of formal issues, we suggest that they be discussed in the forum [BBS.Dragonos.org](https://bbs.dragonos.org/) In the corresponding section of the, use formal language to post for discussion. Or ask questions under the issue of the warehouse.
+&emsp;&emsp;For the discussion of formal issues, we recommend that you use the official language to post on the corresponding section of **[DragonOS's zulip community](https://DragonOS.zulipchat.com)**. Or you can post questions under the issue of this repository.
 
-&emsp;&emsp;While posting, you can forward the post to the communication QQ group, which can make the communication of problems more efficient and facilitate the archiving of problems.
 
 ## List of contributors
 
@@ -58,7 +58,7 @@ Maintainer longjin's Email:[email protected]
 
 ## Reward
 
-&emsp;&emsp;DragonOS is an open source public welfare project, but its development cannot be separated from the support of funds. If you want, you can visit ** [Sponsor - DragonOS](https://dragonos.org/?page_id=37) ** , so as to promote the development of this project. The list of all sponsors will be published. Every bit of your sponsorship will contribute to the development of DragonOS!
+&emsp;&emsp;DragonOS is an open source public welfare project, but its development cannot be separated from the support of funds. If you want, you can visit **[Sponsor - DragonOS](https://dragonos.org/?page_id=37)** , so as to promote the development of this project. The list of all sponsors will be published. Every bit of your sponsorship will contribute to the development of DragonOS!
 
 ### Where will the sponsorship funds be used?
 

BIN
docs/Multiboot2 Specification version 2.0.pdf


+ 39 - 1
docs/community/contact/index.rst

@@ -3,12 +3,50 @@
 与社区建立联系
 ====================================
 
+联系方式
+-------------------------
+
 社区公共邮箱:[email protected]
 
-DragonOS负责人: longjin
+DragonOS社区负责人: longjin
 
 工作邮箱: [email protected]
 
 开发交流QQ群: 115763565
 
 DragonOS官网: https://DragonOS.org
+
+了解开发动态、开发任务,请访问DragonOS的zulip社群: https://DragonOS.zulipchat.com
+
+
+赞助及捐赠
+-------------------------
+
+DragonOS是一个开源项目,我们欢迎任何形式的赞助和捐赠,您的捐赠将用于DragonOS的开发和维护,以及社区的运营。
+
+您可以通过以下方式赞助和捐赠:
+
+- 访问DragonOS官网 https://DragonOS.org ,点击页面右上角的“赞助”按钮,进行捐赠
+- 联系社区负责人,沟通具体的赞助方式等。
+
+财务及捐赠信息公开
+-------------------------
+
+DragonOS社区的捐赠信息将按年进行公开。赞助商、赞助者信息将在收到赞助后,15天内进行公开。
+
+社区管理、财务及法务主体
+-------------------------
+
+DragonOS社区的管理、财务及法务主体为:灵高计算机系统(广州)有限公司。
+
+我们是一家开源公司,我们坚信,开源能为我国将来的IT,打下更好的基础。我们也通过其他业务创收,投入到DragonOS的研发之中。
+
+公司负责DragonOS社区的运营、财务、法务事项处理工作。
+
+地址:广东省广州市番禺区小谷围街广州大学城华南理工大学大学城校区
+
+邮件:[email protected]
+
+官网:https://ringotek.com.cn
+
+

+ 4 - 1
docs/introduction/build_system.md

@@ -233,7 +233,10 @@ make run-docker
 - Docker编译,并写入磁盘镜像,: `make docker`
 - Docker编译,写入磁盘镜像,并在QEMU中运行: `make run-docker`
 - 不编译,直接从已有的磁盘镜像启动: `make qemu`
+- 清理编译产生的文件: `make clean`
+- 编译文档: `make docs` (需要手动安装sphinx以及docs下的`requirements.txt`中的依赖)
+- 清理文档: `make clean-docs`
 
 :::{note}
 如果您需要在vnc中运行DragonOS,请在上述命令后加上`-vnc`后缀。如:`make run-vnc`
-:::
+:::

+ 18 - 6
docs/introduction/features.md

@@ -12,10 +12,14 @@
 
 ### 内存管理
 
-- [x] 页分配器
-- [x] slab分配器
+- [x] 页分配器
+- [x] 小对象分配器
 - [x] VMA
 - [x] MMIO地址空间自动分配
+- [x] 页面映射器
+- [x] 硬件抽象层
+- [x] 独立的用户地址空间管理机制
+- [x] C接口兼容层
 
 ### 多核
 
@@ -31,6 +35,7 @@
 - [x] exec
 - [x] 进程睡眠(支持高精度睡眠)
 - [x] kthread机制
+- [x] 可扩展二进制加载器
 
 #### 同步原语
 
@@ -43,7 +48,10 @@
 ### 调度
 
 - [x] CFS调度器
+- [x] 实时调度器(FIFO、RR)
 - [x] 单核调度
+- [x] 多核调度
+- [x] 负载均衡
 
 ### IPC
 
@@ -56,7 +64,8 @@
 - [x] fat12/16/32
 - [x] Devfs
 - [x] RamFS
-- [x] procfs
+- [x] Procfs
+- [x] Sysfs
 
 ### 异常及中断处理
 
@@ -95,7 +104,7 @@
 - [x] ACPI 高级电源配置模块
 - [x] IDE硬盘
 - [x] AHCI硬盘
-- [x] PCI
+- [x] PCI、PCIe总线
 - [x] XHCI(usb3.0)
 - [x] ps/2 键盘
 - [x] ps/2 鼠标
@@ -107,6 +116,8 @@
 - [x] VirtIO网卡
 - [x] x87FPU
 - [x] TTY终端
+- [x] 浮点处理器
+
 
 ## 用户层
 
@@ -121,9 +132,9 @@
 - [x] 基于字符串匹配的解析
 - [x] 基本的几个命令
 
-### 驱动程序
+### Http Server
 
-- [x] ps/2键盘用户态驱动
+- 使用C编写的简单的Http Server,能够运行静态网站。
 
 ## 软件移植
 
@@ -132,3 +143,4 @@
 - [x] gmp 6.2.1 [https://github.com/DragonOS-Community/gmp-6.2.1](https://github.com/DragonOS-Community/gmp-6.2.1)
 - [x] mpfr 4.1.1 [https://github.com/DragonOS-Community/mpfr](https://github.com/DragonOS-Community/mpfr)
 - [x] mpc 1.2.1 [https://github.com/DragonOS-Community/mpc](https://github.com/DragonOS-Community/mpc)
+- [x] relibc [https://github.com/DragonOS-Community/relibc](https://github.com/DragonOS-Community/relibc)

+ 3 - 1
docs/introduction/index.rst

@@ -3,9 +3,11 @@ DragonOS简介
 
     DragonOS龙操作系统(以下简称“DragonOS”)是一个面向服务器领域的,从0开发内核及用户态环境,并提供Linux兼容性的64位操作系统。它使用Rust与C语言进行编写,并正在逐步淘汰原有的C代码,以在将来提供更好的安全性与可靠性。
 
+**我们致力于打造完全自主可控的数字化未来!**
+
     DragonOS的目标是,构建一个完全独立自主的、开源的、高性能及高可靠性的服务器操作系统,为国家数字基础设施建设提供完全独立自主的底层核心动力。
 
-    作为一个社区驱动的开源操作系统,为了促进其发展,避免让其遭受一些不遵守开源协议的商业公司的侵权,我们决定使用GPLv2协议开放源代码,以严格的开源协议来保护DragonOS。
+    作为一个社区驱动的开源操作系统,为了促进开源社区建设,并避免让其遭受一些不遵守开源协议的商业公司的侵权,我们决定使用GPLv2协议开放源代码,以严格的开源协议来保护DragonOS。
 
     你可能对DragonOS中已经实现了哪些功能感兴趣,您可以转到这里::ref:`功能特性 <_genreal_features>`
 

+ 0 - 15
docs/kernel/core_api/allocate-memory.md

@@ -1,15 +0,0 @@
-# 内存分配指南
-
-DragonOS提供了一些用于内存分配的api。您可以使用*kmalloc*来分配小的内存块,也可以使用*alloc_pages*分配连续的2MB大小的内存页面。
-
-## 选择合适的内存分配器
-
-在内核中,最直接、最简单的分配内存的方式就是,使用`kmalloc()`函数进行分配。并且,出于安全起见,除非内存在分配后一定会被覆盖,且您能确保内存中的脏数据一定不会对程序造成影响,在其余情况下,我们建议使用`kzalloc()`进行内存分配,它将会在`kmalloc()`的基础上,把申请到的内存进行清零。
-
-您可以通过`kmalloc()`函数分配得到32bytes到1MBytes之间的内存对象。并且,这些内存对象具有以下的性质:
-
-- 内存起始地址及大小按照2次幂对齐。(比如,申请的是80bytes的内存空间,那么获得的内存对象大小为128bytes且内存地址按照128bytes对齐)
-
-对于需要大量连续内存的分配,可以使用`alloc_pages()`向页面分配器申请连续的内存页。
-
-当内存空间不再被使用时,那么必须释放他们。若您使用的是`kmalloc()`分配的内存,那么您需要使用`kfree()`释放它。若是使用`alloc_pages()`分配的内存,则需要使用`free_pages()`来释放它们。

+ 0 - 13
docs/kernel/core_api/index.rst

@@ -13,16 +13,3 @@
    data_structures
    casting
    softirq
-
-内存管理
-===================
-
-   这里快速讲解了如何在DragonOS中分配、使用内存。以便您能快速的了解这个模块。
-   
-   详细的内存管理模块的文档请参见::ref:`memory_management_module`
-
-.. toctree::
-   :maxdepth: 1
-
-   allocate-memory
-   mm-api

+ 0 - 267
docs/kernel/core_api/mm-api.md

@@ -1,267 +0,0 @@
-(_core_mm_api)=
-
-# 内存管理API
-
-## SLAB内存池
-
-SLAB内存池提供小内存对象的分配功能。
-
-### `void *kmalloc(unsigned long size, gfp_t gfp)`
-
-&emsp;&emsp;获取小块的内存。
-
-#### 描述
-
-&emsp;&emsp;kmalloc用于获取那些小于2M内存页大小的内存对象。可分配的内存对象大小为32bytes~1MBytes. 且分配的内存块大小、起始地址按照2的n次幂进行对齐。(比如,申请的是80bytes的内存空间,那么获得的内存对象大小为128bytes且内存地址按照128bytes对齐)
-
-##### 参数
-
-**size**
-
-&emsp;&emsp;内存对象的大小
-
-**gfp**
-
-&emsp;&emsp;标志位
-
-### `void *kzalloc(unsigned long size, gfp_t gfp)`
-
-#### 描述
-
-&emsp;&emsp;获取小块的内存,并将其清零。其余功能与kmalloc相同。
-
-
-##### 参数
-
-**size**
-
-&emsp;&emsp;内存对象的大小
-
-**gfp**
-
-&emsp;&emsp;标志位
-
-### `unsigned long kfree(void *address)`
-
-&emsp;&emsp;释放从slab分配的内存。
-
-#### 描述
-
-&emsp;&emsp;该函数用于释放通过kmalloc申请的内存。如果`address`为NULL,则函数被调用后,无事发生。
-
-&emsp;&emsp;请不要通过这个函数释放那些不是从`kmalloc()`或`kzalloc()`申请的内存,否则将会导致系统崩溃。
-
-##### 参数
-
-**address**
-
-&emsp;&emsp;指向内存对象的起始地址的指针
-
-## 物理页管理
-
-DragonOS支持对物理页的直接操作
-
-### `struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)`
-
-#### 描述
-
-&emsp;&emsp;从物理页管理单元中申请一段连续的物理页
-
-#### 参数
-
-**zone_select**
-
-&emsp;&emsp;要申请的物理页所位于的内存区域
-
-可选值:
-
-- `ZONE_DMA` DMA映射专用区域
-- `ZONE_NORMAL` 正常的物理内存区域,已在页表高地址处映射
-- `ZONE_UNMAPPED_IN_PGT` 尚未在页表中映射的区域
-
-**num**
-
-&emsp;&emsp;要申请的连续物理页的数目,该值应当小于64
-
-**flags**
-
-&emsp;&emsp;分配的页面要被设置成的属性
-
-可选值:
-
-- `PAGE_PGT_MAPPED` 页面在页表中已被映射
-- `PAGE_KERNEL_INIT` 内核初始化所占用的页
-- `PAGE_DEVICE` 设备MMIO映射的内存
-- `PAGE_KERNEL` 内核层页
-- `PAGE_SHARED` 共享页
-
-#### 返回值
-
-##### 成功
-
-&emsp;&emsp;成功申请则返回指向起始页面的Page结构体的指针
-
-##### 失败
-
-&emsp;&emsp;当ZONE错误或内存不足时,返回`NULL`
-
-### `void free_pages(struct Page *page, int number)`
-
-#### 描述
-
-&emsp;&emsp;从物理页管理单元中释放一段连续的物理页。
-
-#### 参数
-
-**page**
-
-&emsp;&emsp;要释放的第一个物理页的Page结构体
-
-**number**
-
-&emsp;&emsp;要释放的连续内存页的数量。该值应小于64
-
-## 页表管理
-
-### `int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k)`
-
-#### 描述
-
-&emsp;&emsp;将一段物理地址映射到当前页表的指定虚拟地址处
-
-#### 参数
-
-**virt_addr_start**
-
-&emsp;&emsp;虚拟地址的起始地址
-
-**phys_addr_start**
-
-&emsp;&emsp;物理地址的起始地址
-
-**length**
-
-&emsp;&emsp;要映射的地址空间的长度
-
-**flags**
-
-&emsp;&emsp;页表项的属性
-
-**use4k**
-
-&emsp;&emsp;使用4级页表,将地址区域映射为若干4K页
-
-### `int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k)`
-
-#### 描述
-
-&emsp;&emsp;将一段物理地址映射到指定页表的指定虚拟地址处
-
-#### 参数
-
-**proc_page_table_addr**
-
-&emsp;&emsp;指定的顶层页表的起始地址
-
-**is_phys**
-
-&emsp;&emsp;该顶层页表地址是否为物理地址
-
-**virt_addr_start**
-
-&emsp;&emsp;虚拟地址的起始地址
-
-**phys_addr_start**
-
-&emsp;&emsp;物理地址的起始地址
-
-**length**
-
-&emsp;&emsp;要映射的地址空间的长度
-
-**flags**
-
-&emsp;&emsp;页表项的属性
-
-**user**
-
-&emsp;&emsp;页面是否为用户态可访问
-
-**flush**
-
-&emsp;&emsp;完成映射后,是否刷新TLB
-
-**use4k**
-
-&emsp;&emsp;使用4级页表,将地址区域映射为若干4K页
-
-#### 返回值
-
-- 映射成功:0
-- 映射失败:-EFAULT
-
-### `void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul length)`
-
-#### 描述
-
-&emsp;&emsp;取消给定页表中的指定地址空间的页表项映射。
-
-#### 参数
-
-**proc_page_table_addr**
-
-&emsp;&emsp;指定的顶层页表的基地址
-
-**is_phys**
-
-&emsp;&emsp;该顶层页表地址是否为物理地址
-
-**virt_addr_start**
-
-&emsp;&emsp;虚拟地址的起始地址
-
-**length**
-
-&emsp;&emsp;要取消映射的地址空间的长度
-
-### `mm_unmap_addr(virt_addr, length)`
-
-#### 描述
-
-&emsp;&emsp;该宏定义用于取消当前进程的页表中的指定地址空间的页表项映射。
-
-#### 参数
-
-**virt_addr**
-
-&emsp;&emsp;虚拟地址的起始地址
-
-**length**
-
-&emsp;&emsp;要取消映射的地址空间的长度
-
-## 内存信息获取
-
-### `struct mm_stat_t mm_stat()`
-
-#### 描述
-
-&emsp;&emsp;获取计算机目前的内存空间使用情况
-
-#### 参数
-
-无
-
-#### 返回值
-
-&emsp;&emsp;返回值是一个`mm_mstat_t`结构体,该结构体定义于`mm/mm.h`中。其中包含了以下信息(单位均为字节):
-
-| 参数名        | 解释                      |
-| ---------- | ----------------------- |
-| total      | 计算机的总内存数量大小             |
-| used       | 已使用的内存大小                |
-| free       | 空闲物理页所占的内存大小            |
-| shared     | 共享的内存大小                 |
-| cache_used | 位于slab缓冲区中的已使用的内存大小     |
-| cache_free | 位于slab缓冲区中的空闲的内存大小      |
-| available  | 系统总空闲内存大小(包括kmalloc缓冲区) |

+ 29 - 0
docs/kernel/memory_management/allocate-memory.md

@@ -0,0 +1,29 @@
+# 内存分配指南
+
+&emsp;&emsp;本文将讲述如何在内核中进行内存分配。在开始之前,请您先了解一个基本点:DragonOS的内核使用4KB的页来管理内存,并且具有伙伴分配器和slab分配器。并且对用户空间、内核空间均具有特定的管理机制。
+
+## 1. 安全的分配内存
+
+&emsp;&emsp;在默认情况下,KernelAllocator被绑定为全局内存分配器,它会根据请求分配的内存大小,自动选择使用slab还是伙伴分配器。因此,在内核中,使用Rust原生的
+内存分配函数,或者是创建一个`Box`对象等等,都是安全的。
+
+
+## 2. 手动管理页帧
+
+:::{warning}
+**请格外小心!** 手动管理页帧脱离了Rust的内存安全机制,因此可能会造成内存泄漏或者是内存错误。
+:::
+
+&emsp;&emsp;在某些情况下,我们需要手动分配页帧。例如,我们需要在内核中创建一个新的页表,或者是在内核中创建一个新的地址空间。这时候,我们需要手动分配页帧。使用`LockedFrameAllocator`的`allocate()`函数,能够分配在物理地址上连续的页帧。请注意,由于底层使用的是buddy分配器,因此页帧数目必须是2的n次幂,且最大大小不超过1GB。
+
+&emsp;&emsp;当需要释放页帧的时候,使用`LockedFrameAllocator`的`deallocate()`函数,或者是`deallocate_page_frames()`函数,能够释放在物理地址上连续的页帧。
+
+&emsp;&emsp;当您需要映射页帧的时候,可使用`KernelMapper::lock()`函数,获得一个内核映射器对象,然后进行映射。由于KernelMapper是对PageMapper的封装,因此您在获取KernelMapper之后,可以使用PageMapper相关接口对内核空间的映射进行管理。
+
+:::{warning}
+**千万不要** 使用KernelMapper去映射用户地址空间的内存,这会使得这部分内存脱离用户地址空间的管理,从而导致内存错误。
+:::
+
+## 3. 为用户程序分配内存
+
+&emsp;&emsp;在内核中,您可以使用用户地址空间结构体(`AddressSpace`)的`mmap()`,`map_anonymous()`等函数,为用户程序分配内存。这些函数会自动将用户程序的内存映射到用户地址空间中,并且会自动创建VMA结构体。您可以使用`AddressSpace`的`munmap()`函数,将用户程序的内存从用户地址空间中解除映射,并且销毁VMA结构体。调整权限等操作可以使用`AddressSpace`的`mprotect()`函数。

+ 4 - 4
docs/kernel/memory_management/index.rst

@@ -1,14 +1,14 @@
 .. _memory_management_module:
 
 ====================================
-内存管理文档
+内存管理
 ====================================
 
-   这里讲解了内存管理模块的一些设计及实现原理。
-   
-   如果你正在寻找使用内存管理模块的方法,请转到::ref:`内存管理API文档 <_core_mm_api>`
+   这里讲解了内存管理模块的一些设计及实现原理,以及相应的接口。
 
 .. toctree::
    :maxdepth: 1
 
+   intro
+   allocate-memory
    mmio

+ 20 - 0
docs/kernel/memory_management/intro.md

@@ -0,0 +1,20 @@
+# 内存管理模块简介
+
+## 1. 概述
+
+&emsp;&emsp;DragonOS实现了具有优秀架构设计的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。
+
+&emsp;&emsp;DragonOS的内存管理模块主要由以下类型的组件组成:
+
+- **硬件抽象层(MemoryManagementArch)** - 提供对具体处理器架构的抽象,使得内存管理模块可以在不同的处理器架构上运行
+- **页面映射器(PageMapper)**- 提供对虚拟地址和物理地址的映射,以及页表的创建、填写、销毁、权限管理等操作。分为两种类型:内核页表映射器(KernelMapper)和用户页表映射器(位于具体的用户地址空间结构中)
+- **页面刷新器(PageFlusher)** - 提供对页表的刷新操作(整表刷新、单页刷新、跨核心刷新)
+- **页帧分配器(FrameAllocator)** - 提供对页帧的分配、释放、管理等操作。具体来说,包括BumpAllocator、BuddyAllocator
+- **小对象分配器** - 提供对小内存对象的分配、释放、管理等操作。指的是内核里面的SlabAllocator (SlabAllocator的实现目前还没有完成)
+- **MMIO空间管理器** - 提供对MMIO地址空间的分配、管理操作。(目前这个模块待进一步重构)
+- **用户地址空间管理机制** - 提供对用户地址空间的管理。
+    - VMA机制 - 提供对用户地址空间的管理,包括VMA的创建、销毁、权限管理等操作
+    - 用户映射管理 - 与VMA机制共同作用,管理用户地址空间的映射
+- **系统调用层** - 提供对用户空间的内存管理系统调用,包括mmap、munmap、mprotect、mremap等
+- **C接口兼容层** - 提供对原有的C代码的接口,使得C代码能够正常运行。
+

+ 2 - 1
docs/kernel/process_management/index.rst

@@ -5,4 +5,5 @@
    :maxdepth: 1
 
    kthread
-   pcb
+   pcb
+   load_binary

+ 15 - 0
docs/kernel/process_management/load_binary.md

@@ -0,0 +1,15 @@
+# 加载程序
+
+## 1. 二进制程序装载
+
+&emsp;&emsp;在小节,你将了解DragonOS的二进制程序加载器的原理。
+
+&emsp;&emsp;DragonOS在装载二进制程序时,执行了“探测-装载”的过程。
+
+&emsp;&emsp;在探测阶段,DragonOS会读取文件首部,然后依次调用各个二进制加载器的探测函数,判断该二进制程序是否适用于该加载器。如果适用,则使用这个加载器进行装载。
+
+&emsp;&emsp;在装载阶段,DragonOS会使用上述加载器进行装载。装载器会将二进制程序的各个段映射到内存中,并且得到二进制程序的入口地址。
+
+:::{note}
+目前DragonOS不支持动态链接,因此所有的二进制程序都是静态链接的。并且暂时支持的只有ELF加载器。
+:::

+ 7 - 0
kernel/Cargo.toml

@@ -22,6 +22,9 @@ smoltcp = { git = "https://github.com/DragonOS-Community/smoltcp.git", rev = "90
 num-traits = { git = "https://github.com/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
 num = { version = "0.4.0", default-features = false }
 num-derive = "0.3"
+# 一个no_std的hashmap、hashset
+hashbrown = "0.13.2"
+elf = { version = "0.7.2", default-features = false }
 
 # 构建时依赖项
 [build-dependencies]
@@ -34,4 +37,8 @@ version = "1.4.0"
 features = ["spin_no_std"]
 
 
+# The release profile, used for `cargo build --release`
+[profile.release]
+debug = false
+
 

+ 3 - 2
kernel/src/Makefile

@@ -17,7 +17,7 @@ export ASFLAGS := --64
 LD_LIST := head.o
 
 
-kernel_subdirs := common driver process debug arch exception mm smp sched syscall ktest libs ipc io time
+kernel_subdirs := common driver process debug arch exception smp sched syscall ktest libs ipc io time
 	
 
 
@@ -58,7 +58,8 @@ all: kernel
 	$(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o  -T link.lds
 	@echo "Generating kernel ELF file..."
 # 生成内核文件
-	$(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../../bin/kernel/kernel.elf
+	$(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64  kernel ../../bin/kernel/kernel.elf
+# $(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../../bin/kernel/kernel.elf
 	@echo "Kernel Build Done."
 
 ECHO:

+ 2 - 2
kernel/src/arch/mod.rs

@@ -1,9 +1,9 @@
 pub mod x86_64;
 #[cfg(target_arch = "x86_64")]
-pub use self::x86_64::pci::pci::X86_64PciArch as PciArch;
-#[cfg(target_arch = "x86_64")]
 pub use self::x86_64::*; //公开x86_64架构下的函数,使外界接口统一
+
 use crate::driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber};
+
 /// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数
 pub trait TraitPciArch {
     /// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现

+ 3 - 2
kernel/src/arch/x86_64/asm/irqflags.rs

@@ -3,8 +3,9 @@ use core::arch::asm;
 #[inline]
 pub fn local_irq_save() -> usize {
     let x: usize;
+    // x86_64::registers::rflags::
     unsafe {
-        asm!("pushfq ; pop {} ; cli", out(reg) x, options(nostack));
+        asm!("pushfq; pop {}; cli", out(reg) x, options(nomem, preserves_flags));
     }
     x
 }
@@ -13,6 +14,6 @@ pub fn local_irq_save() -> usize {
 // 恢复先前保存的rflags的值x
 pub fn local_irq_restore(x: usize) {
     unsafe {
-        asm!("push {} ; popfq", in(reg) x, options(nostack));
+        asm!("push {}; popfq", in(reg) x, options(nomem, preserves_flags));
     }
 }

+ 8 - 0
kernel/src/arch/x86_64/context.rs

@@ -16,7 +16,15 @@ pub fn switch_process(
     fp_state_save(prev);
     fp_state_restore(next);
     compiler_fence(core::sync::atomic::Ordering::SeqCst);
+    let new_address_space = next.address_space().unwrap_or_else(|| {
+        panic!(
+            "switch_process: next process:{} address space is null",
+            next.pid
+        )
+    });
     unsafe {
+        // 加载页表
+        new_address_space.read().user_mapper.utable.make_current();
         switch_proc(prev, next);
     }
     compiler_fence(core::sync::atomic::Ordering::SeqCst);

+ 1 - 1
kernel/src/arch/x86_64/fpu.rs

@@ -79,7 +79,7 @@ impl FpState {
 /// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能
 pub fn fp_state_save(pcb: &mut process_control_block) {
     // 该过程中不允许中断
-    let rflags = local_irq_save();
+    let rflags: usize = local_irq_save();
 
     let fp: &mut FpState = if pcb.fp_state == null_mut() {
         let f = Box::leak(Box::new(FpState::default()));

+ 3 - 3
kernel/src/arch/x86_64/interrupt/mod.rs

@@ -41,14 +41,14 @@ impl InterruptArch for X86_64InterruptArch {
     fn is_irq_enabled() -> bool {
         let rflags: u64;
         unsafe {
-            asm!("pushfq; pop {}", out(reg) rflags);
+            asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags));
         }
         return rflags & (1 << 9) != 0;
     }
 
     unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
         compiler_fence(Ordering::SeqCst);
-        let rflags = local_irq_save() as u64;
+        let rflags = local_irq_save();
         let flags = IrqFlags::new(rflags);
         let guard = IrqFlagsGuard::new(flags);
         compiler_fence(Ordering::SeqCst);
@@ -57,7 +57,7 @@ impl InterruptArch for X86_64InterruptArch {
 
     unsafe fn restore_irq(flags: IrqFlags) {
         compiler_fence(Ordering::SeqCst);
-        local_irq_restore(flags.flags() as usize);
+        local_irq_restore(flags.flags());
         compiler_fence(Ordering::SeqCst);
     }
 }

+ 1 - 0
kernel/src/arch/x86_64/libs/mod.rs

@@ -0,0 +1 @@
+

+ 618 - 19
kernel/src/arch/x86_64/mm/mod.rs

@@ -1,28 +1,627 @@
 pub mod barrier;
-use crate::include::bindings::bindings::process_control_block;
+
+use alloc::vec::Vec;
+use hashbrown::HashSet;
+use x86::time::rdtsc;
+use x86_64::registers::model_specific::EferFlags;
+
+use crate::driver::uart::uart::c_uart_send_str;
+use crate::include::bindings::bindings::{
+    disable_textui, enable_textui, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
+    video_reinitialize,
+};
+use crate::libs::align::page_align_up;
+use crate::libs::printk::PrintkWriter;
+use crate::libs::spinlock::SpinLock;
+
+use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount};
+use crate::mm::mmio_buddy::mmio_init;
+use crate::{
+    arch::MMArch,
+    mm::allocator::{buddy::BuddyAllocator, bump::BumpAllocator},
+};
+
+use crate::mm::kernel_mapper::KernelMapper;
+use crate::mm::page::{PageEntry, PageFlags};
+use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, PhysMemoryArea, VirtAddr};
+use crate::syscall::SystemError;
+use crate::{kdebug, kinfo};
 
 use core::arch::asm;
-use core::ptr::read_volatile;
+use core::ffi::c_void;
+use core::fmt::{Debug, Write};
+use core::mem::{self};
 
-use self::barrier::mfence;
+use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
 
-/// @brief 切换进程的页表
-///
-/// @param 下一个进程的pcb。将会把它的页表切换进来。
-///
-/// @return 下一个进程的pcb(把它return的目的主要是为了归还所有权)
-#[inline(always)]
-#[allow(dead_code)]
-pub fn switch_mm(
-    next_pcb: &'static mut process_control_block,
-) -> &'static mut process_control_block {
-    mfence();
-    // kdebug!("to get pml4t");
-    let pml4t = unsafe { read_volatile(&next_pcb.mm.as_ref().unwrap().pgd) };
+pub type PageMapper =
+    crate::mm::page::PageMapper<crate::arch::x86_64::mm::X86_64MMArch, LockedFrameAllocator>;
+
+/// @brief 用于存储物理内存区域的数组
+static mut PHYS_MEMORY_AREAS: [PhysMemoryArea; 512] = [PhysMemoryArea {
+    base: PhysAddr::new(0),
+    size: 0,
+}; 512];
+
+/// 初始的CR3寄存器的值,用于内存管理初始化时,创建的第一个内核页表的位置
+static mut INITIAL_CR3_VALUE: PhysAddr = PhysAddr::new(0);
+
+/// 内核的第一个页表在pml4中的索引
+/// 顶级页表的[256, 512)项是内核的页表
+static KERNEL_PML4E_NO: usize = (X86_64MMArch::PHYS_OFFSET & ((1 << 48) - 1)) >> 39;
+
+static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
+
+#[derive(Clone, Copy)]
+pub struct X86_64MMBootstrapInfo {
+    kernel_code_start: usize,
+    kernel_code_end: usize,
+    kernel_data_end: usize,
+    kernel_rodata_end: usize,
+    start_brk: usize,
+}
+
+impl Debug for X86_64MMBootstrapInfo {
+    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+        write!(
+            f,
+            "kernel_code_start: {:x}, kernel_code_end: {:x}, kernel_data_end: {:x}, kernel_rodata_end: {:x}, start_brk: {:x}",
+            self.kernel_code_start, self.kernel_code_end, self.kernel_data_end, self.kernel_rodata_end, self.start_brk)
+    }
+}
+
+pub static mut BOOTSTRAP_MM_INFO: Option<X86_64MMBootstrapInfo> = None;
+
+/// @brief X86_64的内存管理架构结构体
+#[derive(Debug, Clone, Copy, Hash)]
+pub struct X86_64MMArch;
+
+/// XD标志位是否被保留
+static XD_RESERVED: AtomicBool = AtomicBool::new(false);
+
+impl MemoryManagementArch for X86_64MMArch {
+    /// 4K页
+    const PAGE_SHIFT: usize = 12;
+
+    /// 每个页表项占8字节,总共有512个页表项
+    const PAGE_ENTRY_SHIFT: usize = 9;
+
+    /// 四级页表(PML4T、PDPT、PDT、PT)
+    const PAGE_LEVELS: usize = 4;
+
+    /// 页表项的有效位的index。在x86_64中,页表项的第[0, 47]位表示地址和flag,
+    /// 第[48, 51]位表示保留。因此,有效位的index为52。
+    /// 请注意,第63位是XD位,表示是否允许执行。
+    const ENTRY_ADDRESS_SHIFT: usize = 52;
+
+    const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT;
+
+    const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
+
+    const ENTRY_FLAG_PRESENT: usize = 1 << 0;
+
+    const ENTRY_FLAG_READONLY: usize = 0;
+
+    const ENTRY_FLAG_READWRITE: usize = 1 << 1;
+
+    const ENTRY_FLAG_USER: usize = 1 << 2;
+
+    const ENTRY_FLAG_WRITE_THROUGH: usize = 1 << 3;
+
+    const ENTRY_FLAG_CACHE_DISABLE: usize = 1 << 4;
+
+    const ENTRY_FLAG_NO_EXEC: usize = 1 << 63;
+    /// x86_64不存在EXEC标志位,只有NO_EXEC(XD)标志位
+    const ENTRY_FLAG_EXEC: usize = 0;
+
+    /// 物理地址与虚拟地址的偏移量
+    /// 0xffff_8000_0000_0000
+    const PHYS_OFFSET: usize = Self::PAGE_NEGATIVE_MASK + (Self::PAGE_ADDRESS_SIZE >> 1);
+
+    const USER_END_VADDR: VirtAddr = VirtAddr::new(0x0000_7eff_ffff_ffff);
+    const USER_BRK_START: VirtAddr = VirtAddr::new(0x700000000000);
+    const USER_STACK_START: VirtAddr = VirtAddr::new(0x6ffff0a00000);
 
+    /// @brief 获取物理内存区域
+    unsafe fn init() -> &'static [crate::mm::PhysMemoryArea] {
+        extern "C" {
+            fn _text();
+            fn _etext();
+            fn _edata();
+            fn _erodata();
+            fn _end();
+        }
+
+        Self::init_xd_rsvd();
+
+        let bootstrap_info = X86_64MMBootstrapInfo {
+            kernel_code_start: _text as usize,
+            kernel_code_end: _etext as usize,
+            kernel_data_end: _edata as usize,
+            kernel_rodata_end: _erodata as usize,
+            start_brk: _end as usize,
+        };
+        unsafe {
+            BOOTSTRAP_MM_INFO = Some(bootstrap_info);
+        }
+
+        // 初始化物理内存区域(从multiboot2中获取)
+        let areas_count =
+            Self::init_memory_area_from_multiboot2().expect("init memory area failed");
+        c_uart_send_str(0x3f8, "x86 64 init end\n\0".as_ptr());
+
+        return &PHYS_MEMORY_AREAS[0..areas_count];
+    }
+
+    /// @brief 刷新TLB中,关于指定虚拟地址的条目
+    unsafe fn invalidate_page(address: VirtAddr) {
+        compiler_fence(Ordering::SeqCst);
+        asm!("invlpg [{0}]", in(reg) address.data(), options(nostack, preserves_flags));
+        compiler_fence(Ordering::SeqCst);
+    }
+
+    /// @brief 刷新TLB中,所有的条目
+    unsafe fn invalidate_all() {
+        compiler_fence(Ordering::SeqCst);
+        // 通过设置cr3寄存器,来刷新整个TLB
+        Self::set_table(PageTableKind::User, Self::table(PageTableKind::User));
+        compiler_fence(Ordering::SeqCst);
+    }
+
+    /// @brief 获取顶级页表的物理地址
+    unsafe fn table(_table_kind: PageTableKind) -> PhysAddr {
+        let paddr: usize;
+        compiler_fence(Ordering::SeqCst);
+        asm!("mov {}, cr3", out(reg) paddr, options(nomem, nostack, preserves_flags));
+        compiler_fence(Ordering::SeqCst);
+        return PhysAddr::new(paddr);
+    }
+
+    /// @brief 设置顶级页表的物理地址到处理器中
+    unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
+        compiler_fence(Ordering::SeqCst);
+        asm!("mov cr3, {}", in(reg) table.data(), options(nostack, preserves_flags));
+        compiler_fence(Ordering::SeqCst);
+    }
+
+    /// @brief 判断虚拟地址是否合法
+    fn virt_is_valid(virt: VirtAddr) -> bool {
+        return virt.is_canonical();
+    }
+
+    /// 获取内存管理初始化时,创建的第一个内核页表的地址
+    fn initial_page_table() -> PhysAddr {
+        unsafe {
+            return INITIAL_CR3_VALUE;
+        }
+    }
+
+    /// @brief 创建新的顶层页表
+    ///
+    /// 该函数会创建页表并复制内核的映射到新的页表中
+    ///
+    /// @return 新的页表
+    fn setup_new_usermapper() -> Result<crate::mm::ucontext::UserMapper, SystemError> {
+        let new_umapper: crate::mm::page::PageMapper<X86_64MMArch, LockedFrameAllocator> = unsafe {
+            PageMapper::create(PageTableKind::User, LockedFrameAllocator)
+                .ok_or(SystemError::ENOMEM)?
+        };
+
+        let current_ktable: KernelMapper = KernelMapper::lock();
+        let copy_mapping = |pml4_entry_no| unsafe {
+            let entry: PageEntry<X86_64MMArch> = current_ktable
+                .table()
+                .entry(pml4_entry_no)
+                .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no));
+            new_umapper.table().set_entry(pml4_entry_no, entry)
+        };
+
+        // 复制内核的映射
+        for pml4_entry_no in KERNEL_PML4E_NO..512 {
+            copy_mapping(pml4_entry_no);
+        }
+
+        return Ok(crate::mm::ucontext::UserMapper::new(new_umapper));
+    }
+}
+
+impl X86_64MMArch {
+    unsafe fn init_memory_area_from_multiboot2() -> Result<usize, SystemError> {
+        // 这个数组用来存放内存区域的信息(从C获取)
+        let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed();
+        c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 begin\n\0".as_ptr());
+
+        let mut mb2_count: u32 = 0;
+        multiboot2_iter(
+            Some(multiboot2_get_memory),
+            &mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void,
+            &mut mb2_count,
+        );
+        c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 2\n\0".as_ptr());
+
+        let mb2_count = mb2_count as usize;
+        let mut areas_count = 0usize;
+        let mut total_mem_size = 0usize;
+        for i in 0..mb2_count {
+            // Only use the memory area if its type is 1 (RAM)
+            if mb2_mem_info[i].type_ == 1 {
+                // Skip the memory area if its len is 0
+                if mb2_mem_info[i].len == 0 {
+                    continue;
+                }
+                total_mem_size += mb2_mem_info[i].len as usize;
+                PHYS_MEMORY_AREAS[areas_count].base = PhysAddr::new(mb2_mem_info[i].addr as usize);
+                PHYS_MEMORY_AREAS[areas_count].size = mb2_mem_info[i].len as usize;
+                areas_count += 1;
+            }
+        }
+        c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 end\n\0".as_ptr());
+        kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024);
+
+        return Ok(areas_count);
+    }
+
+    fn init_xd_rsvd() {
+        // 读取ia32-EFER寄存器的值
+        let efer: EferFlags = x86_64::registers::model_specific::Efer::read();
+        if !efer.contains(EferFlags::NO_EXECUTE_ENABLE) {
+            // NO_EXECUTE_ENABLE是false,那么就设置xd_reserved为true
+            kdebug!("NO_EXECUTE_ENABLE is false, set XD_RESERVED to true");
+            XD_RESERVED.store(true, Ordering::Relaxed);
+        }
+        compiler_fence(Ordering::SeqCst);
+    }
+
+    /// 判断XD标志位是否被保留
+    pub fn is_xd_reserved() -> bool {
+        return XD_RESERVED.load(Ordering::Relaxed);
+    }
+}
+
+impl VirtAddr {
+    /// @brief 判断虚拟地址是否合法
+    #[inline(always)]
+    pub fn is_canonical(self) -> bool {
+        let x = self.data() & X86_64MMArch::PHYS_OFFSET;
+        // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址
+        // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址
+        return x == 0 || x == X86_64MMArch::PHYS_OFFSET;
+    }
+}
+
+/// @brief 初始化内存管理模块
+pub fn mm_init() {
+    c_uart_send_str(0x3f8, "mm_init\n\0".as_ptr());
+    PrintkWriter
+        .write_fmt(format_args!("mm_init() called\n"))
+        .unwrap();
+    // printk_color!(GREEN, BLACK, "mm_init() called\n");
+    static _CALL_ONCE: AtomicBool = AtomicBool::new(false);
+    if _CALL_ONCE
+        .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
+        .is_err()
+    {
+        c_uart_send_str(0x3f8, "mm_init err\n\0".as_ptr());
+        panic!("mm_init() can only be called once");
+    }
+
+    unsafe { X86_64MMArch::init() };
+    kdebug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
+    kdebug!("phys[0]=virt[0x{:x}]", unsafe {
+        MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data()
+    });
+
+    // 初始化内存管理器
+    unsafe { allocator_init() };
+    // enable mmio
+    mmio_init();
+    // 启用printk的alloc选项
+    PrintkWriter.enable_alloc();
+}
+
+unsafe fn allocator_init() {
+    let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk;
+    let phy_offset =
+        unsafe { MMArch::virt_2_phys(VirtAddr::new(page_align_up(virt_offset))) }.unwrap();
+
+    kdebug!("PhysArea[0..10] = {:?}", &PHYS_MEMORY_AREAS[0..10]);
+    let mut bump_allocator =
+        BumpAllocator::<X86_64MMArch>::new(&PHYS_MEMORY_AREAS, phy_offset.data());
+    kdebug!(
+        "BumpAllocator created, offset={:?}",
+        bump_allocator.offset()
+    );
+
+    // 暂存初始在head.S中指定的页表的地址,后面再考虑是否需要把它加到buddy的可用空间里面!
+    // 现在不加的原因是,我担心会有安全漏洞问题:这些初始的页表,位于内核的数据段。如果归还到buddy,
+    // 可能会产生一定的安全风险(有的代码可能根据虚拟地址来进行安全校验)
+    let _old_page_table = MMArch::table(PageTableKind::Kernel);
+
+    let new_page_table: PhysAddr;
+    // 使用bump分配器,把所有的内存页都映射到页表
+    {
+        // 用bump allocator创建新的页表
+        let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> =
+            crate::mm::page::PageMapper::<MMArch, _>::create(
+                PageTableKind::Kernel,
+                &mut bump_allocator,
+            )
+            .expect("Failed to create page mapper");
+        new_page_table = mapper.table().phys();
+        kdebug!("PageMapper created");
+
+        // 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
+        {
+            let table = mapper.table();
+            let empty_entry = PageEntry::<MMArch>::new(0);
+            for i in 0..MMArch::PAGE_ENTRY_NUM {
+                table
+                    .set_entry(i, empty_entry)
+                    .expect("Failed to empty page table entry");
+            }
+        }
+        kdebug!("Successfully emptied page table");
+
+        for area in PHYS_MEMORY_AREAS.iter() {
+            // kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size);
+            for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) {
+                let paddr = area.base.add(i * MMArch::PAGE_SIZE);
+                let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap();
+                let flags = kernel_page_flags::<MMArch>(vaddr);
+
+                let flusher = mapper
+                    .map_phys(vaddr, paddr, flags)
+                    .expect("Failed to map frame");
+                // 暂时不刷新TLB
+                flusher.ignore();
+            }
+        }
+
+        // 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射)
+        LowAddressRemapping::remap_at_low_address(&mut mapper);
+    }
+
+    unsafe {
+        INITIAL_CR3_VALUE = new_page_table;
+    }
+    kdebug!(
+        "After mapping all physical memory, DragonOS used: {} KB",
+        bump_allocator.offset() / 1024
+    );
+
+    // 初始化buddy_allocator
+    let buddy_allocator = unsafe { BuddyAllocator::<X86_64MMArch>::new(bump_allocator).unwrap() };
+
+    // 设置全局的页帧分配器
+    unsafe { set_inner_allocator(buddy_allocator) };
+    kinfo!("Successfully initialized buddy allocator");
+    // 关闭显示输出
+    unsafe {
+        disable_textui();
+    }
+    // make the new page table current
+    {
+        let mut binding = INNER_ALLOCATOR.lock();
+        let mut allocator_guard = binding.as_mut().unwrap();
+        kdebug!("To enable new page table.");
+        compiler_fence(Ordering::SeqCst);
+        let mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
+            PageTableKind::Kernel,
+            new_page_table,
+            &mut allocator_guard,
+        );
+        compiler_fence(Ordering::SeqCst);
+        mapper.make_current();
+        compiler_fence(Ordering::SeqCst);
+        kdebug!("New page table enabled");
+    }
+    kdebug!("Successfully enabled new page table");
+    // 重置显示输出目标
     unsafe {
-        asm!("mov cr3, {}", in(reg) pml4t);
+        video_reinitialize(false);
     }
-    mfence();
-    return next_pcb;
+
+    // 打开显示输出
+    unsafe {
+        enable_textui();
+    }
+    kdebug!("Text UI enabled");
+}
+
+#[no_mangle]
+pub extern "C" fn rs_test_buddy() {
+    test_buddy();
+}
+pub fn test_buddy() {
+    // 申请内存然后写入数据然后free掉
+    // 总共申请200MB内存
+    const TOTAL_SIZE: usize = 200 * 1024 * 1024;
+
+    for i in 0..10 {
+        kdebug!("Test buddy, round: {i}");
+        // 存放申请的内存块
+        let mut v: Vec<(PhysAddr, PageFrameCount)> = Vec::with_capacity(60 * 1024);
+        // 存放已经申请的内存块的地址(用于检查重复)
+        let mut addr_set: HashSet<PhysAddr> = HashSet::new();
+
+        let mut allocated = 0usize;
+
+        let mut free_count = 0usize;
+
+        while allocated < TOTAL_SIZE {
+            let mut random_size = 0u64;
+            unsafe { x86::random::rdrand64(&mut random_size) };
+            // 一次最多申请4M
+            random_size = random_size % (1024 * 4096);
+            if random_size == 0 {
+                continue;
+            }
+            let random_size =
+                core::cmp::min(page_align_up(random_size as usize), TOTAL_SIZE - allocated);
+            let random_size = PageFrameCount::from_bytes(random_size.next_power_of_two()).unwrap();
+            // 获取帧
+            let (paddr, allocated_frame_count) =
+                unsafe { LockedFrameAllocator.allocate(random_size).unwrap() };
+            assert!(allocated_frame_count.data().is_power_of_two());
+            assert!(paddr.data() % MMArch::PAGE_SIZE == 0);
+            unsafe {
+                assert!(MMArch::phys_2_virt(paddr)
+                    .as_ref()
+                    .unwrap()
+                    .check_aligned(allocated_frame_count.data() * MMArch::PAGE_SIZE));
+            }
+            allocated += allocated_frame_count.data() * MMArch::PAGE_SIZE;
+            v.push((paddr, allocated_frame_count));
+            assert!(addr_set.insert(paddr), "duplicate address: {:?}", paddr);
+
+            // 写入数据
+            let vaddr = unsafe { MMArch::phys_2_virt(paddr).unwrap() };
+            let slice = unsafe {
+                core::slice::from_raw_parts_mut(
+                    vaddr.data() as *mut u8,
+                    allocated_frame_count.data() * MMArch::PAGE_SIZE,
+                )
+            };
+            for i in 0..slice.len() {
+                slice[i] = ((i + unsafe { rdtsc() } as usize) % 256) as u8;
+            }
+
+            // 随机释放一个内存块
+            if v.len() > 0 {
+                let mut random_index = 0u64;
+                unsafe { x86::random::rdrand64(&mut random_index) };
+                // 70%概率释放
+                if random_index % 10 > 7 {
+                    continue;
+                }
+                random_index = random_index % v.len() as u64;
+                let random_index = random_index as usize;
+                let (paddr, allocated_frame_count) = v.remove(random_index);
+                assert!(addr_set.remove(&paddr));
+                unsafe { LockedFrameAllocator.free(paddr, allocated_frame_count) };
+                free_count += allocated_frame_count.data() * MMArch::PAGE_SIZE;
+            }
+        }
+
+        kdebug!(
+            "Allocated {} MB memory, release: {} MB, no release: {} bytes",
+            allocated / 1024 / 1024,
+            free_count / 1024 / 1024,
+            (allocated - free_count)
+        );
+
+        kdebug!("Now, to release buddy memory");
+        // 释放所有的内存
+        for (paddr, allocated_frame_count) in v {
+            unsafe { LockedFrameAllocator.free(paddr, allocated_frame_count) };
+            assert!(addr_set.remove(&paddr));
+            free_count += allocated_frame_count.data() * MMArch::PAGE_SIZE;
+        }
+
+        kdebug!("release done!, allocated: {allocated}, free_count: {free_count}");
+    }
+}
+/// 全局的页帧分配器
+#[derive(Debug, Clone, Copy, Hash)]
+pub struct LockedFrameAllocator;
+
+impl FrameAllocator for LockedFrameAllocator {
+    unsafe fn allocate(
+        &mut self,
+        count: crate::mm::allocator::page_frame::PageFrameCount,
+    ) -> Option<(PhysAddr, PageFrameCount)> {
+        if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
+            return allocator.allocate(count);
+        } else {
+            return None;
+        }
+    }
+
+    unsafe fn free(
+        &mut self,
+        address: crate::mm::PhysAddr,
+        count: crate::mm::allocator::page_frame::PageFrameCount,
+    ) {
+        assert!(count.data().is_power_of_two());
+        if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
+            return allocator.free(address, count);
+        }
+    }
+
+    unsafe fn usage(&self) -> crate::mm::allocator::page_frame::PageFrameUsage {
+        todo!()
+    }
+}
+
+/// 获取内核地址默认的页面标志
+pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> {
+    let info: X86_64MMBootstrapInfo = BOOTSTRAP_MM_INFO.clone().unwrap();
+
+    if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end {
+        // Remap kernel code  execute
+        return PageFlags::new().set_execute(true).set_write(true);
+    } else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end {
+        // Remap kernel rodata read only
+        return PageFlags::new().set_execute(true);
+    } else {
+        return PageFlags::new().set_write(true).set_execute(true);
+    }
+}
+
+unsafe fn set_inner_allocator(allocator: BuddyAllocator<MMArch>) {
+    static FLAG: AtomicBool = AtomicBool::new(false);
+    if FLAG
+        .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
+        .is_err()
+    {
+        panic!("Cannot set inner allocator twice!");
+    }
+    *INNER_ALLOCATOR.lock() = Some(allocator);
+}
+
+/// 低地址重映射的管理器
+///
+/// 低地址重映射的管理器,在smp初始化完成之前,需要使用低地址的映射,因此需要在smp初始化完成之后,取消这一段映射
+pub struct LowAddressRemapping;
+
+impl LowAddressRemapping {
+    // 映射32M
+    const REMAP_SIZE: usize = 32 * 1024 * 1024;
+
+    pub unsafe fn remap_at_low_address(
+        mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>,
+    ) {
+        for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) {
+            let paddr = PhysAddr::new(i * MMArch::PAGE_SIZE);
+            let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE);
+            let flags = kernel_page_flags::<MMArch>(vaddr);
+
+            let flusher = mapper
+                .map_phys(vaddr, paddr, flags)
+                .expect("Failed to map frame");
+            // 暂时不刷新TLB
+            flusher.ignore();
+        }
+    }
+
+    /// 取消低地址的映射
+    pub unsafe fn unmap_at_low_address(flush: bool) {
+        let mut mapper = KernelMapper::lock();
+        assert!(mapper.as_mut().is_some());
+        for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) {
+            let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE);
+            let flusher = mapper
+                .as_mut()
+                .unwrap()
+                .unmap(vaddr, true)
+                .expect("Failed to unmap frame");
+            if flush == false {
+                flusher.ignore();
+            }
+        }
+    }
+}
+#[no_mangle]
+pub extern "C" fn rs_mm_init() {
+    mm_init();
 }

+ 6 - 0
kernel/src/arch/x86_64/mod.rs

@@ -4,6 +4,7 @@ pub mod context;
 pub mod cpu;
 pub mod fpu;
 pub mod interrupt;
+pub mod libs;
 pub mod mm;
 pub mod msi;
 pub mod pci;
@@ -11,4 +12,9 @@ pub mod rand;
 pub mod sched;
 pub mod syscall;
 
+pub use self::pci::pci::X86_64PciArch as PciArch;
+
+/// 导出内存管理的Arch结构体
+pub use self::mm::X86_64MMArch as MMArch;
+
 pub use interrupt::X86_64InterruptArch as CurrentIrqArch;

+ 1 - 1
kernel/src/arch/x86_64/msi.rs

@@ -12,7 +12,7 @@ pub fn ia64_pci_get_arch_msi_message_address(processor: u16) -> u32 {
 /// @return MSI Message Address
 pub fn ia64_pci_get_arch_msi_message_data(
     vector: u16,
-    processor: u16,
+    _processor: u16,
     trigger: TriggerMode,
 ) -> u32 {
     match trigger {

+ 176 - 22
kernel/src/arch/x86_64/syscall.rs

@@ -1,24 +1,27 @@
-use core::ffi::c_void;
+use core::{ffi::c_void, panic};
+
+use alloc::{string::String, vec::Vec};
 
 use crate::{
+    arch::{asm::current::current_pcb, CurrentIrqArch},
+    exception::InterruptArch,
+    filesystem::vfs::MAX_PATHLEN,
     include::bindings::bindings::{
-        pt_regs, set_system_trap_gate, verify_area, CLONE_FS, CLONE_SIGNAL, CLONE_VM, PAGE_4K_SIZE,
+        pt_regs, set_system_trap_gate, CLONE_FS, CLONE_SIGNAL, CLONE_VM, USER_CS, USER_DS,
     },
     ipc::signal::sys_rt_sigreturn,
-    kinfo,
-    syscall::{Syscall, SystemError, SYS_EXECVE, SYS_FORK, SYS_RT_SIGRETURN, SYS_VFORK},
+    mm::{ucontext::AddressSpace, verify_area, VirtAddr},
+    process::exec::{load_binary_file, ExecParam, ExecParamFlags},
+    syscall::{
+        user_access::{check_and_clone_cstr, check_and_clone_cstr_array},
+        Syscall, SystemError, SYS_EXECVE, SYS_FORK, SYS_RT_SIGRETURN, SYS_VFORK,
+    },
 };
 
 use super::{asm::ptrace::user_mode, mm::barrier::mfence};
 
 extern "C" {
     fn do_fork(regs: *mut pt_regs, clone_flags: u64, stack_start: u64, stack_size: u64) -> u64;
-    fn c_sys_execve(
-        path: *const u8,
-        argv: *const *const u8,
-        envp: *const *const u8,
-        regs: &mut pt_regs,
-    ) -> u64;
 
     fn syscall_int();
 }
@@ -71,23 +74,34 @@ pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () {
 
             // 权限校验
             if from_user
-                && (unsafe { !verify_area(path_ptr as u64, PAGE_4K_SIZE as u64) }
-                    || unsafe { !verify_area(argv_ptr as u64, PAGE_4K_SIZE as u64) })
-                || unsafe { !verify_area(env_ptr as u64, PAGE_4K_SIZE as u64) }
+                && (verify_area(VirtAddr::new(path_ptr), MAX_PATHLEN).is_err()
+                    || verify_area(VirtAddr::new(argv_ptr), MAX_PATHLEN).is_err()
+                    || verify_area(VirtAddr::new(env_ptr), MAX_PATHLEN).is_err())
             {
                 syscall_return!(SystemError::EFAULT.to_posix_errno() as u64, regs);
             } else {
-                syscall_return!(
-                    unsafe {
-                        c_sys_execve(
+                unsafe {
+                    // kdebug!("syscall: execve\n");
+                    syscall_return!(
+                        rs_do_execve(
                             path_ptr as *const u8,
                             argv_ptr as *const *const u8,
                             env_ptr as *const *const u8,
-                            regs,
-                        )
-                    },
-                    regs
-                );
+                            regs
+                        ),
+                        regs
+                    );
+                    // let path = String::from("/bin/about.elf");
+                    // let argv = vec![String::from("/bin/about.elf")];
+                    // let envp = vec![String::from("PATH=/bin")];
+                    // let r = tmp_rs_execve(path, argv, envp, regs);
+                    // kdebug!("syscall: execve r: {:?}\n", r);
+
+                    // syscall_return!(
+                    //     r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize),
+                    //     regs
+                    // )
+                }
             }
         }
 
@@ -104,7 +118,147 @@ pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () {
 
 /// 系统调用初始化
 pub fn arch_syscall_init() -> Result<(), SystemError> {
-    kinfo!("arch_syscall_init\n");
+    // kinfo!("arch_syscall_init\n");
     unsafe { set_system_trap_gate(0x80, 0, syscall_int as *mut c_void) }; // 系统调用门
     return Ok(());
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_do_execve(
+    path: *const u8,
+    argv: *const *const u8,
+    envp: *const *const u8,
+    regs: &mut pt_regs,
+) -> usize {
+    if path.is_null() {
+        return SystemError::EINVAL.to_posix_errno() as usize;
+    }
+
+    let x = || {
+        let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
+        let argv: Vec<String> = check_and_clone_cstr_array(argv)?;
+        let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
+        Ok((path, argv, envp))
+    };
+    let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x();
+    if let Err(e) = r {
+        panic!("Failed to execve: {:?}", e);
+    }
+    let (path, argv, envp) = r.unwrap();
+
+    return tmp_rs_execve(path, argv, envp, regs)
+        .map(|_| 0)
+        .unwrap_or_else(|e| {
+            panic!(
+                "Failed to execve, pid: {} error: {:?}",
+                current_pcb().pid,
+                e
+            )
+        });
+}
+
+/// 执行第一个用户进程的函数(只应该被调用一次)
+///
+/// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。
+#[no_mangle]
+pub extern "C" fn rs_exec_init_process(regs: &mut pt_regs) -> usize {
+    let path = String::from("/bin/shell.elf");
+    let argv = vec![String::from("/bin/shell.elf")];
+    let envp = vec![String::from("PATH=/bin")];
+    let r = tmp_rs_execve(path, argv, envp, regs);
+    // kdebug!("rs_exec_init_process: r: {:?}\n", r);
+    return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize);
+}
+
+/// 临时的execve系统调用实现,以后要把它改为普通的系统调用。
+///
+/// 现在放在这里的原因是,还没有重构中断管理模块,未实现TrapFrame这个抽象,
+/// 导致我们必须手动设置中断返回时,各个寄存器的值,这个过程很繁琐,所以暂时放在这里。
+fn tmp_rs_execve(
+    path: String,
+    argv: Vec<String>,
+    envp: Vec<String>,
+    regs: &mut pt_regs,
+) -> Result<(), SystemError> {
+    // kdebug!(
+    //     "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
+    //     path,
+    //     argv,
+    //     envp
+    // );
+    // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
+    let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+    // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
+    let old_address_space = current_pcb().address_space();
+    // 在pcb中原来的用户地址空间
+    unsafe {
+        current_pcb().drop_address_space();
+    }
+    // 创建新的地址空间并设置为当前地址空间
+    let address_space = AddressSpace::new(true).expect("Failed to create new address space");
+    unsafe {
+        current_pcb().set_address_space(address_space.clone());
+    }
+    assert!(
+        AddressSpace::is_current(&address_space),
+        "Failed to set address space"
+    );
+    // kdebug!("Switch to new address space");
+
+    // 切换到新的用户地址空间
+    unsafe { address_space.read().user_mapper.utable.make_current() };
+
+    drop(old_address_space);
+    drop(irq_guard);
+    // kdebug!("to load binary file");
+    let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
+    // 加载可执行文件
+    let load_result = load_binary_file(&mut param)
+        .unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
+    // kdebug!("load binary file done");
+
+    param.init_info_mut().args = argv;
+    param.init_info_mut().envs = envp;
+
+    // 把proc_init_info写到用户栈上
+
+    let (user_sp, argv_ptr) = unsafe {
+        param
+            .init_info()
+            .push_at(
+                address_space
+                    .write()
+                    .user_stack_mut()
+                    .expect("No user stack found"),
+            )
+            .expect("Failed to push proc_init_info to user stack")
+    };
+
+    // kdebug!("write proc_init_info to user stack done");
+
+    // (兼容旧版libc)把argv的指针写到寄存器内
+    // TODO: 改写旧版libc,不再需要这个兼容
+    regs.rdi = param.init_info().args.len() as u64;
+    regs.rsi = argv_ptr.data() as u64;
+
+    // 设置系统调用返回时的寄存器状态
+    // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
+    regs.rsp = user_sp.data() as u64;
+    regs.rbp = user_sp.data() as u64;
+    regs.rip = load_result.entry_point().data() as u64;
+
+    regs.cs = USER_CS as u64 | 3;
+    regs.ds = USER_DS as u64 | 3;
+    regs.ss = USER_DS as u64 | 3;
+    regs.es = 0;
+    regs.rflags = 0x200;
+    regs.rax = 1;
+
+    // kdebug!("regs: {:?}\n", regs);
+
+    // kdebug!(
+    //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
+    //     load_result.entry_point()
+    // );
+    return Ok(());
+}

+ 8 - 0
kernel/src/common/atomic.h

@@ -9,6 +9,7 @@
  *
  */
 #pragma once
+#include <arch/x86_64/include/asm/cmpxchg.h>
 
 #define atomic_read(atomic)	((atomic)->value)   // 读取原子变量
 #define atomic_set(atomic,val)	(((atomic)->value) = (val)) // 设置原子变量的初始值
@@ -97,3 +98,10 @@ inline void atomic_clear_mask(atomic_t *ato, long mask)
                          : "r"(mask)
                          : "memory");
 }
+
+// cmpxchgq 比较并交换
+inline long atomic_cmpxchg(atomic_t *ato, long oldval, long newval)
+{
+    bool success = arch_try_cmpxchg(&ato->value, &oldval, &newval);
+    return success ? oldval : newval;
+}

+ 20 - 14
kernel/src/driver/acpi/acpi.c

@@ -44,7 +44,8 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_heade
         ul *ent = &(xsdt->Entry);
         for (int i = 0; i < acpi_XSDT_Entry_num; ++i)
         {
-            mm_map_phys_addr(acpi_description_header_base + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
+            // mm_map_phys_addr(acpi_description_header_base + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
+            rs_map_phys(acpi_description_header_base + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
             sdt_header = (struct acpi_system_description_table_header_t *)((ul)(acpi_description_header_base + PAGE_2M_SIZE * i));
 
             if (_fun(sdt_header, _data) == true)
@@ -173,13 +174,14 @@ void acpi_init()
         ul rsdt_phys_base = rsdpv2->rsdp1.RsdtAddress & PAGE_2M_MASK;
         acpi_RSDT_offset = rsdpv2->rsdp1.RsdtAddress - rsdt_phys_base;
 
-        //申请mmio空间
+        // 申请mmio空间
         uint64_t size = 0;
         mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
 
-        //映射rsdt表
+        // 映射rsdt表
         paddr = (uint64_t)rsdt_phys_base;
-        mm_map(&initial_mm, acpi_rsdt_virt_addr_base, PAGE_2M_SIZE, paddr);
+        // mm_map(&initial_mm, acpi_rsdt_virt_addr_base, PAGE_2M_SIZE, paddr);
+        rs_map_phys(acpi_rsdt_virt_addr_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
 
         // rsdt表虚拟地址
         rsdt = (struct acpi_RSDT_Structure_t *)(acpi_rsdt_virt_addr_base + acpi_RSDT_offset);
@@ -192,7 +194,7 @@ void acpi_init()
         printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length);
         printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
 
-        //申请mmio空间
+        // 申请mmio空间
         mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
 
         // 映射所有的Entry的物理地址
@@ -201,23 +203,27 @@ void acpi_init()
         acpi_RSDT_entry_phys_base = MASK_HIGH_32bit(acpi_RSDT_entry_phys_base);
 
         paddr = (uint64_t)acpi_RSDT_entry_phys_base;
-        mm_map(&initial_mm, acpi_description_header_base, PAGE_2M_SIZE, paddr);
+        // mm_map(&initial_mm, acpi_description_header_base, PAGE_2M_SIZE, paddr);
+        rs_map_phys(acpi_description_header_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
     }
     else if (rsdpv1->RsdtAddress != (uint)0x00UL)
     {
         // rsdt表物理地址
         ul rsdt_phys_base = rsdpv1->RsdtAddress & PAGE_2M_MASK;
         acpi_RSDT_offset = rsdpv1->RsdtAddress - rsdt_phys_base;
-        
+
         kdebug("rsdpv1->RsdtAddress=%#018lx", rsdpv1->RsdtAddress);
-        //申请mmio空间
+        // 申请mmio空间
         uint64_t size = 0;
         mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
+        // acpi_rsdt_virt_addr_base = 0xffffb00000000000UL;
+        kdebug("ACPI: mmio created. acpi_rsdt_virt_addr_base = %#018lx,size= %#010lx", acpi_rsdt_virt_addr_base, size);
 
         // kdebug("acpi_rsdt_virt_addr_base = %#018lx,size= %#010lx", acpi_rsdt_virt_addr_base, size);
-        //映射rsdt表
+        // 映射rsdt表
         paddr = (uint64_t)rsdt_phys_base;
-        mm_map(&initial_mm, acpi_rsdt_virt_addr_base, PAGE_2M_SIZE, paddr);
+        // mm_map(&initial_mm, acpi_rsdt_virt_addr_base, PAGE_2M_SIZE, paddr);
+        rs_map_phys(acpi_rsdt_virt_addr_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
         // rsdt表虚拟地址
         rsdt = (struct acpi_RSDT_Structure_t *)(acpi_rsdt_virt_addr_base + acpi_RSDT_offset);
         kdebug("RSDT mapped!");
@@ -231,7 +237,7 @@ void acpi_init()
         printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length);
         printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
 
-        //申请mmio空间
+        // 申请mmio空间
         mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
 
         // 映射所有的Entry的物理地址
@@ -240,9 +246,9 @@ void acpi_init()
         acpi_RSDT_entry_phys_base = MASK_HIGH_32bit(acpi_RSDT_entry_phys_base);
 
         paddr = (uint64_t)acpi_RSDT_entry_phys_base;
-        mm_map(&initial_mm, acpi_description_header_base, PAGE_2M_SIZE, paddr);
-        // kinfo("entry mapped!");
-        
+        // mm_map(&initial_mm, acpi_description_header_base, PAGE_2M_SIZE, paddr);
+        rs_map_phys(acpi_description_header_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
+        kinfo("entry mapped!");
     }
     else
     {

+ 5 - 5
kernel/src/driver/base/char/mod.rs

@@ -71,7 +71,7 @@ impl CharDeviceStruct {
     ///             name: 字符设备名
     ///             char: 字符设备实例
     /// @return: 实例
-    /// 
+    ///
     #[allow(dead_code)]
     pub fn new(dev_t: DeviceNumber, minorct: usize, name: &'static str) -> Self {
         Self {
@@ -84,7 +84,7 @@ impl CharDeviceStruct {
     /// @brief: 获取起始次设备号
     /// @parameter: None
     /// @return: 起始设备号
-    /// 
+    ///
     #[allow(dead_code)]
     pub fn device_number(&self) -> DeviceNumber {
         self.dev_t
@@ -93,7 +93,7 @@ impl CharDeviceStruct {
     /// @brief: 获取起始次设备号
     /// @parameter: None
     /// @return: 起始设备号
-    /// 
+    ///
     #[allow(dead_code)]
     pub fn base_minor(&self) -> usize {
         self.dev_t.minor()
@@ -122,7 +122,7 @@ impl CharDevOps {
 
     /// @brief: 动态获取主设备号
     /// @parameter: None
-    /// @return: 如果成功,返回主设备号,否则,返回错误码 
+    /// @return: 如果成功,返回主设备号,否则,返回错误码
     #[allow(dead_code)]
     fn find_dynamic_major() -> Result<usize, SystemError> {
         let chardevs = CHARDEVS.0.lock();
@@ -171,7 +171,7 @@ impl CharDevOps {
     /// @parameter: baseminor: 主设备号
     ///             count: 次设备号数量
     ///             name: 字符设备名
-    /// @return: 如果注册成功,返回,否则,返回false 
+    /// @return: 如果注册成功,返回,否则,返回false
     #[allow(dead_code)]
     pub fn alloc_chardev_region(
         baseminor: usize,

+ 2 - 1
kernel/src/driver/base/device/mod.rs

@@ -1,3 +1,5 @@
+use alloc::{collections::BTreeMap, string::String, sync::Arc};
+
 use crate::{
     filesystem::{
         sysfs::{
@@ -9,7 +11,6 @@ use crate::{
     libs::spinlock::SpinLock,
     syscall::SystemError,
 };
-use alloc::{collections::BTreeMap, string::String, sync::Arc};
 use core::{any::Any, fmt::Debug};
 
 pub mod bus;

+ 1 - 1
kernel/src/driver/disk/ahci/ahci.c

@@ -26,7 +26,7 @@ void ahci_cpp_init(uint32_t *count_ahci_devices, struct pci_device_structure_hea
 
     // 映射ABAR
     uint32_t bar5 = gen_devs[0]->BAR5;
-    mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
+    rs_map_phys(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
 
     kinfo("ABAR mapped!");
 }

+ 6 - 4
kernel/src/driver/interrupt/apic/apic.c

@@ -86,8 +86,8 @@ void apic_io_apic_init()
 
     // kdebug("(ul)apic_ioapic_map.virtual_index_addr=%#018lx", (ul)apic_ioapic_map.virtual_index_addr);
     // 填写页表,完成地址映射
-    mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE,
-                     PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
+    rs_map_phys((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE,
+                PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
 
     // 设置IO APIC ID 为0x0f000000
     *apic_ioapic_map.virtual_index_addr = 0x00;
@@ -278,8 +278,8 @@ void apic_local_apic_init()
     uint64_t ia32_apic_base = rdmsr(0x1b);
     // kdebug("apic base=%#018lx", (ia32_apic_base & 0x1FFFFFFFFFF000));
     // 映射Local APIC 寄存器地址
-    mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, (ia32_apic_base & 0x1FFFFFFFFFFFFF), PAGE_2M_SIZE,
-                     PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
+    // todo: 
+    rs_map_phys(APIC_LOCAL_APIC_VIRT_BASE_ADDR, (ia32_apic_base & 0x1FFFFFFFFFF000), PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
     uint a, b, c, d;
 
     cpu_cpuid(1, 0, &a, &b, &c, &d);
@@ -357,6 +357,7 @@ void apic_local_apic_init()
  */
 int apic_init()
 {
+    kinfo("Initializing APIC...");
     // 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套,然后处理器重新加载导致数据被抹掉
     for (int i = 32; i <= 55; ++i)
         set_intr_gate(i, 0, interrupt_table[i - 32]);
@@ -396,6 +397,7 @@ int apic_init()
         RCBA_vaddr = 0;
         kwarn("Cannot get RCBA address. RCBA_phys=%#010lx", RCBA_phys);
     }
+    kinfo("APIC initialized.");
     sti();
     return 0;
 }

+ 1 - 1
kernel/src/driver/pci/msi.c

@@ -96,7 +96,7 @@ static __always_inline int __msix_map_table(struct pci_device_structure_header_t
     // pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_offset, pci_dev->msix_table_size, pci_dev->msix_mmio_size);
 
     // 将msix table映射到页表
-    mm_map(&initial_mm, pci_dev->msix_mmio_vaddr, pci_dev->msix_mmio_size, bar);
+    rs_map_phys(pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_mmio_size, PAGE_KERNEL_PAGE);
     return 0;
 }
 

+ 44 - 20
kernel/src/driver/pci/pci.rs

@@ -3,15 +3,17 @@
 
 use super::pci_irq::{IrqType, PciIrqError};
 use crate::arch::{PciArch, TraitPciArch};
-use crate::include::bindings::bindings::{
-    initial_mm, mm_map, mm_struct, PAGE_2M_SIZE, VM_DONTCOPY, VM_IO,
-};
+use crate::include::bindings::bindings::{PAGE_2M_SIZE, VM_DONTCOPY, VM_IO};
 use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
-use crate::mm::mmio_buddy::MMIO_POOL;
+use crate::mm::kernel_mapper::KernelMapper;
+use crate::mm::mmio_buddy::mmio_pool;
+use crate::mm::page::PageFlags;
+use crate::mm::{PhysAddr, VirtAddr};
 use crate::{kdebug, kerror, kinfo, kwarn};
 use alloc::vec::Vec;
 use alloc::{boxed::Box, collections::LinkedList};
 use bitflags::bitflags;
+
 use core::{
     convert::TryFrom,
     fmt::{self, Debug, Display, Formatter},
@@ -632,20 +634,27 @@ impl PciRoot {
         let virtsize_ptr = &mut virtsize as *mut u64;
         let size = bus_number_double * PAGE_2M_SIZE;
         unsafe {
-            let initial_mm_ptr = &mut initial_mm as *mut mm_struct;
-            if let Err(_) =
-                MMIO_POOL.create_mmio(size, (VM_IO | VM_DONTCOPY) as u64, vaddr_ptr, virtsize_ptr)
-            {
+            if let Err(_) = mmio_pool().create_mmio(
+                size as usize,
+                (VM_IO | VM_DONTCOPY) as u64,
+                vaddr_ptr,
+                virtsize_ptr,
+            ) {
                 kerror!("Create mmio failed when initing ecam");
                 return Err(PciError::CreateMmioError);
             };
+
             //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
-            mm_map(
-                initial_mm_ptr,
-                virtaddress,
-                size as u64,
-                self.physical_address_base,
-            );
+            let vaddr = VirtAddr::new(virtaddress as usize);
+            let paddr = PhysAddr::new(self.physical_address_base as usize);
+            // kdebug!("pci root: map: vaddr={vaddr:?}, paddr={paddr:?}, size={size}");
+            let page_flags = PageFlags::mmio_flags();
+            let mut kernel_mapper = KernelMapper::lock();
+            // todo: 添加错误处理代码。因为内核映射器可能是只读的,所以可能会出错
+            assert!(kernel_mapper
+                .map_phys_with_size(vaddr, paddr, size as usize, page_flags, true)
+                .is_ok());
+            drop(kernel_mapper);
         }
         self.mmio_base = Some(virtaddress as *mut u32);
         Ok(0)
@@ -1302,8 +1311,9 @@ impl Display for BarInfo {
         }
     }
 }
-//todo 增加对桥的bar的支持
+// todo 增加对桥的bar的支持
 pub trait PciDeviceBar {}
+
 ///一个普通PCI设备(非桥)有6个BAR寄存器,PciStandardDeviceBar存储其全部信息
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct PciStandardDeviceBar {
@@ -1409,10 +1419,11 @@ pub fn pci_bar_init(
                 let vaddr_ptr = &mut virtaddress as *mut u64;
                 let mut virtsize: u64 = 0;
                 let virtsize_ptr = &mut virtsize as *mut u64;
-                let initial_mm_ptr = &mut initial_mm as *mut mm_struct;
-                //kdebug!("size want={:#x}", size);
-                if let Err(_) = MMIO_POOL.create_mmio(
-                    size,
+
+                let size_want = size as usize;
+
+                if let Err(_) = mmio_pool().create_mmio(
+                    size_want,
                     (VM_IO | VM_DONTCOPY) as u64,
                     vaddr_ptr,
                     virtsize_ptr,
@@ -1421,7 +1432,20 @@ pub fn pci_bar_init(
                     return Err(PciError::CreateMmioError);
                 };
                 //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
-                mm_map(initial_mm_ptr, virtaddress, size as u64, address);
+                let vaddr = VirtAddr::new(virtaddress as usize);
+                let paddr = PhysAddr::new(address as usize);
+                let page_flags = PageFlags::new()
+                    .set_write(true)
+                    .set_execute(true)
+                    .set_page_cache_disable(true)
+                    .set_page_write_through(true);
+                kdebug!("Pci bar init: vaddr={vaddr:?}, paddr={paddr:?}, size_want={size_want}, page_flags={page_flags:?}");
+                let mut kernel_mapper = KernelMapper::lock();
+                // todo: 添加错误处理代码。因为内核映射器可能是只读的,所以可能会出错
+                assert!(kernel_mapper
+                    .map_phys_with_size(vaddr, paddr, size_want, page_flags, true)
+                    .is_ok());
+                drop(kernel_mapper);
             }
             bar_info = BarInfo::Memory {
                 address_type,

+ 4 - 6
kernel/src/driver/pci/pci_irq.rs

@@ -6,16 +6,14 @@ use core::ptr::NonNull;
 use alloc::ffi::CString;
 use alloc::vec::Vec;
 
-use super::pci::{HeaderType, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
+use super::pci::{PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
 use crate::arch::msi::{ia64_pci_get_arch_msi_message_address, ia64_pci_get_arch_msi_message_data};
 use crate::arch::{PciArch, TraitPciArch};
 use crate::include::bindings::bindings::{
     c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
 };
-use crate::libs::volatile::{
-    volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
-};
-use crate::{kdebug, kerror, kinfo, kwarn};
+use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
+
 /// MSIX表的一项
 #[repr(C)]
 struct MsixEntry {
@@ -268,7 +266,7 @@ pub trait PciInterrupt: PciDeviceStructure {
         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
     }
     /// @brief 获取指定数量的中断号 todo 需要中断重构支持
-    fn irq_alloc(num: u16) -> Option<Vec<u16>> {
+    fn irq_alloc(_num: u16) -> Option<Vec<u16>> {
         None
     }
     /// @brief 进行PCI设备中断的安装

+ 1 - 1
kernel/src/driver/uart/uart.rs

@@ -2,7 +2,7 @@ use super::super::base::device::Device;
 use crate::{
     driver::base::{
         char::CharDevice,
-    device::{driver::Driver, DeviceState, DeviceType, IdTable, KObject},
+        device::{driver::Driver, DeviceState, DeviceType, IdTable, KObject},
         platform::{
             self, platform_device::PlatformDevice, platform_driver::PlatformDriver, CompatibleTable,
         },

+ 6 - 11
kernel/src/driver/video/video.c

@@ -34,16 +34,10 @@ void init_frame_buffer()
 {
     kinfo("Re-mapping VBE frame buffer...");
 
-    uint64_t global_CR3 = (uint64_t)get_CR3();
-
-    struct multiboot_tag_framebuffer_info_t info;
-    int reserved;
-
     video_frame_buffer_info.vaddr = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + FRAME_BUFFER_MAPPING_OFFSET;
-    mm_map_proc_page_table(global_CR3, true, video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr,
-                           video_frame_buffer_info.size, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false, true, false);
 
-    flush_tlb();
+    rs_map_phys(video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr, video_frame_buffer_info.size, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
+
     kinfo("VBE frame buffer successfully Re-mapped!");
 }
 
@@ -119,7 +113,6 @@ int video_reinitialize(bool level) // 这个函数会在main.c调用, 保证 vid
         // 启用屏幕刷新软中断
         rs_register_softirq_video();
         rs_raise_softirq(VIDEO_REFRESH_SIRQ);
-
     }
     return 0;
 }
@@ -189,8 +182,10 @@ int video_init()
         video_frame_buffer_info.width * video_frame_buffer_info.height * ((video_frame_buffer_info.bit_depth + 7) / 8);
     // 先临时映射到该地址,稍后再重新映射
     video_frame_buffer_info.vaddr = 0xffff800003000000;
-    mm_map_phys_addr(video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr, video_frame_buffer_info.size,
-                     PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
+    char init_text1[] = "Video driver to map.\n";
+    for (int i = 0; i < sizeof(init_text1) - 1; ++i)
+        c_uart_send(COM1, init_text1[i]);
+    rs_pseudo_map_phys(video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr, video_frame_buffer_info.size);
 
     io_mfence();
     char init_text2[] = "Video driver initialized.\n";

+ 69 - 27
kernel/src/driver/virtio/virtio_impl.rs

@@ -1,59 +1,101 @@
-/// 为virtio-drivers库提供的操作系统接口
-use crate::include::bindings::bindings::{
-    alloc_pages, free_pages, memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE,
-    PAGE_OFFSET, PAGE_SHARED, ZONE_NORMAL,
+use crate::arch::mm::kernel_page_flags;
+
+use crate::arch::MMArch;
+
+use crate::mm::kernel_mapper::KernelMapper;
+use crate::mm::page::PageFlags;
+use crate::mm::{
+    allocator::page_frame::{
+        allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
+    },
+    MemoryManagementArch, PhysAddr, VirtAddr,
 };
-use crate::mm::virt_2_phys;
-use core::mem::size_of;
 use core::ptr::NonNull;
-use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE};
+use virtio_drivers::{BufferDirection, Hal, PAGE_SIZE};
+
 pub struct HalImpl;
 unsafe impl Hal for HalImpl {
     /// @brief 申请用于DMA的内存页
     /// @param pages 页数(4k一页)
     /// @return PhysAddr 获得的内存页的初始物理地址
-    fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) {
-        let page_num = (pages * PAGE_SIZE - 1 + PAGE_2M_SIZE as usize) / PAGE_2M_SIZE as usize;
+    fn dma_alloc(
+        pages: usize,
+        _direction: BufferDirection,
+    ) -> (virtio_drivers::PhysAddr, NonNull<u8>) {
+        let page_num = PageFrameCount::new(
+            ((pages * PAGE_SIZE + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE).next_power_of_two(),
+        );
         unsafe {
-            let pa = alloc_pages(ZONE_NORMAL, page_num as i32, PAGE_SHARED as u64);
-            let page = *pa;
-            //kdebug!("alloc pages num:{},Phyaddr={:#x}",pages,page.addr_phys);
-            (
-                page.addr_phys as PhysAddr,
-                NonNull::new((page.addr_phys as PhysAddr + PAGE_OFFSET as usize) as _).unwrap(),
-            )
+            let (paddr, count) =
+                allocate_page_frames(page_num).expect("VirtIO Impl: alloc page failed");
+            let virt = MMArch::phys_2_virt(paddr).unwrap();
+            // 清空这块区域,防止出现脏数据
+            core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
+
+            let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();
+
+            let mut kernel_mapper = KernelMapper::lock();
+            let kernel_mapper = kernel_mapper.as_mut().unwrap();
+            let flusher = kernel_mapper
+                .remap(virt, dma_flags)
+                .expect("VirtIO Impl: remap failed");
+            flusher.flush();
+            return (
+                paddr.data(),
+                NonNull::new(MMArch::phys_2_virt(paddr).unwrap().data() as _).unwrap(),
+            );
         }
     }
     /// @brief 释放用于DMA的内存页
     /// @param paddr 起始物理地址 pages 页数(4k一页)
     /// @return i32 0表示成功
-    unsafe fn dma_dealloc(paddr: PhysAddr, _vaddr: NonNull<u8>, pages: usize) -> i32 {
-        let page_num = (pages * PAGE_SIZE - 1 + PAGE_2M_SIZE as usize) / PAGE_2M_SIZE as usize;
+    unsafe fn dma_dealloc(
+        paddr: virtio_drivers::PhysAddr,
+        vaddr: NonNull<u8>,
+        pages: usize,
+    ) -> i32 {
+        let page_count = PageFrameCount::new(
+            ((pages * PAGE_SIZE + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE).next_power_of_two(),
+        );
+
+        // 恢复页面属性
+        let vaddr = VirtAddr::new(vaddr.as_ptr() as *mut u8 as usize);
+        let mut kernel_mapper = KernelMapper::lock();
+        let kernel_mapper = kernel_mapper.as_mut().unwrap();
+        let flusher = kernel_mapper
+            .remap(vaddr, kernel_page_flags(vaddr))
+            .expect("VirtIO Impl: remap failed");
+        flusher.flush();
+
         unsafe {
-            let pa = (memory_management_struct.pages_struct as usize
-                + (paddr >> PAGE_2M_SHIFT) * size_of::<Page>()) as *mut Page;
-            //kdebug!("free pages num:{},Phyaddr={}",page_num,paddr);
-            free_pages(pa, page_num as i32);
+            deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
         }
         return 0;
     }
     /// @brief mmio物理地址转换为虚拟地址,不需要使用
     /// @param paddr 起始物理地址
     /// @return NonNull<u8> 虚拟地址的指针
-    unsafe fn mmio_phys_to_virt(_paddr: PhysAddr, _size: usize) -> NonNull<u8> {
+    unsafe fn mmio_phys_to_virt(_paddr: virtio_drivers::PhysAddr, _size: usize) -> NonNull<u8> {
         NonNull::new((0) as _).unwrap()
     }
     /// @brief 与真实物理设备共享
     /// @param buffer 要共享的buffer _direction:设备到driver或driver到设备
     /// @return buffer在内存中的物理地址
-    unsafe fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
-        let vaddr = buffer.as_ptr() as *mut u8 as usize;
+    unsafe fn share(
+        buffer: NonNull<[u8]>,
+        _direction: BufferDirection,
+    ) -> virtio_drivers::PhysAddr {
+        let vaddr = VirtAddr::new(buffer.as_ptr() as *mut u8 as usize);
         //kdebug!("virt:{:x}", vaddr);
         // Nothing to do, as the host already has access to all memory.
-        virt_2_phys(vaddr)
+        return MMArch::virt_2_phys(vaddr).unwrap().data();
     }
     /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做)
-    unsafe fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) {
+    unsafe fn unshare(
+        _paddr: virtio_drivers::PhysAddr,
+        _buffer: NonNull<[u8]>,
+        _direction: BufferDirection,
+    ) {
         // Nothing to do, as the host already has access to all memory and we didn't copy the buffer
         // anywhere else.
     }

+ 3 - 3
kernel/src/exception/mod.rs

@@ -19,15 +19,15 @@ pub trait InterruptArch: Send + Sync {
 
 #[derive(Debug, Clone, Copy)]
 pub struct IrqFlags {
-    flags: u64,
+    flags: usize,
 }
 
 impl IrqFlags {
-    pub fn new(flags: u64) -> Self {
+    pub fn new(flags: usize) -> Self {
         IrqFlags { flags }
     }
 
-    pub fn flags(&self) -> u64 {
+    pub fn flags(&self) -> usize {
         self.flags
     }
 }

+ 1 - 0
kernel/src/exception/softirq.rs

@@ -46,6 +46,7 @@ pub fn softirq_init() -> Result<(), SystemError> {
             cpu_pending[i as usize] = VecStatus::default();
         }
     }
+    kinfo!("Softirq initialized.");
     return Ok(());
 }
 

+ 9 - 6
kernel/src/filesystem/procfs/mod.rs

@@ -10,6 +10,7 @@ use alloc::{
 };
 
 use crate::{
+    arch::asm::current::current_pcb,
     filesystem::vfs::{
         core::{generate_inode_id, ROOT_INODE},
         FileType,
@@ -168,13 +169,15 @@ impl ProcFSInode {
                 .to_owned(),
         );
 
-        // 当前进程运行过程中占用内存的峰值
-        let hiwater_vm: u64 =
-            unsafe { *(*pcb.mm).vmas }.vm_end - unsafe { *(*pcb.mm).vmas }.vm_start;
+        let binding = current_pcb().address_space().unwrap();
+        let address_space_guard = binding.read();
+        // todo: 当前进程运行过程中占用内存的峰值
+        let hiwater_vm: u64 = 0;
+        // 进程代码段的大小
+        let text = (address_space_guard.end_code - address_space_guard.start_code) / 1024;
         // 进程数据段的大小
-        let text: u64 = unsafe { *pcb.mm }.code_addr_end - unsafe { *pcb.mm }.code_addr_start;
-        // 进程代码的大小
-        let data: u64 = unsafe { *pcb.mm }.data_addr_end - unsafe { *pcb.mm }.data_addr_start;
+        let data = (address_space_guard.end_data - address_space_guard.start_data) / 1024;
+        drop(address_space_guard);
 
         pdata.append(
             &mut format!("\nVmPeak:\t{} kB", hiwater_vm)

+ 15 - 29
kernel/src/filesystem/sysfs/bus.rs

@@ -1,9 +1,5 @@
 use super::{LockedSysFSInode, SYS_BUS_INODE};
-use crate::{
-    filesystem::vfs::IndexNode,
-    kdebug,
-    syscall::SystemError,
-};
+use crate::{filesystem::vfs::IndexNode, kdebug, syscall::SystemError};
 use alloc::sync::Arc;
 
 /// @brief: 注册bus,在sys/bus下生成文件夹
@@ -58,20 +54,15 @@ pub fn sys_bus_init(
 /// @parameter bus_name: 总线名
 ///            name: 设备名
 /// @return: 操作成功,返回device inode,操作失败,返回错误码
-pub fn bus_driver_register(
-    bus_name: &str,
-    name: &str,
-) -> Result<Arc<dyn IndexNode>, SystemError> {
+pub fn bus_driver_register(bus_name: &str, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
     match SYS_BUS_INODE().find(bus_name) {
         Ok(platform) => match platform.find("drivers") {
-            Ok(device) => {
-                device
-                    .as_any_ref()
-                    .downcast_ref::<LockedSysFSInode>()
-                    .ok_or(SystemError::E2BIG)
-                    .unwrap()
-                    .add_dir(name)
-            }
+            Ok(device) => device
+                .as_any_ref()
+                .downcast_ref::<LockedSysFSInode>()
+                .ok_or(SystemError::E2BIG)
+                .unwrap()
+                .add_dir(name),
             Err(_) => return Err(SystemError::EXDEV),
         },
         Err(_) => return Err(SystemError::EXDEV),
@@ -82,20 +73,15 @@ pub fn bus_driver_register(
 /// @parameter bus_name: 总线名
 ///            name: 驱动名
 /// @return: 操作成功,返回drivers inode,操作失败,返回错误码
-pub fn bus_device_register(
-    bus_name: &str,
-    name: &str,
-) -> Result<Arc<dyn IndexNode>, SystemError> {
+pub fn bus_device_register(bus_name: &str, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
     match SYS_BUS_INODE().find(bus_name) {
         Ok(platform) => match platform.find("devices") {
-            Ok(device) => {
-                device
-                    .as_any_ref()
-                    .downcast_ref::<LockedSysFSInode>()
-                    .ok_or(SystemError::E2BIG)
-                    .unwrap()
-                    .add_dir(name)
-            }
+            Ok(device) => device
+                .as_any_ref()
+                .downcast_ref::<LockedSysFSInode>()
+                .ok_or(SystemError::E2BIG)
+                .unwrap()
+                .add_dir(name),
             Err(_) => return Err(SystemError::EXDEV),
         },
         Err(_) => return Err(SystemError::EXDEV),

+ 1 - 1
kernel/src/filesystem/vfs/VFS.h

@@ -22,7 +22,7 @@
 #define VFS_DPT_MBR 0 // MBR分区表
 #define VFS_DPT_GPT 1 // GPT分区表
 
-#define VFS_MAX_PATHLEN 1024
+#define VFS_MAX_PATHLEN 4096
 
 /**
  * @brief inode的属性

+ 1 - 1
kernel/src/filesystem/vfs/file.rs

@@ -173,7 +173,7 @@ impl File {
     ///
     /// @param origin 调整的起始位置
     pub fn lseek(&mut self, origin: SeekFrom) -> Result<usize, SystemError> {
-        let file_type = self.inode.metadata().unwrap().file_type;
+        let file_type = self.inode.metadata()?.file_type;
         match file_type {
             FileType::Pipe | FileType::CharDevice => {
                 return Err(SystemError::ESPIPE);

+ 53 - 64
kernel/src/head.S

@@ -255,7 +255,7 @@ ENTRY(_start64)
     movq	$0x1b,	%rcx		// 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu
 	rdmsr
 	bt	$8,	%rax
-	jnc	load_cr3
+	jnc	load_apu_cr3
 
     // 2. 设置临时页表
     // 最高级
@@ -263,7 +263,11 @@ ENTRY(_start64)
     mov $__PDPTE, %ebx
     or $0x3, %ebx
     mov %ebx, 0(%eax)
-    mov %ebx, 256(%eax)
+
+    mov $__PML4E, %eax
+    // 加256个表项, 映射高地址
+    add $2048, %eax
+    mov %ebx, 0(%eax)
 
     // 次级
     mov $__PDPTE, %eax
@@ -271,6 +275,28 @@ ENTRY(_start64)
     or $0x3, %ebx
     mov %ebx, 0(%eax)
 
+    // 次低级
+    mov $__PDE, %eax
+    mov $50, %ecx
+    mov $__PT_S, %ebx
+    or $0x3, %ebx
+.fill_pde_64:
+    mov %ebx, 0(%eax)
+    add $0x1000, %ebx
+    add $8, %eax
+    loop .fill_pde_64
+
+    // 最低级
+    // 循环 512*50=25600 次,填满50页
+    mov $25600, %ecx
+    mov $__PT_S, %eax
+    mov $0x3, %ebx
+.fill_pt_64:
+    mov %ebx, 0(%eax)
+    add $0x1000, %ebx
+    add $8, %eax
+    loop .fill_pt_64
+
 
 // ==== 加载CR3寄存器
 
@@ -279,7 +305,20 @@ load_cr3:
     movq $__PML4E, %rax //设置页目录基地址
     
     movq %rax, %cr3
-    
+    jmp to_switch_seg
+
+load_apu_cr3:
+    // 由于内存管理模块重置了页表,因此ap核心初始化的时候,需要使用新的内核页表。
+    // 这个页表的值由smp模块设置到__APU_START_CR3变量中
+
+    // 加载__APU_START_CR3中的值
+    movq $__APU_START_CR3, %rax
+    movq 0(%rax), %rax
+    movq %rax, %cr3
+    jmp to_switch_seg
+
+to_switch_seg:
+
     movq switch_seg(%rip), %rax
     // 由于ljmp和lcall在GAS中不受支持,因此我们需要先伪造函数调用现场,通过lret的方式,给它跳转过去。才能更新cs寄存器
     // 实在是太妙了!Amazing!
@@ -481,73 +520,23 @@ ENTRY(head_stack_start)
 
 // 初始化页表
 .align 0x1000 //设置为4k对齐
-//.org 0x1000 //设置页表位置为内核执行头程序的0x1000处
-
 __PML4E:
-    .quad 0x103007 // 用户访问,可读写,已存在, 地址在31~12位
-    .fill	255,8,0
-	.quad 0x103003
-	.fill	255,8,0
-
-.org	0x2000
-
+    .skip 0x1000
 __PDPTE:
+	.skip 0x1000
 
-	.quad	0x104003 // 用户访问,可读写,已存在
-	.fill	511,8,0
-
-.org	0x3000
-
+// 三级页表
 __PDE:
+    .skip 0x1000
+
+// 预留50个四级页表,总共表示100M的内存空间。这50个页表占用200KB的空间
+__PT_S:
+    .skip 0x32000
 
-	.quad	0x000083    // 用户访问,可读写,已存在
-	.quad	0x200083
-	.quad	0x400083
-	.quad	0x600083
-	.quad	0x800083
-    .quad	0xa00083
-	.quad	0xc00083
-	.quad	0xe00083
-	.quad	0x1000083
-	.quad	0x1200083
-	.quad	0x1400083
-	.quad	0x1600083
-	.quad	0x1800083
-	.quad	0x1a00083
-	.quad	0x1c00083
-	.quad	0x1e00083
-	.quad	0x2000083
-	.quad	0x2200083
-	.quad	0x2400083
-	.quad	0x2600083
-	.quad	0x2800083
-	.quad	0x2a00083
-	.quad	0x2c00083
-	.quad	0x2e00083
-	.quad	0x3000083
-	.quad	0x3200083
-	.quad	0x3400083
-	.quad	0x3600083
-
-
-	.quad	0xe0000083		/*虚拟地址0x 3000000 初始情况下,帧缓冲区映射到这里*/ 
-	.quad	0xe0200083
-	.quad	0xe0400083
-	.quad	0xe0600083		/*0x1000000*/
-	.quad	0xe0800083
-	.quad	0xe0a00083
-	.quad	0xe0c00083
-	.quad	0xe0e00083
-    .quad	0xe1000083
-    .quad	0xe1200083
-    .quad	0xe1400083
-    .quad	0xe1600083
-    .quad	0xe1800083
-    .quad	0xe1a00083
-    .quad	0xe1c00083
-    .quad	0xe1e00083
-	.fill	468,8,0
 
+.global __APU_START_CR3
+__APU_START_CR3:
+    .quad 0
 
 // GDT表
 

+ 2 - 1
kernel/src/include/bindings/wrapper.h

@@ -32,6 +32,7 @@
 #include <common/unistd.h>
 #include <driver/disk/ahci/ahci.h>
 #include <driver/disk/ahci/ahci_rust.h>
+#include <driver/multiboot2/multiboot2.h>
 #include <driver/pci/pci.h>
 #include <driver/video/video.h>
 #include <driver/virtio/virtio.h>
@@ -49,4 +50,4 @@
 #include <time/clocksource.h>
 #include <time/sleep.h>
 #include <driver/pci/pci_irq.h>
-#include <common/errno.h>
+#include <common/errno.h>

+ 4 - 4
kernel/src/ipc/signal.rs

@@ -133,7 +133,7 @@ fn signal_send_sig_info(
     // 信号符合要求,可以发送
 
     let mut retval = Err(SystemError::ESRCH);
-    let mut flags: u64 = 0;
+    let mut flags: usize = 0;
     // 如果上锁成功,则发送信号
     if !lock_process_sighand(target_pcb, &mut flags).is_none() {
         compiler_fence(core::sync::atomic::Ordering::SeqCst);
@@ -153,7 +153,7 @@ fn signal_send_sig_info(
 /// @return 指向sighand_struct的可变引用
 fn lock_process_sighand<'a>(
     pcb: &'a mut process_control_block,
-    flags: &mut u64,
+    flags: &mut usize,
 ) -> Option<&'a mut sighand_struct> {
     // kdebug!("lock_process_sighand");
 
@@ -175,10 +175,10 @@ fn lock_process_sighand<'a>(
 /// @brief 对pcb的sighand结构体中的siglock进行放锁,并恢复之前存储的rflags
 /// @param pcb 目标pcb
 /// @param flags 用来保存rflags的变量,将这个值恢复到rflags寄存器中
-fn unlock_process_sighand(pcb: &mut process_control_block, flags: u64) {
+fn unlock_process_sighand(pcb: &mut process_control_block, flags: usize) {
     let lock = unsafe { &mut (*pcb.sighand).siglock };
 
-    spin_unlock_irqrestore(lock, &flags);
+    spin_unlock_irqrestore(lock, flags);
 }
 
 /// @brief 判断是否需要强制发送信号,然后发送信号

+ 10 - 5
kernel/src/lib.rs

@@ -1,13 +1,18 @@
 #![no_std] // <1>
 #![no_main] // <1>
 #![feature(alloc_error_handler)]
+#![feature(allocator_api)]
+#![feature(arbitrary_self_types)]
 #![feature(const_mut_refs)]
-#![feature(core_intrinsics)] // <2>
+#![feature(core_intrinsics)]
 #![feature(c_void_variant)]
-#![feature(drain_filter)] // 允许Vec的drain_filter特性
+#![feature(drain_filter)]
 #![feature(panic_info_message)]
 #![feature(ptr_internals)]
 #![feature(trait_upcasting)]
+#![feature(slice_ptr_get)]
+#![feature(vec_into_raw_parts)]
+
 #[allow(non_upper_case_globals)]
 #[allow(non_camel_case_types)]
 #[allow(non_snake_case)]
@@ -37,6 +42,7 @@ mod time;
 extern crate alloc;
 #[macro_use]
 extern crate bitflags;
+extern crate elf;
 #[macro_use]
 extern crate lazy_static;
 extern crate num;
@@ -44,11 +50,10 @@ extern crate num;
 extern crate num_derive;
 extern crate smoltcp;
 extern crate thingbuf;
-
 #[cfg(target_arch = "x86_64")]
 extern crate x86;
 
-use mm::allocator::KernelAllocator;
+use crate::mm::allocator::kernel_allocator::KernelAllocator;
 
 // <3>
 use crate::{
@@ -59,7 +64,7 @@ use crate::{
 
 // 声明全局的slab分配器
 #[cfg_attr(not(test), global_allocator)]
-pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator {};
+pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator;
 
 /// 全局的panic处理函数
 #[panic_handler]

+ 27 - 1
kernel/src/libs/align.rs

@@ -3,7 +3,7 @@
 
 use core::{alloc::GlobalAlloc, fmt::Debug, ptr::Unique};
 
-use crate::{syscall::SystemError, KERNEL_ALLOCATOR};
+use crate::{arch::MMArch, mm::MemoryManagementArch, syscall::SystemError, KERNEL_ALLOCATOR};
 
 /// # AlignedBox
 ///
@@ -112,3 +112,29 @@ impl<T: Clone + SafeForZero, const ALIGN: usize> Clone for AlignedBox<T, ALIGN>
 pub unsafe trait SafeForZero {}
 
 unsafe impl<const NUM: usize> SafeForZero for [u8; NUM] {}
+
+/// 将给定的地址按照页面大小,向上对齐。
+///
+/// 参数 `addr`:要对齐的地址。
+///
+/// 返回值:对齐后的地址。
+pub fn page_align_up(addr: usize) -> usize {
+    let page_size = MMArch::PAGE_SIZE;
+    return (addr + page_size - 1) & (!(page_size - 1));
+}
+
+/// ## 检查是否对齐
+///
+/// 检查给定的值是否对齐到给定的对齐要求。
+///
+/// ## 参数
+/// - `value`:要检查的值
+/// - `align`:对齐要求,必须是2的幂次方,且不为0,否则运行时panic
+///
+/// ## 返回值
+///
+/// 如果对齐则返回`true`,否则返回`false`
+pub fn check_aligned(value: usize, align: usize) -> bool {
+    assert!(align != 0 && align.is_power_of_two());
+    return value & (align - 1) == 0;
+}

+ 785 - 0
kernel/src/libs/elf.rs

@@ -0,0 +1,785 @@
+use core::{
+    cmp::min,
+    intrinsics::{likely, unlikely},
+    ops::Range,
+};
+
+use alloc::vec::Vec;
+use elf::{endian::AnyEndian, file::FileHeader, segment::ProgramHeader};
+
+use crate::{
+    arch::MMArch,
+    current_pcb,
+    io::SeekFrom,
+    kerror,
+    libs::align::page_align_up,
+    mm::{
+        allocator::page_frame::{PageFrameCount, VirtPageFrame},
+        syscall::{MapFlags, ProtFlags},
+        ucontext::InnerAddressSpace,
+        MemoryManagementArch, VirtAddr,
+    },
+    process::{
+        abi::AtType,
+        exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam},
+    },
+    syscall::{
+        user_access::{clear_user, copy_to_user},
+        SystemError,
+    },
+};
+
+use super::rwlock::RwLockWriteGuard;
+
+#[derive(Debug)]
+pub struct ElfLoader;
+
+pub const ELF_LOADER: ElfLoader = ElfLoader::new();
+
+impl ElfLoader {
+    #[cfg(target_arch = "x86_64")]
+    pub const ELF_PAGE_SIZE: usize = MMArch::PAGE_SIZE;
+
+    /// 读取文件的缓冲区大小
+    pub const FILE_READ_BUF_SIZE: usize = 512 * 1024;
+
+    pub const fn new() -> Self {
+        Self
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    pub fn probe_x86_64(
+        &self,
+        param: &ExecParam,
+        ehdr: &FileHeader<AnyEndian>,
+    ) -> Result<(), ExecError> {
+        // 只支持 64 位的 ELF 文件
+        if ehdr.class != elf::file::Class::ELF64 {
+            return Err(ExecError::WrongArchitecture);
+        }
+
+        // 判断架构是否匹配
+        if ElfMachine::from(ehdr.e_machine) != ElfMachine::X86_64 {
+            return Err(ExecError::WrongArchitecture);
+        }
+
+        // 判断是否以可执行文件的形式加载
+        if param.load_mode() == ExecLoadMode::Exec {
+            // 检查文件类型是否为可执行文件
+            if ElfType::from(ehdr.e_type) != ElfType::Executable {
+                return Err(ExecError::NotExecutable);
+            }
+        } else {
+            return Err(ExecError::NotSupported);
+        }
+
+        return Ok(());
+    }
+
+    /// 设置用户堆空间,映射[start, end)区间的虚拟地址,并把brk指针指向end
+    ///
+    /// ## 参数
+    ///
+    /// - `user_vm_guard` - 用户虚拟地址空间
+    /// - `start` - 本次映射的起始地址
+    /// - `end` - 本次映射的结束地址(不包含)
+    /// - `prot_flags` - 本次映射的权限
+    fn set_elf_brk(
+        &self,
+        user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>,
+        start: VirtAddr,
+        end: VirtAddr,
+        prot_flags: ProtFlags,
+    ) -> Result<(), ExecError> {
+        let start = self.elf_page_start(start);
+        let end = self.elf_page_align_up(end);
+        // kdebug!("set_elf_brk: start={:?}, end={:?}", start, end);
+        if end > start {
+            let r = user_vm_guard.map_anonymous(
+                start,
+                end - start,
+                prot_flags,
+                MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE,
+                false,
+            );
+            if r.is_err() {
+                kerror!("set_elf_brk: map_anonymous failed, err={:?}", r);
+                return Err(ExecError::OutOfMemory);
+            }
+        }
+        user_vm_guard.elf_brk_start = end;
+        user_vm_guard.elf_brk = end;
+        return Ok(());
+    }
+
+    /// 计算addr在ELF PAGE内的偏移
+    fn elf_page_offset(&self, addr: VirtAddr) -> usize {
+        addr.data() & (Self::ELF_PAGE_SIZE - 1)
+    }
+
+    fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr {
+        VirtAddr::new(addr.data() & (!(Self::ELF_PAGE_SIZE - 1)))
+    }
+
+    fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr {
+        VirtAddr::new((addr.data() + Self::ELF_PAGE_SIZE - 1) & (!(Self::ELF_PAGE_SIZE - 1)))
+    }
+
+    /// 根据ELF的p_flags生成对应的ProtFlags
+    fn make_prot(&self, p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags {
+        let mut prot = ProtFlags::empty();
+        if p_flags & elf::abi::PF_R != 0 {
+            prot |= ProtFlags::PROT_READ;
+        }
+        if p_flags & elf::abi::PF_W != 0 {
+            prot |= ProtFlags::PROT_WRITE;
+        }
+        if p_flags & elf::abi::PF_X != 0 {
+            prot |= ProtFlags::PROT_EXEC;
+        }
+
+        // todo: 增加与架构相关的处理
+        // ref:  https://opengrok.ringotek.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#572
+
+        return prot;
+    }
+
+    /// 加载ELF文件到用户空间
+    ///
+    /// 参考Linux的elf_map函数
+    /// https://opengrok.ringotek.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#365
+    /// ## 参数
+    ///
+    /// - `user_vm_guard`:用户空间地址空间
+    /// - `param`:执行参数
+    /// - `phent`:ELF文件的ProgramHeader
+    /// - `addr_to_map`:当前段应该被加载到的内存地址
+    /// - `prot`:保护标志
+    /// - `map_flags`:映射标志
+    /// - `total_size`:ELF文件的总大小
+    ///
+    /// ## 返回值
+    ///
+    /// - `Ok((VirtAddr, bool))`:如果成功加载,则bool值为true,否则为false. VirtAddr为加载的地址
+    fn load_elf_segment(
+        &self,
+        user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>,
+        param: &mut ExecParam,
+        phent: &ProgramHeader,
+        mut addr_to_map: VirtAddr,
+        prot: &ProtFlags,
+        map_flags: &MapFlags,
+        total_size: usize,
+    ) -> Result<(VirtAddr, bool), SystemError> {
+        // kdebug!("load_elf_segment: addr_to_map={:?}", addr_to_map);
+
+        // 映射位置的偏移量(页内偏移)
+        let beginning_page_offset = self.elf_page_offset(addr_to_map);
+        addr_to_map = self.elf_page_start(addr_to_map);
+        // 计算要映射的内存的大小
+        let map_size = phent.p_filesz as usize
+            + self.elf_page_offset(VirtAddr::new(phent.p_vaddr as usize))
+            + beginning_page_offset;
+        let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data();
+        // 当前段在文件中的大小
+        let seg_in_file_size = phent.p_filesz as usize;
+        // 当前段在文件中的偏移量
+        let file_offset = phent.p_offset as usize;
+
+        // 如果当前段的大小为0,则直接返回.
+        // 段在文件中的大小为0,是合法的,但是段在内存中的大小不能为0
+        if map_size == 0 {
+            return Ok((addr_to_map, true));
+        }
+
+        let map_err_handler = |err: SystemError| {
+            if err == SystemError::EEXIST {
+                kerror!(
+                    "Pid: {}, elf segment at {:p} overlaps with existing mapping",
+                    current_pcb().pid,
+                    addr_to_map.as_ptr::<u8>()
+                );
+            }
+            err
+        };
+        // 由于后面需要把ELF文件的内容加载到内存,因此暂时把当前段的权限设置为可写
+        let tmp_prot = if !prot.contains(ProtFlags::PROT_WRITE) {
+            *prot | ProtFlags::PROT_WRITE
+        } else {
+            *prot
+        };
+
+        // 映射到的虚拟地址。请注意,这个虚拟地址是user_vm_guard这个地址空间的虚拟地址。不一定是当前进程地址空间的
+        let map_addr: VirtAddr;
+
+        // total_size is the size of the ELF (interpreter) image.
+        // The _first_ mmap needs to know the full size, otherwise
+        // randomization might put this image into an overlapping
+        // position with the ELF binary image. (since size < total_size)
+        // So we first map the 'big' image - and unmap the remainder at
+        // the end. (which unmap is needed for ELF images with holes.)
+        if total_size != 0 {
+            let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data();
+
+            // kdebug!("total_size={}", total_size);
+
+            map_addr = user_vm_guard
+                .map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false)
+                .map_err(map_err_handler)?
+                .virt_address();
+            // kdebug!("map ok: addr_to_map={:?}", addr_to_map);
+
+            let to_unmap = map_addr + map_size;
+            let to_unmap_size = total_size - map_size;
+
+            // kdebug!("to_unmap={:?}, to_unmap_size={}", to_unmap, to_unmap_size);
+            user_vm_guard.munmap(
+                VirtPageFrame::new(to_unmap),
+                PageFrameCount::from_bytes(to_unmap_size).unwrap(),
+            )?;
+
+            // 加载文件到内存
+            self.do_load_file(
+                map_addr + beginning_page_offset,
+                seg_in_file_size,
+                file_offset,
+                param,
+            )?;
+            if tmp_prot != *prot {
+                user_vm_guard.mprotect(
+                    VirtPageFrame::new(map_addr),
+                    PageFrameCount::from_bytes(page_align_up(map_size)).unwrap(),
+                    *prot,
+                )?;
+            }
+        } else {
+            // kdebug!("total size = 0");
+
+            map_addr = user_vm_guard
+                .map_anonymous(addr_to_map, map_size, tmp_prot, *map_flags, false)?
+                .virt_address();
+            // kdebug!(
+            //     "map ok: addr_to_map={:?}, map_addr={map_addr:?},beginning_page_offset={beginning_page_offset:?}",
+            //     addr_to_map
+            // );
+
+            // 加载文件到内存
+            self.do_load_file(
+                map_addr + beginning_page_offset,
+                seg_in_file_size,
+                file_offset,
+                param,
+            )?;
+
+            if tmp_prot != *prot {
+                user_vm_guard.mprotect(
+                    VirtPageFrame::new(map_addr),
+                    PageFrameCount::from_bytes(page_align_up(map_size)).unwrap(),
+                    *prot,
+                )?;
+            }
+        }
+        // kdebug!("load_elf_segment OK: map_addr={:?}", map_addr);
+        return Ok((map_addr, true));
+    }
+
+    /// 加载ELF文件到用户空间
+    ///
+    /// ## 参数
+    ///
+    /// - `vaddr`:要加载到的虚拟地址
+    /// - `size`:要加载的大小
+    /// - `offset_in_file`:在文件内的偏移量
+    /// - `param`:执行参数
+    fn do_load_file(
+        &self,
+        mut vaddr: VirtAddr,
+        size: usize,
+        offset_in_file: usize,
+        param: &mut ExecParam,
+    ) -> Result<(), SystemError> {
+        let file = param.file_mut();
+        if (file.metadata()?.size as usize) < offset_in_file + size {
+            return Err(SystemError::ENOEXEC);
+        }
+        let buf_size = min(size, Self::FILE_READ_BUF_SIZE);
+        let mut buf = vec![0u8; buf_size];
+
+        let mut remain = size;
+
+        file.lseek(SeekFrom::SeekSet(offset_in_file as i64))?;
+
+        while remain > 0 {
+            let read_size = min(remain, buf_size);
+            file.read(read_size, &mut buf[..read_size])?;
+            // kdebug!("copy_to_user: vaddr={:?}, read_size = {read_size}", vaddr);
+            unsafe {
+                copy_to_user(vaddr, &buf[..read_size]).map_err(|_| SystemError::EFAULT)?;
+            }
+
+            vaddr += read_size;
+            remain -= read_size;
+        }
+        return Ok(());
+    }
+
+    /// 我们需要显式的把数据段之后剩余的内存页都清零。
+    fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> {
+        let nbyte = self.elf_page_offset(elf_bss);
+        if nbyte > 0 {
+            let nbyte = Self::ELF_PAGE_SIZE - nbyte;
+            unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?;
+        }
+        return Ok(());
+    }
+
+    /// 创建auxv
+    ///
+    /// ## 参数
+    ///
+    /// - `param`:执行参数
+    /// - `entrypoint_vaddr`:程序入口地址
+    /// - `phdr_vaddr`:程序头表地址
+    /// - `elf_header`:ELF文件头
+    fn create_auxv(
+        &self,
+        param: &mut ExecParam,
+        entrypoint_vaddr: VirtAddr,
+        phdr_vaddr: Option<VirtAddr>,
+        ehdr: &elf::file::FileHeader<AnyEndian>,
+    ) -> Result<(), ExecError> {
+        let phdr_vaddr = phdr_vaddr.unwrap_or(VirtAddr::new(0));
+
+        let init_info = param.init_info_mut();
+        init_info
+            .auxv
+            .insert(AtType::PhEnt as u8, ehdr.e_phentsize as usize);
+        init_info
+            .auxv
+            .insert(AtType::PageSize as u8, MMArch::PAGE_SIZE);
+        init_info.auxv.insert(AtType::Phdr as u8, phdr_vaddr.data());
+        init_info
+            .auxv
+            .insert(AtType::PhNum as u8, ehdr.e_phnum as usize);
+        init_info
+            .auxv
+            .insert(AtType::Entry as u8, entrypoint_vaddr.data());
+
+        return Ok(());
+    }
+
+    /// 解析文件的ehdr
+    fn parse_ehdr(data: &[u8]) -> Result<FileHeader<AnyEndian>, elf::ParseError> {
+        let ident_buf = data.get_bytes(0..elf::abi::EI_NIDENT)?;
+        let ident = elf::file::parse_ident::<AnyEndian>(ident_buf)?;
+
+        let tail_start = elf::abi::EI_NIDENT;
+        let tail_end = match ident.1 {
+            elf::file::Class::ELF32 => tail_start + elf::file::ELF32_EHDR_TAILSIZE,
+            elf::file::Class::ELF64 => tail_start + elf::file::ELF64_EHDR_TAILSIZE,
+        };
+        let tail_buf = data.get_bytes(tail_start..tail_end)?;
+
+        let ehdr: FileHeader<_> = FileHeader::parse_tail(ident, tail_buf)?;
+        return Ok(ehdr);
+    }
+
+    /// 解析文件的program header table
+    ///
+    /// ## 参数
+    ///
+    /// - `param`:执行参数
+    /// - `ehdr`:文件头
+    /// - `data_buf`:用于缓存SegmentTable的Vec。
+    ///     这是因为SegmentTable的生命周期与data_buf一致。初始化这个Vec的大小为0即可。
+    ///
+    /// ## 说明
+    ///
+    /// 这个函数由elf库的`elf::elf_bytes::find_phdrs`修改而来。
+    fn parse_segments<'a>(
+        param: &mut ExecParam,
+        ehdr: &FileHeader<AnyEndian>,
+        data_buf: &'a mut Vec<u8>,
+    ) -> Result<Option<elf::segment::SegmentTable<'a, AnyEndian>>, elf::ParseError> {
+        // It's Ok to have no program headers
+        if ehdr.e_phoff == 0 {
+            return Ok(None);
+        }
+        let file = param.file_mut();
+        // If the number of segments is greater than or equal to PN_XNUM (0xffff),
+        // e_phnum is set to PN_XNUM, and the actual number of program header table
+        // entries is contained in the sh_info field of the section header at index 0.
+        let mut phnum = ehdr.e_phnum as usize;
+        if phnum == elf::abi::PN_XNUM as usize {
+            let shoff: usize = ehdr.e_shoff.try_into()?;
+
+            // 从磁盘读取shdr的前2个entry
+            file.lseek(SeekFrom::SeekSet(shoff as i64))
+                .map_err(|_| elf::ParseError::BadOffset(shoff as u64))?;
+            let shdr_buf_size = ehdr.e_shentsize * 2;
+            let mut shdr_buf = vec![0u8; shdr_buf_size as usize];
+            file.read(shdr_buf_size as usize, &mut shdr_buf)
+                .map_err(|_| elf::ParseError::BadOffset(shoff as u64))?;
+
+            let mut offset = 0;
+            let shdr0 = <elf::section::SectionHeader as elf::parse::ParseAt>::parse_at(
+                ehdr.endianness,
+                ehdr.class,
+                &mut offset,
+                &shdr_buf,
+            )?;
+            phnum = shdr0.sh_info.try_into()?;
+        }
+
+        // Validate phentsize before trying to read the table so that we can error early for corrupted files
+        let entsize = <ProgramHeader as elf::parse::ParseAt>::validate_entsize(
+            ehdr.class,
+            ehdr.e_phentsize as usize,
+        )?;
+        let phoff: usize = ehdr.e_phoff.try_into()?;
+        let size = entsize
+            .checked_mul(phnum)
+            .ok_or(elf::ParseError::IntegerOverflow)?;
+        phoff
+            .checked_add(size)
+            .ok_or(elf::ParseError::IntegerOverflow)?;
+
+        // 读取program header table
+
+        file.lseek(SeekFrom::SeekSet(phoff as i64))
+            .map_err(|_| elf::ParseError::BadOffset(phoff as u64))?;
+        data_buf.clear();
+        data_buf.resize(size, 0);
+
+        file.read(size, data_buf)
+            .expect("read program header table failed");
+        let buf = data_buf.get_bytes(0..size)?;
+
+        return Ok(Some(elf::segment::SegmentTable::new(
+            ehdr.endianness,
+            ehdr.class,
+            buf,
+        )));
+    }
+}
+
+impl BinaryLoader for ElfLoader {
+    fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError> {
+        // let elf_bytes =
+        //     ElfBytes::<AnyEndian>::minimal_parse(buf).map_err(|_| ExecError::NotExecutable)?;
+
+        let ehdr = Self::parse_ehdr(buf).map_err(|_| ExecError::NotExecutable)?;
+
+        #[cfg(target_arch = "x86_64")]
+        return self.probe_x86_64(param, &ehdr);
+
+        #[cfg(not(target_arch = "x86_64"))]
+        unimplemented!("Unsupported architecture");
+    }
+
+    fn load(
+        self: &'static Self,
+        param: &mut ExecParam,
+        head_buf: &[u8],
+    ) -> Result<BinaryLoaderResult, ExecError> {
+        // 解析elf文件头
+        let ehdr = Self::parse_ehdr(head_buf).map_err(|_| ExecError::NotExecutable)?;
+
+        // 参考linux-5.19的load_elf_binary函数
+        // https://opengrok.ringotek.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#1034
+
+        let elf_type = ElfType::from(ehdr.e_type);
+        // kdebug!("ehdr = {:?}", ehdr);
+
+        let binding = param.vm().clone();
+        let mut user_vm = binding.write();
+
+        // todo: 增加对user stack上的内存是否具有可执行权限的处理(方法:寻找phdr里面的PT_GNU_STACK段)
+
+        // todo: 增加对动态链接的处理
+
+        // kdebug!("to parse segments");
+        // 加载ELF文件并映射到用户空间
+        let mut phdr_buf = Vec::new();
+        let loadable_sections = Self::parse_segments(param, &ehdr, &mut phdr_buf)
+            .map_err(|_| ExecError::ParseError)?
+            .ok_or(ExecError::ParseError)?
+            .iter()
+            .filter(|seg| seg.p_type == elf::abi::PT_LOAD);
+
+        // kdebug!("loadable_sections = {:?}", loadable_sections);
+
+        let mut elf_brk = VirtAddr::new(0);
+        let mut elf_bss = VirtAddr::new(0);
+        let mut start_code: Option<VirtAddr> = None;
+        let mut end_code: Option<VirtAddr> = None;
+        let mut start_data: Option<VirtAddr> = None;
+        let mut end_data: Option<VirtAddr> = None;
+
+        // 加载的时候的偏移量(这个偏移量在加载动态链接段的时候产生,由于还没有动态链接,因此暂时不可变。)
+        // 请不要删除load_bias! 以免到时候写动态链接的时候忘记了。
+        let load_bias = 0usize;
+        let mut bss_prot_flags = ProtFlags::empty();
+        // 是否是第一个加载的段
+        let mut first_pt_load = true;
+        // program header的虚拟地址
+        let mut phdr_vaddr: Option<VirtAddr> = None;
+        for seg_to_load in loadable_sections {
+            // kdebug!("seg_to_load = {:?}", seg_to_load);
+            if unlikely(elf_brk > elf_bss) {
+                // kdebug!(
+                //     "to set brk, elf_brk = {:?}, elf_bss = {:?}",
+                //     elf_brk,
+                //     elf_bss
+                // );
+                self.set_elf_brk(
+                    &mut user_vm,
+                    elf_bss + load_bias,
+                    elf_brk + load_bias,
+                    bss_prot_flags,
+                )?;
+                let nbyte = self.elf_page_offset(elf_bss);
+                if nbyte > 0 {
+                    let nbyte = min(Self::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss);
+                    unsafe {
+                        // This bss-zeroing can fail if the ELF file specifies odd protections.
+                        // So we don't check the return value.
+                        clear_user(elf_bss + load_bias, nbyte).ok();
+                    }
+                }
+            }
+
+            // 生成ProtFlags.
+            // TODO: 当有了动态链接之后,需要根据情况设置这里的has_interpreter
+            let elf_prot_flags = self.make_prot(seg_to_load.p_flags, false, false);
+
+            let mut elf_map_flags = MapFlags::MAP_PRIVATE;
+
+            let vaddr = VirtAddr::new(seg_to_load.p_vaddr as usize);
+
+            if !first_pt_load {
+                elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
+            } else if elf_type == ElfType::Executable {
+                /*
+                 * This logic is run once for the first LOAD Program
+                 * Header for ET_EXEC binaries. No special handling
+                 * is needed.
+                 */
+                elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
+            } else if elf_type == ElfType::DSO {
+                // TODO: 支持动态链接
+                unimplemented!("DragonOS currently does not support dynamic linking!");
+            }
+
+            // 加载这个段到用户空间
+            // todo: 引入动态链接后,这里的total_size要按照实际的填写,而不一定是0
+
+            let e = self
+                .load_elf_segment(
+                    &mut user_vm,
+                    param,
+                    &seg_to_load,
+                    vaddr + load_bias,
+                    &elf_prot_flags,
+                    &elf_map_flags,
+                    0,
+                )
+                .map_err(|e| match e {
+                    SystemError::EFAULT => ExecError::BadAddress(None),
+                    SystemError::ENOMEM => ExecError::OutOfMemory,
+                    _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)),
+                })?;
+
+            // 如果地址不对,那么就报错
+            if !e.1 {
+                return Err(ExecError::BadAddress(Some(e.0)));
+            }
+
+            if first_pt_load {
+                first_pt_load = false;
+                if elf_type == ElfType::DSO {
+                    // todo: 在这里增加对load_bias和reloc_func_desc的更新代码
+                    todo!()
+                }
+            }
+
+            // kdebug!("seg_to_load.p_offset={}", seg_to_load.p_offset);
+            // kdebug!("e_phoff={}", ehdr.e_phoff);
+            // kdebug!("seg_to_load.p_filesz={}", seg_to_load.p_filesz);
+            // Figure out which segment in the file contains the Program Header Table,
+            // and map to the associated virtual address.
+            if (seg_to_load.p_offset <= ehdr.e_phoff)
+                && (ehdr.e_phoff < (seg_to_load.p_offset + seg_to_load.p_filesz))
+            {
+                phdr_vaddr = Some(VirtAddr::new(
+                    (ehdr.e_phoff - seg_to_load.p_offset + seg_to_load.p_vaddr) as usize,
+                ));
+            }
+
+            let p_vaddr = VirtAddr::new(seg_to_load.p_vaddr as usize);
+            if (seg_to_load.p_flags & elf::abi::PF_X) != 0 {
+                if start_code.is_none() || start_code.as_ref().unwrap() > &p_vaddr {
+                    start_code = Some(p_vaddr);
+                }
+            }
+
+            if start_data.is_none()
+                || (start_data.is_some() && start_data.as_ref().unwrap() > &p_vaddr)
+            {
+                start_data = Some(p_vaddr);
+            }
+
+            // 如果程序段要加载的目标地址不在用户空间内,或者是其他不合法的情况,那么就报错
+            if !p_vaddr.check_user()
+                || seg_to_load.p_filesz > seg_to_load.p_memsz
+                || seg_to_load.p_memsz > MMArch::USER_END_VADDR.data() as u64
+            {
+                // kdebug!("ERR:     p_vaddr={p_vaddr:?}");
+                return Err(ExecError::InvalidParemeter);
+            }
+
+            drop(p_vaddr);
+
+            // end vaddr of this segment(code+data+bss)
+            let seg_end_vaddr_f = self.elf_page_align_up(VirtAddr::new(
+                (seg_to_load.p_vaddr + seg_to_load.p_filesz) as usize,
+            ));
+
+            if seg_end_vaddr_f > elf_bss {
+                elf_bss = seg_end_vaddr_f;
+            }
+
+            if ((seg_to_load.p_flags & elf::abi::PF_X) != 0)
+                && (end_code.is_none()
+                    || (end_code.is_some() && end_code.as_ref().unwrap() < &seg_end_vaddr_f))
+            {
+                end_code = Some(seg_end_vaddr_f);
+            }
+
+            if end_data.is_none()
+                || (end_data.is_some() && end_data.as_ref().unwrap() < &seg_end_vaddr_f)
+            {
+                end_data = Some(seg_end_vaddr_f);
+            }
+
+            drop(seg_end_vaddr_f);
+
+            let seg_end_vaddr = VirtAddr::new((seg_to_load.p_vaddr + seg_to_load.p_memsz) as usize);
+
+            if seg_end_vaddr > elf_brk {
+                bss_prot_flags = elf_prot_flags;
+                elf_brk = seg_end_vaddr;
+            }
+        }
+        // kdebug!("elf load: phdr_vaddr={phdr_vaddr:?}");
+        let program_entrypoint = VirtAddr::new(ehdr.e_entry as usize + load_bias);
+        let phdr_vaddr = if phdr_vaddr.is_some() {
+            Some(phdr_vaddr.unwrap() + load_bias)
+        } else {
+            None
+        };
+
+        elf_bss += load_bias;
+        elf_brk += load_bias;
+        start_code = start_code.map(|v| v + load_bias);
+        end_code = end_code.map(|v| v + load_bias);
+        start_data = start_data.map(|v| v + load_bias);
+        end_data = end_data.map(|v| v + load_bias);
+
+        // kdebug!(
+        //     "to set brk: elf_bss: {:?}, elf_brk: {:?}, bss_prot_flags: {:?}",
+        //     elf_bss,
+        //     elf_brk,
+        //     bss_prot_flags
+        // );
+        self.set_elf_brk(&mut user_vm, elf_bss, elf_brk, bss_prot_flags)?;
+
+        if likely(elf_bss != elf_brk) && unlikely(self.pad_zero(elf_bss).is_err()) {
+            // kdebug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}");
+            return Err(ExecError::BadAddress(Some(elf_bss)));
+        }
+        // todo: 动态链接:增加加载interpreter的代码
+        // kdebug!("to create auxv");
+
+        self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?;
+
+        // kdebug!("auxv create ok");
+        user_vm.start_code = start_code.unwrap_or(VirtAddr::new(0));
+        user_vm.end_code = end_code.unwrap_or(VirtAddr::new(0));
+        user_vm.start_data = start_data.unwrap_or(VirtAddr::new(0));
+        user_vm.end_data = end_data.unwrap_or(VirtAddr::new(0));
+
+        let result = BinaryLoaderResult::new(program_entrypoint);
+        // kdebug!("elf load OK!!!");
+        return Ok(result);
+    }
+}
+
+/// Elf机器架构,对应于e_machine字段。在ABI中,以EM_开头的常量是e_machine字段的值。
+#[derive(Debug, Eq, PartialEq)]
+pub enum ElfMachine {
+    I386,
+    AArch32,
+    AArch64,
+    X86_64,
+    RiscV,
+    /// 龙芯架构
+    LoongArch,
+    /// 未知架构
+    Unknown,
+}
+
+impl From<u16> for ElfMachine {
+    fn from(machine: u16) -> Self {
+        match machine {
+            0x03 => Self::I386,
+            0x28 => Self::AArch32,
+            0xb7 => Self::AArch64,
+            0x3e => Self::X86_64,
+            0xf3 => Self::RiscV,
+            0x102 => Self::LoongArch,
+            // 未知架构
+            _ => Self::Unknown,
+        }
+    }
+}
+
+/// Elf文件类型,对应于e_type字段。在ABI中,以ET_开头的常量是e_type字段的值。
+#[derive(Debug, Eq, PartialEq)]
+pub enum ElfType {
+    /// 可重定位文件
+    Relocatable,
+    /// 可执行文件
+    Executable,
+    /// 动态链接库
+    DSO,
+    /// 核心转储文件
+    Core,
+    /// 未知类型
+    Unknown,
+}
+
+impl From<u16> for ElfType {
+    fn from(elf_type: u16) -> Self {
+        match elf_type {
+            0x01 => Self::Relocatable,
+            0x02 => Self::Executable,
+            0x03 => Self::DSO,
+            0x04 => Self::Core,
+            _ => Self::Unknown,
+        }
+    }
+}
+
+// Simple convenience extension trait to wrap get() with .ok_or(SliceReadError)
+trait ReadBytesExt<'data> {
+    fn get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError>;
+}
+impl<'data> ReadBytesExt<'data> for &'data [u8] {
+    fn get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError> {
+        let start = range.start;
+        let end = range.end;
+        self.get(range)
+            .ok_or(elf::ParseError::SliceReadError((start, end)))
+    }
+}

+ 33 - 5
kernel/src/libs/libUI/screen_manager.c

@@ -44,10 +44,10 @@ static struct scm_buffer_info_t *__create_buffer(uint64_t type)
     buf->width = video_frame_buffer_info.width;
     buf->size = video_frame_buffer_info.size;
 
-    struct Page *p = alloc_pages(ZONE_NORMAL, PAGE_2M_ALIGN(video_frame_buffer_info.size) / PAGE_2M_SIZE, 0);
-    if (p == NULL)
+    void* buf_vaddr = kzalloc(video_frame_buffer_info.size, 0);
+    if (buf_vaddr == NULL)
         goto failed;
-    buf->vaddr = (uint64_t)phys_2_virt(p->addr_phys);
+    buf->vaddr = buf_vaddr;
     return buf;
 failed:;
     kfree(buf);
@@ -74,7 +74,7 @@ static int __destroy_buffer(struct scm_buffer_info_t *buf)
         return -EINVAL;
 
     // 释放内存页
-    free_pages(Phy_to_2M_Page(virt_2_phys(buf->vaddr)), PAGE_2M_ALIGN(video_frame_buffer_info.size) / PAGE_2M_SIZE);
+    kfree((void*)buf->vaddr);
     return 0;
 }
 
@@ -295,7 +295,35 @@ int scm_framework_enable(struct scm_ui_framework_t *ui)
     }
     else
         __current_framework = ui;
+    ui->ui_ops->enable(NULL);
+    spin_unlock(&scm_screen_own_lock);
+    return retval;
+}
+
+/**
+ * @brief 禁用某个ui框架,将它的帧缓冲区从屏幕上移除
+ *
+ * @param ui 要禁用的ui框架
+ * @return int 返回码
+ */
+int scm_framework_disable(struct scm_ui_framework_t *ui)
+{
+    if (ui->buf->vaddr == NULL)
+        return -EINVAL;
+    spin_lock(&scm_screen_own_lock);
+    if (ui != __current_framework)
+        return -EINVAL;
+    int retval = 0;
+    if (__scm_double_buffer_enabled == true)
+    {
+        retval = video_set_refresh_target(NULL);
+        if (retval == 0)
+            __current_framework = NULL;
+    }
+    else
+        __current_framework = NULL;
 
+    ui->ui_ops->disable(NULL);
     spin_unlock(&scm_screen_own_lock);
     return retval;
 }
@@ -307,7 +335,7 @@ int scm_framework_enable(struct scm_ui_framework_t *ui)
 void scm_reinit()
 {
     scm_enable_alloc();
-    video_reinitialize(false);
+    // video_reinitialize(false);
 
     // 遍历当前所有使用帧缓冲区的框架,更新地址
     // 逐个检查已经注册了的ui框架,将其缓冲区更改为双缓冲

+ 3 - 1
kernel/src/libs/libUI/screen_manager.h

@@ -115,4 +115,6 @@ int scm_enable_double_buffer();
  * @param ui 要启动的ui框架
  * @return int 返回码
  */
-int scm_framework_enable(struct scm_ui_framework_t *ui);
+int scm_framework_enable(struct scm_ui_framework_t *ui);
+
+int scm_framework_disable(struct scm_ui_framework_t *ui);

+ 25 - 1
kernel/src/libs/libUI/textui.c

@@ -21,6 +21,9 @@ static struct textui_private_info_t __private_info = {0};
 static struct List __windows_list;
 static spinlock_t change_lock;
 
+// 用于标记是否允许输出到屏幕
+static atomic_t __put_window_enable_flag = {1};
+
 /**
  * @brief 初始化window对象
  *
@@ -69,7 +72,7 @@ static int __textui_init_window(struct textui_window_t *window, uint8_t flags, u
 int textui_install_handler(struct scm_buffer_info_t *buf)
 {
     // return printk_init(buf);
-    c_uart_send_str(COM1, "textui_install_handler");
+    c_uart_send_str(COM1, "textui_install_handler\n");
     return 0;
 }
 
@@ -81,11 +84,14 @@ int textui_uninstall_handler(void *args)
 int textui_enable_handler(void *args)
 {
     c_uart_send_str(COM1, "textui_enable_handler\n");
+    atomic_cmpxchg(&__put_window_enable_flag, 0, 1);
     return 0;
 }
 
 int textui_disable_handler(void *args)
 {
+    c_uart_send_str(COM1, "textui_disable_handler\n");
+    atomic_set(&__put_window_enable_flag, 0);
     return 0;
 }
 
@@ -215,6 +221,13 @@ int textui_putchar_window(struct textui_window_t *window, uint16_t character, ui
     // uint64_t rflags = 0; // 加锁后rflags存储到这里
     spin_lock_no_preempt(&window->lock);
     c_uart_send(COM1, character);
+    // 如果禁止输出,直接返回
+    if(atomic_read(&__put_window_enable_flag) == 0)
+    {
+        spin_unlock_no_preempt(&window->lock);
+        return 0;
+    }
+
     if (unlikely(character == '\n'))
     {
         // 换行时还需要输出\r
@@ -346,3 +359,14 @@ int textui_init()
     c_uart_send_str(COM1, "text ui initialized\n");
     return 0;
 }
+
+
+void enable_textui()
+{
+    scm_framework_enable(&textui_framework);
+}
+
+void disable_textui()
+{
+    scm_framework_disable(&textui_framework);
+}

+ 5 - 1
kernel/src/libs/libUI/textui.h

@@ -180,4 +180,8 @@ uint32_t __textui_get_current_window_id();
  *
  * @return int
  */
-int textui_init();
+int textui_init();
+
+void enable_textui();
+
+void disable_textui();

+ 1 - 0
kernel/src/libs/mod.rs

@@ -1,6 +1,7 @@
 pub mod align;
 pub mod atomic;
 pub mod casting;
+pub mod elf;
 pub mod ffi_convert;
 #[macro_use]
 pub mod int_like;

+ 4 - 0
kernel/src/libs/printk.c

@@ -594,7 +594,9 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
 int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ...)
 {
     uint64_t rflags;
+    io_mfence();
     spin_lock_irqsave(&__printk_lock, rflags);
+    io_mfence();
     va_list args;
     va_start(args, fmt);
     char buf[4096]; // vsprintf()的缓冲区
@@ -610,7 +612,9 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ..
         // 输出
         textui_putchar(current, FRcolor, BKcolor);
     }
+    io_mfence();
     spin_unlock_irqrestore(&__printk_lock, rflags);
+    io_mfence();
     return i;
 }
 

+ 92 - 10
kernel/src/libs/printk.rs

@@ -1,8 +1,15 @@
 #![allow(unused)]
-use crate::include::bindings::bindings::{printk_color, BLACK, WHITE};
+use crate::{
+    driver::uart::uart::c_uart_send_str,
+    include::bindings::bindings::{printk_color, BLACK, WHITE},
+};
 use ::core::ffi::c_char;
 use alloc::vec::Vec;
-use core::fmt;
+use core::{
+    fmt::{self, Write},
+    intrinsics::{likely, unlikely},
+    sync::atomic::{AtomicBool, Ordering},
+};
 
 // ====== 定义颜色 ======
 /// 白色
@@ -52,15 +59,15 @@ macro_rules! printk_color {
 #[macro_export]
 macro_rules! kdebug {
     ($($arg:tt)*) => {
-        $crate::libs::printk::PrintkWriter.__write_string((alloc::fmt::format(format_args!("[ DEBUG ] ({}:{})\t", file!(), line!()))+
-                                                                alloc::fmt::format(format_args!($($arg)*)).as_str() + "\n").as_str())
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)))
+
     }
 }
 
 #[macro_export]
 macro_rules! kinfo {
     ($($arg:tt)*) => {
-        $crate::libs::printk::PrintkWriter.__write_string((alloc::string::String::from("[ INFO ] ")+ alloc::fmt::format(format_args!($($arg)*)).as_str() + "\n").as_str())
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)))
     }
 }
 
@@ -68,7 +75,7 @@ macro_rules! kinfo {
 macro_rules! kwarn {
     ($($arg:tt)*) => {
         $crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::printk::COLOR_YELLOW, $crate::libs::printk::COLOR_BLACK, "[ WARN ] ");
-        $crate::libs::printk::PrintkWriter.__write_string((alloc::fmt::format(format_args!($($arg)*)) + "\n").as_str())
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
     }
 }
 
@@ -76,8 +83,7 @@ macro_rules! kwarn {
 macro_rules! kerror {
     ($($arg:tt)*) => {
         $crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::printk::COLOR_RED, $crate::libs::printk::COLOR_BLACK, "[ ERROR ] ");
-        $crate::libs::printk::PrintkWriter.__write_string((alloc::fmt::format(format_args!("({}:{})\t", file!(), line!())) +
-                                                                alloc::fmt::format(format_args!($($arg)*)).as_str() + "\n").as_str())
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
     }
 }
 
@@ -85,17 +91,29 @@ macro_rules! kerror {
 macro_rules! kBUG {
     ($($arg:tt)*) => {
         $crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::printk::COLOR_RED, $crate::libs::printk::COLOR_BLACK, "[ BUG ] ");
-        $crate::libs::printk::PrintkWriter.__write_string((alloc::fmt::format(format_args!("({}:{})\t", file!(), line!())) +
-                                                                alloc::fmt::format(format_args!($($arg)*)).as_str() + "\n").as_str())
+        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
     }
 }
 
 pub struct PrintkWriter;
 
+/// 由于内存管理初始化完成之前,无法使用动态内存分配,所以需要在内存管理初始化完成之后才能使用动态内存分配
+static ALLOW_ALLOC_ATOMIC: AtomicBool = AtomicBool::new(false);
+static mut ALLOW_ALLOC_BOOL: bool = false;
+
 impl PrintkWriter {
+    #[inline]
+    pub fn __write_fmt(&mut self, args: fmt::Arguments) {
+        self.write_fmt(args);
+    }
+
     /// 调用C语言编写的printk_color,并输出白底黑字(暂时只支持ascii字符)
     /// @param str: 要写入的字符
     pub fn __write_string(&mut self, s: &str) {
+        if unlikely(!self.allow_alloc()) {
+            self.__write_string_on_stack(s);
+            return;
+        }
         let str_to_print = self.__utf8_to_ascii(s);
         unsafe {
             printk_color(WHITE, BLACK, str_to_print.as_ptr() as *const c_char);
@@ -103,12 +121,36 @@ impl PrintkWriter {
     }
 
     pub fn __write_string_color(&self, fr_color: u32, bk_color: u32, s: &str) {
+        if unlikely(!self.allow_alloc()) {
+            self.__write_string_on_stack(s);
+            return;
+        }
+
         let str_to_print = self.__utf8_to_ascii(s);
         unsafe {
             printk_color(fr_color, bk_color, str_to_print.as_ptr() as *const c_char);
         }
     }
 
+    #[inline]
+    fn allow_alloc(&self) -> bool {
+        // 由于allow_alloc只可能由false变为true
+        // 因此采用两种方式读取它,一种是原子操作,一种是普通的bool,以优化性能。
+        if likely(unsafe { ALLOW_ALLOC_BOOL }) {
+            return true;
+        } else {
+            return ALLOW_ALLOC_ATOMIC.load(Ordering::SeqCst);
+        }
+    }
+
+    /// 允许动态内存分配
+    pub fn enable_alloc(&self) {
+        ALLOW_ALLOC_ATOMIC.store(true, Ordering::SeqCst);
+        unsafe {
+            ALLOW_ALLOC_BOOL = true;
+        }
+    }
+
     /// 将s这个utf8字符串,转换为ascii字符串
     /// @param s 待转换的utf8字符串
     /// @return Vec<u8> 转换结束后的Ascii字符串
@@ -125,6 +167,46 @@ impl PrintkWriter {
         ascii_str.push(b'\0');
         return ascii_str;
     }
+
+    fn __write_string_on_stack(&self, s: &str) {
+        let s_len = s.len();
+        assert!(s_len < 1024, "s_len is too long");
+        let mut str_to_print: [u8; 1024] = [0; 1024];
+        let mut i = 0;
+        for byte in s.bytes() {
+            match byte {
+                0..=127 => {
+                    str_to_print[i] = byte;
+                    i += 1;
+                }
+                _ => {}
+            }
+        }
+        str_to_print[i] = b'\0';
+        unsafe {
+            printk_color(WHITE, BLACK, str_to_print.as_ptr() as *const c_char);
+        }
+    }
+
+    fn __write_string_color_on_stack(&self, fr_color: u32, bk_color: u32, s: &str) {
+        let s_len = s.len();
+        assert!(s_len < 1024, "s_len is too long");
+        let mut str_to_print: [u8; 1024] = [0; 1024];
+        let mut i = 0;
+        for byte in s.bytes() {
+            match byte {
+                0..=127 => {
+                    str_to_print[i] = byte;
+                    i += 1;
+                }
+                _ => {}
+            }
+        }
+        str_to_print[i] = b'\0';
+        unsafe {
+            printk_color(fr_color, bk_color, str_to_print.as_ptr() as *const c_char);
+        }
+    }
 }
 
 /// 为Printk Writer实现core::fmt::Write, 使得能够借助Rust自带的格式化组件,格式化字符并输出

+ 43 - 5
kernel/src/libs/rwlock.rs

@@ -7,7 +7,10 @@ use core::{
     sync::atomic::{AtomicU32, Ordering},
 };
 
-use crate::syscall::SystemError;
+use crate::{
+    process::preempt::{preempt_disable, preempt_enable},
+    syscall::SystemError,
+};
 
 ///RwLock读写锁
 
@@ -110,6 +113,15 @@ impl<T> RwLock<T> {
     #[inline]
     /// @brief 尝试获取READER守卫
     pub fn try_read(&self) -> Option<RwLockReadGuard<T>> {
+        preempt_disable();
+        let r = self.inner_try_read();
+        if r.is_none() {
+            preempt_enable();
+        }
+        return r;
+    }
+
+    fn inner_try_read(&self) -> Option<RwLockReadGuard<T>> {
         let reader_value = self.current_reader();
         //得到自增后的reader_value, 包括了尝试获得READER守卫的进程
         let value;
@@ -165,6 +177,18 @@ impl<T> RwLock<T> {
     #[inline]
     /// @brief 尝试获得WRITER守卫
     pub fn try_write(&self) -> Option<RwLockWriteGuard<T>> {
+        preempt_disable();
+        let r = self.inner_try_write();
+        if r.is_none() {
+            preempt_enable();
+        }
+
+        return r;
+    } //当架构为arm时,有些代码需要作出调整compare_exchange=>compare_exchange_weak
+
+    #[cfg(target_arch = "x86_64")]
+    #[allow(dead_code)]
+    fn inner_try_write(&self) -> Option<RwLockWriteGuard<T>> {
         let res: bool = self
             .lock
             .compare_exchange(0, WRITER, Ordering::Acquire, Ordering::Relaxed)
@@ -178,7 +202,7 @@ impl<T> RwLock<T> {
         } else {
             return None;
         }
-    } //当架构为arm时,有些代码需要作出调整compare_exchange=>compare_exchange_weak
+    }
 
     #[allow(dead_code)]
     #[inline]
@@ -196,8 +220,18 @@ impl<T> RwLock<T> {
     #[inline]
     /// @brief 尝试获得UPGRADER守卫
     pub fn try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<T>> {
-        //获得UPGRADER守卫不需要查看读者位
-        //如果获得读者锁失败,不需要撤回fetch_or的原子操作
+        preempt_disable();
+        let r = self.inner_try_upgradeable_read();
+        if r.is_none() {
+            preempt_enable();
+        }
+
+        return r;
+    }
+
+    fn inner_try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<T>> {
+        // 获得UPGRADER守卫不需要查看读者位
+        // 如果获得读者锁失败,不需要撤回fetch_or的原子操作
         if self.lock.fetch_or(UPGRADED, Ordering::Acquire) & (WRITER | UPGRADED) == 0 {
             return Some(RwLockUpgradableGuard {
                 inner: self,
@@ -318,7 +352,7 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
 
         let inner: &RwLock<T> = self.inner;
 
-        //自动移去UPGRADED比特位
+        // 自动移去UPGRADED比特位
         mem::drop(self);
 
         RwLockReadGuard {
@@ -422,6 +456,7 @@ impl<'rwlock, T> Drop for RwLockReadGuard<'rwlock, T> {
     fn drop(&mut self) {
         debug_assert!(self.lock.load(Ordering::Relaxed) & !(WRITER | UPGRADED) > 0);
         self.lock.fetch_sub(READER, Ordering::Release);
+        preempt_enable();
     }
 }
 
@@ -432,6 +467,7 @@ impl<'rwlock, T> Drop for RwLockUpgradableGuard<'rwlock, T> {
             UPGRADED
         );
         self.inner.lock.fetch_sub(UPGRADED, Ordering::AcqRel);
+        preempt_enable();
         //这里为啥要AcqRel? Release应该就行了?
     }
 }
@@ -442,5 +478,7 @@ impl<'rwlock, T> Drop for RwLockWriteGuard<'rwlock, T> {
         self.inner
             .lock
             .fetch_and(!(WRITER | UPGRADED), Ordering::Release);
+
+        preempt_enable();
     }
 }

+ 16 - 16
kernel/src/libs/spinlock.rs

@@ -13,8 +13,8 @@ use crate::syscall::SystemError;
 
 /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
 #[inline]
-pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
-    *flags = local_irq_save() as u64;
+pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut usize) {
+    *flags = local_irq_save();
     unsafe {
         spin_lock(lock);
     }
@@ -22,12 +22,11 @@ pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
 
 /// @brief 恢复rflags以及中断状态并解锁自旋锁
 #[inline]
-pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
+pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: usize) {
     unsafe {
         spin_unlock(lock);
     }
-    // kdebug!("123");
-    local_irq_restore(*flags as usize);
+    local_irq_restore(flags);
 }
 
 /// 判断一个自旋锁是否已经被加锁
@@ -129,27 +128,27 @@ impl RawSpinlock {
     }
 
     /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
-    pub fn lock_irqsave(&self, flags: &mut u64) {
-        *flags = local_irq_save() as u64;
+    pub fn lock_irqsave(&self, flags: &mut usize) {
+        *flags = local_irq_save();
         self.lock();
     }
 
     /// @brief 恢复rflags以及中断状态并解锁自旋锁
-    pub fn unlock_irqrestore(&self, flags: &u64) {
+    pub fn unlock_irqrestore(&self, flags: usize) {
         self.unlock();
-        local_irq_restore(*flags as usize);
+        local_irq_restore(flags);
     }
 
     /// @brief 尝试保存中断状态到flags中,关闭中断,并对自旋锁加锁
     /// @return 加锁成功->true
     ///         加锁失败->false
     #[inline(always)]
-    pub fn try_lock_irqsave(&self, flags: &mut u64) -> bool {
-        *flags = local_irq_save() as u64;
+    pub fn try_lock_irqsave(&self, flags: &mut usize) -> bool {
+        *flags = local_irq_save();
         if self.try_lock() {
             return true;
         }
-        local_irq_restore(*flags as usize);
+        local_irq_restore(*flags);
         return false;
     }
 }
@@ -168,7 +167,7 @@ pub struct SpinLock<T> {
 #[derive(Debug)]
 pub struct SpinLockGuard<'a, T: 'a> {
     lock: &'a SpinLock<T>,
-    flag: u64,
+    flag: usize,
 }
 
 /// 向编译器保证,SpinLock在线程之间是安全的.
@@ -194,7 +193,8 @@ impl<T> SpinLock<T> {
     }
 
     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
-        let mut flags: u64 = 0;
+        let mut flags: usize = 0;
+
         self.lock.lock_irqsave(&mut flags);
         // 加锁成功,返回一个守卫
         return SpinLockGuard {
@@ -214,7 +214,7 @@ impl<T> SpinLock<T> {
     }
 
     pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
-        let mut flags: u64 = 0;
+        let mut flags: usize = 0;
         if self.lock.try_lock_irqsave(&mut flags) {
             return Ok(SpinLockGuard {
                 lock: self,
@@ -245,7 +245,7 @@ impl<T> DerefMut for SpinLockGuard<'_, T> {
 impl<T> Drop for SpinLockGuard<'_, T> {
     fn drop(&mut self) {
         if self.flag != 0 {
-            self.lock.lock.unlock_irqrestore(&self.flag);
+            self.lock.lock.unlock_irqrestore(self.flag);
         } else {
             self.lock.lock.unlock();
         }

+ 28 - 22
kernel/src/main.c

@@ -37,6 +37,7 @@
 
 extern int rs_tty_init();
 extern void rs_softirq_init();
+extern void rs_mm_init();
 
 ul bsp_idt_size, bsp_gdt_size;
 
@@ -93,7 +94,8 @@ void system_initialize()
     sys_vector_init();
 
     //  初始化内存管理单元
-    mm_init();
+    // mm_init();
+    rs_mm_init();
 
     // 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
     // 原因是,系统启动初期,framebuffer被映射到48M地址处,
@@ -115,9 +117,10 @@ void system_initialize()
     // ===========================
 
     acpi_init();
-
-    // 初始化中断模块
+    io_mfence();
     sched_init();
+    io_mfence();
+    // 初始化中断模块
     irq_init();
 
     // softirq_init();
@@ -125,9 +128,8 @@ void system_initialize()
 
     current_pcb->cpu_id = 0;
     current_pcb->preempt_count = 0;
-    
-    syscall_init();
 
+    syscall_init();
     io_mfence();
 
     rs_timekeeping_init();
@@ -139,36 +141,44 @@ void system_initialize()
     rs_jiffies_init();
     io_mfence();
 
-    rs_clocksource_boot_finish();
-    // 这里必须加内存屏障,否则会出错
     io_mfence();
-    smp_init();
-    io_mfence();
-
     vfs_init();
     rs_tty_init();
+    io_mfence();
+    // 由于进程管理模块依赖于文件系统,因此必须在文件系统初始化完毕后再初始化进程管理模块
+    // 并且,因为smp的IDLE进程的初始化依赖于进程管理模块,
+    // 因此必须在进程管理模块初始化完毕后再初始化smp。
+    io_mfence();
+
+    process_init();
+
+    io_mfence();
+    rs_clocksource_boot_finish();
+
+    io_mfence();
 
     cpu_init();
+
     ps2_keyboard_init();
-    // tty_init();
-    // ps2_mouse_init();
-    // ata_init();
+    io_mfence();
+
     pci_init();
+
     rs_pci_init();
-    io_mfence();
 
-    // test_slab();
-    // test_mm();
+    // 这里必须加内存屏障,否则会出错
+    io_mfence();
+    smp_init();
+    io_mfence();
 
-    // process_init();
     HPET_init();
+
     io_mfence();
     HPET_measure_freq();
     io_mfence();
     // current_pcb->preempt_count = 0;
     // kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
 
-    process_init();
     // 启用double buffer
     // scm_enable_double_buffer();  // 因为时序问题, 该函数调用被移到 initial_kernel_thread
     io_mfence();
@@ -180,10 +190,6 @@ void system_initialize()
 
     apic_timer_init();
     io_mfence();
-
-    // 这里不能删除,否则在O1会报错
-    // while (1)
-    //     pause();
 }
 
 // 操作系统内核从这里开始执行

+ 0 - 27
kernel/src/mm/Makefile

@@ -1,27 +0,0 @@
-
-CFLAGS += -I .
-
-
-all:mm.o slab.o mm-stat.o vma.o mmap.o utils.o mmio.o 
-
-mm.o: mm.c
-	$(CC) $(CFLAGS) -c mm.c -o mm.o
-
-slab.o: slab.c
-	$(CC) $(CFLAGS) -c slab.c -o slab.o
-
-mm-stat.o: mm-stat.c
-	$(CC) $(CFLAGS) -c mm-stat.c -o mm-stat.o
-
-vma.o: vma.c
-	$(CC) $(CFLAGS) -c vma.c -o vma.o
-
-mmap.o: mmap.c
-	$(CC) $(CFLAGS) -c mmap.c -o mmap.o
-
-utils.o: utils.c
-	$(CC) $(CFLAGS) -c utils.c -o utils.o
-
-mmio.o: mmio.c
-	$(CC) $(CFLAGS) -c mmio.c -o mmio.o
-

+ 0 - 55
kernel/src/mm/allocator.rs

@@ -1,55 +0,0 @@
-use super::gfp::__GFP_ZERO;
-use crate::include::bindings::bindings::{gfp_t, kfree, kmalloc, PAGE_2M_SIZE};
-
-use core::alloc::{GlobalAlloc, Layout};
-
-/// 类kmalloc的分配器应当实现的trait
-pub trait LocalAlloc {
-    unsafe fn local_alloc(&self, layout: Layout, gfp: gfp_t) -> *mut u8;
-    unsafe fn local_alloc_zeroed(&self, layout: Layout, gfp: gfp_t) -> *mut u8;
-    unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout);
-}
-
-pub struct KernelAllocator {}
-
-/// 为内核SLAB分配器实现LocalAlloc的trait
-impl LocalAlloc for KernelAllocator {
-    unsafe fn local_alloc(&self, layout: Layout, gfp: gfp_t) -> *mut u8 {
-        if layout.size() > (PAGE_2M_SIZE as usize / 2) {
-            return core::ptr::null_mut();
-        }
-        return kmalloc(layout.size() as u64, gfp) as *mut u8;
-    }
-
-    unsafe fn local_alloc_zeroed(&self, layout: Layout, gfp: gfp_t) -> *mut u8 {
-        if layout.size() > (PAGE_2M_SIZE as usize / 2) {
-            return core::ptr::null_mut();
-        }
-        return kmalloc(layout.size() as u64, gfp | __GFP_ZERO) as *mut u8;
-    }
-    #[allow(unused_variables)]
-    unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) {
-        kfree(ptr as *mut ::core::ffi::c_void);
-    }
-}
-
-/// 为内核slab分配器实现GlobalAlloc特性
-unsafe impl GlobalAlloc for KernelAllocator {
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        self.local_alloc(layout, 0)
-    }
-
-    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-        self.local_alloc_zeroed(layout, 0)
-    }
-
-    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
-        self.local_dealloc(ptr, layout);
-    }
-}
-
-/// 内存分配错误处理函数
-#[alloc_error_handler]
-pub fn global_alloc_err_handler(layout: Layout) -> ! {
-    panic!("global_alloc_error, layout: {:?}", layout);
-}

+ 667 - 0
kernel/src/mm/allocator/buddy.rs

@@ -0,0 +1,667 @@
+/// @Author: [email protected]
+/// @Author: [email protected]
+/// @Date: 2023-03-28 16:03:47
+/// @FilePath: /DragonOS/kernel/src/mm/allocator/buddy.rs
+/// @Description: 伙伴分配器
+use crate::arch::MMArch;
+use crate::mm::allocator::bump::BumpAllocator;
+use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
+use crate::mm::{MemoryManagementArch, PhysAddr, VirtAddr};
+use crate::{kdebug, kerror, kwarn};
+use core::cmp::{max, min};
+use core::fmt::Debug;
+use core::intrinsics::{likely, unlikely};
+
+use core::{marker::PhantomData, mem};
+
+// 一个全局变量MAX_ORDER,用来表示buddy算法的最大阶数 [MIN_ORDER, MAX_ORDER)左闭右开区间
+const MAX_ORDER: usize = 31;
+// 4KB
+const MIN_ORDER: usize = 12;
+
+/// 保存buddy算法中每一页存放的BuddyEntry的信息,占据每个页的起始位置
+#[derive(Debug)]
+pub struct PageList<A> {
+    // 页存放entry的数量
+    entry_num: usize,
+    // 下一个页面的地址
+    next_page: PhysAddr,
+    phantom: PhantomData<A>,
+}
+
+impl<A> Clone for PageList<A> {
+    fn clone(&self) -> Self {
+        Self {
+            entry_num: self.entry_num,
+            next_page: self.next_page,
+            phantom: PhantomData,
+        }
+    }
+}
+
+impl<A> PageList<A> {
+    #[allow(dead_code)]
+    fn empty() -> Self {
+        Self {
+            entry_num: 0,
+            next_page: PhysAddr::new(0),
+            phantom: PhantomData,
+        }
+    }
+    fn new(entry_num: usize, next_page: PhysAddr) -> Self {
+        Self {
+            entry_num,
+            next_page,
+            phantom: PhantomData,
+        }
+    }
+}
+
+/// @brief: 用来表示 buddy 算法中的一个 buddy 块,整体存放在area的头部
+// 这种方式会出现对齐问题
+// #[repr(packed)]
+#[repr(C)]
+#[derive(Debug)]
+pub struct BuddyAllocator<A> {
+    // 存放每个阶的空闲“链表”的头部地址
+    free_area: [PhysAddr; (MAX_ORDER - MIN_ORDER) as usize],
+    phantom: PhantomData<A>,
+}
+
+impl<A: MemoryManagementArch> BuddyAllocator<A> {
+    const BUDDY_ENTRIES: usize =
+    // 定义一个变量记录buddy表的大小
+        (A::PAGE_SIZE - mem::size_of::<PageList<A>>()) / mem::size_of::<PhysAddr>();
+    
+    pub unsafe fn new(mut bump_allocator: BumpAllocator<A>) -> Option<Self> {
+        let initial_free_pages = bump_allocator.usage().free();
+        kdebug!("Free pages before init buddy: {:?}", initial_free_pages);
+        kdebug!("Buddy entries: {}", Self::BUDDY_ENTRIES);
+        // 最高阶的链表页数
+        let max_order_linked_list_page_num = max(
+            1,
+            (((initial_free_pages.data() * A::PAGE_SIZE) >> (MAX_ORDER - 1)) + Self::BUDDY_ENTRIES
+                - 1)
+                / Self::BUDDY_ENTRIES,
+        );
+
+        let mut free_area: [PhysAddr; (MAX_ORDER - MIN_ORDER) as usize] =
+            [PhysAddr::new(0); (MAX_ORDER - MIN_ORDER) as usize];
+
+        // Buddy初始占用的空间从bump分配
+        for f in free_area.iter_mut() {
+            let curr_page = bump_allocator.allocate_one();
+            // 保存每个阶的空闲链表的头部地址
+            *f = curr_page.unwrap();
+            // 清空当前页
+            core::ptr::write_bytes(MMArch::phys_2_virt(*f)?.data() as *mut u8, 0, A::PAGE_SIZE);
+
+            let page_list: PageList<A> = PageList::new(0, PhysAddr::new(0));
+            Self::write_page(*f, page_list);
+        }
+
+        // 分配最高阶的链表页
+        for _ in 1..max_order_linked_list_page_num {
+            let curr_page = bump_allocator.allocate_one().unwrap();
+            // 清空当前页
+            core::ptr::write_bytes(
+                MMArch::phys_2_virt(curr_page)?.data() as *mut u8,
+                0,
+                A::PAGE_SIZE,
+            );
+
+            let page_list: PageList<A> =
+                PageList::new(0, free_area[Self::order2index((MAX_ORDER - 1) as u8)]);
+            Self::write_page(curr_page, page_list);
+            free_area[Self::order2index((MAX_ORDER - 1) as u8)] = curr_page;
+        }
+
+        let initial_bump_offset = bump_allocator.offset();
+        let pages_to_buddy = bump_allocator.usage().free();
+        kdebug!("pages_to_buddy {:?}", pages_to_buddy);
+        // kdebug!("initial_bump_offset {:#x}", initial_bump_offset);
+        let mut paddr = initial_bump_offset;
+        let mut remain_pages = pages_to_buddy;
+        // 设置entry,这里假设了bump_allocator当前offset之后,所有的area的地址是连续的.
+        // TODO: 这里需要修改,按照area来处理
+        for i in MIN_ORDER..MAX_ORDER {
+            // kdebug!("i {i}, remain pages={}", remain_pages.data());
+            if remain_pages.data() < (1 << (i - MIN_ORDER)) {
+                break;
+            }
+
+            assert!(paddr & ((1 << i) - 1) == 0);
+
+            if likely(i != MAX_ORDER - 1) {
+                // 要填写entry
+                if paddr & (1 << i) != 0 {
+                    let page_list_paddr: PhysAddr = free_area[Self::order2index(i as u8)];
+                    let mut page_list: PageList<A> = Self::read_page(page_list_paddr);
+
+                    A::write(
+                        Self::entry_virt_addr(page_list_paddr, page_list.entry_num),
+                        paddr,
+                    );
+                    page_list.entry_num += 1;
+                    Self::write_page(page_list_paddr, page_list);
+
+                    paddr += 1 << i;
+                    remain_pages -= 1 << (i - MIN_ORDER);
+                };
+            } else {
+                // 往最大的阶数的链表中添加entry(注意要考虑到最大阶数的链表可能有多页)
+                // 断言剩余页面数量是MAX_ORDER-1阶的整数倍
+
+                let mut entries = (remain_pages.data() * A::PAGE_SIZE) >> i;
+                let mut page_list_paddr: PhysAddr = free_area[Self::order2index(i as u8)];
+                let block_size = 1usize << i;
+
+                if entries > Self::BUDDY_ENTRIES {
+                    // 在第一页填写一些entries
+                    let num = entries % Self::BUDDY_ENTRIES;
+                    entries -= num;
+
+                    let mut page_list: PageList<A> = Self::read_page(page_list_paddr);
+                    for _j in 0..num {
+                        A::write(
+                            Self::entry_virt_addr(page_list_paddr, page_list.entry_num),
+                            paddr,
+                        );
+                        page_list.entry_num += 1;
+                        paddr += block_size;
+                        remain_pages -= 1 << (i - MIN_ORDER);
+                    }
+                    page_list_paddr = page_list.next_page;
+                    Self::write_page(page_list_paddr, page_list);
+                    assert!(!page_list_paddr.is_null());
+                }
+
+                while entries > 0 {
+                    let mut page_list: PageList<A> = Self::read_page(page_list_paddr);
+
+                    for _ in 0..Self::BUDDY_ENTRIES {
+                        A::write(
+                            Self::entry_virt_addr(page_list_paddr, page_list.entry_num),
+                            paddr,
+                        );
+                        page_list.entry_num += 1;
+                        paddr += block_size;
+                        remain_pages -= 1 << (i - MIN_ORDER);
+                        entries -= 1;
+                        if entries == 0 {
+                            break;
+                        }
+                    }
+                    page_list_paddr = page_list.next_page;
+                    Self::write_page(page_list_paddr, page_list);
+
+                    if likely(entries > 0) {
+                        assert!(!page_list_paddr.is_null());
+                    }
+                }
+            }
+        }
+
+        let mut remain_bytes = remain_pages.data() * A::PAGE_SIZE;
+
+        assert!(remain_bytes < (1 << MAX_ORDER - 1));
+
+        for i in (MIN_ORDER..MAX_ORDER).rev() {
+            if remain_bytes & (1 << i) != 0 {
+                let page_list_paddr: PhysAddr = free_area[Self::order2index(i as u8)];
+                let mut page_list: PageList<A> = Self::read_page(page_list_paddr);
+
+                A::write(
+                    Self::entry_virt_addr(page_list_paddr, page_list.entry_num),
+                    paddr,
+                );
+                page_list.entry_num += 1;
+                Self::write_page(page_list_paddr, page_list);
+
+                paddr += 1 << i;
+                remain_bytes -= 1 << i;
+            }
+        }
+
+        assert!(remain_bytes == 0);
+        assert!(paddr == initial_bump_offset + pages_to_buddy.data() * A::PAGE_SIZE);
+
+        // Self::print_free_area(free_area);
+        let allocator = Self {
+            free_area,
+            phantom: PhantomData,
+        };
+
+        Some(allocator)
+    }
+    /// 获取第j个entry的虚拟地址,
+    /// j从0开始计数
+    pub fn entry_virt_addr(base_addr: PhysAddr, j: usize) -> VirtAddr {
+        let entry_virt_addr = unsafe { A::phys_2_virt(Self::entry_addr(base_addr, j)) };
+        return entry_virt_addr.unwrap();
+    }
+    pub fn entry_addr(base_addr: PhysAddr, j: usize) -> PhysAddr {
+        let entry_addr = base_addr + mem::size_of::<PageList<A>>() + j * mem::size_of::<PhysAddr>();
+        return entry_addr;
+    }
+    pub fn read_page<T>(addr: PhysAddr) -> T {
+        let page_list = unsafe { A::read(A::phys_2_virt(addr).unwrap()) };
+        return page_list;
+    }
+
+    pub fn write_page(curr_page: PhysAddr, page_list: PageList<A>) {
+        // 把物理地址转换为虚拟地址
+        let virt_addr = unsafe { A::phys_2_virt(curr_page) };
+        let virt_addr = virt_addr.unwrap();
+        unsafe { A::write(virt_addr, page_list) };
+    }
+
+    /// 从order转换为free_area的下标
+    ///
+    /// # 参数
+    ///
+    /// - `order` - order
+    ///
+    /// # 返回值
+    ///
+    /// free_area的下标
+    #[inline]
+    fn order2index(order: u8) -> usize {
+        (order as usize - MIN_ORDER) as usize
+    }
+
+    /// 从空闲链表的开头,取出1个指定阶数的伙伴块,如果没有,则返回None
+    ///
+    /// ## 参数
+    ///
+    /// - `order` - 伙伴块的阶数
+    fn pop_front(&mut self, order: u8) -> Option<PhysAddr> {
+        let mut alloc_in_specific_order = |spec_order: u8| {
+            // 先尝试在order阶的“空闲链表”的开头位置分配一个伙伴块
+            let mut page_list_addr = self.free_area[Self::order2index(spec_order)];
+            let mut page_list: PageList<A> = Self::read_page(page_list_addr);
+
+            // kdebug!("page_list={page_list:?}");
+
+            // 循环删除头部的空闲链表页
+            while page_list.entry_num == 0 {
+                let next_page_list_addr = page_list.next_page;
+                // 找完了,都是空的
+                if next_page_list_addr.is_null() {
+                    return None;
+                }
+
+                if !next_page_list_addr.is_null() {
+                    // 此时page_list已经没有空闲伙伴块了,又因为非唯一页,需要删除该page_list
+                    self.free_area[Self::order2index(spec_order)] = next_page_list_addr;
+                    drop(page_list);
+                    // kdebug!("FREE: page_list_addr={:b}", page_list_addr.data());
+                    unsafe {
+                        self.buddy_free(page_list_addr, MMArch::PAGE_SHIFT as u8);
+                    }
+                }
+                // 由于buddy_free可能导致首部的链表页发生变化,因此需要重新读取
+                let next_page_list_addr = self.free_area[Self::order2index(spec_order)];
+                assert!(!next_page_list_addr.is_null());
+                page_list = Self::read_page(next_page_list_addr);
+                page_list_addr = next_page_list_addr;
+            }
+
+            // 有空闲页面,直接分配
+            if page_list.entry_num > 0 {
+                let entry: PhysAddr = unsafe {
+                    A::read(Self::entry_virt_addr(
+                        page_list_addr,
+                        page_list.entry_num - 1,
+                    ))
+                };
+                if entry.is_null() {
+                    kerror!(
+                        "entry is null, entry={:?}, order={}, entry_num = {}",
+                        entry,
+                        spec_order,
+                        page_list.entry_num - 1
+                    );
+                }
+                // kdebug!("entry={entry:?}");
+                // 更新page_list的entry_num
+                page_list.entry_num -= 1;
+                let tmp_current_entry_num = page_list.entry_num;
+                if page_list.entry_num == 0 {
+                    if !page_list.next_page.is_null() {
+                        // 此时page_list已经没有空闲伙伴块了,又因为非唯一页,需要删除该page_list
+                        self.free_area[Self::order2index(spec_order)] = page_list.next_page;
+                        drop(page_list);
+                        unsafe { self.buddy_free(page_list_addr, MMArch::PAGE_SHIFT as u8) };
+                    } else {
+                        Self::write_page(page_list_addr, page_list);
+                    }
+                } else {
+                    // 若entry_num不为0,说明该page_list还有空闲伙伴块,需要更新该page_list
+                    // 把更新后的page_list写回
+                    Self::write_page(page_list_addr, page_list.clone());
+                }
+
+                // 检测entry 是否对齐
+                if !entry.check_aligned(1 << spec_order) {
+                    panic!("entry={:?} is not aligned, spec_order={spec_order}, page_list.entry_num={}", entry,tmp_current_entry_num);
+                }
+                return Some(entry);
+            }
+            return None;
+        };
+
+        let result: Option<PhysAddr> = alloc_in_specific_order(order as u8);
+        // kdebug!("result={:?}", result);
+        if result.is_some() {
+            return result;
+        }
+        // 尝试从更大的链表中分裂
+
+        let mut current_order = (order + 1) as usize;
+        let mut x: Option<PhysAddr> = None;
+        while current_order < MAX_ORDER {
+            x = alloc_in_specific_order(current_order as u8);
+            // kdebug!("current_order={:?}", current_order);
+            if x.is_some() {
+                break;
+            }
+            current_order += 1;
+        }
+
+        // kdebug!("x={:?}", x);
+        // 如果找到一个大的块,就进行分裂
+        if x.is_some() {
+            // 分裂到order阶
+            while current_order > order as usize {
+                current_order -= 1;
+                // 把后面那半块放回空闲链表
+
+                let buddy = *x.as_ref().unwrap() + (1 << current_order);
+                // kdebug!("x={:?}, buddy={:?}", x, buddy);
+                // kdebug!("current_order={:?}, buddy={:?}", current_order, buddy);
+                unsafe { self.buddy_free(buddy, current_order as u8) };
+            }
+            return x;
+        }
+
+        return None;
+    }
+
+    /// 从伙伴系统中分配count个页面
+    ///
+    /// ## 参数
+    ///
+    /// - `count`:需要分配的页面数
+    ///
+    /// ## 返回值
+    ///
+    /// 返回分配的页面的物理地址和页面数
+    fn buddy_alloc(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
+        assert!(count.data().is_power_of_two());
+        // 计算需要分配的阶数
+        let mut order = log2(count.data() as usize);
+        if count.data() & ((1 << order) - 1) != 0 {
+            order += 1;
+        }
+        let order = (order + MIN_ORDER) as u8;
+        if order as usize >= MAX_ORDER {
+            return None;
+        }
+
+        // kdebug!("buddy_alloc: order = {}", order);
+        // 获取该阶数的一个空闲页面
+        let free_addr = self.pop_front(order);
+        // kdebug!(
+        //     "buddy_alloc: order = {}, free_addr = {:?}",
+        //     order,
+        //     free_addr
+        // );
+        return free_addr
+            .map(|addr| (addr, PageFrameCount::new(1 << (order as usize - MIN_ORDER))));
+    }
+
+    /// 释放一个块
+    ///
+    /// ## 参数
+    ///
+    /// - `base` - 块的起始地址
+    /// - `order` - 块的阶数
+    unsafe fn buddy_free(&mut self, mut base: PhysAddr, order: u8) {
+        // kdebug!("buddy_free: base = {:?}, order = {}", base, order);
+        let mut order = order as usize;
+
+        while order < MAX_ORDER {
+            // 检测地址是否合法
+            if base.data() & ((1 << (order)) - 1) != 0 {
+                panic!(
+                    "buddy_free: base is not aligned, base = {:#x}, order = {}",
+                    base.data(),
+                    order
+                );
+            }
+
+            // 在链表中寻找伙伴块
+            // 伙伴块的地址是base ^ (1 << order)
+            let buddy_addr = PhysAddr::new(base.data() ^ (1 << order));
+
+            let first_page_list_paddr = self.free_area[Self::order2index(order as u8)];
+            let mut page_list_paddr = first_page_list_paddr;
+            let mut page_list: PageList<A> = Self::read_page(page_list_paddr);
+            let first_page_list = page_list.clone();
+
+            let mut buddy_entry_virt_vaddr = None;
+            let mut buddy_entry_page_list_paddr = None;
+            // 除非order是最大的,否则尝试查找伙伴块
+            if likely(order != MAX_ORDER - 1) {
+                'outer: loop {
+                    for i in 0..page_list.entry_num {
+                        let entry_virt_addr = Self::entry_virt_addr(page_list_paddr, i);
+                        let entry: PhysAddr = unsafe { A::read(entry_virt_addr) };
+                        if entry == buddy_addr {
+                            // 找到了伙伴块,记录该entry相关信息,然后退出查找
+                            buddy_entry_virt_vaddr = Some(entry_virt_addr);
+                            buddy_entry_page_list_paddr = Some(page_list_paddr);
+                            break 'outer;
+                        }
+                    }
+                    if page_list.next_page.is_null() {
+                        break;
+                    }
+                    page_list_paddr = page_list.next_page;
+                    page_list = Self::read_page(page_list_paddr);
+                }
+            }
+
+            // 如果没有找到伙伴块
+            if buddy_entry_virt_vaddr.is_none() {
+                assert!(
+                    page_list.entry_num <= Self::BUDDY_ENTRIES,
+                    "buddy_free: page_list.entry_num > Self::BUDDY_ENTRIES"
+                );
+
+                // 当前第一个page_list没有空间了
+                if first_page_list.entry_num == Self::BUDDY_ENTRIES {
+                    // 如果当前order是最小的,那么就把这个块当作新的page_list使用
+                    let new_page_list_addr = if order == MIN_ORDER {
+                        base
+                    } else {
+                        // 否则分配新的page_list
+                        // 请注意,分配之后,有可能当前的entry_num会减1(伙伴块分裂),造成出现整个链表为null的entry数量为Self::BUDDY_ENTRIES+1的情况
+                        // 但是不影响,我们在后面插入链表项的时候,会处理这种情况,检查链表中的第2个页是否有空位
+                        self.buddy_alloc(PageFrameCount::new(1))
+                            .expect("buddy_alloc failed: no enough memory")
+                            .0
+                    };
+
+                    // 清空这个页面
+                    core::ptr::write_bytes(
+                        A::phys_2_virt(new_page_list_addr)
+                            .expect(
+                                "Buddy free: failed to get virt address of [new_page_list_addr]",
+                            )
+                            .as_ptr::<u8>(),
+                        0,
+                        1 << order,
+                    );
+                    assert!(
+                        first_page_list_paddr == self.free_area[Self::order2index(order as u8)]
+                    );
+                    // 初始化新的page_list
+                    let new_page_list = PageList::new(0, first_page_list_paddr);
+                    Self::write_page(new_page_list_addr, new_page_list);
+                    self.free_area[Self::order2index(order as u8)] = new_page_list_addr;
+                }
+
+                // 由于上面可能更新了第一个链表页,因此需要重新获取这个值
+                let first_page_list_paddr = self.free_area[Self::order2index(order as u8)];
+                let first_page_list: PageList<A> = Self::read_page(first_page_list_paddr);
+
+                // 检查第二个page_list是否有空位
+                let second_page_list = if first_page_list.next_page.is_null() {
+                    None
+                } else {
+                    Some(Self::read_page::<PageList<A>>(first_page_list.next_page))
+                };
+
+                let (paddr, mut page_list) = if let Some(second) = second_page_list {
+                    // 第二个page_list有空位
+                    // 应当符合之前的假设:还有1个空位
+                    assert!(second.entry_num == Self::BUDDY_ENTRIES - 1);
+
+                    (first_page_list.next_page, second)
+                } else {
+                    // 在第一个page list中分配
+                    (first_page_list_paddr, first_page_list)
+                };
+
+                // kdebug!("to write entry, page_list_base={paddr:?}, page_list.entry_num={}, value={base:?}", page_list.entry_num);
+                assert!(page_list.entry_num < Self::BUDDY_ENTRIES);
+                // 把要归还的块,写入到链表项中
+                unsafe { A::write(Self::entry_virt_addr(paddr, page_list.entry_num), base) }
+                page_list.entry_num += 1;
+                Self::write_page(paddr, page_list);
+                return;
+            } else {
+                // 如果找到了伙伴块,合并,向上递归
+
+                // 伙伴块所在的表项的虚拟地址
+                let buddy_entry_virt_addr = buddy_entry_virt_vaddr.unwrap();
+                // 伙伴块所在的page_list的物理地址
+                let buddy_entry_page_list_paddr = buddy_entry_page_list_paddr.unwrap();
+
+                let mut page_list_paddr = self.free_area[Self::order2index(order as u8)];
+                let mut page_list = Self::read_page::<PageList<A>>(page_list_paddr);
+                // 找第一个有空闲块的链表页。跳过空闲链表页。不进行回收的原因是担心出现死循环
+                while page_list.entry_num == 0 {
+                    if page_list.next_page.is_null() {
+                        panic!(
+                            "buddy_free: page_list.entry_num == 0 && page_list.next_page.is_null()"
+                        );
+                    }
+                    page_list_paddr = page_list.next_page;
+                    page_list = Self::read_page(page_list_paddr);
+                }
+
+                // 如果伙伴块不在第一个链表页,则把第一个链表中的某个空闲块替换到伙伴块的位置
+                if page_list_paddr != buddy_entry_page_list_paddr {
+                    let entry: PhysAddr = unsafe {
+                        A::read(Self::entry_virt_addr(
+                            page_list_paddr,
+                            page_list.entry_num - 1,
+                        ))
+                    };
+                    // 把这个空闲块写入到伙伴块的位置
+                    unsafe {
+                        A::write(buddy_entry_virt_addr, entry);
+                    }
+                    // 设置刚才那个entry为空
+                    unsafe {
+                        A::write(
+                            Self::entry_virt_addr(page_list_paddr, page_list.entry_num - 1),
+                            PhysAddr::new(0),
+                        );
+                    }
+                    // 更新当前链表页的统计数据
+                    page_list.entry_num -= 1;
+                    Self::write_page(page_list_paddr, page_list);
+                } else {
+                    // 伙伴块所在的链表页就是第一个链表页
+                    let last_entry: PhysAddr = unsafe {
+                        A::read(Self::entry_virt_addr(
+                            page_list_paddr,
+                            page_list.entry_num - 1,
+                        ))
+                    };
+
+                    // 如果最后一个空闲块不是伙伴块,则把最后一个空闲块移动到伙伴块的位置
+                    // 否则后面的操作也将删除这个伙伴块
+                    if last_entry != buddy_addr {
+                        unsafe {
+                            A::write(buddy_entry_virt_addr, last_entry);
+                            A::write(
+                                Self::entry_virt_addr(page_list_paddr, page_list.entry_num - 1),
+                                PhysAddr::new(0),
+                            );
+                        }
+                    } else {
+                        unsafe {
+                            A::write(
+                                Self::entry_virt_addr(page_list_paddr, page_list.entry_num - 1),
+                                PhysAddr::new(0),
+                            );
+                        }
+                    }
+                    // 更新当前链表页的统计数据
+                    page_list.entry_num -= 1;
+                    Self::write_page(page_list_paddr, page_list);
+                }
+            }
+            base = min(base, buddy_addr);
+            order += 1;
+        }
+        // 走到这一步,order应该为MAX_ORDER-1
+        assert!(order == MAX_ORDER - 1);
+    }
+}
+
+impl<A: MemoryManagementArch> FrameAllocator for BuddyAllocator<A> {
+    unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
+        return self.buddy_alloc(count);
+    }
+
+    /// 释放一个块
+    ///
+    /// ## 参数
+    ///
+    /// - `base` - 块的起始地址
+    /// - `count` - 块的页数(必须是2的幂)
+    ///
+    /// ## Panic
+    ///
+    /// 如果count不是2的幂,会panic
+    unsafe fn free(&mut self, base: PhysAddr, count: PageFrameCount) {
+        // 要求count是2的幂
+        if unlikely(!count.data().is_power_of_two()) {
+            kwarn!("buddy free: count is not power of two");
+        }
+        let mut order = log2(count.data() as usize);
+        if count.data() & ((1 << order) - 1) != 0 {
+            order += 1;
+        }
+        let order = (order + MIN_ORDER) as u8;
+        // kdebug!("free: base={:?}, count={:?}", base, count);
+        self.buddy_free(base, order);
+    }
+
+    unsafe fn usage(&self) -> PageFrameUsage {
+        todo!("BuddyAllocator::usage")
+    }
+}
+
+/// 一个用于计算整数的对数的函数,会向下取整。(由于内核不能进行浮点运算,因此需要这个函数)
+fn log2(x: usize) -> usize {
+    let leading_zeros = x.leading_zeros() as usize;
+    let log2x = 63 - leading_zeros;
+    return log2x;
+}

+ 112 - 0
kernel/src/mm/allocator/bump.rs

@@ -0,0 +1,112 @@
+/// @Auther: Kong
+/// @Date: 2023-03-27 06:54:08
+/// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
+/// @Description: bump allocator线性分配器
+use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
+use crate::mm::{MemoryManagementArch, PhysAddr, PhysMemoryArea};
+use core::marker::PhantomData;
+
+/// 线性分配器
+pub struct BumpAllocator<MMA> {
+    // 表示可用物理内存区域的数组。每个 PhysMemoryArea 结构体描述一个物理内存区域的起始地址和大小。
+    areas: &'static [PhysMemoryArea],
+    // 表示当前分配的物理内存的偏移量.
+    offset: usize,
+    // 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。
+    phantom: PhantomData<MMA>,
+}
+
+/// 为BumpAllocator实现FrameAllocator
+impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
+    /// @brief: 创建一个线性分配器
+    /// @param Fareas 当前的内存区域
+    /// @param offset 当前的偏移量
+    /// @return 分配器本身
+    pub fn new(areas: &'static [PhysMemoryArea], offset: usize) -> Self {
+        Self {
+            areas,
+            offset,
+            phantom: PhantomData,
+        }
+    }
+    // @brief 获取页帧使用情况
+    pub fn areas(&self) -> &'static [PhysMemoryArea] {
+        return self.areas;
+    }
+    // @brief 获取当前分配的物理内存的偏移量
+    pub fn offset(&self) -> usize {
+        return self.offset;
+    }
+}
+
+impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
+    /// @brief: 分配count个物理页帧
+    /// @param  mut self
+    /// @param  count 分配的页帧数量
+    /// @return 分配后的物理地址
+    unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
+        let mut offset = self.offset();
+        // 遍历所有的物理内存区域
+        for area in self.areas().iter() {
+            // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
+            // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
+            let area_base = (area.base.data() + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
+            // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
+            // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
+            let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SIZE - 1);
+
+            // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
+            if offset >= area_end {
+                continue;
+            }
+
+            // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
+            if offset < area_base {
+                offset = area_base;
+            } else if offset < area_end {
+                // 将offset对齐到PAGE_SIZE
+                offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
+            }
+            // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧
+            if offset + count.data() * MMA::PAGE_SIZE <= area_end {
+                let res_page_phys = offset;
+                // 将offset增加至分配后的内存
+                self.offset = offset + count.data() * MMA::PAGE_SIZE;
+
+                return Some((PhysAddr(res_page_phys), count));
+            }
+        }
+        return None;
+    }
+
+    unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) {
+        // TODO: 支持释放页帧
+        unimplemented!("BumpAllocator::free not implemented");
+    }
+    /// @brief: 获取内存区域页帧的使用情况
+    /// @param  self
+    /// @return 页帧的使用情况
+    unsafe fn usage(&self) -> PageFrameUsage {
+        let mut total = 0;
+        let mut used = 0;
+        for area in self.areas().iter() {
+            // 将area的base地址与PAGE_SIZE对齐,对其时向上取整
+            let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
+            // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整
+            let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
+
+            total += (area_end - area_base) >> MMA::PAGE_SHIFT;
+            // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中
+            if self.offset >= area_end {
+                used += (area_end - area_base) >> MMA::PAGE_SHIFT;
+            } else if self.offset < area_base {
+                // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中
+                continue;
+            } else {
+                used += (self.offset - area_base) >> MMA::PAGE_SHIFT;
+            }
+        }
+        let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total));
+        return frame;
+    }
+}

+ 101 - 0
kernel/src/mm/allocator/kernel_allocator.rs

@@ -0,0 +1,101 @@
+use crate::{
+    arch::mm::LockedFrameAllocator,
+    libs::align::page_align_up,
+    mm::{MMArch, MemoryManagementArch, VirtAddr},
+};
+
+use core::{
+    alloc::{AllocError, GlobalAlloc, Layout},
+    intrinsics::unlikely,
+    ptr::NonNull,
+};
+
+use super::page_frame::{FrameAllocator, PageFrameCount};
+
+/// 类kmalloc的分配器应当实现的trait
+pub trait LocalAlloc {
+    unsafe fn local_alloc(&self, layout: Layout) -> *mut u8;
+    unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8;
+    unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout);
+}
+
+pub struct KernelAllocator;
+
+impl KernelAllocator {
+    unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+        // 计算需要申请的页数,向上取整
+        let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
+        let page_frame_count = PageFrameCount::new(count);
+        let (phy_addr, allocated_frame_count) = LockedFrameAllocator
+            .allocate(page_frame_count)
+            .ok_or(AllocError)?;
+
+        let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? };
+        if unlikely(virt_addr.is_null()) {
+            return Err(AllocError);
+        }
+
+        let slice = unsafe {
+            core::slice::from_raw_parts_mut(
+                virt_addr.data() as *mut u8,
+                allocated_frame_count.data() * MMArch::PAGE_SIZE,
+            )
+        };
+        return Ok(NonNull::from(slice));
+    }
+
+    unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) {
+        // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。
+        let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
+        let page_frame_count = PageFrameCount::new(count);
+        let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap();
+        LockedFrameAllocator.free(phy_addr, page_frame_count);
+    }
+}
+
+/// 为内核SLAB分配器实现LocalAlloc的trait
+impl LocalAlloc for KernelAllocator {
+    unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
+        return self
+            .alloc_in_buddy(layout)
+            .map(|x| x.as_mut_ptr() as *mut u8)
+            .unwrap_or(core::ptr::null_mut() as *mut u8);
+    }
+
+    unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        return self
+            .alloc_in_buddy(layout)
+            .map(|x| {
+                let ptr: *mut u8 = x.as_mut_ptr();
+                core::ptr::write_bytes(ptr, 0, x.len());
+                ptr
+            })
+            .unwrap_or(core::ptr::null_mut() as *mut u8);
+    }
+
+    unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) {
+        self.free_in_buddy(ptr, layout);
+    }
+}
+
+/// 为内核slab分配器实现GlobalAlloc特性
+unsafe impl GlobalAlloc for KernelAllocator {
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        return self.local_alloc(layout);
+        // self.local_alloc_zeroed(layout, 0)
+    }
+
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        self.local_alloc_zeroed(layout)
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        self.local_dealloc(ptr, layout);
+    }
+}
+
+/// 内存分配错误处理函数
+#[alloc_error_handler]
+pub fn global_alloc_err_handler(layout: Layout) -> ! {
+    panic!("global_alloc_error, layout: {:?}", layout);
+}

+ 5 - 0
kernel/src/mm/allocator/mod.rs

@@ -0,0 +1,5 @@
+pub mod buddy;
+pub mod bump;
+pub mod kernel_allocator;
+pub mod page_frame;
+pub mod slab;

+ 338 - 0
kernel/src/mm/allocator/page_frame.rs

@@ -0,0 +1,338 @@
+use core::{
+    intrinsics::unlikely,
+    ops::{Add, AddAssign, Mul, Sub, SubAssign},
+};
+
+use crate::{
+    arch::{mm::LockedFrameAllocator, MMArch},
+    mm::{MemoryManagementArch, PhysAddr, VirtAddr},
+};
+
+/// @brief 物理页帧的表示
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub struct PhysPageFrame {
+    /// 物理页页号
+    number: usize,
+}
+
+#[allow(dead_code)]
+impl PhysPageFrame {
+    pub fn new(paddr: PhysAddr) -> Self {
+        return Self {
+            number: paddr.data() / MMArch::PAGE_SIZE,
+        };
+    }
+
+    /// @brief 获取当前页对应的物理地址
+    pub fn phys_address(&self) -> PhysAddr {
+        return PhysAddr::new(self.number * MMArch::PAGE_SIZE);
+    }
+
+    pub fn next_by(&self, n: usize) -> Self {
+        return Self {
+            number: self.number + n,
+        };
+    }
+
+    pub fn next(&self) -> Self {
+        return self.next_by(1);
+    }
+
+    /// 构造物理页帧的迭代器,范围为[start, end)
+    pub fn iter_range(start: Self, end: Self) -> PhysPageFrameIter {
+        return PhysPageFrameIter::new(start, end);
+    }
+}
+
+/// @brief 物理页帧的迭代器
+#[derive(Debug)]
+pub struct PhysPageFrameIter {
+    current: PhysPageFrame,
+    /// 结束的物理页帧(不包含)
+    end: PhysPageFrame,
+}
+
+impl PhysPageFrameIter {
+    pub fn new(start: PhysPageFrame, end: PhysPageFrame) -> Self {
+        return Self {
+            current: start,
+            end,
+        };
+    }
+}
+
+impl Iterator for PhysPageFrameIter {
+    type Item = PhysPageFrame;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if unlikely(self.current == self.end) {
+            return None;
+        }
+        let current = self.current.next();
+        return Some(current);
+    }
+}
+
+/// 虚拟页帧的表示
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub struct VirtPageFrame {
+    /// 虚拟页页号
+    number: usize,
+}
+
+impl VirtPageFrame {
+    pub fn new(vaddr: VirtAddr) -> Self {
+        return Self {
+            number: vaddr.data() / MMArch::PAGE_SIZE,
+        };
+    }
+
+    /// 获取当前虚拟页对应的虚拟地址
+    pub fn virt_address(&self) -> VirtAddr {
+        return VirtAddr::new(self.number * MMArch::PAGE_SIZE);
+    }
+
+    pub fn next_by(&self, n: usize) -> Self {
+        return Self {
+            number: self.number + n,
+        };
+    }
+
+    pub fn next(&self) -> Self {
+        return self.next_by(1);
+    }
+
+    /// 构造虚拟页帧的迭代器,范围为[start, end)
+    pub fn iter_range(start: Self, end: Self) -> VirtPageFrameIter {
+        return VirtPageFrameIter {
+            current: start,
+            end,
+        };
+    }
+
+    pub fn add(&self, n: PageFrameCount) -> Self {
+        return Self {
+            number: self.number + n.data(),
+        };
+    }
+}
+
+/// 虚拟页帧的迭代器
+#[derive(Debug)]
+pub struct VirtPageFrameIter {
+    current: VirtPageFrame,
+    /// 结束的虚拟页帧(不包含)
+    end: VirtPageFrame,
+}
+
+impl VirtPageFrameIter {
+    /// @brief 构造虚拟页帧的迭代器,范围为[start, end)
+    pub fn new(start: VirtPageFrame, end: VirtPageFrame) -> Self {
+        return Self {
+            current: start,
+            end,
+        };
+    }
+}
+
+impl Iterator for VirtPageFrameIter {
+    type Item = VirtPageFrame;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if unlikely(self.current == self.end) {
+            return None;
+        }
+        let current: VirtPageFrame = self.current;
+        self.current = self.current.next_by(1);
+        return Some(current);
+    }
+}
+
+/// 页帧使用的数量
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+pub struct PageFrameCount(usize);
+
+impl PageFrameCount {
+    // @brief 初始化PageFrameCount
+    pub const fn new(count: usize) -> Self {
+        return Self(count);
+    }
+    // @brief 获取页帧数量
+    pub fn data(&self) -> usize {
+        return self.0;
+    }
+
+    /// 计算这一段页帧占用的字节数
+    pub fn bytes(&self) -> usize {
+        return self.0 * MMArch::PAGE_SIZE;
+    }
+
+    /// 将字节数转换为页帧数量
+    ///
+    /// 如果字节数不是页帧大小的整数倍,则返回None. 否则返回页帧数量
+    pub fn from_bytes(bytes: usize) -> Option<Self> {
+        if bytes & MMArch::PAGE_OFFSET_MASK != 0 {
+            return None;
+        } else {
+            return Some(Self(bytes / MMArch::PAGE_SIZE));
+        }
+    }
+}
+
+impl Add for PageFrameCount {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        return Self(self.0 + rhs.0);
+    }
+}
+
+impl AddAssign for PageFrameCount {
+    fn add_assign(&mut self, rhs: Self) {
+        self.0 += rhs.0;
+    }
+}
+
+impl Sub for PageFrameCount {
+    type Output = Self;
+
+    fn sub(self, rhs: Self) -> Self::Output {
+        return Self(self.0 - rhs.0);
+    }
+}
+
+impl SubAssign for PageFrameCount {
+    fn sub_assign(&mut self, rhs: Self) {
+        self.0 -= rhs.0;
+    }
+}
+
+impl Mul for PageFrameCount {
+    type Output = Self;
+
+    fn mul(self, rhs: Self) -> Self::Output {
+        return Self(self.0 * rhs.0);
+    }
+}
+
+impl Add<usize> for PageFrameCount {
+    type Output = Self;
+
+    fn add(self, rhs: usize) -> Self::Output {
+        return Self(self.0 + rhs);
+    }
+}
+
+impl AddAssign<usize> for PageFrameCount {
+    fn add_assign(&mut self, rhs: usize) {
+        self.0 += rhs;
+    }
+}
+
+impl Sub<usize> for PageFrameCount {
+    type Output = Self;
+
+    fn sub(self, rhs: usize) -> Self::Output {
+        return Self(self.0 - rhs);
+    }
+}
+
+impl SubAssign<usize> for PageFrameCount {
+    fn sub_assign(&mut self, rhs: usize) {
+        self.0 -= rhs;
+    }
+}
+
+impl Mul<usize> for PageFrameCount {
+    type Output = Self;
+
+    fn mul(self, rhs: usize) -> Self::Output {
+        return Self(self.0 * rhs);
+    }
+}
+
+// 页帧使用情况
+#[derive(Debug)]
+pub struct PageFrameUsage {
+    used: PageFrameCount,
+    total: PageFrameCount,
+}
+
+#[allow(dead_code)]
+impl PageFrameUsage {
+    /// @brief:  初始化FrameUsage
+    /// @param PageFrameCount used 已使用的页帧数量
+    /// @param PageFrameCount total 总的页帧数量
+    pub fn new(used: PageFrameCount, total: PageFrameCount) -> Self {
+        return Self { used, total };
+    }
+    // @brief 获取已使用的页帧数量
+    pub fn used(&self) -> PageFrameCount {
+        return self.used;
+    }
+    // @brief 获取空闲的页帧数量
+    pub fn free(&self) -> PageFrameCount {
+        return PageFrameCount(self.total.0 - self.used.0);
+    }
+    // @brief 获取总的页帧数量
+    pub fn total(&self) -> PageFrameCount {
+        return self.total;
+    }
+}
+
+/// 能够分配页帧的分配器需要实现的trait
+pub trait FrameAllocator {
+    // @brief 分配count个页帧
+    unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)>;
+
+    // @brief 通过地址释放count个页帧
+    unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount);
+    // @brief 分配一个页帧
+    unsafe fn allocate_one(&mut self) -> Option<PhysAddr> {
+        return self.allocate(PageFrameCount::new(1)).map(|(addr, _)| addr);
+    }
+    // @brief 通过地址释放一个页帧
+    unsafe fn free_one(&mut self, address: PhysAddr) {
+        return self.free(address, PageFrameCount::new(1));
+    }
+    // @brief 获取页帧使用情况
+    unsafe fn usage(&self) -> PageFrameUsage;
+}
+
+/// @brief 通过一个 &mut T 的引用来对一个实现了 FrameAllocator trait 的类型进行调用,使代码更加灵活
+impl<T: FrameAllocator> FrameAllocator for &mut T {
+    unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
+        return T::allocate(self, count);
+    }
+    unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) {
+        return T::free(self, address, count);
+    }
+    unsafe fn allocate_one(&mut self) -> Option<PhysAddr> {
+        return T::allocate_one(self);
+    }
+    unsafe fn free_one(&mut self, address: PhysAddr) {
+        return T::free_one(self, address);
+    }
+    unsafe fn usage(&self) -> PageFrameUsage {
+        return T::usage(self);
+    }
+}
+
+/// @brief 从全局的页帧分配器中分配连续count个页帧
+///
+/// @param count 请求分配的页帧数量
+pub unsafe fn allocate_page_frames(count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
+    let frame = unsafe { LockedFrameAllocator.allocate(count)? };
+    return Some(frame);
+}
+
+/// @brief 向全局页帧分配器释放连续count个页帧
+///
+/// @param frame 要释放的第一个页帧
+/// @param count 要释放的页帧数量 (必须是2的n次幂)
+pub unsafe fn deallocate_page_frames(frame: PhysPageFrame, count: PageFrameCount) {
+    unsafe {
+        LockedFrameAllocator.free(frame.phys_address(), count);
+    }
+}

+ 123 - 0
kernel/src/mm/allocator/slab.rs

@@ -0,0 +1,123 @@
+//! 当前slab分配器暂时不使用,等待后续完善后合并主线
+#![allow(dead_code)]
+
+use core::alloc::Layout;
+
+// 定义Slab,用来存放空闲块
+pub struct Slab {
+    block_size: usize,
+    free_block_list: FreeBlockList,
+}
+
+impl Slab {
+    /// @brief: 初始化一个slab
+    /// @param {usize} start_addr
+    /// @param {usize} slab_size
+    /// @param {usize} block_size
+    pub unsafe fn new(start_addr: usize, slab_size: usize, block_size: usize) -> Slab {
+        let blocks_num = slab_size / block_size;
+        return Slab {
+            block_size: block_size,
+            free_block_list: FreeBlockList::new(start_addr, block_size, blocks_num),
+        };
+    }
+
+    /// @brief: 获取slab中可用的block数
+    pub fn used_blocks(&self) -> usize {
+        return self.free_block_list.len();
+    }
+
+    /// @brief: 扩大free_block_list
+    /// @param {*} mut
+    /// @param {usize} start_addr
+    /// @param {usize} slab_size
+    pub fn grow(&mut self, start_addr: usize, slab_size: usize) {
+        let num_of_blocks = slab_size / self.block_size;
+        let mut block_list =
+            unsafe { FreeBlockList::new(start_addr, self.block_size, num_of_blocks) };
+        // 将新链表接到原链表的后面
+        while let Some(block) = block_list.pop() {
+            self.free_block_list.push(block);
+        }
+    }
+    /// @brief: 从slab中分配一个block
+    /// @return 分配的内存地址
+    pub fn allocate(&mut self, _layout: Layout) -> Option<*mut u8> {
+        match self.free_block_list.pop() {
+            Some(block) => return Some(block.addr() as *mut u8),
+            None => return None,
+        }
+    }
+    /// @brief: 将block归还给slab
+    pub fn free(&mut self, ptr: *mut u8) {
+        let ptr = ptr as *mut FreeBlock;
+        unsafe {
+            self.free_block_list.push(&mut *ptr);
+        }
+    }
+}
+/// slab中的空闲块
+struct FreeBlockList {
+    len: usize,
+    head: Option<&'static mut FreeBlock>,
+}
+
+impl FreeBlockList {
+    unsafe fn new(start_addr: usize, block_size: usize, num_of_blocks: usize) -> FreeBlockList {
+        let mut new_list = FreeBlockList::new_empty();
+        for i in (0..num_of_blocks).rev() {
+            // 从后往前分配,避免内存碎片
+            let new_block = (start_addr + i * block_size) as *mut FreeBlock;
+            new_list.push(&mut *new_block);
+        }
+        return new_list;
+    }
+
+    fn new_empty() -> FreeBlockList {
+        return FreeBlockList { len: 0, head: None };
+    }
+
+    fn len(&self) -> usize {
+        return self.len;
+    }
+
+    /// @brief: 将空闲块从链表中弹出
+    fn pop(&mut self) -> Option<&'static mut FreeBlock> {
+        // 从链表中弹出一个空闲块
+        let block = self.head.take().map(|node| {
+            self.head = node.next.take();
+            self.len -= 1;
+            node
+        });
+        return block;
+    }
+
+    /// @brief: 将空闲块压入链表
+    fn push(&mut self, free_block: &'static mut FreeBlock) {
+        free_block.next = self.head.take();
+        self.len += 1;
+        self.head = Some(free_block);
+    }
+
+    fn is_empty(&self) -> bool {
+        return self.head.is_none();
+    }
+}
+
+impl Drop for FreeBlockList {
+    fn drop(&mut self) {
+        while let Some(_) = self.pop() {}
+    }
+}
+
+struct FreeBlock {
+    next: Option<&'static mut FreeBlock>,
+}
+
+impl FreeBlock {
+    /// @brief: 获取FreeBlock的地址
+    /// @return {*}
+    fn addr(&self) -> usize {
+        return self as *const _ as usize;
+    }
+}

+ 135 - 0
kernel/src/mm/c_adapter.rs

@@ -0,0 +1,135 @@
+//! 这是暴露给C的接口,用于在C语言中使用Rust的内存分配器。
+
+use core::intrinsics::unlikely;
+
+use alloc::vec::Vec;
+use hashbrown::HashMap;
+
+use crate::{
+    arch::mm::LowAddressRemapping,
+    include::bindings::bindings::{gfp_t, PAGE_U_S},
+    kerror,
+    libs::{align::page_align_up, spinlock::SpinLock},
+    mm::MMArch,
+    syscall::SystemError,
+};
+
+use super::{
+    allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, no_init::pseudo_map_phys,
+    page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
+};
+
+lazy_static! {
+    // 用于记录内核分配给C的空间信息
+    static ref C_ALLOCATION_MAP: SpinLock<HashMap<VirtAddr, (VirtAddr, usize, usize)>> = SpinLock::new(HashMap::new());
+}
+
+/// [EXTERN TO C] Use pseudo mapper to map physical memory to virtual memory.
+#[no_mangle]
+pub unsafe extern "C" fn rs_pseudo_map_phys(vaddr: usize, paddr: usize, size: usize) {
+    let vaddr = VirtAddr::new(vaddr);
+    let paddr = PhysAddr::new(paddr);
+    let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
+    pseudo_map_phys(vaddr, paddr, count);
+}
+
+/// [EXTERN TO C] Use kernel mapper to map physical memory to virtual memory.
+#[no_mangle]
+pub unsafe extern "C" fn rs_map_phys(vaddr: usize, paddr: usize, size: usize, flags: usize) {
+    let mut vaddr = VirtAddr::new(vaddr);
+    let mut paddr = PhysAddr::new(paddr);
+    let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
+    // kdebug!("rs_map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
+
+    let mut page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
+    if flags & PAGE_U_S as usize != 0 {
+        page_flags = page_flags.set_user(true);
+    }
+
+    let mut kernel_mapper = KernelMapper::lock();
+    let mut kernel_mapper = kernel_mapper.as_mut();
+    assert!(kernel_mapper.is_some());
+    for _i in 0..count.data() {
+        let flusher = kernel_mapper
+            .as_mut()
+            .unwrap()
+            .map_phys(vaddr, paddr, page_flags)
+            .unwrap();
+
+        flusher.flush();
+
+        vaddr += MMArch::PAGE_SIZE;
+        paddr += MMArch::PAGE_SIZE;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn kzalloc(size: usize, _gfp: gfp_t) -> usize {
+    // kdebug!("kzalloc: size: {size}");
+    return do_kmalloc(size, true);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn kmalloc(size: usize, _gfp: gfp_t) -> usize {
+    // kdebug!("kmalloc: size: {size}");
+    // 由于C代码不规范,因此都全部清空
+    return do_kmalloc(size, true);
+}
+
+fn do_kmalloc(size: usize, zero: bool) -> usize {
+    let space: Vec<u8> = if zero {
+        vec![0u8; size]
+    } else {
+        let mut v = Vec::with_capacity(size);
+        unsafe {
+            v.set_len(size);
+        }
+        v
+    };
+
+    assert!(space.len() == size);
+    let (ptr, len, cap) = space.into_raw_parts();
+    if !ptr.is_null() {
+        let vaddr = VirtAddr::new(ptr as usize);
+        let len = len as usize;
+        let cap = cap as usize;
+        let mut guard = C_ALLOCATION_MAP.lock();
+        if unlikely(guard.contains_key(&vaddr)) {
+            drop(guard);
+            unsafe {
+                drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
+            }
+            panic!(
+                "do_kmalloc: vaddr {:?} already exists in C Allocation Map, query size: {size}, zero: {zero}",
+                vaddr
+            );
+        }
+        // 插入到C Allocation Map中
+        guard.insert(vaddr, (vaddr, len, cap));
+        return vaddr.data();
+    } else {
+        return SystemError::ENOMEM.to_posix_errno() as i64 as usize;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn kfree(vaddr: usize) -> usize {
+    let vaddr = VirtAddr::new(vaddr);
+    let mut guard = C_ALLOCATION_MAP.lock();
+    let p = guard.remove(&vaddr);
+    drop(guard);
+
+    if p.is_none() {
+        kerror!("kfree: vaddr {:?} not found in C Allocation Map", vaddr);
+        return SystemError::EINVAL.to_posix_errno() as i64 as usize;
+    }
+    let (vaddr, len, cap) = p.unwrap();
+    drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
+    return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_unmap_at_low_addr() -> usize {
+    LowAddressRemapping::unmap_at_low_address(true);
+    return 0;
+}

+ 0 - 79
kernel/src/mm/internal.h

@@ -1,79 +0,0 @@
-#pragma once
-
-#include "mm.h"
-
-
-// 当vma被成功合并后的返回值
-#define __VMA_MERGED 1
-
-/**
- * @brief 将vma结构体插入mm_struct的链表之中
- *
- * @param mm 内存空间分布结构体
- * @param vma 待插入的VMA结构体
- * @param prev 链表的前一个结点
- */
-void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev);
-
-/**
- * @brief 将vma给定结构体从vma链表的结点之中删除
- *
- * @param mm 内存空间分布结构体
- * @param vma 待插入的VMA结构体
- */
-void __vma_unlink_list(struct mm_struct *mm, struct vm_area_struct *vma);
-
-/**
- * @brief 获取指定虚拟地址处映射的物理地址
- *
- * @param mm 内存空间分布结构体
- * @param vaddr 虚拟地址
- * @return uint64_t 已映射的物理地址
- */
-uint64_t __mm_get_paddr(struct mm_struct *mm, uint64_t vaddr);
-
-/**
- * @brief 创建anon_vma,并将其与页面结构体进行绑定
- * 若提供的页面结构体指针为NULL,则只创建,不绑定
- *
- * @param page 页面结构体的指针
- * @param lock_page 是否将页面结构体加锁
- * @return struct anon_vma_t* 创建好的anon_vma
- */
-struct anon_vma_t *__anon_vma_create_alloc(struct Page *page, bool lock_page);
-
-/**
- * @brief 释放anon vma结构体
- *
- * @param anon_vma 待释放的anon_vma结构体
- * @return int 返回码
- */
-int __anon_vma_free(struct anon_vma_t *anon_vma);
-
-/**
- * @brief 将指定的vma加入到anon_vma的管理范围之中
- *
- * @param anon_vma 页面的anon_vma
- * @param vma 待加入的vma
- * @return int 返回码
- */
-int __anon_vma_add(struct anon_vma_t *anon_vma, struct vm_area_struct *vma);
-
-/**
- * @brief 从anon_vma的管理范围中删除指定的vma
- * (在进入这个函数之前,应该要对anon_vma加锁)
- * @param vma 将要取消对应的anon_vma管理的vma结构体
- * @return int 返回码
- */
-int __anon_vma_del(struct vm_area_struct *vma);
-
-/**
- * @brief 创建mmio对应的页结构体
- * 
- * @param paddr 物理地址
- * @return struct Page* 创建成功的page
- */
-struct Page* __create_mmio_page_struct(uint64_t paddr);
-
-// 判断给定的两个值是否跨越了2M边界
-#define CROSS_2M_BOUND(val1, val2) ((val1 & PAGE_2M_MASK) != (val2 & PAGE_2M_MASK))

+ 145 - 0
kernel/src/mm/kernel_mapper.rs

@@ -0,0 +1,145 @@
+use super::{page::PageFlags, PageTableKind, PhysAddr, VirtAddr};
+use crate::{
+    arch::{
+        asm::irqflags::{local_irq_restore, local_irq_save},
+        mm::{LockedFrameAllocator, PageMapper},
+    },
+    libs::align::page_align_up,
+    mm::allocator::page_frame::PageFrameCount,
+    mm::{MMArch, MemoryManagementArch},
+    smp::core::smp_get_processor_id,
+    syscall::SystemError,
+};
+use core::{
+    ops::Deref,
+    sync::atomic::{compiler_fence, AtomicUsize, Ordering},
+};
+
+/// 标志当前没有处理器持有内核映射器的锁
+/// 之所以需要这个标志,是因为AtomicUsize::new(0)会把0当作一个处理器的id
+const KERNEL_MAPPER_NO_PROCESSOR: usize = !0;
+/// 当前持有内核映射器锁的处理器
+static KERNEL_MAPPER_LOCK_OWNER: AtomicUsize = AtomicUsize::new(KERNEL_MAPPER_NO_PROCESSOR);
+/// 内核映射器的锁计数器
+static KERNEL_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+pub struct KernelMapper {
+    /// 内核空间映射器
+    mapper: PageMapper,
+    /// 标记当前映射器是否为只读
+    readonly: bool,
+}
+
+impl KernelMapper {
+    fn lock_cpu(cpuid: usize, mapper: PageMapper) -> Self {
+        loop {
+            match KERNEL_MAPPER_LOCK_OWNER.compare_exchange_weak(
+                KERNEL_MAPPER_NO_PROCESSOR,
+                cpuid,
+                Ordering::Acquire,
+                Ordering::Relaxed,
+            ) {
+                Ok(_) => break,
+                // 当前处理器已经持有了锁
+                Err(id) if id == cpuid => break,
+                // either CAS failed, or some other hardware thread holds the lock
+                Err(_) => core::hint::spin_loop(),
+            }
+        }
+
+        let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_add(1, Ordering::Relaxed);
+        compiler_fence(Ordering::Acquire);
+
+        // 本地核心已经持有过锁,因此标记当前加锁获得的映射器为只读
+        let readonly = prev_count > 0;
+
+        return Self { mapper, readonly };
+    }
+
+    /// @brief 锁定内核映射器, 并返回一个内核映射器对象
+    #[inline(always)]
+    pub fn lock() -> Self {
+        let cpuid = smp_get_processor_id() as usize;
+        let mapper = unsafe { PageMapper::current(PageTableKind::Kernel, LockedFrameAllocator) };
+        return Self::lock_cpu(cpuid, mapper);
+    }
+
+    /// @brief 获取内核映射器的page mapper的可变引用。如果当前映射器为只读,则返回 None
+    #[inline(always)]
+    pub fn as_mut(&mut self) -> Option<&mut PageMapper> {
+        if self.readonly {
+            return None;
+        } else {
+            return Some(&mut self.mapper);
+        }
+    }
+
+    /// @brief 获取内核映射器的page mapper的不可变引用
+    #[inline(always)]
+    pub fn as_ref(&self) -> &PageMapper {
+        return &self.mapper;
+    }
+
+    /// 映射一段物理地址到指定的虚拟地址。
+    ///
+    /// ## 参数
+    ///
+    /// - `vaddr`: 要映射的虚拟地址
+    /// - `paddr`: 要映射的物理地址
+    /// - `size`: 要映射的大小(字节,必须是页大小的整数倍,否则会向上取整)
+    /// - `flags`: 页面标志
+    /// - `flush`: 是否刷新TLB
+    ///
+    /// ## 返回
+    ///
+    /// - 成功:返回Ok(())
+    /// - 失败: 如果当前映射器为只读,则返回EAGAIN_OR_EWOULDBLOCK
+    pub unsafe fn map_phys_with_size(
+        &mut self,
+        mut vaddr: VirtAddr,
+        mut paddr: PhysAddr,
+        size: usize,
+        flags: PageFlags<MMArch>,
+        flush: bool,
+    ) -> Result<(), SystemError> {
+        if self.readonly {
+            return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+        }
+
+        let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
+        // kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
+
+        for _ in 0..count.data() {
+            let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap();
+
+            if flush {
+                flusher.flush();
+            }
+
+            vaddr += MMArch::PAGE_SIZE;
+            paddr += MMArch::PAGE_SIZE;
+        }
+        return Ok(());
+    }
+}
+
+impl Drop for KernelMapper {
+    fn drop(&mut self) {
+        // 为了防止fetch_sub和store之间,由于中断,导致store错误清除了owner,导致错误,因此需要关中断。
+        let flags = local_irq_save();
+        let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_sub(1, Ordering::Relaxed);
+        if prev_count == 1 {
+            KERNEL_MAPPER_LOCK_OWNER.store(KERNEL_MAPPER_NO_PROCESSOR, Ordering::Release);
+        }
+        local_irq_restore(flags);
+        compiler_fence(Ordering::Release);
+    }
+}
+
+impl Deref for KernelMapper {
+    type Target = PageMapper;
+
+    fn deref(&self) -> &Self::Target {
+        return self.as_ref();
+    }
+}

+ 0 - 196
kernel/src/mm/mm-stat.c

@@ -1,196 +0,0 @@
-/**
- * @file mm-stat.c
- * @author longjin([email protected])
- * @brief 查询内存信息
- * @version 0.1
- * @date 2022-08-06
- *
- * @copyright Copyright (c) 2022
- *
- */
-
-#include "mm.h"
-#include "slab.h"
-#include <common/errno.h>
-#include <process/ptrace.h>
-
-extern const struct slab kmalloc_cache_group[16];
-
-static int __empty_2m_pages(int zone);
-static int __count_in_using_2m_pages(int zone);
-static uint64_t __count_kmalloc_free();
-static uint64_t __count_kmalloc_using();
-static uint64_t __count_kmalloc_total();
-uint64_t sys_mm_stat(struct pt_regs *regs);
-
-/**
- * @brief 获取指定zone中的空闲2M页的数量
- *
- * @param zone 内存zone号
- * @return int 空闲2M页数量
- */
-static int __count_empty_2m_pages(int zone)
-{
-    int zone_start = 0, zone_end = 0;
-
-    uint64_t attr = 0;
-    switch (zone)
-    {
-    case ZONE_DMA:
-        // DMA区域
-        zone_start = 0;
-        zone_end = ZONE_DMA_INDEX;
-        attr |= PAGE_PGT_MAPPED;
-        break;
-    case ZONE_NORMAL:
-        zone_start = ZONE_DMA_INDEX;
-        zone_end = ZONE_NORMAL_INDEX;
-        attr |= PAGE_PGT_MAPPED;
-        break;
-    case ZONE_UNMAPPED_IN_PGT:
-        zone_start = ZONE_NORMAL_INDEX;
-        zone_end = ZONE_UNMAPPED_INDEX;
-        attr = 0;
-        break;
-    default:
-        kerror("In __count_empty_2m_pages: param: zone invalid.");
-        // 返回错误码
-        return -EINVAL;
-        break;
-    }
-
-    uint64_t result = 0;
-    for (int i = zone_start; i <= zone_end; ++i)
-    {
-        result += (memory_management_struct.zones_struct + i)->count_pages_free;
-    }
-    return result;
-}
-
-/**
- * @brief 获取指定zone中的正在使用的2M页的数量
- *
- * @param zone 内存zone号
- * @return int 空闲2M页数量
- */
-static int __count_in_using_2m_pages(int zone)
-{
-    int zone_start = 0, zone_end = 0;
-
-    uint64_t attr = 0;
-    switch (zone)
-    {
-    case ZONE_DMA:
-        // DMA区域
-        zone_start = 0;
-        zone_end = ZONE_DMA_INDEX;
-        attr |= PAGE_PGT_MAPPED;
-        break;
-    case ZONE_NORMAL:
-        zone_start = ZONE_DMA_INDEX;
-        zone_end = ZONE_NORMAL_INDEX;
-        attr |= PAGE_PGT_MAPPED;
-        break;
-    case ZONE_UNMAPPED_IN_PGT:
-        zone_start = ZONE_NORMAL_INDEX;
-        zone_end = ZONE_UNMAPPED_INDEX;
-        attr = 0;
-        break;
-    default:
-        kerror("In __count_in_using_2m_pages: param: zone invalid.");
-        // 返回错误码
-        return -EINVAL;
-        break;
-    }
-
-    uint64_t result = 0;
-    for (int i = zone_start; i <= zone_end; ++i)
-    {
-        result += (memory_management_struct.zones_struct + i)->count_pages_using;
-    }
-    return result;
-}
-
-/**
- * @brief 计算kmalloc缓冲区中的空闲内存
- *
- * @return uint64_t 空闲内存(字节)
- */
-static uint64_t __count_kmalloc_free()
-{
-    uint64_t result = 0;
-    for (int i = 0; i < sizeof(kmalloc_cache_group) / sizeof(struct slab); ++i)
-    {
-        result += kmalloc_cache_group[i].size * kmalloc_cache_group[i].count_total_free;
-    }
-    return result;
-}
-
-/**
- * @brief 计算kmalloc缓冲区中已使用的内存
- *
- * @return uint64_t 已使用的内存(字节)
- */
-static uint64_t __count_kmalloc_using()
-{
-    uint64_t result = 0;
-    for (int i = 0; i < sizeof(kmalloc_cache_group) / sizeof(struct slab); ++i)
-    {
-        result += kmalloc_cache_group[i].size * kmalloc_cache_group[i].count_total_using;
-    }
-    return result;
-}
-
-/**
- * @brief 计算kmalloc缓冲区中总共占用的内存
- *
- * @return uint64_t 缓冲区占用的内存(字节)
- */
-static uint64_t __count_kmalloc_total()
-{
-    uint64_t result = 0;
-    for (int i = 0; i < sizeof(kmalloc_cache_group) / sizeof(struct slab); ++i)
-    {
-        result += kmalloc_cache_group[i].size *
-                  (kmalloc_cache_group[i].count_total_free + kmalloc_cache_group[i].count_total_using);
-    }
-    return result;
-}
-
-/**
- * @brief 获取系统当前的内存信息(未上锁,不一定精准)
- *
- * @return struct mm_stat_t 内存信息结构体
- */
-struct mm_stat_t mm_stat()
-{
-    struct mm_stat_t tmp = {0};
-    // 统计物理页的信息
-    tmp.used = __count_in_using_2m_pages(ZONE_NORMAL) * PAGE_2M_SIZE;
-    tmp.free = __count_empty_2m_pages(ZONE_NORMAL) * PAGE_2M_SIZE;
-    tmp.total = tmp.used + tmp.free;
-    tmp.shared = 0;
-    // 统计kmalloc slab中的信息
-    tmp.cache_free = __count_kmalloc_free();
-    tmp.cache_used = __count_kmalloc_using();
-    tmp.available = tmp.free + tmp.cache_free;
-    return tmp;
-}
-
-/**
- * @brief 获取内存信息的系统调用
- *
- * @param r8 返回的内存信息结构体的地址
- * @return uint64_t
- */
-uint64_t sys_do_mstat(struct mm_stat_t *dst, bool from_user)
-{
-    if (dst == NULL)
-        return -EFAULT;
-    struct mm_stat_t stat = mm_stat();
-    if (from_user)
-        copy_to_user((void *)dst, &stat, sizeof(struct mm_stat_t));
-    else
-        memcpy((void *)dst, &stat, sizeof(struct mm_stat_t));
-    return 0;
-}

+ 0 - 175
kernel/src/mm/mm-types.h

@@ -4,179 +4,4 @@
 #include <common/spinlock.h>
 #include <common/atomic.h>
 
-struct mm_struct;
-struct anon_vma_t;
 typedef uint64_t vm_flags_t;
-
-/**
- * @brief 内存页表结构体
- *
- */
-typedef struct
-{
-    unsigned long pml4t;
-} pml4t_t;
-
-typedef struct
-{
-    unsigned long pdpt;
-} pdpt_t;
-
-typedef struct
-{
-    unsigned long pdt;
-} pdt_t;
-
-typedef struct
-{
-    unsigned long pt;
-} pt_t;
-
-// Address Range Descriptor Structure 地址范围描述符
-struct ARDS
-{
-    ul BaseAddr;           // 基地址
-    ul Length;             // 内存长度   以字节为单位
-    unsigned int type;     // 本段内存的类型
-                           // type=1 表示可以被操作系统使用
-                           // type=2 ARR - 内存使用中或被保留,操作系统不能使用
-                           // 其他 未定义,操作系统需要将其视为ARR
-} __attribute__((packed)); // 修饰该结构体不会生成对齐空间,改用紧凑格式
-
-struct memory_desc
-{
-
-    struct ARDS e820[32]; // 物理内存段结构数组
-    ul len_e820;          // 物理内存段长度
-
-    ul *bmp;      // 物理空间页映射位图
-    ul bmp_len;   //  bmp的长度
-    ul bits_size; // 物理地址空间页数量
-
-    struct Page *pages_struct;
-    ul count_pages;      // struct page结构体的总数
-    ul pages_struct_len; // pages_struct链表的长度
-
-    struct Zone *zones_struct;
-    ul count_zones;      // zone结构体的数量
-    ul zones_struct_len; // zones_struct列表的长度
-
-    ul kernel_code_start, kernel_code_end; // 内核程序代码段起始地址、结束地址
-    ul kernel_data_end, rodata_end;        // 内核程序数据段结束地址、 内核程序只读段结束地址
-    uint64_t start_brk;                    // 堆地址的起始位置
-
-    ul end_of_struct; // 内存页管理结构的结束地址
-};
-
-struct Zone
-{
-    // 指向内存页的指针
-    struct Page *pages_group;
-    ul count_pages; // 本区域的struct page结构体总数
-
-    // 本内存区域的起始、结束的页对齐地址
-    ul zone_addr_start;
-    ul zone_addr_end;
-    ul zone_length; // 区域长度
-
-    // 本区域空间的属性
-    ul attr;
-
-    struct memory_desc *gmd_struct;
-
-    // 本区域正在使用中和空闲中的物理页面数量
-    ul count_pages_using;
-    ul count_pages_free;
-
-    // 物理页被引用次数
-    ul total_pages_link;
-};
-
-struct Page
-{
-    // 本页所属的内存域结构体
-    struct Zone *zone;
-    // 本页对应的物理地址
-    ul addr_phys;
-    // 页面属性
-    ul attr;
-    // 页面被引用的次数
-    ul ref_counts;
-    // 本页的创建时间
-    ul age;
-    
-    struct anon_vma_t *anon_vma;    // 本页对应的anon_vma
-
-    spinlock_t op_lock; // 页面操作锁
-
-};
-
-/**
- * @brief 虚拟内存区域(VMA)结构体
- *
- */
-struct vm_area_struct
-{
-    struct vm_area_struct *vm_prev, *vm_next;
-
-    // 虚拟内存区域的范围是一个左闭右开的区间:[vm_start, vm_end)
-    uint64_t vm_start;       // 区域的起始地址
-    uint64_t vm_end;         // 区域的结束地址
-    struct mm_struct *vm_mm; // 虚拟内存区域对应的mm结构体
-    vm_flags_t vm_flags;     // 虚拟内存区域的标志位, 具体可选值请见mm.h
-    
-    
-    struct List anon_vma_list;  // anon_vma的链表结点
-    struct anon_vma_t * anon_vma;   // 属于的anon_vma
-
-    struct vm_operations_t *vm_ops; // 操作方法
-    atomic_t ref_count;             // 引用计数
-    pgoff_t page_offset;    // 起始地址在当前VMA所占的2M物理页中的偏移量
-    void *private_data;
-};
-
-/**
- * @brief 内存空间分布结构体
- * 包含了进程内存空间分布的信息
- */
-struct mm_struct
-{
-    pml4t_t *pgd;                // 内存页表指针
-    struct vm_area_struct *vmas; // VMA列表
-    // 代码段空间
-    uint64_t code_addr_start, code_addr_end;
-    // 数据段空间
-    uint64_t data_addr_start, data_addr_end;
-    // 只读数据段空间
-    uint64_t rodata_addr_start, rodata_addr_end;
-    // BSS段的空间
-    uint64_t bss_start, bss_end;
-    // 动态内存分配区(堆区域)
-    uint64_t brk_start, brk_end;
-    // 应用层栈基地址
-    uint64_t stack_start;
-};
-
-/**
- * @brief 匿名vma对象的结构体
- *
- * anon_vma与每个内存页结构体进行一对一绑定
- * anon_vma也连接着一切使用到该内存页的vma,当发生页面换出时,应当更新与该page相关的所有vma在页表中的映射信息。
- */
-struct anon_vma_t
-{
-    // anon vma的操作信号量
-    semaphore_t sem;
-    
-    /**
-     * 记录当前有多少个vma与该anon_vma关联,当vma被释放时,
-     * 应当检查这个值。当该值为0时,应当释放anon_vma结构体
-     */
-    atomic_t ref_count;
-
-    // todo: 把下面的循环链表更换成红黑树
-    // 与当前anon_vma相关的vma的列表
-    struct List vma_list;
-    // 当前anon vma对应的page
-    struct Page* page;
-};

+ 0 - 686
kernel/src/mm/mm.c

@@ -1,686 +0,0 @@
-#include "mm.h"
-#include "mm-types.h"
-#include "mmio.h"
-#include "slab.h"
-#include <common/printk.h>
-#include <common/kprint.h>
-#include <driver/multiboot2/multiboot2.h>
-#include <process/process.h>
-#include <common/compiler.h>
-#include <common/errno.h>
-#include <debug/traceback/traceback.h>
-
-uint64_t mm_Total_Memory = 0;
-uint64_t mm_total_2M_pages = 0;
-struct mm_struct initial_mm = {0};
-
-struct memory_desc memory_management_struct = {{0}, 0};
-
-/**
- * @brief 从页表中获取pdt页表项的内容
- *
- * @param proc_page_table_addr 页表的地址
- * @param is_phys 页表地址是否为物理地址
- * @param virt_addr_start 要清除的虚拟地址的起始地址
- * @param length 要清除的区域的长度
- * @param clear 是否清除标志位
- */
-uint64_t mm_get_PDE(ul proc_page_table_addr, bool is_phys, ul virt_addr, bool clear);
-
-/**
- * @brief 检查页表是否存在不为0的页表项
- *
- * @param ptr 页表基指针
- * @return int8_t 存在 -> 1
- *                不存在 -> 0
- */
-int8_t mm_check_page_table(uint64_t *ptr)
-{
-    for (int i = 0; i < 512; ++i, ++ptr)
-    {
-        if (*ptr != 0)
-            return 1;
-    }
-    return 0;
-}
-
-void mm_init()
-{
-    kinfo("Initializing memory management unit...");
-    // 设置内核程序不同部分的起止地址
-    memory_management_struct.kernel_code_start = (ul)&_text;
-    memory_management_struct.kernel_code_end = (ul)&_etext;
-    memory_management_struct.kernel_data_end = (ul)&_edata;
-    memory_management_struct.rodata_end = (ul)&_erodata;
-    memory_management_struct.start_brk = (ul)&_end;
-
-    struct multiboot_mmap_entry_t mb2_mem_info[512];
-    int count;
-
-    multiboot2_iter(multiboot2_get_memory, mb2_mem_info, &count);
-    io_mfence();
-    for (int i = 0; i < count; ++i)
-    {
-        io_mfence();
-        // 可用的内存
-        if (mb2_mem_info->type == 1)
-            mm_Total_Memory += mb2_mem_info->len;
-
-        // kdebug("[i=%d] mb2_mem_info[i].type=%d, mb2_mem_info[i].addr=%#018lx", i, mb2_mem_info[i].type, mb2_mem_info[i].addr);
-        // 保存信息到mms
-        memory_management_struct.e820[i].BaseAddr = mb2_mem_info[i].addr;
-        memory_management_struct.e820[i].Length = mb2_mem_info[i].len;
-        memory_management_struct.e820[i].type = mb2_mem_info[i].type;
-        memory_management_struct.len_e820 = i;
-
-        // 脏数据
-        if (mb2_mem_info[i].type > 4 || mb2_mem_info[i].len == 0 || mb2_mem_info[i].type < 1)
-            break;
-    }
-    printk("[ INFO ] Total amounts of RAM : %ld bytes\n", mm_Total_Memory);
-
-    // 计算有效内存页数
-    io_mfence();
-    for (int i = 0; i < memory_management_struct.len_e820; ++i)
-    {
-        if (memory_management_struct.e820[i].type != 1)
-            continue;
-        io_mfence();
-        // 将内存段的起始物理地址按照2M进行对齐
-        ul addr_start = PAGE_2M_ALIGN(memory_management_struct.e820[i].BaseAddr);
-        // 将内存段的终止物理地址的低2M区域清空,以实现对齐
-        ul addr_end = ((memory_management_struct.e820[i].BaseAddr + memory_management_struct.e820[i].Length) & PAGE_2M_MASK);
-
-        // 内存段不可用
-        if (addr_end <= addr_start)
-            continue;
-        io_mfence();
-        mm_total_2M_pages += ((addr_end - addr_start) >> PAGE_2M_SHIFT);
-    }
-    kinfo("Total amounts of 2M pages : %ld.", mm_total_2M_pages);
-
-    // 物理地址空间的最大地址(包含了物理内存、内存空洞、ROM等)
-    ul max_addr = memory_management_struct.e820[memory_management_struct.len_e820].BaseAddr + memory_management_struct.e820[memory_management_struct.len_e820].Length;
-    // 初始化mms的bitmap
-    // bmp的指针指向截止位置的4k对齐的上边界(防止修改了别的数据)
-    io_mfence();
-    memory_management_struct.bmp = (unsigned long *)((memory_management_struct.start_brk + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
-    memory_management_struct.bits_size = max_addr >> PAGE_2M_SHIFT;                                                                                         // 物理地址空间的最大页面数
-    memory_management_struct.bmp_len = (((unsigned long)(max_addr >> PAGE_2M_SHIFT) + sizeof(unsigned long) * 8 - 1) / 8) & (~(sizeof(unsigned long) - 1)); // bmp由多少个unsigned long变量组成
-    io_mfence();
-
-    // 初始化bitmap, 先将整个bmp空间全部置位。稍后再将可用物理内存页复位。
-    memset(memory_management_struct.bmp, 0xff, memory_management_struct.bmp_len);
-    io_mfence();
-    // 初始化内存页结构
-    // 将页结构映射于bmp之后
-    memory_management_struct.pages_struct = (struct Page *)(((unsigned long)memory_management_struct.bmp + memory_management_struct.bmp_len + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
-
-    memory_management_struct.count_pages = max_addr >> PAGE_2M_SHIFT;
-    memory_management_struct.pages_struct_len = ((max_addr >> PAGE_2M_SHIFT) * sizeof(struct Page) + sizeof(long) - 1) & (~(sizeof(long) - 1));
-    // 将pages_struct全部清空,以备后续初始化
-    memset(memory_management_struct.pages_struct, 0x00, memory_management_struct.pages_struct_len); // init pages memory
-
-    io_mfence();
-    // 初始化内存区域
-    memory_management_struct.zones_struct = (struct Zone *)(((ul)memory_management_struct.pages_struct + memory_management_struct.pages_struct_len + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
-    io_mfence();
-    // 由于暂时无法计算zone结构体的数量,因此先将其设为0
-    memory_management_struct.count_zones = 0;
-    io_mfence();
-    // zones-struct 成员变量暂时按照5个来计算
-    memory_management_struct.zones_struct_len = (10 * sizeof(struct Zone) + sizeof(ul) - 1) & (~(sizeof(ul) - 1));
-    io_mfence();
-    memset(memory_management_struct.zones_struct, 0x00, memory_management_struct.zones_struct_len);
-
-    // ==== 遍历e820数组,完成成员变量初始化工作 ===
-
-    for (int i = 0; i < memory_management_struct.len_e820; ++i)
-    {
-        io_mfence();
-        if (memory_management_struct.e820[i].type != 1) // 不是操作系统可以使用的物理内存
-            continue;
-        ul addr_start = PAGE_2M_ALIGN(memory_management_struct.e820[i].BaseAddr);
-        ul addr_end = (memory_management_struct.e820[i].BaseAddr + memory_management_struct.e820[i].Length) & PAGE_2M_MASK;
-
-        if (addr_end <= addr_start)
-            continue;
-
-        // zone init
-        struct Zone *z = memory_management_struct.zones_struct + memory_management_struct.count_zones;
-        ++memory_management_struct.count_zones;
-
-        z->zone_addr_start = addr_start;
-        z->zone_addr_end = addr_end;
-        z->zone_length = addr_end - addr_start;
-
-        z->count_pages_using = 0;
-        z->count_pages_free = (addr_end - addr_start) >> PAGE_2M_SHIFT;
-        z->total_pages_link = 0;
-
-        z->attr = 0;
-        z->gmd_struct = &memory_management_struct;
-
-        z->count_pages = (addr_end - addr_start) >> PAGE_2M_SHIFT;
-        z->pages_group = (struct Page *)(memory_management_struct.pages_struct + (addr_start >> PAGE_2M_SHIFT));
-
-        // 初始化页
-        struct Page *p = z->pages_group;
-
-        for (int j = 0; j < z->count_pages; ++j, ++p)
-        {
-            p->zone = z;
-            p->addr_phys = addr_start + PAGE_2M_SIZE * j;
-            p->attr = 0;
-
-            p->ref_counts = 0;
-            p->age = 0;
-
-            // 将bmp中对应的位 复位
-            *(memory_management_struct.bmp + ((p->addr_phys >> PAGE_2M_SHIFT) >> 6)) ^= (1UL << ((p->addr_phys >> PAGE_2M_SHIFT) % 64));
-        }
-    }
-
-    // 初始化0~2MB的物理页
-    // 由于这个区间的内存由多个内存段组成,因此不会被以上代码初始化,需要我们手动配置page[0]。
-    io_mfence();
-    memory_management_struct.pages_struct->zone = memory_management_struct.zones_struct;
-    memory_management_struct.pages_struct->addr_phys = 0UL;
-    set_page_attr(memory_management_struct.pages_struct, PAGE_PGT_MAPPED | PAGE_KERNEL_INIT | PAGE_KERNEL);
-    memory_management_struct.pages_struct->ref_counts = 1;
-    memory_management_struct.pages_struct->age = 0;
-    // 将第0页的标志位给置上
-    //*(memory_management_struct.bmp) |= 1UL;
-
-    // 计算zone结构体的总长度(按照64位对齐)
-    memory_management_struct.zones_struct_len = (memory_management_struct.count_zones * sizeof(struct Zone) + sizeof(ul) - 1) & (~(sizeof(ul) - 1));
-
-    ZONE_DMA_INDEX = 0;
-    ZONE_NORMAL_INDEX = memory_management_struct.count_zones ;
-    ZONE_UNMAPPED_INDEX = 0;
-
-    //kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
-    //  设置内存页管理结构的地址,预留了一段空间,防止内存越界。
-    memory_management_struct.end_of_struct = (ul)((ul)memory_management_struct.zones_struct + memory_management_struct.zones_struct_len + sizeof(long) * 32) & (~(sizeof(long) - 1));
-
-    // 初始化内存管理单元结构所占的物理页的结构体
-    ul mms_max_page = (virt_2_phys(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT); // 内存管理单元所占据的序号最大的物理页
-    // kdebug("mms_max_page=%ld", mms_max_page);
-
-    struct Page *tmp_page = NULL;
-    ul page_num;
-    // 第0个page已经在上方配置
-    for (ul j = 1; j <= mms_max_page; ++j)
-    {
-        barrier();
-        tmp_page = memory_management_struct.pages_struct + j;
-        page_init(tmp_page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
-        barrier();
-        page_num = tmp_page->addr_phys >> PAGE_2M_SHIFT;
-        *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
-        ++tmp_page->zone->count_pages_using;
-        --tmp_page->zone->count_pages_free;
-    }
-
-    kinfo("Memory management unit initialize complete!");
-
-    flush_tlb();
-    // todo: 在这里增加代码,暂时停止视频输出,否则可能会导致图像数据写入slab的区域,从而造成异常
-    // 初始化slab内存池
-    slab_init();
-    page_table_init();
-
-    initial_mm.pgd = (pml4t_t *)get_CR3();
-
-    initial_mm.code_addr_start = memory_management_struct.kernel_code_start;
-    initial_mm.code_addr_end = memory_management_struct.kernel_code_end;
-
-    initial_mm.data_addr_start = (ul)&_data;
-    initial_mm.data_addr_end = memory_management_struct.kernel_data_end;
-
-    initial_mm.rodata_addr_start = (ul)&_rodata;
-    initial_mm.rodata_addr_end = (ul)&_erodata;
-    initial_mm.bss_start = (uint64_t)&_bss;
-    initial_mm.bss_end = (uint64_t)&_ebss;
-
-    initial_mm.brk_start = memory_management_struct.start_brk;
-    initial_mm.brk_end = current_pcb->addr_limit;
-
-    initial_mm.stack_start = _stack_start;
-    initial_mm.vmas = NULL;
-
-    
-    
-    mmio_init();
-}
-
-/**
- * @brief 初始化内存页
- *
- * @param page 内存页结构体
- * @param flags 标志位
- * 本函数只负责初始化内存页,允许对同一页面进行多次初始化
- * 而维护计数器及置位bmp标志位的功能,应当在分配页面的时候手动完成
- * @return unsigned long
- */
-unsigned long page_init(struct Page *page, ul flags)
-{
-    page->attr |= flags;
-    // 若页面的引用计数为0或是共享页,增加引用计数
-    if ((!page->ref_counts) || (page->attr & PAGE_SHARED))
-    {
-        ++page->ref_counts;
-        barrier();
-        if (page->zone)
-            ++page->zone->total_pages_link;
-    }
-    page->anon_vma = NULL;
-    spin_init(&(page->op_lock));
-    return 0;
-}
-
-/**
- * @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
- *
- * @param zone_select 选择内存区域, 可选项:dma, mapped in pgt(normal), unmapped in pgt
- * @param num 需要申请的连续内存页的数量 num<64
- * @param flags 将页面属性设置成flag
- * @return struct Page*
- */
-struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)
-{
-    ul zone_start = 0, zone_end = 0;
-    if (num >= 64 && num <= 0)
-    {
-        kerror("alloc_pages(): num is invalid.");
-        return NULL;
-    }
-
-    ul attr = flags;
-    switch (zone_select)
-    {
-    case ZONE_DMA:
-        // DMA区域
-        zone_start = 0;
-        zone_end = ZONE_DMA_INDEX;
-        attr |= PAGE_PGT_MAPPED;
-        break;
-    case ZONE_NORMAL:
-        zone_start = ZONE_DMA_INDEX;
-        zone_end = ZONE_NORMAL_INDEX;
-        attr |= PAGE_PGT_MAPPED;
-        break;
-    case ZONE_UNMAPPED_IN_PGT:
-        zone_start = ZONE_NORMAL_INDEX;
-        zone_end = ZONE_UNMAPPED_INDEX;
-        attr = 0;
-        break;
-
-    default:
-        kerror("In alloc_pages: param: zone_select incorrect.");
-        // 返回空
-        return NULL;
-        break;
-    }
-
-    for (int i = zone_start; i < zone_end; ++i)
-    {
-        if ((memory_management_struct.zones_struct + i)->count_pages_free < num)
-            continue;
-
-        struct Zone *z = memory_management_struct.zones_struct + i;
-        // 区域对应的起止页号
-        ul page_start = (z->zone_addr_start >> PAGE_2M_SHIFT);
-        ul page_end = (z->zone_addr_end >> PAGE_2M_SHIFT);
-
-        ul tmp = 64 - page_start % 64;
-        for (ul j = page_start; j < page_end; j += ((j % 64) ? tmp : 64))
-        {
-            // 按照bmp中的每一个元素进行查找
-            // 先将p定位到bmp的起始元素
-            ul *p = memory_management_struct.bmp + (j >> 6);
-
-            ul shift = j % 64;
-            ul tmp_num = ((1UL << num) - 1);
-            for (ul k = shift; k < 64; ++k)
-            {
-                // 寻找连续num个空页
-                if (!((k ? ((*p >> k) | (*(p + 1) << (64 - k))) : *p) & tmp_num))
-
-                {
-                    ul start_page_num = j + k - shift; // 计算得到要开始获取的内存页的页号
-                    for (ul l = 0; l < num; ++l)
-                    {
-                        struct Page *x = memory_management_struct.pages_struct + start_page_num + l;
-
-                        // 分配页面,手动配置属性及计数器
-                        // 置位bmp
-                        *(memory_management_struct.bmp + ((x->addr_phys >> PAGE_2M_SHIFT) >> 6)) |= (1UL << (x->addr_phys >> PAGE_2M_SHIFT) % 64);
-                        ++(z->count_pages_using);
-                        --(z->count_pages_free);
-                        page_init(x, attr);
-                    }
-                    // 成功分配了页面,返回第一个页面的指针
-                    // kwarn("start page num=%d\n", start_page_num);
-                    return (struct Page *)(memory_management_struct.pages_struct + start_page_num);
-                }
-            }
-        }
-    }
-    kBUG("Cannot alloc page, ZONE=%d\tnums=%d, mm_total_2M_pages=%d", zone_select, num, mm_total_2M_pages);
-    return NULL;
-}
-
-/**
- * @brief 清除页面的引用计数, 计数为0时清空除页表已映射以外的所有属性
- *
- * @param p 物理页结构体
- * @return unsigned long
- */
-unsigned long page_clean(struct Page *p)
-{
-    --p->ref_counts;
-    --p->zone->total_pages_link;
-
-    // 若引用计数为空,则清空除PAGE_PGT_MAPPED以外的所有属性
-    if (!p->ref_counts)
-    {
-        p->attr &= PAGE_PGT_MAPPED;
-    }
-    return 0;
-}
-
-/**
- * @brief Get the page's attr
- *
- * @param page 内存页结构体
- * @return ul 属性
- */
-ul get_page_attr(struct Page *page)
-{
-    if (page == NULL)
-    {
-        kBUG("get_page_attr(): page == NULL");
-        return EPAGE_NULL;
-    }
-    else
-        return page->attr;
-}
-
-/**
- * @brief Set the page's attr
- *
- * @param page 内存页结构体
- * @param flags  属性
- * @return ul 错误码
- */
-ul set_page_attr(struct Page *page, ul flags)
-{
-    if (page == NULL)
-    {
-        kBUG("get_page_attr(): page == NULL");
-        return EPAGE_NULL;
-    }
-    else
-    {
-        page->attr = flags;
-        return 0;
-    }
-}
-/**
- * @brief 释放连续number个内存页
- *
- * @param page 第一个要被释放的页面的结构体
- * @param number 要释放的内存页数量 number<64
- */
-
-void free_pages(struct Page *page, int number)
-{
-    if (page == NULL)
-    {
-        kerror("free_pages() page is invalid.");
-        return;
-    }
-
-    if (number >= 64 || number <= 0)
-    {
-        kerror("free_pages(): number %d is invalid.", number);
-        return;
-    }
-
-    ul page_num;
-    for (int i = 0; i < number; ++i, ++page)
-    {
-        page_num = page->addr_phys >> PAGE_2M_SHIFT;
-        // 复位bmp
-        *(memory_management_struct.bmp + (page_num >> 6)) &= ~(1UL << (page_num % 64));
-        // 更新计数器
-        --page->zone->count_pages_using;
-        ++page->zone->count_pages_free;
-        page->attr = 0;
-    }
-
-    return;
-}
-
-/**
- * @brief 重新初始化页表的函数
- * 将所有物理页映射到线性地址空间
- */
-void page_table_init()
-{
-    kinfo("Re-Initializing page table...");
-    ul *global_CR3 = get_CR3();
-
-    int js = 0;
-    ul *tmp_addr;
-    for (int i = 0; i < memory_management_struct.count_zones; ++i)
-    {
-        struct Zone *z = memory_management_struct.zones_struct + i;
-        struct Page *p = z->pages_group;
-
-        if (i == ZONE_UNMAPPED_INDEX && ZONE_UNMAPPED_INDEX != 0)
-            break;
-
-        for (int j = 0; j < z->count_pages; ++j)
-        {
-            mm_map_proc_page_table((uint64_t)get_CR3(), true, (ul)phys_2_virt(p->addr_phys), p->addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE, false, true, false);
-
-            ++p;
-            ++js;
-        }
-    }
-
-    
-    barrier();
-        // ========= 在IDLE进程的顶层页表中添加对内核地址空间的映射 =====================
-
-    // 由于IDLE进程的顶层页表的高地址部分会被后续进程所复制,为了使所有进程能够共享相同的内核空间,
-    //  因此需要先在IDLE进程的顶层页表内映射二级页表
-
-    uint64_t *idle_pml4t_vaddr = (uint64_t *)phys_2_virt((uint64_t)get_CR3() & (~0xfffUL));
-
-    for (int i = 256; i < 512; ++i)
-    {
-        uint64_t *tmp = idle_pml4t_vaddr + i;
-        barrier();
-        if (*tmp == 0)
-        {
-            void *pdpt = kmalloc(PAGE_4K_SIZE, 0);
-            barrier();
-            memset(pdpt, 0, PAGE_4K_SIZE);
-            barrier();
-            set_pml4t(tmp, mk_pml4t(virt_2_phys(pdpt), PAGE_KERNEL_PGT));
-        }
-    }
-    barrier();
-    flush_tlb();
-    kinfo("Page table Initialized. Affects:%d", js);
-}
-
-/**
- * @brief 从页表中获取pdt页表项的内容
- *
- * @param proc_page_table_addr 页表的地址
- * @param is_phys 页表地址是否为物理地址
- * @param virt_addr_start 要清除的虚拟地址的起始地址
- * @param length 要清除的区域的长度
- * @param clear 是否清除标志位
- */
-uint64_t mm_get_PDE(ul proc_page_table_addr, bool is_phys, ul virt_addr, bool clear)
-{
-    ul *tmp;
-    if (is_phys)
-        tmp = phys_2_virt((ul *)((ul)proc_page_table_addr & (~0xfffUL)) + ((virt_addr >> PAGE_GDT_SHIFT) & 0x1ff));
-    else
-        tmp = (ul *)((ul)proc_page_table_addr & (~0xfffUL)) + ((virt_addr >> PAGE_GDT_SHIFT) & 0x1ff);
-
-    // pml4页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    tmp = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + ((virt_addr >> PAGE_1G_SHIFT) & 0x1ff));
-
-    // pdpt页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    // 读取pdt页表项
-    tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr) >> PAGE_2M_SHIFT) & 0x1ff)));
-
-    if (clear) // 清除页表项的标志位
-        return *tmp & (~0x1fff);
-    else
-        return *tmp;
-}
-
-/**
- * @brief 从mms中寻找Page结构体
- *
- * @param phys_addr
- * @return struct Page*
- */
-static struct Page *mm_find_page(uint64_t phys_addr, uint32_t zone_select)
-{
-    uint32_t zone_start, zone_end;
-    switch (zone_select)
-    {
-    case ZONE_DMA:
-        // DMA区域
-        zone_start = 0;
-        zone_end = ZONE_DMA_INDEX;
-        break;
-    case ZONE_NORMAL:
-        zone_start = ZONE_DMA_INDEX;
-        zone_end = ZONE_NORMAL_INDEX;
-        break;
-    case ZONE_UNMAPPED_IN_PGT:
-        zone_start = ZONE_NORMAL_INDEX;
-        zone_end = ZONE_UNMAPPED_INDEX;
-        break;
-
-    default:
-        kerror("In mm_find_page: param: zone_select incorrect.");
-        // 返回空
-        return NULL;
-        break;
-    }
-
-    for (int i = zone_start; i <= zone_end; ++i)
-    {
-        if ((memory_management_struct.zones_struct + i)->count_pages_using == 0)
-            continue;
-
-        struct Zone *z = memory_management_struct.zones_struct + i;
-
-        // 区域对应的起止页号
-        ul page_start = (z->zone_addr_start >> PAGE_2M_SHIFT);
-        ul page_end = (z->zone_addr_end >> PAGE_2M_SHIFT);
-
-        ul tmp = 64 - page_start % 64;
-        for (ul j = page_start; j < page_end; j += ((j % 64) ? tmp : 64))
-        {
-            // 按照bmp中的每一个元素进行查找
-            // 先将p定位到bmp的起始元素
-            ul *p = memory_management_struct.bmp + (j >> 6);
-
-            ul shift = j % 64;
-            for (ul k = shift; k < 64; ++k)
-            {
-                if ((*p >> k) & 1) // 若当前页已分配
-                {
-                    uint64_t page_num = j + k - shift;
-                    struct Page *x = memory_management_struct.pages_struct + page_num;
-
-                    if (x->addr_phys == phys_addr) // 找到对应的页
-                        return x;
-                }
-            }
-        }
-    }
-    return NULL;
-}
-
-/**
- * @brief 调整堆区域的大小(暂时只能增加堆区域)
- *
- * @todo 缩小堆区域
- * @param old_brk_end_addr 原本的堆内存区域的结束地址
- * @param offset 新的地址相对于原地址的偏移量
- * @return uint64_t
- */
-uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset)
-{
-
-    uint64_t end_addr = PAGE_2M_ALIGN(old_brk_end_addr + offset);
-    if (offset >= 0)
-    {
-        for (uint64_t i = old_brk_end_addr; i < end_addr; i += PAGE_2M_SIZE)
-        {
-            struct vm_area_struct *vma = NULL;
-            mm_create_vma(current_pcb->mm, i, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
-            mm_map(current_pcb->mm, i, PAGE_2M_SIZE, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys);
-            // mm_map_vma(vma, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, 0, PAGE_2M_SIZE);
-        }
-        current_pcb->mm->brk_end = end_addr;
-    }
-    else
-    {
-
-        // 释放堆内存
-        for (uint64_t i = end_addr; i < old_brk_end_addr; i += PAGE_2M_SIZE)
-        {
-            uint64_t phys = mm_get_PDE((uint64_t)phys_2_virt((uint64_t)current_pcb->mm->pgd), false, i, true);
-
-            // 找到对应的页
-            struct Page *p = mm_find_page(phys, ZONE_NORMAL);
-            if (p == NULL)
-            {
-                kerror("cannot find page addr=%#018lx", phys);
-                return end_addr;
-            }
-
-            free_pages(p, 1);
-        }
-
-        mm_unmap_proc_table((uint64_t)phys_2_virt((uint64_t)current_pcb->mm->pgd), false, end_addr, PAGE_2M_ALIGN(ABS(offset)));
-        // 在页表中取消映射
-    }
-    return end_addr;
-}
-
-/**
- * @brief 创建mmio对应的页结构体
- *
- * @param paddr 物理地址
- * @return struct Page* 创建成功的page
- */
-struct Page *__create_mmio_page_struct(uint64_t paddr)
-{
-    struct Page *p = (struct Page *)kzalloc(sizeof(struct Page), 0);
-    if (p == NULL)
-        return NULL;
-    p->addr_phys = paddr;
-    page_init(p, PAGE_DEVICE);
-    return p;
-}

+ 14 - 365
kernel/src/mm/mm.h

@@ -6,9 +6,9 @@
 #include <mm/mm-types.h>
 #include <process/process.h>
 
-// 每个页表的项数
-// 64位下,每个页表4k,每条页表项8B,故一个页表有512条
-#define PTRS_PER_PGT 512
+extern void rs_pseudo_map_phys(uint64_t virt_addr, uint64_t phys_addr, uint64_t size);
+extern void rs_map_phys(uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags);
+extern uint64_t rs_unmap_at_low_addr();
 
 // 内核层的起始地址
 #define PAGE_OFFSET 0xffff800000000000UL
@@ -39,9 +39,6 @@
 // 虚拟地址与物理地址转换
 #define virt_2_phys(addr) ((unsigned long)(addr)-PAGE_OFFSET)
 #define phys_2_virt(addr) ((unsigned long *)((unsigned long)(addr) + PAGE_OFFSET))
-// 获取对应的页结构体
-#define Virt_To_2M_Page(kaddr) (memory_management_struct.pages_struct + (virt_2_phys(kaddr) >> PAGE_2M_SHIFT))
-#define Phy_to_2M_Page(kaddr) (memory_management_struct.pages_struct + ((unsigned long)(kaddr) >> PAGE_2M_SHIFT))
 
 // 在这个地址以上的虚拟空间,用来进行特殊的映射
 #define SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE 0xffffa00000000000UL
@@ -49,7 +46,6 @@
 #define IO_APIC_MAPPING_OFFSET 0xfec00000UL
 #define LOCAL_APIC_MAPPING_OFFSET 0xfee00000UL
 #define AHCI_MAPPING_OFFSET 0xff200000UL // AHCI 映射偏移量,之后使用了4M的地址
-#define XHCI_MAPPING_OFFSET 0x100000000 // XHCI控制器映射偏移量(后方请预留1GB的虚拟空间来映射不同的controller)
 
 // ===== 内存区域属性 =====
 // DMA区域
@@ -138,59 +134,21 @@
 
 #define PAGE_USER_4K_PAGE (PAGE_U_S | PAGE_R_W | PAGE_PRESENT)
 
-// ===== 错误码定义 ====
-// 物理页结构体为空
-#define EPAGE_NULL 1
-
 /**
  * @brief 刷新TLB的宏定义
  * 由于任何写入cr3的操作都会刷新TLB,因此这个宏定义可以刷新TLB
  */
-#define flush_tlb()                                                                                                    \
-    do                                                                                                                 \
-    {                                                                                                                  \
-        ul tmp;                                                                                                        \
-        io_mfence();                                                                                                   \
-        __asm__ __volatile__("movq %%cr3, %0\n\t"                                                                      \
-                             "movq %0, %%cr3\n\t"                                                                      \
-                             : "=r"(tmp)::"memory");                                                                   \
-                                                                                                                       \
+#define flush_tlb()                                  \
+    do                                               \
+    {                                                \
+        ul tmp;                                      \
+        io_mfence();                                 \
+        __asm__ __volatile__("movq %%cr3, %0\n\t"    \
+                             "movq %0, %%cr3\n\t"    \
+                             : "=r"(tmp)::"memory"); \
+                                                     \
     } while (0);
 
-/**
- * @brief 系统内存信息结构体(单位:字节)
- *
- */
-struct mm_stat_t
-{
-    uint64_t total;      // 计算机的总内存数量大小
-    uint64_t used;       // 已使用的内存大小
-    uint64_t free;       // 空闲物理页所占的内存大小
-    uint64_t shared;     // 共享的内存大小
-    uint64_t cache_used; // 位于slab缓冲区中的已使用的内存大小
-    uint64_t cache_free; // 位于slab缓冲区中的空闲的内存大小
-    uint64_t available;  // 系统总空闲内存大小(包括kmalloc缓冲区)
-};
-
-/**
- * @brief 虚拟内存区域的操作方法的结构体
- *
- */
-struct vm_operations_t
-{
-    /**
-     * @brief vm area 被打开时的回调函数
-     *
-     */
-    void (*open)(struct vm_area_struct *area);
-    /**
-     * @brief vm area将要被移除的时候,将会调用该回调函数
-     *
-     */
-    void (*close)(struct vm_area_struct *area);
-};
-
-extern struct memory_desc memory_management_struct;
 
 // 导出内核程序的几个段的起止地址
 extern char _text;
@@ -203,26 +161,6 @@ extern char _bss;
 extern char _ebss;
 extern char _end;
 
-// 每个区域的索引
-
-int ZONE_DMA_INDEX = 0;
-int ZONE_NORMAL_INDEX = 0;
-int ZONE_UNMAPPED_INDEX = 0;
-
-// 初始化内存管理单元
-void mm_init();
-
-/**
- * @brief 初始化内存页
- *
- * @param page 内存页结构体
- * @param flags 标志位
- * 本函数只负责初始化内存页,允许对同一页面进行多次初始化
- * 而维护计数器及置位bmp标志位的功能,应当在分配页面的时候手动完成
- * @return unsigned long
- */
-unsigned long page_init(struct Page *page, ul flags);
-
 /**
  * @brief 读取CR3寄存器的值(存储了页目录的基地址)
  *
@@ -231,70 +169,11 @@ unsigned long page_init(struct Page *page, ul flags);
 unsigned long *get_CR3()
 {
     ul *tmp;
-    __asm__ __volatile__("movq %%cr3, %0\n\t" : "=r"(tmp)::"memory");
+    __asm__ __volatile__("movq %%cr3, %0\n\t"
+                         : "=r"(tmp)::"memory");
     return tmp;
 }
 
-/**
- * @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
- *
- * @param zone_select 选择内存区域, 可选项:dma, mapped in pgt(normal), unmapped in pgt
- * @param num 需要申请的内存页的数量 num<64
- * @param flags 将页面属性设置成flag
- * @return struct Page*
- */
-struct Page *alloc_pages(unsigned int zone_select, int num, ul flags);
-
-/**
- * @brief 清除页面的引用计数, 计数为0时清空除页表已映射以外的所有属性
- *
- * @param p 物理页结构体
- * @return unsigned long
- */
-unsigned long page_clean(struct Page *page);
-
-/**
- * @brief 释放连续number个内存页
- *
- * @param page 第一个要被释放的页面的结构体
- * @param number 要释放的内存页数量 number<64
- */
-void free_pages(struct Page *page, int number);
-
-/**
- * @brief Get the page's attr
- *
- * @param page 内存页结构体
- * @return ul 属性
- */
-ul get_page_attr(struct Page *page);
-
-/**
- * @brief Set the page's attr
- *
- * @param page 内存页结构体
- * @param flags  属性
- * @return ul 错误码
- */
-ul set_page_attr(struct Page *page, ul flags);
-
-#define mk_pml4t(addr, attr) ((unsigned long)(addr) | (unsigned long)(attr))
-/**
- * @brief 设置pml4页表的页表项
- * @param pml4tptr pml4页表项的地址
- * @param pml4val pml4页表项的值
- */
-#define set_pml4t(pml4tptr, pml4tval) (*(pml4tptr) = (pml4tval))
-
-#define mk_pdpt(addr, attr) ((unsigned long)(addr) | (unsigned long)(attr))
-#define set_pdpt(pdptptr, pdptval) (*(pdptptr) = (pdptval))
-
-#define mk_pdt(addr, attr) ((unsigned long)(addr) | (unsigned long)(attr))
-#define set_pdt(pdtptr, pdtval) (*(pdtptr) = (pdtval))
-
-#define mk_pt(addr, attr) ((unsigned long)(addr) | (unsigned long)(attr))
-#define set_pt(ptptr, ptval) (*(ptptr) = (ptval))
-
 /*
  *  vm_area_struct中的vm_flags的可选值
  * 对应的结构体请见mm-types.h
@@ -312,233 +191,3 @@ ul set_page_attr(struct Page *page, ul flags);
 
 /* VMA basic access permission flags */
 #define VM_ACCESS_FLAGS (VM_READ | VM_WRITE | VM_EXEC)
-
-/**
- * @brief 初始化虚拟内存区域结构体
- *
- * @param vma
- * @param mm
- */
-static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
-{
-    memset(vma, 0, sizeof(struct vm_area_struct));
-    vma->vm_mm = mm;
-    vma->vm_prev = vma->vm_next = NULL;
-    vma->vm_ops = NULL;
-    list_init(&vma->anon_vma_list);
-}
-
-/**
- * @brief 判断给定的vma是否为当前进程所属的vma
- *
- * @param vma 给定的vma结构体
- * @return true
- * @return false
- */
-static inline bool vma_is_foreign(struct vm_area_struct *vma)
-{
-    if (current_pcb->mm == NULL)
-        return true;
-    if (current_pcb->mm != vma->vm_mm)
-        return true;
-    return false;
-}
-
-static inline bool vma_is_accessible(struct vm_area_struct *vma)
-{
-    return vma->vm_flags & VM_ACCESS_FLAGS;
-}
-
-/**
- * @brief 获取一块新的vma结构体,并将其与指定的mm进行绑定
- *
- * @param mm 与VMA绑定的内存空间分布结构体
- * @return struct vm_area_struct* 新的VMA
- */
-struct vm_area_struct *vm_area_alloc(struct mm_struct *mm);
-
-/**
- * @brief 释放vma结构体
- *
- * @param vma 待释放的vma结构体
- */
-void vm_area_free(struct vm_area_struct *vma);
-
-/**
- * @brief 从链表中删除指定的vma结构体
- *
- * @param vma
- */
-void vm_area_del(struct vm_area_struct *vma);
-
-/**
- * @brief 查找第一个符合“addr < vm_end”条件的vma
- *
- * @param mm 内存空间分布结构体
- * @param addr 虚拟地址
- * @return struct vm_area_struct* 符合条件的vma
- */
-struct vm_area_struct *vma_find(struct mm_struct *mm, uint64_t addr);
-
-/**
- * @brief 插入vma
- *
- * @param mm
- * @param vma
- * @return int
- */
-int vma_insert(struct mm_struct *mm, struct vm_area_struct *vma);
-
-/**
- * @brief 重新初始化页表的函数
- * 将所有物理页映射到线性地址空间
- */
-void page_table_init();
-
-/**
- * @brief 将物理地址映射到页表的函数
- *
- * @param virt_addr_start 要映射到的虚拟地址的起始位置
- * @param phys_addr_start 物理地址的起始位置
- * @param length 要映射的区域的长度(字节)
- * @param flags 标志位
- * @param use4k 是否使用4k页
- */
-int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k);
-
-/**
- * @brief 将将物理地址填写到进程的页表的函数
- *
- * @param proc_page_table_addr 页表的基地址
- * @param is_phys 页表的基地址是否为物理地址
- * @param virt_addr_start 要映射到的虚拟地址的起始位置
- * @param phys_addr_start 物理地址的起始位置
- * @param length 要映射的区域的长度(字节)
- * @param user 用户态是否可访问
- * @param flush 是否刷新tlb
- * @param use4k 是否使用4k页
- */
-int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length,
-                           ul flags, bool user, bool flush, bool use4k);
-
-int mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags);
-
-/**
- * @brief 从页表中清除虚拟地址的映射
- *
- * @param proc_page_table_addr 页表的地址
- * @param is_phys 页表地址是否为物理地址
- * @param virt_addr_start 要清除的虚拟地址的起始地址
- * @param length 要清除的区域的长度
- */
-void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul length);
-
-/**
- * @brief 取消当前进程的页表中的虚拟地址映射
- *
- * @param virt_addr 虚拟地址
- * @param length 地址长度
- */
-#define mm_unmap_addr(virt_addr, length) ({ mm_unmap_proc_table((uint64_t)get_CR3(), true, virt_addr, length); })
-
-/**
- * @brief 创建VMA
- *
- * @param mm 要绑定的内存空间分布结构体
- * @param vaddr 起始虚拟地址
- * @param length 长度(字节)
- * @param vm_flags vma的标志
- * @param vm_ops vma的操作接口
- * @param res_vma 返回的vma指针
- * @return int 错误码
- */
-int mm_create_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, vm_flags_t vm_flags,
-                  struct vm_operations_t *vm_ops, struct vm_area_struct **res_vma);
-
-/**
- * @brief 将指定的物理地址映射到指定的vma处
- *
- * @param vma 要进行映射的VMA结构体
- * @param paddr 起始物理地址
- * @param offset 要映射的起始位置在vma中的偏移量
- * @param length 要映射的长度
- * @return int 错误码
- */
-int mm_map_vma(struct vm_area_struct *vma, uint64_t paddr, uint64_t offset, uint64_t length);
-
-/**
- * @brief 在页表中映射物理地址到指定的虚拟地址(需要页表中已存在对应的vma)
- *
- * @param mm 内存管理结构体
- * @param vaddr 虚拟地址
- * @param length 长度(字节)
- * @param paddr 物理地址
- * @return int 返回码
- */
-int mm_map(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t paddr);
-
-/**
- * @brief 在页表中取消指定的vma的映射
- *
- * @param mm 指定的mm
- * @param vma 待取消映射的vma
- * @param paddr 返回的被取消映射的起始物理地址
- * @return int 返回码
- */
-int mm_unmap_vma(struct mm_struct *mm, struct vm_area_struct *vma, uint64_t *paddr);
-
-/**
- * @brief 解除一段虚拟地址的映射(这些地址必须在vma中存在)
- *
- * @param mm 内存空间结构体
- * @param vaddr 起始地址
- * @param length 结束地址
- * @param destroy 是否释放vma结构体
- * @return int 错误码
- */
-int mm_unmap(struct mm_struct *mm, uint64_t vaddr, uint64_t length, bool destroy);
-
-/**
- * @brief 检测是否为有效的2M页(物理内存页)
- *
- * @param paddr 物理地址
- * @return int8_t 是 -> 1
- *                 否 -> 0
- */
-int8_t mm_is_2M_page(uint64_t paddr);
-
-/**
- * @brief 检查页表是否存在不为0的页表项
- *
- * @param ptr 页表基指针
- * @return int8_t 存在 -> 1
- *                不存在 -> 0
- */
-int8_t mm_check_page_table(uint64_t *ptr);
-
-/**
- * @brief 调整堆区域的大小(暂时只能增加堆区域)
- *
- * @todo 缩小堆区域
- * @param old_brk_end_addr 原本的堆内存区域的结束地址
- * @param offset 新的地址相对于原地址的偏移量
- * @return uint64_t
- */
-uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset);
-
-/**
- * @brief 获取系统当前的内存信息(未上锁,不一定精准)
- *
- * @return struct mm_stat_t 内存信息结构体
- */
-struct mm_stat_t mm_stat();
-
-/**
- * @brief 检测指定地址是否已经被映射
- *
- * @param page_table_phys_addr 页表的物理地址
- * @param virt_addr 要检测的地址
- * @return true 已经被映射
- * @return false
- */
-bool mm_check_mapped(ul page_table_phys_addr, uint64_t virt_addr);

+ 0 - 582
kernel/src/mm/mmap.c

@@ -1,582 +0,0 @@
-#include "mm.h"
-#include "slab.h"
-#include "internal.h"
-#include <common/compiler.h>
-#include <debug/bug.h>
-
-extern uint64_t mm_total_2M_pages;
-
-/**
- * @brief 虚拟地址长度所需要的entry数量
- *
- */
-typedef struct
-{
-    int64_t num_PML4E;
-    int64_t num_PDPTE;
-    int64_t num_PDE;
-    int64_t num_PTE;
-} mm_pgt_entry_num_t;
-
-/**
- * @brief 计算虚拟地址长度对应的页表entry数量
- *
- * @param length 长度
- * @param ent 返回的entry数量结构体
- */
-static void mm_calculate_entry_num(uint64_t length, mm_pgt_entry_num_t *ent)
-{
-    if (ent == NULL)
-        return;
-    ent->num_PML4E = (length + (1UL << PAGE_GDT_SHIFT) - 1) >> PAGE_GDT_SHIFT;
-    ent->num_PDPTE = (length + PAGE_1G_SIZE - 1) >> PAGE_1G_SHIFT;
-    ent->num_PDE = (length + PAGE_2M_SIZE - 1) >> PAGE_2M_SHIFT;
-    ent->num_PTE = (length + PAGE_4K_SIZE - 1) >> PAGE_4K_SHIFT;
-}
-
-/**
- * @brief 将物理地址映射到页表的函数
- *
- * @param virt_addr_start 要映射到的虚拟地址的起始位置
- * @param phys_addr_start 物理地址的起始位置
- * @param length 要映射的区域的长度(字节)
- * @param flags 标志位
- * @param use4k 是否使用4k页
- */
-int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k)
-{
-    uint64_t global_CR3 = (uint64_t)get_CR3();
-
-    return mm_map_proc_page_table(global_CR3, true, virt_addr_start, phys_addr_start, length, flags, false, true, use4k);
-}
-
-int mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags)
-{
-    uint64_t global_CR3 = (uint64_t)get_CR3();
-    return mm_map_proc_page_table(global_CR3, true, virt_addr_start, phys_addr_start, length, flags, true, true, false);
-}
-
-/**
- * @brief 将将物理地址填写到进程的页表的函数
- *
- * @param proc_page_table_addr 页表的基地址
- * @param is_phys 页表的基地址是否为物理地址
- * @param virt_addr_start 要映射到的虚拟地址的起始位置
- * @param phys_addr_start 物理地址的起始位置
- * @param length 要映射的区域的长度(字节)
- * @param user 用户态是否可访问
- * @param flush 是否刷新tlb
- * @param use4k 是否使用4k页
- */
-int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k)
-{
-
-    // 计算线性地址对应的pml4页表项的地址
-    mm_pgt_entry_num_t pgt_num;
-    mm_calculate_entry_num(length, &pgt_num);
-
-    // 已映射的内存大小
-    uint64_t length_mapped = 0;
-
-    // 对user标志位进行校正
-    if ((flags & PAGE_U_S) != 0)
-        user = true;
-    else
-        user = false;
-
-    uint64_t pml4e_id = ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff);
-    uint64_t *pml4_ptr;
-    if (is_phys)
-        pml4_ptr = phys_2_virt((ul *)((ul)proc_page_table_addr & (~0xfffUL)));
-    else
-        pml4_ptr = (ul *)((ul)proc_page_table_addr & (~0xfffUL));
-
-    // 循环填写顶层页表
-    for (; (pgt_num.num_PML4E > 0) && pml4e_id < 512; ++pml4e_id)
-    {
-        // 剩余需要处理的pml4E -1
-        --(pgt_num.num_PML4E);
-
-        ul *pml4e_ptr = pml4_ptr + pml4e_id;
-
-        // 创建新的二级页表
-        if (*pml4e_ptr == 0)
-        {
-            ul *virt_addr = kmalloc(PAGE_4K_SIZE, 0);
-            memset(virt_addr, 0, PAGE_4K_SIZE);
-            set_pml4t(pml4e_ptr, mk_pml4t(virt_2_phys(virt_addr), (user ? PAGE_USER_PGT : PAGE_KERNEL_PGT)));
-        }
-
-        uint64_t pdpte_id = (((virt_addr_start + length_mapped) >> PAGE_1G_SHIFT) & 0x1ff);
-        uint64_t *pdpt_ptr = (uint64_t *)phys_2_virt(*pml4e_ptr & (~0xfffUL));
-
-        // 循环填写二级页表
-        for (; (pgt_num.num_PDPTE > 0) && pdpte_id < 512; ++pdpte_id)
-        {
-            --pgt_num.num_PDPTE;
-            uint64_t *pdpte_ptr = (pdpt_ptr + pdpte_id);
-
-            // 创建新的三级页表
-            if (*pdpte_ptr == 0)
-            {
-                ul *virt_addr = kmalloc(PAGE_4K_SIZE, 0);
-                memset(virt_addr, 0, PAGE_4K_SIZE);
-                set_pdpt(pdpte_ptr, mk_pdpt(virt_2_phys(virt_addr), (user ? PAGE_USER_DIR : PAGE_KERNEL_DIR)));
-            }
-
-            uint64_t pde_id = (((virt_addr_start + length_mapped) >> PAGE_2M_SHIFT) & 0x1ff);
-            uint64_t *pd_ptr = (uint64_t *)phys_2_virt(*pdpte_ptr & (~0xfffUL));
-
-            // 循环填写三级页表,初始化2M物理页
-            for (; (pgt_num.num_PDE > 0) && pde_id < 512; ++pde_id)
-            {
-                --pgt_num.num_PDE;
-                // 计算当前2M物理页对应的pdt的页表项的物理地址
-                ul *pde_ptr = pd_ptr + pde_id;
-                // ====== 使用4k页 =======
-                if (unlikely(use4k))
-                {
-                    // kdebug("use 4k");
-                    if (*pde_ptr == 0)
-                    {
-                        // 创建四级页表
-                        uint64_t *vaddr = kmalloc(PAGE_4K_SIZE, 0);
-                        memset(vaddr, 0, PAGE_4K_SIZE);
-                        set_pdt(pde_ptr, mk_pdt(virt_2_phys(vaddr), (user ? PAGE_USER_PDE : PAGE_KERNEL_PDE)));
-                    }
-                    else if (unlikely(*pde_ptr & (1 << 7)))
-                    {
-                        // 当前页表项已经被映射了2MB物理页
-                        goto failed;
-                    }
-
-                    uint64_t pte_id = (((virt_addr_start + length_mapped) >> PAGE_4K_SHIFT) & 0x1ff);
-                    uint64_t *pt_ptr = (uint64_t *)phys_2_virt(*pde_ptr & (~0xfffUL));
-
-                    // 循环填写4级页表,初始化4K页
-                    for (; (pgt_num.num_PTE > 0) && pte_id < 512; ++pte_id)
-                    {
-                        --pgt_num.num_PTE;
-                        uint64_t *pte_ptr = pt_ptr + pte_id;
-
-                        if (unlikely(*pte_ptr != 0))
-                            kwarn("pte already exists.");
-                        else
-                            set_pt(pte_ptr, mk_pt((ul)phys_addr_start + length_mapped, flags | (user ? PAGE_USER_4K_PAGE : PAGE_KERNEL_4K_PAGE)));
-                        length_mapped += PAGE_4K_SIZE;
-                    }
-                }
-                // ======= 使用2M页 ========
-                else
-                {
-                    if (unlikely((*pde_ptr != 0) && user == true))
-                    {
-                        // 如果是用户态可访问的页,则释放当前新获取的物理页
-                        if (likely((((ul)phys_addr_start + length_mapped) >> PAGE_2M_SHIFT) < mm_total_2M_pages)) // 校验是否为内存中的物理页
-                            free_pages(Phy_to_2M_Page((ul)phys_addr_start + length_mapped), 1);
-                        length_mapped += PAGE_2M_SIZE;
-                        continue;
-                    }
-                    // 页面写穿,禁止缓存
-                    set_pdt(pde_ptr, mk_pdt((ul)phys_addr_start + length_mapped, flags | (user ? PAGE_USER_PAGE : PAGE_KERNEL_PAGE)));
-                    length_mapped += PAGE_2M_SIZE;
-                }
-            }
-        }
-    }
-    if (likely(flush))
-        flush_tlb();
-    return 0;
-failed:;
-    kerror("Map memory failed. use4k=%d, vaddr=%#018lx, paddr=%#018lx", use4k, virt_addr_start, phys_addr_start);
-    return -EFAULT;
-}
-
-/**
- * @brief 从页表中清除虚拟地址的映射
- *
- * @param proc_page_table_addr 页表的地址
- * @param is_phys 页表地址是否为物理地址
- * @param virt_addr_start 要清除的虚拟地址的起始地址
- * @param length 要清除的区域的长度
- */
-void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul length)
-{
-
-    // 计算线性地址对应的pml4页表项的地址
-    mm_pgt_entry_num_t pgt_num;
-    mm_calculate_entry_num(length, &pgt_num);
-    // 已取消映射的内存大小
-    uint64_t length_unmapped = 0;
-
-    uint64_t pml4e_id = ((virt_addr_start >> PAGE_GDT_SHIFT) & 0x1ff);
-    uint64_t *pml4_ptr;
-    if (is_phys)
-        pml4_ptr = phys_2_virt((ul *)((ul)proc_page_table_addr & (~0xfffUL)));
-    else
-        pml4_ptr = (ul *)((ul)proc_page_table_addr & (~0xfffUL));
-
-    // 循环填写顶层页表
-    for (; (pgt_num.num_PML4E > 0) && pml4e_id < 512; ++pml4e_id)
-    {
-        // 剩余需要处理的pml4E -1
-        --(pgt_num.num_PML4E);
-
-        ul *pml4e_ptr = NULL;
-        pml4e_ptr = pml4_ptr + pml4e_id;
-
-        // 二级页表不存在
-        if (*pml4e_ptr == 0)
-        {
-            continue;
-        }
-
-        uint64_t pdpte_id = (((virt_addr_start + length_unmapped) >> PAGE_1G_SHIFT) & 0x1ff);
-        uint64_t *pdpt_ptr = (uint64_t *)phys_2_virt(*pml4e_ptr & (~0xfffUL));
-        // kdebug("pdpt_ptr=%#018lx", pdpt_ptr);
-
-        // 循环处理二级页表
-        for (; (pgt_num.num_PDPTE > 0) && pdpte_id < 512; ++pdpte_id)
-        {
-            --pgt_num.num_PDPTE;
-            uint64_t *pdpte_ptr = (pdpt_ptr + pdpte_id);
-            // kdebug("pgt_num.num_PDPTE=%ld pdpte_ptr=%#018lx", pgt_num.num_PDPTE, pdpte_ptr);
-
-            // 三级页表为空
-            if (*pdpte_ptr == 0)
-            {
-                continue;
-            }
-
-            uint64_t pde_id = (((virt_addr_start + length_unmapped) >> PAGE_2M_SHIFT) & 0x1ff);
-            uint64_t *pd_ptr = (uint64_t *)phys_2_virt(*pdpte_ptr & (~0xfffUL));
-            // kdebug("pd_ptr=%#018lx, *pd_ptr=%#018lx", pd_ptr, *pd_ptr);
-
-            // 循环处理三级页表
-            for (; (pgt_num.num_PDE > 0) && pde_id < 512; ++pde_id)
-            {
-                --pgt_num.num_PDE;
-                // 计算当前2M物理页对应的pdt的页表项的物理地址
-                ul *pde_ptr = pd_ptr + pde_id;
-
-                // 存在4级页表
-                if (((*pde_ptr) & (1 << 7)) == 0)
-                {
-                    // 存在4K页
-                    uint64_t pte_id = (((virt_addr_start + length_unmapped) >> PAGE_4K_SHIFT) & 0x1ff);
-                    uint64_t *pt_ptr = (uint64_t *)phys_2_virt(*pde_ptr & (~0xfffUL));
-                    // 循环处理4K页表
-                    for (; pgt_num.num_PTE > 0 && pte_id < 512; ++pte_id)
-                    {
-                        uint64_t *pte_ptr = pt_ptr + pte_id;
-                        --pgt_num.num_PTE;
-                        *pte_ptr = 0;
-                        length_unmapped += PAGE_4K_SIZE;
-                    }
-
-                    // 4级页表已经空了,释放页表
-                    if (unlikely(mm_check_page_table(pt_ptr)) == 0)
-                    {
-                        *pde_ptr = 0;
-                        kfree(pt_ptr);
-                    }
-                }
-                else
-                {
-                    *pde_ptr = 0;
-                    length_unmapped += PAGE_2M_SIZE;
-                    pgt_num.num_PTE -= 512;
-                }
-            }
-
-            // 3级页表已经空了,释放页表
-            if (unlikely(mm_check_page_table(pd_ptr)) == 0)
-            {
-                *pdpte_ptr = 0;
-                kfree(pd_ptr);
-            }
-        }
-        // 2级页表已经空了,释放页表
-        if (unlikely(mm_check_page_table(pdpt_ptr)) == 0)
-        {
-            *pml4e_ptr = 0;
-            kfree(pdpt_ptr);
-        }
-    }
-    flush_tlb();
-}
-
-/**
- * @brief 创建VMA
- *
- * @param mm 要绑定的内存空间分布结构体
- * @param vaddr 起始虚拟地址
- * @param length 长度(字节)
- * @param vm_flags vma的标志
- * @param vm_ops vma的操作接口
- * @param res_vma 返回的vma指针
- * @return int 错误码
- */
-int mm_create_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, vm_flags_t vm_flags, struct vm_operations_t *vm_ops, struct vm_area_struct **res_vma)
-{
-    int retval = 0;
-    // 输入的地址如果不是4K对齐,则报错
-    if (unlikely(vaddr & (PAGE_4K_SIZE - 1)))
-        return -EINVAL;
-
-    struct vm_area_struct *vma = vm_area_alloc(mm);
-    if (unlikely(vma == NULL))
-        return -ENOMEM;
-    vma->vm_ops = vm_ops;
-    vma->vm_flags = vm_flags;
-    vma->vm_start = vaddr;
-    vma->vm_end = vaddr + length;
-    // 将VMA加入mm的链表
-    retval = vma_insert(mm, vma);
-    if (retval == -EEXIST || retval == __VMA_MERGED) // 之前已经存在了相同的vma,直接返回
-    {
-        *res_vma = vma_find(mm, vma->vm_start);
-        kfree(vma);
-        if (retval == -EEXIST)
-            return -EEXIST;
-        else
-            return 0;
-    }
-
-    if (res_vma != NULL)
-        *res_vma = vma;
-    return 0;
-}
-
-/**
- * @brief 将指定的物理地址映射到指定的vma处
- *
- * @param vma 要进行映射的VMA结构体
- * @param paddr 起始物理地址
- * @param offset 要映射的起始位置在vma中的偏移量
- * @param length 要映射的长度
- * @return int 错误码
- */
-int mm_map_vma(struct vm_area_struct *vma, uint64_t paddr, uint64_t offset, uint64_t length)
-{
-   int retval = 0;
-    uint64_t mapped = 0;
-    BUG_ON((offset & (PAGE_4K_SIZE - 1)) != 0);
-    length = PAGE_4K_ALIGN(length); // 将length按照4K进行对齐
-    // 获取物理地址对应的页面
-    struct Page *pg;
-    uint64_t page_flags = 0;
-    if (vma->vm_flags & VM_IO) // 对于mmio的内存,创建新的page结构体
-    {
-        page_flags = PAGE_PWT | PAGE_PCD;
-        if (unlikely(vma->anon_vma == NULL || vma->anon_vma->page == NULL))
-            pg = __create_mmio_page_struct(paddr);
-        else
-            pg = vma->anon_vma->page;
-    }
-    else
-        pg = Phy_to_2M_Page(paddr);
-
-    if (unlikely(pg->anon_vma == NULL)) // 若页面不存在anon_vma,则为页面创建anon_vma
-    {
-        spin_lock(&pg->op_lock);
-        if (unlikely(pg->anon_vma == NULL))
-            __anon_vma_create_alloc(pg, false);
-        spin_unlock(&pg->op_lock);
-    }
-    barrier();
-    // 将anon vma与vma进行绑定
-    __anon_vma_add(pg->anon_vma, vma);
-    barrier();
-    // 长度超过界限
-    BUG_ON(vma->vm_start + offset + length > vma->vm_end);
-
-    /*
-        todo: 限制页面的读写权限
-    */
-
-    // ==== 将地址映射到页表 ====
-    uint64_t len_4k, len_2m;
-    // 将地址使用4k页填补,使得地址按照2M对齐
-    len_4k = PAGE_2M_ALIGN(vma->vm_start + offset) - (vma->vm_start + offset);
-    if (len_4k > 0)
-        len_4k = (len_4k > length) ? length : len_4k;
-    if (len_4k)
-    {
-        if (vma->vm_flags & VM_USER)
-            page_flags |= PAGE_USER_4K_PAGE;
-        else
-            page_flags |= PAGE_KERNEL_4K_PAGE;
-
-        // 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
-        retval = mm_map_proc_page_table((uint64_t)vma->vm_mm->pgd, true, vma->vm_start + offset, paddr, len_4k, page_flags, false, false, true);
-        if (unlikely(retval != 0))
-            goto failed;
-
-        mapped += len_4k;
-        length -= len_4k;
-    }
-
-    len_4k = length % PAGE_2M_SIZE;
-    len_2m = length / PAGE_2M_SIZE;
-
-    // 映射连续的2M页
-    if (likely(len_2m > 0))
-    {
-        if (vma->vm_flags & VM_USER)
-            page_flags |= PAGE_USER_PAGE;
-        else
-            page_flags |= PAGE_KERNEL_PAGE;
-        // 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
-        retval = mm_map_proc_page_table((uint64_t)vma->vm_mm->pgd, true, vma->vm_start + offset + mapped, paddr + mapped, len_2m, page_flags, false, false, false);
-
-        if (unlikely(retval != 0))
-            goto failed;
-        mapped += len_2m;
-    }
-    // 最后再使用4K页填补
-    if (likely(len_4k > 0))
-    {
-
-        if (vma->vm_flags & VM_USER)
-            page_flags |= PAGE_USER_4K_PAGE;
-        else
-            page_flags |= PAGE_KERNEL_4K_PAGE;
-
-        // 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
-        retval = mm_map_proc_page_table((uint64_t)vma->vm_mm->pgd, true, vma->vm_start + offset + mapped, paddr + mapped, len_4k, page_flags, false, false, true);
-
-        if (unlikely(retval != 0))
-            goto failed;
-        mapped += len_4k;
-    }
-
-    if (vma->vm_flags & VM_IO)
-        vma->page_offset = 0;
-
-    flush_tlb();
-    return 0;
-failed:;
-    kdebug("map VMA failed.");
-    return retval;
-}
-
-/**
- * @brief 在页表中映射物理地址到指定的虚拟地址(需要页表中已存在对应的vma)
- *
- * @param mm 内存管理结构体
- * @param vaddr 虚拟地址
- * @param length 长度(字节)
- * @param paddr 物理地址
- * @return int 返回码
- */
-int mm_map(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t paddr)
-{
-    int retval = 0;
-    uint64_t offset = 0;
-    for (uint64_t mapped = 0; mapped < length;)
-    {
-
-        struct vm_area_struct *vma = vma_find(mm, vaddr + mapped);
-        if (unlikely(vma == NULL))
-        {
-            kerror("Map addr failed: vma not found. At address: %#018lx, pid=%ld", vaddr + mapped, current_pcb->pid);
-            return -EINVAL;
-        }
-
-        // if (unlikely(vma->vm_start != (vaddr + mapped)))
-        // {
-        //     kerror("Map addr failed: addr_start is not equal to current: %#018lx.", vaddr + mapped);
-        //     return -EINVAL;
-        // }
-
-        offset = vaddr + mapped - vma->vm_start;
-        uint64_t m_len = vma->vm_end - vma->vm_start - offset;
-        // kdebug("start=%#018lx, offset=%ld", vma->vm_start, offset);
-        retval = mm_map_vma(vma, paddr + mapped, offset, m_len);
-        if (unlikely(retval != 0))
-            goto failed;
-
-        mapped += m_len;
-    }
-    return 0;
-failed:;
-    kerror("Map addr failed.");
-    return retval;
-}
-
-/**
- * @brief 在页表中取消指定的vma的映射
- *
- * @param mm 指定的mm
- * @param vma 待取消映射的vma
- * @param paddr 返回的被取消映射的起始物理地址
- * @return int 返回码
- */
-int mm_unmap_vma(struct mm_struct *mm, struct vm_area_struct *vma, uint64_t *paddr)
-{
-    // 确保vma对应的mm与指定的mm相一致
-    if (unlikely(vma->vm_mm != mm))
-        return -EINVAL;
-    struct anon_vma_t *anon = vma->anon_vma;
-    if (paddr != NULL)
-        *paddr = __mm_get_paddr(mm, vma->vm_start);
-    if (anon == NULL)
-        kwarn("anon is NULL");
-    semaphore_down(&anon->sem);
-
-    mm_unmap_proc_table((uint64_t)mm->pgd, true, vma->vm_start, vma->vm_end - vma->vm_start);
-    __anon_vma_del(vma);
-    /** todo: 这里应该会存在bug,应修复。
-     * 若anon_vma的等待队列上有其他的进程,由于anon_vma被释放
-     * 这些在等待队列上的进程将无法被唤醒。
-     */
-    list_init(&vma->anon_vma_list);
-
-    semaphore_up(&anon->sem);
-
-    return 0;
-}
-
-/**
- * @brief 解除一段虚拟地址的映射(这些地址必须在vma中存在)
- *
- * @param mm 内存空间结构体
- * @param vaddr 起始地址
- * @param length 结束地址
- * @param destroy 是否释放vma结构体
- * @return int 错误码
- */
-int mm_unmap(struct mm_struct *mm, uint64_t vaddr, uint64_t length, bool destroy)
-{
-    int retval = 0;
-    for (uint64_t unmapped = 0; unmapped < length;)
-    {
-        struct vm_area_struct *vma = vma_find(mm, vaddr + unmapped);
-        if (unlikely(vma == NULL))
-        {
-            kerror("Unmap addr failed: vma not found. At address: %#018lx, pid=%ld", vaddr + unmapped, current_pcb->pid);
-            return -EINVAL;
-        }
-
-        if (unlikely(vma->vm_start != (vaddr + unmapped)))
-        {
-            kerror("Unmap addr failed: addr_start is not equal to current: %#018lx.", vaddr + unmapped);
-            return -EINVAL;
-        }
-        if (vma->anon_vma != NULL)
-            mm_unmap_vma(mm, vma, NULL);
-
-        unmapped += vma->vm_end - vma->vm_start;
-        // 释放vma结构体
-        if (destroy)
-        {
-            vm_area_del(vma);
-            vm_area_free(vma);
-        }
-    }
-    return 0;
-failed:;
-    kerror("Unmap addr failed.");
-    return retval;
-}

+ 0 - 9
kernel/src/mm/mmio.c

@@ -1,9 +0,0 @@
-#include "mmio.h"
-#include <common/math.h>
-extern void __mmio_buddy_init();
-
-void mmio_init()
-{
-    __mmio_buddy_init();
-    kinfo("mmio_init success");
-}

+ 1 - 3
kernel/src/mm/mmio.h

@@ -1,7 +1,5 @@
 #pragma once
 #include "mm.h"
 
-extern void mmio_buddy_init();
-extern void mmio_create();
+extern void mmio_create(uint32_t size, uint64_t vm_flagsu, uint64_t* res_vaddr, uint64_t* res_length);
 extern int mmio_release(int vaddr, int length);
-void mmio_init();

+ 160 - 219
kernel/src/mm/mmio_buddy.rs

@@ -1,16 +1,19 @@
 use crate::libs::spinlock::{SpinLock, SpinLockGuard};
+use crate::mm::kernel_mapper::KernelMapper;
 use crate::syscall::SystemError;
 use crate::{
     arch::asm::current::current_pcb,
-    include::bindings::bindings::{
-        initial_mm, mm_create_vma, mm_unmap, vm_area_del, vm_area_free, vm_area_struct, vm_flags_t,
-        vma_find, MMIO_BASE, MMIO_TOP, PAGE_1G_SHIFT, PAGE_1G_SIZE, PAGE_2M_SIZE, PAGE_4K_SHIFT,
-        PAGE_4K_SIZE, VM_DONTCOPY, VM_IO,
-    },
-    kdebug, kerror,
+    include::bindings::bindings::{vm_flags_t, PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
+    kdebug,
+    mm::{MMArch, MemoryManagementArch},
 };
-use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
-use core::{mem, ptr::null_mut};
+use crate::{kerror, kinfo, kwarn};
+use alloc::{collections::LinkedList, vec::Vec};
+use core::mem;
+use core::mem::MaybeUninit;
+use core::sync::atomic::{compiler_fence, Ordering};
+
+use super::VirtAddr;
 
 // 最大的伙伴块的幂
 const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT;
@@ -19,8 +22,15 @@ const MMIO_BUDDY_MIN_EXP: u32 = PAGE_4K_SHIFT;
 // 内存池数组的范围
 const MMIO_BUDDY_REGION_COUNT: u32 = MMIO_BUDDY_MAX_EXP - MMIO_BUDDY_MIN_EXP + 1;
 
-lazy_static! {
-    pub static ref MMIO_POOL: MmioBuddyMemPool = MmioBuddyMemPool::new();
+const MMIO_BASE: VirtAddr = VirtAddr::new(0xffffa10000000000);
+const MMIO_TOP: VirtAddr = VirtAddr::new(0xffffa20000000000);
+
+const PAGE_1G_SIZE: usize = 1 << 30;
+
+static mut __MMIO_POOL: Option<MmioBuddyMemPool> = None;
+
+pub fn mmio_pool() -> &'static mut MmioBuddyMemPool {
+    unsafe { __MMIO_POOL.as_mut().unwrap() }
 }
 
 pub enum MmioResult {
@@ -32,25 +42,49 @@ pub enum MmioResult {
 }
 
 /// @brief buddy内存池
+#[derive(Debug)]
 pub struct MmioBuddyMemPool {
-    pool_start_addr: u64,
-    pool_size: u64,
+    pool_start_addr: VirtAddr,
+    pool_size: usize,
     free_regions: [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize],
 }
-impl Default for MmioBuddyMemPool {
-    fn default() -> Self {
-        MmioBuddyMemPool {
-            pool_start_addr: MMIO_BASE as u64,
-            pool_size: (MMIO_TOP - MMIO_BASE) as u64,
-            free_regions: unsafe { mem::zeroed() },
-        }
-    }
-}
+
 impl MmioBuddyMemPool {
     fn new() -> Self {
-        return MmioBuddyMemPool {
-            ..Default::default()
+        let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
+            MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };
+        for i in 0..MMIO_BUDDY_REGION_COUNT {
+            free_regions[i as usize] = MaybeUninit::new(SpinLock::new(MmioFreeRegionList::new()));
+        }
+        let free_regions = unsafe {
+            mem::transmute::<_, [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize]>(
+                free_regions,
+            )
+        };
+
+        let pool = MmioBuddyMemPool {
+            pool_start_addr: MMIO_BASE,
+            pool_size: MMIO_TOP - MMIO_BASE,
+            free_regions,
         };
+        kdebug!("MMIO buddy pool init: created");
+
+        let cnt_1g_blocks = (MMIO_TOP - MMIO_BASE) >> 30;
+        let mut vaddr_base = MMIO_BASE;
+        kdebug!("total 1G blocks: {cnt_1g_blocks}");
+        for _i in 0..cnt_1g_blocks {
+            compiler_fence(Ordering::SeqCst);
+            match pool.give_back_block(vaddr_base, PAGE_1G_SHIFT) {
+                Ok(_) => {
+                    vaddr_base += PAGE_1G_SIZE;
+                }
+                Err(_) => {
+                    panic!("MMIO buddy pool init failed");
+                }
+            }
+        }
+        kdebug!("MMIO buddy pool init success");
+        return pool;
     }
 
     /// @brief 创建新的地址区域结构体
@@ -58,9 +92,12 @@ impl MmioBuddyMemPool {
     /// @param vaddr 虚拟地址
     ///
     /// @return 创建好的地址区域结构体
-    fn create_region(&self, vaddr: u64) -> Box<MmioBuddyAddrRegion> {
-        let mut region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion::new());
-        region.vaddr = vaddr;
+    fn create_region(&self, vaddr: VirtAddr) -> MmioBuddyAddrRegion {
+        // kdebug!("create_region for vaddr: {vaddr:?}");
+
+        let region: MmioBuddyAddrRegion = MmioBuddyAddrRegion::new(vaddr);
+
+        // kdebug!("create_region for vaddr: {vaddr:?} OK!!!");
         return region;
     }
 
@@ -75,16 +112,16 @@ impl MmioBuddyMemPool {
     /// @return Ok(i32) 返回0
     ///
     /// @return Err(SystemError) 返回错误码
-    fn give_back_block(&self, vaddr: u64, exp: u32) -> Result<i32, SystemError> {
+    fn give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError> {
         // 确保内存对齐,低位都要为0
-        if (vaddr & ((1 << exp) - 1)) != 0 {
+        if (vaddr.data() & ((1 << exp) - 1)) != 0 {
             return Err(SystemError::EINVAL);
         }
-        let region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
+        let region: MmioBuddyAddrRegion = self.create_region(vaddr);
         // 加入buddy
-        let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
-            &mut self.free_regions[exp2index(exp)].lock();
-        self.push_block(region, list_guard);
+        let mut list_guard = self.free_regions[exp2index(exp)].lock();
+
+        self.push_block(region, &mut list_guard);
         return Ok(0);
     }
 
@@ -97,12 +134,12 @@ impl MmioBuddyMemPool {
     /// @param list_guard 【exp-1】对应的链表
     fn split_block(
         &self,
-        region: Box<MmioBuddyAddrRegion>,
+        region: MmioBuddyAddrRegion,
         exp: u32,
         low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
     ) {
-        let vaddr: u64 = self.calculate_block_vaddr(region.vaddr, exp - 1);
-        let new_region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
+        let vaddr = self.calculate_block_vaddr(region.vaddr, exp - 1);
+        let new_region: MmioBuddyAddrRegion = self.create_region(vaddr);
         self.push_block(region, low_list_guard);
         self.push_block(new_region, low_list_guard);
     }
@@ -113,7 +150,7 @@ impl MmioBuddyMemPool {
     ///
     /// @param list_guard exp对应的链表
     ///
-    /// @return Ok(Box<MmioBuddyAddrRegion>) 符合要求的内存区域。
+    /// @return Ok(MmioBuddyAddrRegion) 符合要求的内存区域。
     ///
     /// @return Err(MmioResult)
     /// - 没有满足要求的内存块时,返回ENOFOUND
@@ -123,7 +160,7 @@ impl MmioBuddyMemPool {
         &self,
         exp: u32,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
-    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
+    ) -> Result<MmioBuddyAddrRegion, MmioResult> {
         // 申请范围错误
         if exp < MMIO_BUDDY_MIN_EXP || exp > MMIO_BUDDY_MAX_EXP {
             kdebug!("query_addr_region: exp wrong");
@@ -256,12 +293,9 @@ impl MmioBuddyMemPool {
     ///
     /// @param exp 内存区域的大小(2^exp)
     ///
-    /// @return Ok(Box<MmioBuddyAddrRegion>)符合要求的内存块信息结构体。
+    /// @return Ok(MmioBuddyAddrRegion)符合要求的内存块信息结构体。
     /// @return Err(MmioResult) 没有满足要求的内存块时,返回__query_addr_region的错误码。
-    fn mmio_buddy_query_addr_region(
-        &self,
-        exp: u32,
-    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
+    fn mmio_buddy_query_addr_region(&self, exp: u32) -> Result<MmioBuddyAddrRegion, MmioResult> {
         let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
             &mut self.free_regions[exp2index(exp)].lock();
         match self.query_addr_region(exp, list_guard) {
@@ -279,7 +313,7 @@ impl MmioBuddyMemPool {
     /// @param list_guard 目标链表
     fn push_block(
         &self,
-        region: Box<MmioBuddyAddrRegion>,
+        region: MmioBuddyAddrRegion,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
     ) {
         list_guard.list.push_back(region);
@@ -288,8 +322,8 @@ impl MmioBuddyMemPool {
 
     /// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
     #[inline(always)]
-    fn calculate_block_vaddr(&self, vaddr: u64, exp: u32) -> u64 {
-        return vaddr ^ (1 << exp);
+    fn calculate_block_vaddr(&self, vaddr: VirtAddr, exp: u32) -> VirtAddr {
+        return VirtAddr::new(vaddr.data() ^ (1 << exp as usize));
     }
 
     /// @brief 寻找并弹出指定内存块的伙伴块
@@ -306,10 +340,10 @@ impl MmioBuddyMemPool {
     /// - 没有找到伙伴块,返回ENOFOUND
     fn pop_buddy_block(
         &self,
-        vaddr: u64,
+        vaddr: VirtAddr,
         exp: u32,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
-    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
+    ) -> Result<MmioBuddyAddrRegion, MmioResult> {
         if list_guard.list.len() == 0 {
             return Err(MmioResult::ISEMPTY);
         } else {
@@ -317,7 +351,7 @@ impl MmioBuddyMemPool {
             let buddy_vaddr = self.calculate_block_vaddr(vaddr, exp);
 
             // element 只会有一个元素
-            let mut element: Vec<Box<MmioBuddyAddrRegion>> = list_guard
+            let mut element: Vec<MmioBuddyAddrRegion> = list_guard
                 .list
                 .drain_filter(|x| x.vaddr == buddy_vaddr)
                 .collect();
@@ -335,13 +369,13 @@ impl MmioBuddyMemPool {
     ///
     /// @param list_guard 【exp】对应的链表
     ///
-    /// @return Ok(Box<MmioBuddyAddrRegion>) 内存块信息结构体的引用。
+    /// @return Ok(MmioBuddyAddrRegion) 内存块信息结构体的引用。
     ///
     /// @return Err(MmioResult) 当链表为空,无法删除时,返回ISEMPTY
     fn pop_block(
         &self,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
-    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
+    ) -> Result<MmioBuddyAddrRegion, MmioResult> {
         if !list_guard.list.is_empty() {
             list_guard.num_free -= 1;
             return Ok(list_guard.list.pop_back().unwrap());
@@ -377,17 +411,15 @@ impl MmioBuddyMemPool {
                 break;
             }
             // 获取内存块
-            let vaddr: u64 = list_guard.list.back().unwrap().vaddr;
+            let vaddr: VirtAddr = list_guard.list.back().unwrap().vaddr;
             // 获取伙伴内存块
             match self.pop_buddy_block(vaddr, exp, list_guard) {
                 Err(err) => {
                     return Err(err);
                 }
                 Ok(buddy_region) => {
-                    let region: Box<MmioBuddyAddrRegion> = list_guard.list.pop_back().unwrap();
-                    let copy_region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion {
-                        vaddr: region.vaddr,
-                    });
+                    let region: MmioBuddyAddrRegion = list_guard.list.pop_back().unwrap();
+                    let copy_region = region.clone();
                     // 在两块内存都被取出之后才进行合并
                     match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
                         Err(err) => {
@@ -415,8 +447,8 @@ impl MmioBuddyMemPool {
     /// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL
     fn merge_blocks(
         &self,
-        region_1: Box<MmioBuddyAddrRegion>,
-        region_2: Box<MmioBuddyAddrRegion>,
+        region_1: MmioBuddyAddrRegion,
+        region_2: MmioBuddyAddrRegion,
         exp: u32,
         high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
     ) -> Result<MmioResult, MmioResult> {
@@ -444,102 +476,43 @@ impl MmioBuddyMemPool {
     /// @return Err(SystemError) 失败返回错误码
     pub fn create_mmio(
         &self,
-        size: u32,
-        vm_flags: vm_flags_t,
+        size: usize,
+        _vm_flags: vm_flags_t,
         res_vaddr: *mut u64,
         res_length: *mut u64,
     ) -> Result<i32, SystemError> {
         if size > PAGE_1G_SIZE || size == 0 {
             return Err(SystemError::EPERM);
         }
-        let mut retval: i32 = 0;
+        let retval: i32 = 0;
         // 计算前导0
-        let mut size_exp: u32 = 31 - size.leading_zeros();
+        #[cfg(target_arch = "x86_64")]
+        let mut size_exp: u32 = 63 - size.leading_zeros();
         // 记录最终申请的空间大小
-        let mut new_size: u32 = size;
+        let mut new_size = size;
         // 对齐要申请的空间大小
         // 如果要申请的空间大小小于4k,则分配4k
         if size_exp < PAGE_4K_SHIFT {
-            new_size = PAGE_4K_SIZE;
+            new_size = PAGE_4K_SIZE as usize;
             size_exp = PAGE_4K_SHIFT;
         } else if (new_size & (!(1 << size_exp))) != 0 {
             // 向左对齐空间大小
             size_exp += 1;
             new_size = 1 << size_exp;
         }
-        match MMIO_POOL.mmio_buddy_query_addr_region(size_exp) {
+        match self.mmio_buddy_query_addr_region(size_exp) {
             Ok(region) => {
-                unsafe {
-                    *res_vaddr = region.vaddr;
-                    *res_length = new_size as u64;
-                }
-                // 创建vma
-                let flags: u64 = vm_flags | (VM_IO | VM_DONTCOPY) as u64;
-                let len_4k: u64 = (new_size % PAGE_2M_SIZE) as u64;
-                let len_2m: u64 = new_size as u64 - len_4k;
-                let mut loop_i: u64 = 0;
-                // 先分配2M的vma
-                loop {
-                    if loop_i >= len_2m {
-                        break;
-                    }
-                    let vma: *mut *mut vm_area_struct = null_mut();
-                    retval = unsafe {
-                        mm_create_vma(
-                            &mut initial_mm,
-                            region.vaddr + loop_i,
-                            PAGE_2M_SIZE.into(),
-                            flags,
-                            null_mut(),
-                            vma,
-                        )
-                    };
-                    if retval != 0 {
-                        kdebug!(
-                            "failed to create mmio 2m vma. pid = {:?}",
-                            current_pcb().pid
-                        );
-                        unsafe {
-                            vm_area_del(*vma);
-                            vm_area_free(*vma);
-                        }
-                        return Err(SystemError::from_posix_errno(retval).unwrap());
-                    }
-                    loop_i += PAGE_2M_SIZE as u64;
-                }
-                // 分配4K的vma
-                loop_i = len_2m;
-                loop {
-                    if loop_i >= size as u64 {
-                        break;
-                    }
-                    let vma: *mut *mut vm_area_struct = null_mut();
-                    retval = unsafe {
-                        mm_create_vma(
-                            &mut initial_mm,
-                            region.vaddr + loop_i,
-                            PAGE_4K_SIZE.into(),
-                            flags,
-                            null_mut(),
-                            vma,
-                        )
-                    };
-                    if retval != 0 {
-                        kdebug!(
-                            "failed to create mmio 4k vma. pid = {:?}",
-                            current_pcb().pid
-                        );
-                        unsafe {
-                            vm_area_del(*vma);
-                            vm_area_free(*vma);
-                        }
-                        return Err(SystemError::from_posix_errno(retval).unwrap());
-                    }
-                    loop_i += PAGE_4K_SIZE as u64;
-                }
+                // todo: 是否需要创建vma?或者用新重写的机制去做?
+                // kdebug!(
+                //     "create_mmio: vaddr = {:?}, length = {}",
+                //     region.vaddr,
+                //     new_size
+                // );
+                unsafe { *res_vaddr = region.vaddr.data() as u64 };
+                unsafe { *res_length = new_size as u64 };
             }
             Err(_) => {
-                kdebug!("failed to create mmio vma.pid = {:?}", current_pcb().pid);
+                kerror!("failed to create mmio. pid = {:?}", current_pcb().pid);
                 return Err(SystemError::ENOMEM);
             }
         }
@@ -555,83 +528,62 @@ impl MmioBuddyMemPool {
     /// @return Ok(i32) 成功返回0
     ///
     /// @return Err(SystemError) 失败返回错误码
-    pub fn release_mmio(&self, vaddr: u64, length: u64) -> Result<i32, SystemError> {
-        //先将要释放的空间取消映射
-        unsafe {
-            mm_unmap(&mut initial_mm, vaddr, length, false);
+    pub fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
+        assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
+        assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
+        if vaddr < self.pool_start_addr
+            || vaddr.data() >= self.pool_start_addr.data() + self.pool_size
+        {
+            return Err(SystemError::EINVAL);
         }
-        let mut loop_i: u64 = 0;
-        loop {
-            if loop_i >= length {
-                break;
-            }
-            // 获取要释放的vma的结构体
-            let vma: *mut vm_area_struct = unsafe { vma_find(&mut initial_mm, vaddr + loop_i) };
-            if vma == null_mut() {
-                kdebug!(
-                    "mmio_release failed: vma not found. At address: {:?}, pid = {:?}",
-                    vaddr + loop_i,
-                    current_pcb().pid
-                );
-                return Err(SystemError::EINVAL);
-            }
-            // 检查vma起始地址是否正确
-            if unsafe { (*vma).vm_start != (vaddr + loop_i) } {
-                kdebug!(
-                    "mmio_release failed: addr_start is not equal to current: {:?}. pid = {:?}",
-                    vaddr + loop_i,
-                    current_pcb().pid
-                );
-                return Err(SystemError::EINVAL);
-            }
-            // 将vma对应空间归还
-            match MMIO_POOL.give_back_block(unsafe { (*vma).vm_start }, unsafe {
-                31 - ((*vma).vm_end - (*vma).vm_start).leading_zeros()
-            }) {
-                Ok(_) => {
-                    loop_i += unsafe { (*vma).vm_end - (*vma).vm_start };
-                    unsafe {
-                        vm_area_del(vma);
-                        vm_area_free(vma);
-                    }
-                }
-                Err(err) => {
-                    // vma对应空间没有成功归还的话,就不删除vma
-                    kdebug!(
-                        "mmio_release give_back failed: pid = {:?}",
-                        current_pcb().pid
-                    );
-                    return Err(err);
-                }
-            }
+        // todo: 重构MMIO管理机制,创建类似全局的manager之类的,管理MMIO的空间?
+
+        // 暂时认为传入的vaddr都是正确的
+        let page_count = length / MMArch::PAGE_SIZE;
+        // 取消映射
+        let mut bindings = KernelMapper::lock();
+        let mut kernel_mapper = bindings.as_mut();
+        if kernel_mapper.is_none() {
+            kwarn!("release_mmio: kernel_mapper is read only");
+            return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
+        }
+
+        for i in 0..page_count {
+            unsafe {
+                kernel_mapper
+                    .as_mut()
+                    .unwrap()
+                    .unmap(vaddr + i * MMArch::PAGE_SIZE, true)
+            };
         }
+
+        // todo: 归还到buddy
+
         return Ok(0);
     }
 }
 
 /// @brief mmio伙伴系统内部的地址区域结构体
-pub struct MmioBuddyAddrRegion {
-    vaddr: u64,
+#[derive(Debug, Clone)]
+struct MmioBuddyAddrRegion {
+    vaddr: VirtAddr,
 }
 impl MmioBuddyAddrRegion {
-    pub fn new() -> Self {
-        return MmioBuddyAddrRegion {
-            ..Default::default()
-        };
+    pub fn new(vaddr: VirtAddr) -> Self {
+        return MmioBuddyAddrRegion { vaddr };
     }
-}
-impl Default for MmioBuddyAddrRegion {
-    fn default() -> Self {
-        MmioBuddyAddrRegion {
-            vaddr: Default::default(),
-        }
+
+    #[allow(dead_code)]
+    pub fn vaddr(&self) -> VirtAddr {
+        return self.vaddr;
     }
 }
 
 /// @brief 空闲页数组结构体
+#[derive(Debug)]
 pub struct MmioFreeRegionList {
     /// 存储mmio_buddy的地址链表
-    list: LinkedList<Box<MmioBuddyAddrRegion>>,
+    list: LinkedList<MmioBuddyAddrRegion>,
     /// 空闲块的数量
     num_free: i64,
 }
@@ -652,25 +604,6 @@ impl Default for MmioFreeRegionList {
     }
 }
 
-/// @brief 初始化mmio的伙伴系统
-#[no_mangle]
-pub extern "C" fn __mmio_buddy_init() {
-    // 创建一堆1GB的地址块
-    let cnt_1g_blocks: u32 = ((MMIO_TOP - MMIO_BASE) / PAGE_1G_SIZE as i64) as u32;
-    let mut vaddr_base: u64 = MMIO_BASE as u64;
-    for _ in 0..cnt_1g_blocks {
-        match MMIO_POOL.give_back_block(vaddr_base, PAGE_1G_SHIFT) {
-            Ok(_) => {
-                vaddr_base += PAGE_1G_SIZE as u64;
-            }
-            Err(_) => {
-                kerror!("__mmio_buddy_init failed");
-                return;
-            }
-        }
-    }
-}
-
 /// @brief 将内存对象大小的幂转换成内存池中的数组的下标
 ///
 /// @param exp内存大小
@@ -681,6 +614,15 @@ fn exp2index(exp: u32) -> usize {
     return (exp - 12) as usize;
 }
 
+pub fn mmio_init() {
+    kdebug!("Initializing MMIO buddy memory pool...");
+    // 初始化mmio内存池
+    unsafe {
+        __MMIO_POOL = Some(MmioBuddyMemPool::new());
+    }
+
+    kinfo!("MMIO buddy memory pool init done");
+}
 /// @brief 创建一块mmio区域,并将vma绑定到initial_mm
 ///
 /// @param size mmio区域的大小(字节)
@@ -699,7 +641,8 @@ pub extern "C" fn mmio_create(
     res_vaddr: *mut u64,
     res_length: *mut u64,
 ) -> i32 {
-    if let Err(err) = MMIO_POOL.create_mmio(size, vm_flags, res_vaddr, res_length) {
+    // kdebug!("mmio_create");
+    if let Err(err) = mmio_pool().create_mmio(size as usize, vm_flags, res_vaddr, res_length) {
         return err.to_posix_errno();
     } else {
         return 0;
@@ -717,9 +660,7 @@ pub extern "C" fn mmio_create(
 /// @return Err(i32) 失败返回错误码
 #[no_mangle]
 pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
-    if let Err(err) = MMIO_POOL.release_mmio(vaddr, length) {
-        return err.to_posix_errno();
-    } else {
-        return 0;
-    }
+    return mmio_pool()
+        .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
+        .unwrap_or_else(|err| err.to_posix_errno());
 }

+ 609 - 4
kernel/src/mm/mod.rs

@@ -1,9 +1,63 @@
-use crate::include::bindings::bindings::{mm_struct, process_control_block, PAGE_OFFSET};
+use alloc::sync::Arc;
+
+use crate::{
+    arch::MMArch,
+    include::bindings::bindings::{process_control_block, PAGE_OFFSET},
+    syscall::SystemError,
+};
+
+use core::{
+    cmp,
+    fmt::Debug,
+    intrinsics::unlikely,
+    ops::{Add, AddAssign, Sub, SubAssign},
+    ptr,
+    sync::atomic::{AtomicBool, Ordering},
+};
+
+use self::{
+    allocator::page_frame::{VirtPageFrame, VirtPageFrameIter},
+    page::round_up_to_page_size,
+    ucontext::{AddressSpace, UserMapper},
+};
 
 pub mod allocator;
+pub mod c_adapter;
 pub mod gfp;
+pub mod kernel_mapper;
 pub mod mmio_buddy;
+pub mod no_init;
+pub mod page;
 pub mod syscall;
+pub mod ucontext;
+
+/// 内核INIT进程的用户地址空间结构体(仅在process_init中初始化)
+static mut __INITIAL_PROCESS_ADDRESS_SPACE: Option<Arc<AddressSpace>> = None;
+
+/// 获取内核INIT进程的用户地址空间结构体
+#[allow(non_snake_case)]
+#[inline(always)]
+pub fn INITIAL_PROCESS_ADDRESS_SPACE() -> Arc<AddressSpace> {
+    unsafe {
+        return __INITIAL_PROCESS_ADDRESS_SPACE
+            .as_ref()
+            .expect("INITIAL_PROCESS_ADDRESS_SPACE is null")
+            .clone();
+    }
+}
+
+/// 设置内核INIT进程的用户地址空间结构体全局变量
+#[allow(non_snake_case)]
+pub unsafe fn set_INITIAL_PROCESS_ADDRESS_SPACE(address_space: Arc<AddressSpace>) {
+    static INITIALIZED: AtomicBool = AtomicBool::new(false);
+    if INITIALIZED
+        .compare_exchange(false, true, Ordering::SeqCst, Ordering::Acquire)
+        .is_err()
+    {
+        panic!("INITIAL_PROCESS_ADDRESS_SPACE is already initialized");
+    }
+    __INITIAL_PROCESS_ADDRESS_SPACE = Some(address_space);
+}
 
 /// @brief 将内核空间的虚拟地址转换为物理地址
 #[inline(always)]
@@ -17,10 +71,561 @@ pub fn phys_2_virt(addr: usize) -> usize {
     addr + PAGE_OFFSET as usize
 }
 
-// ====== 重构内存管理后,请删除18-24行 ======
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
+pub enum PageTableKind {
+    /// 用户可访问的页表
+    User,
+    /// 内核页表
+    Kernel,
+}
+
+/// 物理内存地址
+#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
+#[repr(transparent)]
+pub struct PhysAddr(usize);
+
+impl PhysAddr {
+    #[inline(always)]
+    pub const fn new(address: usize) -> Self {
+        Self(address)
+    }
+
+    /// @brief 获取物理地址的值
+    #[inline(always)]
+    pub fn data(&self) -> usize {
+        self.0
+    }
+
+    /// @brief 将物理地址加上一个偏移量
+    #[inline(always)]
+    pub fn add(self, offset: usize) -> Self {
+        Self(self.0 + offset)
+    }
+
+    /// @brief 判断物理地址是否按照指定要求对齐
+    #[inline(always)]
+    pub fn check_aligned(&self, align: usize) -> bool {
+        return self.0 & (align - 1) == 0;
+    }
+
+    #[inline(always)]
+    pub fn is_null(&self) -> bool {
+        return self.0 == 0;
+    }
+}
+
+impl Debug for PhysAddr {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        write!(f, "PhysAddr({:#x})", self.0)
+    }
+}
+
+impl core::ops::Add<usize> for PhysAddr {
+    type Output = Self;
+
+    #[inline(always)]
+    fn add(self, rhs: usize) -> Self::Output {
+        return Self(self.0 + rhs);
+    }
+}
+
+impl core::ops::AddAssign<usize> for PhysAddr {
+    #[inline(always)]
+    fn add_assign(&mut self, rhs: usize) {
+        self.0 += rhs;
+    }
+}
+
+impl core::ops::Add<PhysAddr> for PhysAddr {
+    type Output = Self;
+
+    #[inline(always)]
+    fn add(self, rhs: PhysAddr) -> Self::Output {
+        return Self(self.0 + rhs.0);
+    }
+}
+
+impl core::ops::AddAssign<PhysAddr> for PhysAddr {
+    #[inline(always)]
+    fn add_assign(&mut self, rhs: PhysAddr) {
+        self.0 += rhs.0;
+    }
+}
+
+impl core::ops::Sub<usize> for PhysAddr {
+    type Output = Self;
+
+    #[inline(always)]
+    fn sub(self, rhs: usize) -> Self::Output {
+        return Self(self.0 - rhs);
+    }
+}
+
+impl core::ops::SubAssign<usize> for PhysAddr {
+    #[inline(always)]
+    fn sub_assign(&mut self, rhs: usize) {
+        self.0 -= rhs;
+    }
+}
+
+impl core::ops::Sub<PhysAddr> for PhysAddr {
+    type Output = usize;
+
+    #[inline(always)]
+    fn sub(self, rhs: PhysAddr) -> Self::Output {
+        return self.0 - rhs.0;
+    }
+}
+
+impl core::ops::SubAssign<PhysAddr> for PhysAddr {
+    #[inline(always)]
+    fn sub_assign(&mut self, rhs: PhysAddr) {
+        self.0 -= rhs.0;
+    }
+}
+
+/// 虚拟内存地址
+#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
+#[repr(transparent)]
+pub struct VirtAddr(usize);
+
+impl VirtAddr {
+    #[inline(always)]
+    pub const fn new(address: usize) -> Self {
+        return Self(address);
+    }
+
+    /// @brief 获取虚拟地址的值
+    #[inline(always)]
+    pub fn data(&self) -> usize {
+        return self.0;
+    }
+
+    /// @brief 判断虚拟地址的类型
+    #[inline(always)]
+    pub fn kind(&self) -> PageTableKind {
+        if self.check_user() {
+            return PageTableKind::User;
+        } else {
+            return PageTableKind::Kernel;
+        }
+    }
+
+    /// @brief 判断虚拟地址是否按照指定要求对齐
+    #[inline(always)]
+    pub fn check_aligned(&self, align: usize) -> bool {
+        return self.0 & (align - 1) == 0;
+    }
+
+    /// @brief 判断虚拟地址是否在用户空间
+    #[inline(always)]
+    pub fn check_user(&self) -> bool {
+        if self < &MMArch::USER_END_VADDR {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    #[inline(always)]
+    pub fn as_ptr<T>(self) -> *mut T {
+        return self.0 as *mut T;
+    }
+
+    #[inline(always)]
+    pub fn is_null(&self) -> bool {
+        return self.0 == 0;
+    }
+}
+
+impl Add<VirtAddr> for VirtAddr {
+    type Output = Self;
+
+    #[inline(always)]
+    fn add(self, rhs: VirtAddr) -> Self::Output {
+        return Self(self.0 + rhs.0);
+    }
+}
+
+impl Add<usize> for VirtAddr {
+    type Output = Self;
+
+    #[inline(always)]
+    fn add(self, rhs: usize) -> Self::Output {
+        return Self(self.0 + rhs);
+    }
+}
+
+impl Sub<VirtAddr> for VirtAddr {
+    type Output = usize;
+
+    #[inline(always)]
+    fn sub(self, rhs: VirtAddr) -> Self::Output {
+        return self.0 - rhs.0;
+    }
+}
+
+impl Sub<usize> for VirtAddr {
+    type Output = Self;
+
+    #[inline(always)]
+    fn sub(self, rhs: usize) -> Self::Output {
+        return Self(self.0 - rhs);
+    }
+}
+
+impl AddAssign<usize> for VirtAddr {
+    #[inline(always)]
+    fn add_assign(&mut self, rhs: usize) {
+        self.0 += rhs;
+    }
+}
+
+impl AddAssign<VirtAddr> for VirtAddr {
+    #[inline(always)]
+    fn add_assign(&mut self, rhs: VirtAddr) {
+        self.0 += rhs.0;
+    }
+}
+
+impl SubAssign<usize> for VirtAddr {
+    #[inline(always)]
+    fn sub_assign(&mut self, rhs: usize) {
+        self.0 -= rhs;
+    }
+}
+
+impl SubAssign<VirtAddr> for VirtAddr {
+    #[inline(always)]
+    fn sub_assign(&mut self, rhs: VirtAddr) {
+        self.0 -= rhs.0;
+    }
+}
+
+impl Debug for VirtAddr {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        write!(f, "VirtAddr({:#x})", self.0)
+    }
+}
+
+/// @brief 物理内存区域
+#[derive(Clone, Copy, Debug)]
+pub struct PhysMemoryArea {
+    /// 物理基地址
+    pub base: PhysAddr,
+    /// 该区域的物理内存大小
+    pub size: usize,
+}
+
+pub trait MemoryManagementArch: Clone + Copy + Debug {
+    /// 页面大小的shift(假如页面4K,那么这个值就是12,因为2^12=4096)
+    const PAGE_SHIFT: usize;
+    /// 每个页表的页表项数目。(以2^n次幂来表示)假如有512个页表项,那么这个值就是9
+    const PAGE_ENTRY_SHIFT: usize;
+    /// 页表层级数量
+    const PAGE_LEVELS: usize;
+
+    /// 页表项的有效位的index(假如页表项的第0-51位有效,那么这个值就是52)
+    const ENTRY_ADDRESS_SHIFT: usize;
+    /// 页面的页表项的默认值
+    const ENTRY_FLAG_DEFAULT_PAGE: usize;
+    /// 页表的页表项的默认值
+    const ENTRY_FLAG_DEFAULT_TABLE: usize;
+    /// 页表项的present位被置位之后的值
+    const ENTRY_FLAG_PRESENT: usize;
+    /// 页表项为read only时的值
+    const ENTRY_FLAG_READONLY: usize;
+    /// 页表项为可读写状态的值
+    const ENTRY_FLAG_READWRITE: usize;
+    /// 页面项标记页面为user page的值
+    const ENTRY_FLAG_USER: usize;
+    /// 页面项标记页面为write through的值
+    const ENTRY_FLAG_WRITE_THROUGH: usize;
+    /// 页面项标记页面为cache disable的值
+    const ENTRY_FLAG_CACHE_DISABLE: usize;
+    /// 标记当前页面不可执行的标志位(Execute disable)(也就是说,不能从这段内存里面获取处理器指令)
+    const ENTRY_FLAG_NO_EXEC: usize;
+    /// 标记当前页面可执行的标志位(Execute enable)
+    const ENTRY_FLAG_EXEC: usize;
+
+    /// 虚拟地址与物理地址的偏移量
+    const PHYS_OFFSET: usize;
+
+    /// 每个页面的大小
+    const PAGE_SIZE: usize = 1 << Self::PAGE_SHIFT;
+    /// 通过这个mask,获取地址的页内偏移量
+    const PAGE_OFFSET_MASK: usize = Self::PAGE_SIZE - 1;
+    /// 页表项的地址、数据部分的shift。
+    /// 打个比方,如果这个值为52,那么意味着页表项的[0, 52)位,用于表示地址以及其他的标志位
+    const PAGE_ADDRESS_SHIFT: usize = Self::PAGE_LEVELS * Self::PAGE_ENTRY_SHIFT + Self::PAGE_SHIFT;
+    /// 最大的虚拟地址(对于不同的架构,由于上述PAGE_ADDRESS_SHIFT可能包括了reserved bits, 事实上能表示的虚拟地址应该比这个值要小)
+    const PAGE_ADDRESS_SIZE: usize = 1 << Self::PAGE_ADDRESS_SHIFT;
+    /// 页表项的值与这个常量进行与运算,得到的结果是所填写的物理地址
+    const PAGE_ADDRESS_MASK: usize = Self::PAGE_ADDRESS_SIZE - Self::PAGE_SIZE;
+    /// 每个页表项的大小
+    const PAGE_ENTRY_SIZE: usize = 1 << (Self::PAGE_SHIFT - Self::PAGE_ENTRY_SHIFT);
+    /// 每个页表的页表项数目
+    const PAGE_ENTRY_NUM: usize = 1 << Self::PAGE_ENTRY_SHIFT;
+    /// 该字段用于根据虚拟地址,获取该虚拟地址在对应的页表中是第几个页表项
+    const PAGE_ENTRY_MASK: usize = Self::PAGE_ENTRY_NUM - 1;
+
+    const PAGE_NEGATIVE_MASK: usize = !((Self::PAGE_ADDRESS_SIZE) - 1);
+
+    const ENTRY_ADDRESS_SIZE: usize = 1 << Self::ENTRY_ADDRESS_SHIFT;
+    /// 该mask用于获取页表项中地址字段
+    const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - Self::PAGE_SIZE;
+    /// 这个mask用于获取页表项中的flags
+    const ENTRY_FLAGS_MASK: usize = !Self::ENTRY_ADDRESS_MASK;
+
+    /// 用户空间的最高地址
+    const USER_END_VADDR: VirtAddr;
+    /// 用户堆的起始地址
+    const USER_BRK_START: VirtAddr;
+    /// 用户栈起始地址(向下生长,不包含该值)
+    const USER_STACK_START: VirtAddr;
+
+    /// @brief 用于初始化内存管理模块与架构相关的信息。
+    /// 该函数应调用其他模块的接口,生成内存区域结构体,提供给BumpAllocator使用
+    unsafe fn init() -> &'static [PhysMemoryArea];
+
+    /// @brief 读取指定虚拟地址的值,并假设它是类型T的指针
+    #[inline(always)]
+    unsafe fn read<T>(address: VirtAddr) -> T {
+        return ptr::read(address.data() as *const T);
+    }
+
+    /// @brief 将value写入到指定的虚拟地址
+    #[inline(always)]
+    unsafe fn write<T>(address: VirtAddr, value: T) {
+        ptr::write(address.data() as *mut T, value);
+    }
+
+    #[inline(always)]
+    unsafe fn write_bytes(address: VirtAddr, value: u8, count: usize) {
+        ptr::write_bytes(address.data() as *mut u8, value, count);
+    }
+
+    /// @brief 刷新TLB中,关于指定虚拟地址的条目
+    unsafe fn invalidate_page(address: VirtAddr);
+
+    /// @brief 刷新TLB中,所有的条目
+    unsafe fn invalidate_all();
+
+    /// @brief 获取顶级页表的物理地址
+    unsafe fn table(table_kind: PageTableKind) -> PhysAddr;
+
+    /// @brief 设置顶级页表的物理地址到处理器中
+    unsafe fn set_table(table_kind: PageTableKind, table: PhysAddr);
+
+    /// @brief 将物理地址转换为虚拟地址.
+    ///
+    /// @param phys 物理地址
+    ///
+    /// @return 转换后的虚拟地址。如果转换失败,返回None
+    #[inline(always)]
+    unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
+        if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) {
+            return Some(VirtAddr::new(vaddr));
+        } else {
+            return None;
+        }
+    }
+
+    /// 将虚拟地址转换为物理地址
+    ///
+    /// ## 参数
+    ///
+    /// - `virt` 虚拟地址
+    ///
+    /// ## 返回值
+    ///
+    /// 转换后的物理地址。如果转换失败,返回None
+    #[inline(always)]
+    unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
+        if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
+            return Some(PhysAddr::new(paddr));
+        } else {
+            return None;
+        }
+    }
+
+    /// @brief 判断指定的虚拟地址是否正确(符合规范)
+    fn virt_is_valid(virt: VirtAddr) -> bool;
+
+    /// 获取内存管理初始化时,创建的第一个内核页表的地址
+    fn initial_page_table() -> PhysAddr;
+
+    /// 初始化新的usermapper,为用户进程创建页表
+    fn setup_new_usermapper() -> Result<UserMapper, SystemError>;
+}
+
+/// @brief 虚拟地址范围
+/// 该结构体用于表示一个虚拟地址范围,包括起始地址与大小
+///
+/// 请注意与VMA进行区分,该结构体被VMA所包含
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct VirtRegion {
+    start: VirtAddr,
+    size: usize,
+}
+
+#[allow(dead_code)]
+impl VirtRegion {
+    /// # 创建一个新的虚拟地址范围
+    pub fn new(start: VirtAddr, size: usize) -> Self {
+        VirtRegion { start, size }
+    }
+
+    /// 获取虚拟地址范围的起始地址
+    #[inline(always)]
+    pub fn start(&self) -> VirtAddr {
+        self.start
+    }
+
+    /// 获取虚拟地址范围的截止地址(不包括返回的地址)
+    #[inline(always)]
+    pub fn end(&self) -> VirtAddr {
+        return self.start().add(self.size);
+    }
+
+    /// # Create a new VirtRegion from a range [start, end)
+    ///
+    /// If end <= start, return None
+    pub fn between(start: VirtAddr, end: VirtAddr) -> Option<Self> {
+        if unlikely(end.data() <= start.data()) {
+            return None;
+        }
+        let size = end.data() - start.data();
+        return Some(VirtRegion::new(start, size));
+    }
+
+    /// # 取两个虚拟地址范围的交集
+    ///
+    /// 如果两个虚拟地址范围没有交集,返回None
+    pub fn intersect(&self, other: &VirtRegion) -> Option<VirtRegion> {
+        let start = self.start.max(other.start);
+        let end = self.end().min(other.end());
+        return VirtRegion::between(start, end);
+    }
+
+    /// 设置虚拟地址范围的起始地址
+    #[inline(always)]
+    pub fn set_start(&mut self, start: VirtAddr) {
+        self.start = start;
+    }
+
+    #[inline(always)]
+    pub fn size(&self) -> usize {
+        self.size
+    }
+
+    /// 设置虚拟地址范围的大小
+    #[inline(always)]
+    pub fn set_size(&mut self, size: usize) {
+        self.size = size;
+    }
+
+    /// 判断虚拟地址范围是否为空
+    #[inline(always)]
+    pub fn is_empty(&self) -> bool {
+        self.size == 0
+    }
+
+    /// 将虚拟地址区域的大小向上对齐到页大小
+    #[inline(always)]
+    pub fn round_up_size_to_page(self) -> Self {
+        return VirtRegion::new(self.start, round_up_to_page_size(self.size));
+    }
+
+    /// 判断两个虚拟地址范围是否由于具有交集而导致冲突
+    #[inline(always)]
+    pub fn collide(&self, other: &VirtRegion) -> bool {
+        return self.intersect(other).is_some();
+    }
+
+    pub fn iter_pages(&self) -> VirtPageFrameIter {
+        return VirtPageFrame::iter_range(
+            VirtPageFrame::new(self.start),
+            VirtPageFrame::new(self.end()),
+        );
+    }
+
+    /// 获取[self.start(), region.start())的虚拟地址范围
+    ///
+    /// 如果self.start() >= region.start(),返回None
+    pub fn before(self, region: &VirtRegion) -> Option<Self> {
+        return Self::between(self.start(), region.start());
+    }
+
+    /// 获取[region.end(),self.end())的虚拟地址范围
+    ///
+    /// 如果 self.end() >= region.end() ,返回None
+    pub fn after(self, region: &VirtRegion) -> Option<Self> {
+        // if self.end() > region.end() none
+        return Self::between(region.end(), self.end());
+    }
+
+    /// 把当前虚拟地址范围内的某个虚拟地址,转换为另一个虚拟地址范围内的虚拟地址
+    ///
+    /// 如果vaddr不在当前虚拟地址范围内,返回None
+    ///
+    /// 如果vaddr在当前虚拟地址范围内,返回vaddr在new_base中的虚拟地址
+    pub fn rebase(self, vaddr: VirtAddr, new_base: &VirtRegion) -> Option<VirtAddr> {
+        if !self.contains(vaddr) {
+            return None;
+        }
+        let offset = vaddr.data() - self.start().data();
+        let new_start = new_base.start().data() + offset;
+        return Some(VirtAddr::new(new_start));
+    }
+
+    /// 判断虚拟地址范围是否包含指定的虚拟地址
+    pub fn contains(&self, addr: VirtAddr) -> bool {
+        return self.start() <= addr && addr < self.end();
+    }
+
+    /// 创建当前虚拟地址范围的页面迭代器
+    pub fn pages(&self) -> VirtPageFrameIter {
+        return VirtPageFrame::iter_range(
+            VirtPageFrame::new(self.start()),
+            VirtPageFrame::new(self.end()),
+        );
+    }
+}
+
+impl PartialOrd for VirtRegion {
+    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
+        return self.start.partial_cmp(&other.start);
+    }
+}
+
+impl Ord for VirtRegion {
+    fn cmp(&self, other: &Self) -> cmp::Ordering {
+        return self.start.cmp(&other.start);
+    }
+}
+
+/// ## 判断虚拟地址是否超出了用户空间
+///
+/// 如果虚拟地址超出了用户空间,返回Err(SystemError::EFAULT).
+/// 如果end < start,返回Err(SystemError::EOVERFLOW)
+///
+/// 否则返回Ok(())
+pub fn verify_area(addr: VirtAddr, size: usize) -> Result<(), SystemError> {
+    let end = addr.add(size);
+    if unlikely(end.data() < addr.data()) {
+        return Err(SystemError::EOVERFLOW);
+    }
+
+    if !addr.check_user() || !end.check_user() {
+        return Err(SystemError::EFAULT);
+    }
+
+    return Ok(());
+}
+// ====== 重构内存管理、进程管理后,请删除这几行 BEGIN ======
 //BUG pcb问题
 unsafe impl Send for process_control_block {}
 unsafe impl Sync for process_control_block {}
 
-unsafe impl Send for mm_struct {}
-unsafe impl Sync for mm_struct {}
+// ====== 重构内存管理后,请删除这几行 END =======

+ 79 - 0
kernel/src/mm/no_init.rs

@@ -0,0 +1,79 @@
+//! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能
+//!
+//! 这里假设在内核引导文件中,已经填写了前100M的内存映射关系,因此这里不需要任何动态分配。
+//!
+//! 映射关系为:
+//!
+//! 虚拟地址 0-100M与虚拟地址 0x8000_0000_0000 - 0x8000_0640_0000 之间具有重映射关系。
+//! 也就是说,他们的第二级页表在最顶级页表中,占用了第0和第256个页表项。
+//!
+
+use crate::mm::{MMArch, MemoryManagementArch, PhysAddr};
+use core::marker::PhantomData;
+
+use super::{
+    allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
+    page::PageFlags,
+    PageTableKind, VirtAddr,
+};
+
+/// 伪分配器
+struct PseudoAllocator<MMA> {
+    phantom: PhantomData<MMA>,
+}
+
+impl<MMA: MemoryManagementArch> PseudoAllocator<MMA> {
+    pub const fn new() -> Self {
+        Self {
+            phantom: PhantomData,
+        }
+    }
+}
+
+/// 为NoInitAllocator实现FrameAllocator
+impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
+    unsafe fn allocate(&mut self, _count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
+        panic!("NoInitAllocator can't allocate page frame");
+    }
+
+    unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) {
+        panic!("NoInitAllocator can't free page frame");
+    }
+    /// @brief: 获取内存区域页帧的使用情况
+    /// @param  self
+    /// @return 页帧的使用情况
+    unsafe fn usage(&self) -> PageFrameUsage {
+        panic!("NoInitAllocator can't get page frame usage");
+    }
+}
+
+/// Use pseudo mapper to map physical memory to virtual memory.
+///
+/// ## Safety
+///
+/// 调用该函数时,必须保证内存管理器尚未初始化。否则将导致未定义的行为
+///
+/// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
+pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
+    assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
+    assert!(paddr.check_aligned(MMArch::PAGE_SIZE));
+
+    let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();
+
+    let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
+        PageTableKind::Kernel,
+        MMArch::table(PageTableKind::Kernel),
+        &mut pseudo_allocator,
+    );
+
+    let flags: PageFlags<MMArch> = PageFlags::new().set_write(true).set_execute(true);
+
+    for i in 0..count.data() {
+        let vaddr = vaddr + i * MMArch::PAGE_SIZE;
+        let paddr = paddr + i * MMArch::PAGE_SIZE;
+        let flusher = mapper.map_phys(vaddr, paddr, flags).unwrap();
+        flusher.ignore();
+    }
+
+    mapper.make_current();
+}

+ 924 - 0
kernel/src/mm/page.rs

@@ -0,0 +1,924 @@
+use core::{
+    fmt::{self, Debug, Error, Formatter},
+    marker::PhantomData,
+    mem,
+    ops::Add,
+    sync::atomic::{compiler_fence, Ordering},
+};
+
+use crate::{
+    arch::{interrupt::ipi::send_ipi, MMArch},
+    exception::ipi::{IpiKind, IpiTarget},
+    kerror, kwarn,
+};
+
+use super::{
+    allocator::page_frame::FrameAllocator, syscall::ProtFlags, MemoryManagementArch, PageTableKind,
+    PhysAddr, VirtAddr,
+};
+
+#[derive(Debug)]
+pub struct PageTable<Arch> {
+    /// 当前页表表示的虚拟地址空间的起始地址
+    base: VirtAddr,
+    /// 当前页表所在的物理地址
+    phys: PhysAddr,
+    /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1])
+    level: usize,
+    phantom: PhantomData<Arch>,
+}
+
+#[allow(dead_code)]
+impl<Arch: MemoryManagementArch> PageTable<Arch> {
+    pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self {
+        Self {
+            base,
+            phys,
+            level,
+            phantom: PhantomData,
+        }
+    }
+
+    /// 获取顶级页表
+    ///
+    /// ## 参数
+    ///
+    /// - table_kind 页表类型
+    ///
+    /// ## 返回值
+    ///
+    /// 返回顶级页表
+    pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self {
+        return Self::new(
+            VirtAddr::new(0),
+            Arch::table(table_kind),
+            Arch::PAGE_LEVELS - 1,
+        );
+    }
+
+    /// 获取当前页表的物理地址
+    #[inline(always)]
+    pub fn phys(&self) -> PhysAddr {
+        self.phys
+    }
+
+    /// 当前页表表示的虚拟地址空间的起始地址
+    #[inline(always)]
+    pub fn base(&self) -> VirtAddr {
+        self.base
+    }
+
+    /// 获取当前页表的层级
+    #[inline(always)]
+    pub fn level(&self) -> usize {
+        self.level
+    }
+
+    /// 获取当前页表自身所在的虚拟地址
+    #[inline(always)]
+    pub unsafe fn virt(&self) -> VirtAddr {
+        return Arch::phys_2_virt(self.phys).unwrap();
+    }
+
+    /// 获取第i个页表项所表示的虚拟内存空间的起始地址
+    pub fn entry_base(&self, i: usize) -> Option<VirtAddr> {
+        if i < Arch::PAGE_ENTRY_NUM {
+            let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
+            return Some(self.base.add(i << shift));
+        } else {
+            return None;
+        }
+    }
+
+    /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分)
+    pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> {
+        if i < Arch::PAGE_ENTRY_NUM {
+            return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE));
+        } else {
+            return None;
+        }
+    }
+
+    /// 获取当前页表的第i个页表项
+    pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
+        let entry_virt = self.entry_virt(i)?;
+        return Some(PageEntry::new(Arch::read::<usize>(entry_virt)));
+    }
+
+    /// 设置当前页表的第i个页表项
+    pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> {
+        let entry_virt = self.entry_virt(i)?;
+        Arch::write::<usize>(entry_virt, entry.data());
+        return Some(());
+    }
+
+    /// 判断当前页表的第i个页表项是否已经填写了值
+    ///
+    /// ## 参数
+    /// - Some(true) 如果已经填写了值
+    /// - Some(false) 如果未填写值
+    /// - None 如果i超出了页表项的范围
+    pub fn entry_mapped(&self, i: usize) -> Option<bool> {
+        let etv = unsafe { self.entry_virt(i) }?;
+        if unsafe { Arch::read::<usize>(etv) } != 0 {
+            return Some(true);
+        } else {
+            return Some(false);
+        }
+    }
+
+    /// 根据虚拟地址,获取对应的页表项在页表中的下标
+    ///
+    /// ## 参数
+    ///
+    /// - addr: 虚拟地址
+    ///
+    /// ## 返回值
+    ///
+    /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None
+    pub unsafe fn index_of(&self, addr: VirtAddr) -> Option<usize> {
+        let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK);
+        let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
+
+        let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1;
+        if addr < self.base || addr >= self.base.add(mask) {
+            return None;
+        } else {
+            return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK);
+        }
+    }
+
+    /// 获取第i个页表项指向的下一级页表
+    pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> {
+        if self.level == 0 {
+            return None;
+        }
+
+        // 返回下一级页表
+        return Some(PageTable::new(
+            self.entry_base(index)?,
+            self.entry(index)?.address().ok()?,
+            self.level - 1,
+        ));
+    }
+}
+
+/// 页表项
+#[derive(Copy, Clone)]
+pub struct PageEntry<Arch> {
+    data: usize,
+    phantom: PhantomData<Arch>,
+}
+
+impl<Arch> Debug for PageEntry<Arch> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
+        f.write_fmt(format_args!("PageEntry({:#x})", self.data))
+    }
+}
+
+impl<Arch: MemoryManagementArch> PageEntry<Arch> {
+    #[inline(always)]
+    pub fn new(data: usize) -> Self {
+        Self {
+            data,
+            phantom: PhantomData,
+        }
+    }
+
+    #[inline(always)]
+    pub fn data(&self) -> usize {
+        self.data
+    }
+
+    /// 获取当前页表项指向的物理地址
+    ///
+    /// ## 返回值
+    ///
+    /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址
+    /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
+    #[inline(always)]
+    pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
+        let paddr = PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK);
+
+        if self.present() {
+            Ok(paddr)
+        } else {
+            Err(paddr)
+        }
+    }
+
+    #[inline(always)]
+    pub fn flags(&self) -> PageFlags<Arch> {
+        unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
+    }
+
+    #[inline(always)]
+    pub fn set_flags(&mut self, flags: PageFlags<Arch>) {
+        self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
+    }
+
+    #[inline(always)]
+    pub fn present(&self) -> bool {
+        return self.data & Arch::ENTRY_FLAG_PRESENT != 0;
+    }
+}
+
+/// 页表项的标志位
+#[derive(Copy, Clone, Hash)]
+pub struct PageFlags<Arch> {
+    data: usize,
+    phantom: PhantomData<Arch>,
+}
+
+#[allow(dead_code)]
+impl<Arch: MemoryManagementArch> PageFlags<Arch> {
+    #[inline(always)]
+    pub fn new() -> Self {
+        let mut r = unsafe {
+            Self::from_data(
+                Arch::ENTRY_FLAG_DEFAULT_PAGE
+                    | Arch::ENTRY_FLAG_READONLY
+                    | Arch::ENTRY_FLAG_NO_EXEC,
+            )
+        };
+
+        #[cfg(target_arch = "x86_64")]
+        {
+            if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
+                r = r.set_execute(true);
+            }
+        }
+
+        return r;
+    }
+
+    /// 根据ProtFlags生成PageFlags
+    ///
+    /// ## 参数
+    ///
+    /// - prot_flags: 页的保护标志
+    /// - user: 用户空间是否可访问
+    pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> {
+        let flags: PageFlags<Arch> = PageFlags::new()
+            .set_user(user)
+            .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
+            .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
+
+        return flags;
+    }
+
+    #[inline(always)]
+    pub fn data(&self) -> usize {
+        self.data
+    }
+
+    #[inline(always)]
+    pub const unsafe fn from_data(data: usize) -> Self {
+        return Self {
+            data: data,
+            phantom: PhantomData,
+        };
+    }
+
+    /// 为新页表的页表项设置默认值
+    ///
+    /// 默认值为:
+    /// - present
+    /// - read only
+    /// - kernel space
+    /// - no exec
+    #[inline(always)]
+    pub fn new_page_table(user: bool) -> Self {
+        return unsafe {
+            let r = Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE);
+            if user {
+                r.set_user(true)
+            } else {
+                r
+            }
+        };
+    }
+
+    /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。
+    ///
+    /// ## 参数
+    /// - flag 要更新的标志位的值
+    /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0
+    ///
+    /// ## 返回值
+    ///
+    /// 更新后的页表项
+    #[inline(always)]
+    #[must_use]
+    pub fn update_flags(mut self, flag: usize, value: bool) -> Self {
+        if value {
+            self.data |= flag;
+        } else {
+            self.data &= !flag;
+        }
+        return self;
+    }
+
+    /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true)
+    #[inline(always)]
+    pub fn has_flag(&self, flag: usize) -> bool {
+        return self.data & flag == flag;
+    }
+
+    #[inline(always)]
+    pub fn present(&self) -> bool {
+        return self.has_flag(Arch::ENTRY_FLAG_PRESENT);
+    }
+
+    /// 设置当前页表项的权限
+    ///
+    /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问
+    #[must_use]
+    #[inline(always)]
+    pub fn set_user(self, value: bool) -> Self {
+        return self.update_flags(Arch::ENTRY_FLAG_USER, value);
+    }
+
+    /// 用户态是否可以访问当前页表项
+    #[inline(always)]
+    pub fn has_user(&self) -> bool {
+        return self.has_flag(Arch::ENTRY_FLAG_USER);
+    }
+
+    /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读
+    ///
+    /// ## 返回值
+    ///
+    /// 更新后的页表项.
+    ///
+    /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项
+    #[must_use]
+    #[inline(always)]
+    pub fn set_write(self, value: bool) -> Self {
+        // 有的架构同时具有可写和不可写的标志位,因此需要同时更新
+        return self
+            .update_flags(Arch::ENTRY_FLAG_READONLY, !value)
+            .update_flags(Arch::ENTRY_FLAG_READWRITE, value);
+    }
+
+    /// 当前页表项是否可写
+    #[inline(always)]
+    pub fn has_write(&self) -> bool {
+        // 有的架构同时具有可写和不可写的标志位,因此需要同时判断
+        return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY)
+            == Arch::ENTRY_FLAG_READWRITE;
+    }
+
+    /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行
+    #[must_use]
+    #[inline(always)]
+    pub fn set_execute(self, mut value: bool) -> Self {
+        #[cfg(target_arch = "x86_64")]
+        {
+            // 如果xd位被保留,那么将可执行性设置为true
+            if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
+                value = true;
+            }
+        }
+
+        // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新
+        return self
+            .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value)
+            .update_flags(Arch::ENTRY_FLAG_EXEC, value);
+    }
+
+    /// 当前页表项是否可执行
+    #[inline(always)]
+    pub fn has_execute(&self) -> bool {
+        // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断
+        return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC)
+            == Arch::ENTRY_FLAG_EXEC;
+    }
+
+    /// 设置当前页表项的缓存策略
+    ///
+    /// ## 参数
+    ///
+    /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。
+    #[inline(always)]
+    pub fn set_page_cache_disable(self, value: bool) -> Self {
+        return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value);
+    }
+
+    /// 获取当前页表项的缓存策略
+    ///
+    /// ## 返回值
+    ///
+    /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。
+    #[inline(always)]
+    pub fn has_page_cache_disable(&self) -> bool {
+        return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE);
+    }
+
+    /// 设置当前页表项的写穿策略
+    ///
+    /// ## 参数
+    ///
+    /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
+    #[inline(always)]
+    pub fn set_page_write_through(self, value: bool) -> Self {
+        return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value);
+    }
+
+    /// 获取当前页表项的写穿策略
+    ///
+    /// ## 返回值
+    ///
+    /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。
+    #[inline(always)]
+    pub fn has_page_write_through(&self) -> bool {
+        return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH);
+    }
+
+    /// MMIO内存的页表项标志
+    #[inline(always)]
+    pub fn mmio_flags() -> Self {
+        return Self::new()
+            .set_user(false)
+            .set_write(true)
+            .set_execute(true)
+            .set_page_cache_disable(true)
+            .set_page_write_through(true);
+    }
+}
+
+impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("PageFlags")
+            .field("bits", &format_args!("{:#0x}", self.data))
+            .field("present", &self.present())
+            .field("has_write", &self.has_write())
+            .field("has_execute", &self.has_execute())
+            .field("has_user", &self.has_user())
+            .finish()
+    }
+}
+
+/// 页表映射器
+#[derive(Hash)]
+pub struct PageMapper<Arch, F> {
+    /// 页表类型
+    table_kind: PageTableKind,
+    /// 根页表物理地址
+    table_paddr: PhysAddr,
+    /// 页分配器
+    frame_allocator: F,
+    phantom: PhantomData<fn() -> Arch>,
+}
+
+impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
+    /// 创建新的页面映射器
+    ///
+    /// ## 参数
+    /// - table_kind 页表类型
+    /// - table_paddr 根页表物理地址
+    /// - allocator 页分配器
+    ///
+    /// ## 返回值
+    ///
+    /// 页面映射器
+    pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self {
+        return Self {
+            table_kind,
+            table_paddr,
+            frame_allocator: allocator,
+            phantom: PhantomData,
+        };
+    }
+
+    /// 创建页表,并为这个页表创建页面映射器
+    pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> {
+        let table_paddr = allocator.allocate_one()?;
+        // 清空页表
+        let table_vaddr = Arch::phys_2_virt(table_paddr)?;
+        Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE);
+        return Some(Self::new(table_kind, table_paddr, allocator));
+    }
+
+    /// 获取当前页表的页面映射器
+    #[inline(always)]
+    pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self {
+        let table_paddr = Arch::table(table_kind);
+        return Self::new(table_kind, table_paddr, allocator);
+    }
+
+    /// 判断当前页表分配器所属的页表是否是当前页表
+    #[inline(always)]
+    pub fn is_current(&self) -> bool {
+        return unsafe { self.table().phys() == Arch::table(self.table_kind) };
+    }
+
+    /// 将当前页表分配器所属的页表设置为当前页表
+    #[inline(always)]
+    pub unsafe fn make_current(&self) {
+        Arch::set_table(self.table_kind, self.table_paddr);
+    }
+
+    /// 获取当前页表分配器所属的根页表的结构体
+    #[inline(always)]
+    pub fn table(&self) -> PageTable<Arch> {
+        // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的
+        return unsafe {
+            PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1)
+        };
+    }
+
+    /// 获取当前PageMapper所对应的页分配器实例的引用
+    #[inline(always)]
+    #[allow(dead_code)]
+    pub fn allocator_ref(&self) -> &F {
+        return &self.frame_allocator;
+    }
+
+    /// 获取当前PageMapper所对应的页分配器实例的可变引用
+    #[inline(always)]
+    pub fn allocator_mut(&mut self) -> &mut F {
+        return &mut self.frame_allocator;
+    }
+
+    /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址
+    pub unsafe fn map(
+        &mut self,
+        virt: VirtAddr,
+        flags: PageFlags<Arch>,
+    ) -> Option<PageFlush<Arch>> {
+        compiler_fence(Ordering::SeqCst);
+        let phys: PhysAddr = self.frame_allocator.allocate_one()?;
+        compiler_fence(Ordering::SeqCst);
+        return self.map_phys(virt, phys, flags);
+    }
+
+    /// 映射一个物理页到指定的虚拟地址
+    pub unsafe fn map_phys(
+        &mut self,
+        virt: VirtAddr,
+        phys: PhysAddr,
+        flags: PageFlags<Arch>,
+    ) -> Option<PageFlush<Arch>> {
+        // 验证虚拟地址和物理地址是否对齐
+        if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
+            kerror!(
+                "Try to map unaligned page: virt={:?}, phys={:?}",
+                virt,
+                phys
+            );
+            return None;
+        }
+        let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
+
+        // TODO: 验证flags是否合法
+
+        // 创建页表项
+        let entry = PageEntry::new(phys.data() | flags.data());
+        let mut table = self.table();
+        loop {
+            let i = table.index_of(virt)?;
+            assert!(i < Arch::PAGE_ENTRY_NUM);
+            if table.level() == 0 {
+                // todo: 检查是否已经映射
+                // 现在不检查的原因是,刚刚启动系统时,内核会映射一些页。
+                if table.entry_mapped(i)? == true {
+                    kwarn!("Page {:?} already mapped", virt);
+                }
+                // kdebug!("Mapping {:?} to {:?}, i = {i}, entry={:?}, flags={:?}", virt, phys, entry, flags);
+                compiler_fence(Ordering::SeqCst);
+                table.set_entry(i, entry);
+                compiler_fence(Ordering::SeqCst);
+                return Some(PageFlush::new(virt));
+            } else {
+                let next_table = table.next_level_table(i);
+                if let Some(next_table) = next_table {
+                    table = next_table;
+                    // kdebug!("Mapping {:?} to next level table...", virt);
+                } else {
+                    // kdebug!("Allocating next level table for {:?}..., i={i}", virt);
+                    // 分配下一级页表
+                    let frame = self.frame_allocator.allocate_one()?;
+                    // 清空这个页帧
+                    MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
+
+                    // 设置页表项的flags
+                    // let flags = Arch::ENTRY_FLAG_READWRITE
+                    //     | Arch::ENTRY_FLAG_DEFAULT_TABLE
+                    //     | if virt.kind() == PageTableKind::User {
+                    //         Arch::ENTRY_FLAG_USER
+                    //     } else {
+                    //         0
+                    //     };
+                    let flags: PageFlags<MMArch> =
+                        PageFlags::new_page_table(virt.kind() == PageTableKind::User);
+
+                    // kdebug!("Flags: {:?}", flags);
+
+                    // 把新分配的页表映射到当前页表
+                    table.set_entry(i, PageEntry::new(frame.data() | flags.data()));
+
+                    // 获取新分配的页表
+                    table = table.next_level_table(i)?;
+                }
+            }
+        }
+    }
+
+    /// 将物理地址映射到具有线性偏移量的虚拟地址
+    #[allow(dead_code)]
+    pub unsafe fn map_linearly(
+        &mut self,
+        phys: PhysAddr,
+        flags: PageFlags<Arch>,
+    ) -> Option<(VirtAddr, PageFlush<Arch>)> {
+        let virt: VirtAddr = Arch::phys_2_virt(phys)?;
+        return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
+    }
+
+    /// 修改虚拟地址的页表项的flags,并返回页表项刷新器
+    ///
+    /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效
+    ///
+    /// ## 参数
+    /// - virt 虚拟地址
+    /// - flags 新的页表项的flags
+    ///
+    /// ## 返回值
+    ///
+    /// 如果修改成功,返回刷新器,否则返回None
+    pub unsafe fn remap(
+        &mut self,
+        virt: VirtAddr,
+        flags: PageFlags<Arch>,
+    ) -> Option<PageFlush<Arch>> {
+        return self
+            .visit(virt, |p1, i| {
+                let mut entry = p1.entry(i)?;
+                entry.set_flags(flags);
+                p1.set_entry(i, entry);
+                Some(PageFlush::new(virt))
+            })
+            .flatten();
+    }
+
+    /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags
+    ///
+    /// ## 参数
+    ///
+    /// - virt 虚拟地址
+    ///
+    /// ## 返回值
+    ///
+    /// 如果查找成功,返回物理地址和页表项的flags,否则返回None
+    pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> {
+        let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
+        let paddr = entry.address().ok()?;
+        let flags = entry.flags();
+        return Some((paddr, flags));
+    }
+
+    /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器
+    ///
+    /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效
+    ///
+    /// ## 参数
+    ///
+    /// - virt 虚拟地址
+    /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
+    ///
+    /// ## 返回值
+    /// 如果取消成功,返回刷新器,否则返回None
+    pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
+        let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
+        self.frame_allocator.free_one(paddr);
+        return Some(flusher);
+    }
+
+    /// 取消虚拟地址的映射,并返回物理地址和页表项的flags
+    ///
+    /// ## 参数
+    ///
+    /// - vaddr 虚拟地址
+    /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
+    ///
+    /// ## 返回值
+    ///
+    /// 如果取消成功,返回物理地址和页表项的flags,否则返回None
+    pub unsafe fn unmap_phys(
+        &mut self,
+        virt: VirtAddr,
+        unmap_parents: bool,
+    ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> {
+        if !virt.check_aligned(Arch::PAGE_SIZE) {
+            kerror!("Try to unmap unaligned page: virt={:?}", virt);
+            return None;
+        }
+
+        let mut table = self.table();
+        return unmap_phys_inner(virt, &mut table, unmap_parents, self.allocator_mut())
+            .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt)));
+    }
+
+    /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F
+    fn visit<T>(
+        &self,
+        virt: VirtAddr,
+        f: impl FnOnce(&mut PageTable<Arch>, usize) -> T,
+    ) -> Option<T> {
+        let mut table = self.table();
+        unsafe {
+            loop {
+                let i = table.index_of(virt)?;
+                if table.level() == 0 {
+                    return Some(f(&mut table, i));
+                } else {
+                    table = table.next_level_table(i)?;
+                }
+            }
+        }
+    }
+}
+
+/// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】
+///
+/// ## 参数
+///
+/// - vaddr 虚拟地址
+/// - table 页表
+/// - unmap_parents 是否在父页表内,取消空闲子页表的映射
+/// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内)
+///
+/// ## 返回值
+///
+/// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None
+unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
+    vaddr: VirtAddr,
+    table: &mut PageTable<Arch>,
+    unmap_parents: bool,
+    allocator: &mut impl FrameAllocator,
+) -> Option<(PhysAddr, PageFlags<Arch>)> {
+    // 获取页表项的索引
+    let i = table.index_of(vaddr)?;
+
+    // 如果当前是最后一级页表,直接取消页面映射
+    if table.level() == 0 {
+        let entry = table.entry(i)?;
+        table.set_entry(i, PageEntry::new(0));
+        return Some((entry.address().ok()?, entry.flags()));
+    }
+
+    let mut subtable = table.next_level_table(i)?;
+    // 递归地取消映射
+    let result = unmap_phys_inner(vaddr, &mut subtable, unmap_parents, allocator)?;
+
+    // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables,
+    // as these mappings may become out of sync
+    if unmap_parents {
+        // 如果子页表已经没有映射的页面了,就取消子页表的映射
+
+        // 检查子页表中是否还有映射的页面
+        let x = (0..Arch::PAGE_ENTRY_NUM)
+            .map(|k| subtable.entry(k).expect("invalid page entry"))
+            .any(|e| e.present());
+        if !x {
+            // 如果没有,就取消子页表的映射
+            table.set_entry(i, PageEntry::new(0));
+            // 释放子页表
+            allocator.free_one(subtable.phys());
+        }
+    }
+
+    return Some(result);
+}
+
+impl<Arch, F: Debug> Debug for PageMapper<Arch, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("PageMapper")
+            .field("table_paddr", &self.table_paddr)
+            .field("frame_allocator", &self.frame_allocator)
+            .finish()
+    }
+}
+
+/// 页表刷新器的trait
+pub trait Flusher<Arch> {
+    /// 取消对指定的page flusher的刷新
+    fn consume(&mut self, flush: PageFlush<Arch>);
+}
+
+/// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法,
+/// 否则会造成对页表的更改被忽略,这是不安全的
+#[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
+pub struct PageFlush<Arch> {
+    virt: VirtAddr,
+    phantom: PhantomData<Arch>,
+}
+
+impl<Arch: MemoryManagementArch> PageFlush<Arch> {
+    pub fn new(virt: VirtAddr) -> Self {
+        return Self {
+            virt,
+            phantom: PhantomData,
+        };
+    }
+
+    pub fn flush(self) {
+        unsafe { Arch::invalidate_page(self.virt) };
+    }
+
+    /// 忽略掉这个刷新器
+    pub unsafe fn ignore(self) {
+        mem::forget(self);
+    }
+}
+
+/// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法,
+/// 否则会造成对页表的更改被忽略,这是不安全的
+#[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
+pub struct PageFlushAll<Arch: MemoryManagementArch> {
+    phantom: PhantomData<fn() -> Arch>,
+}
+
+#[allow(dead_code)]
+impl<Arch: MemoryManagementArch> PageFlushAll<Arch> {
+    pub fn new() -> Self {
+        return Self {
+            phantom: PhantomData,
+        };
+    }
+
+    pub fn flush(self) {
+        unsafe { Arch::invalidate_all() };
+    }
+
+    /// 忽略掉这个刷新器
+    pub unsafe fn ignore(self) {
+        mem::forget(self);
+    }
+}
+
+impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> {
+    /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了)
+    fn consume(&mut self, flush: PageFlush<Arch>) {
+        unsafe { flush.ignore() };
+    }
+}
+
+impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T {
+    /// 允许一个flusher consume掉另一个flusher
+    fn consume(&mut self, flush: PageFlush<Arch>) {
+        <T as Flusher<Arch>>::consume(self, flush);
+    }
+}
+
+impl<Arch: MemoryManagementArch> Flusher<Arch> for () {
+    fn consume(&mut self, _flush: PageFlush<Arch>) {}
+}
+
+impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> {
+    fn drop(&mut self) {
+        unsafe {
+            Arch::invalidate_all();
+        }
+    }
+}
+
+/// 未在当前CPU上激活的页表的刷新器
+///
+/// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表
+///
+/// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销)
+#[derive(Debug)]
+pub struct InactiveFlusher;
+
+impl InactiveFlusher {
+    pub fn new() -> Self {
+        return Self {};
+    }
+}
+
+impl Flusher<MMArch> for InactiveFlusher {
+    fn consume(&mut self, flush: PageFlush<MMArch>) {
+        unsafe {
+            flush.ignore();
+        }
+    }
+}
+
+impl Drop for InactiveFlusher {
+    fn drop(&mut self) {
+        // 发送刷新页表的IPI
+        send_ipi(IpiKind::FlushTLB, IpiTarget::Other);
+    }
+}
+
+/// # 把一个地址向下对齐到页大小
+pub fn round_down_to_page_size(addr: usize) -> usize {
+    addr & !(MMArch::PAGE_SIZE - 1)
+}
+
+/// # 把一个地址向上对齐到页大小
+pub fn round_up_to_page_size(addr: usize) -> usize {
+    round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1)
+}

+ 0 - 713
kernel/src/mm/slab.c

@@ -1,713 +0,0 @@
-#include "slab.h"
-#include <common/compiler.h>
-
-struct slab kmalloc_cache_group[16] =
-    {
-        {32, 0, 0, NULL, NULL, NULL, NULL},
-        {64, 0, 0, NULL, NULL, NULL, NULL},
-        {128, 0, 0, NULL, NULL, NULL, NULL},
-        {256, 0, 0, NULL, NULL, NULL, NULL},
-        {512, 0, 0, NULL, NULL, NULL, NULL},
-        {1024, 0, 0, NULL, NULL, NULL, NULL}, // 1KB
-        {2048, 0, 0, NULL, NULL, NULL, NULL},
-        {4096, 0, 0, NULL, NULL, NULL, NULL}, // 4KB
-        {8192, 0, 0, NULL, NULL, NULL, NULL},
-        {16384, 0, 0, NULL, NULL, NULL, NULL},
-        {32768, 0, 0, NULL, NULL, NULL, NULL},
-        {65536, 0, 0, NULL, NULL, NULL, NULL},
-        {131072, 0, 0, NULL, NULL, NULL, NULL}, // 128KB
-        {262144, 0, 0, NULL, NULL, NULL, NULL},
-        {524288, 0, 0, NULL, NULL, NULL, NULL},
-        {1048576, 0, 0, NULL, NULL, NULL, NULL}, // 1MB
-};
-
-/**
- * @brief 创建一个内存池
- *
- * @param size 内存池容量大小
- * @param constructor 构造函数
- * @param destructor 析构函数
- * @param arg 参数
- * @return struct slab* 构建好的内存池对象
- */
-struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg)
-{
-    struct slab *slab_pool = (struct slab *)kmalloc(sizeof(struct slab), 0);
-
-    // BUG
-    if (slab_pool == NULL)
-    {
-        kBUG("slab_create()->kmalloc()->slab == NULL");
-        return NULL;
-    }
-
-    memset(slab_pool, 0, sizeof(struct slab));
-
-    slab_pool->size = SIZEOF_LONG_ALIGN(size);
-    slab_pool->count_total_using = 0;
-    slab_pool->count_total_free = 0;
-    // 直接分配cache_pool_entry结构体,避免每次访问都要检测是否为NULL,提升效率
-    slab_pool->cache_pool_entry = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
-
-    // BUG
-    if (slab_pool->cache_pool_entry == NULL)
-    {
-        kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
-        kfree(slab_pool);
-        return NULL;
-    }
-    memset(slab_pool->cache_pool_entry, 0, sizeof(struct slab_obj));
-
-    // dma内存池设置为空
-    slab_pool->cache_dma_pool_entry = NULL;
-
-    // 设置构造及析构函数
-    slab_pool->constructor = constructor;
-    slab_pool->destructor = destructor;
-
-    list_init(&slab_pool->cache_pool_entry->list);
-
-    // 分配属于内存池的内存页
-    slab_pool->cache_pool_entry->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
-
-    // BUG
-    if (slab_pool->cache_pool_entry->page == NULL)
-    {
-        kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
-        kfree(slab_pool->cache_pool_entry);
-        kfree(slab_pool);
-        return NULL;
-    }
-
-    // page_init(slab_pool->cache_pool_entry->page, PAGE_KERNEL);
-
-    slab_pool->cache_pool_entry->count_using = 0;
-    slab_pool->cache_pool_entry->count_free = PAGE_2M_SIZE / slab_pool->size;
-
-    slab_pool->count_total_free = slab_pool->cache_pool_entry->count_free;
-
-    slab_pool->cache_pool_entry->vaddr = phys_2_virt(slab_pool->cache_pool_entry->page->addr_phys);
-
-    // bitmap有多少有效位
-    slab_pool->cache_pool_entry->bmp_count = slab_pool->cache_pool_entry->count_free;
-
-    // 计算位图所占的空间 占用多少byte(按unsigned long大小的上边缘对齐)
-    slab_pool->cache_pool_entry->bmp_len = ((slab_pool->cache_pool_entry->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
-    // 初始化位图
-    slab_pool->cache_pool_entry->bmp = (ul *)kmalloc(slab_pool->cache_pool_entry->bmp_len, 0);
-
-    // BUG
-    if (slab_pool->cache_pool_entry->bmp == NULL)
-    {
-        kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
-        free_pages(slab_pool->cache_pool_entry->page, 1);
-        kfree(slab_pool->cache_pool_entry);
-        kfree(slab_pool);
-        return NULL;
-    }
-    // 将位图清空
-    memset(slab_pool->cache_pool_entry->bmp, 0, slab_pool->cache_pool_entry->bmp_len);
-
-    return slab_pool;
-}
-
-/**
- * @brief 销毁内存池
- * 只有当slab是空的时候才能销毁
- * @param slab_pool 要销毁的内存池
- * @return ul
- *
- */
-ul slab_destroy(struct slab *slab_pool)
-{
-    struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
-    if (slab_pool->count_total_using)
-    {
-        kBUG("slab_cache->count_total_using != 0");
-        return ESLAB_NOTNULL;
-    }
-
-    struct slab_obj *tmp_slab_obj = NULL;
-    while (!list_empty(&slab_obj_ptr->list))
-    {
-        tmp_slab_obj = slab_obj_ptr;
-        // 获取下一个slab_obj的起始地址
-        slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
-
-        list_del(&tmp_slab_obj->list);
-
-        kfree(tmp_slab_obj->bmp);
-
-        page_clean(tmp_slab_obj->page);
-
-        free_pages(tmp_slab_obj->page, 1);
-
-        kfree(tmp_slab_obj);
-    }
-
-    kfree(slab_obj_ptr->bmp);
-    page_clean(slab_obj_ptr->page);
-    free_pages(slab_obj_ptr->page, 1);
-    kfree(slab_obj_ptr);
-    kfree(slab_pool);
-    return 0;
-}
-
-/**
- * @brief 分配SLAB内存池中的内存对象
- *
- * @param slab_pool slab内存池
- * @param arg 传递给内存对象构造函数的参数
- * @return void* 内存空间的虚拟地址
- */
-void *slab_malloc(struct slab *slab_pool, ul arg)
-{
-    struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
-    struct slab_obj *tmp_slab_obj = NULL;
-
-    // slab内存池中已经没有空闲的内存对象,进行扩容
-    if (slab_pool->count_total_free == 0)
-    {
-        tmp_slab_obj = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
-
-        // BUG
-        if (tmp_slab_obj == NULL)
-        {
-            kBUG("slab_malloc()->kmalloc()->slab->tmp_slab_obj == NULL");
-            return NULL;
-        }
-
-        memset(tmp_slab_obj, 0, sizeof(struct slab_obj));
-        list_init(&tmp_slab_obj->list);
-
-        tmp_slab_obj->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
-
-        // BUG
-        if (tmp_slab_obj->page == NULL)
-        {
-            kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->page == NULL");
-            kfree(tmp_slab_obj);
-            return NULL;
-        }
-
-        tmp_slab_obj->count_using = 0;
-        tmp_slab_obj->count_free = PAGE_2M_SIZE / slab_pool->size;
-        tmp_slab_obj->vaddr = phys_2_virt(tmp_slab_obj->page->addr_phys);
-        tmp_slab_obj->bmp_count = tmp_slab_obj->count_free;
-        // 计算位图所占的空间 占用多少byte(按unsigned long大小的上边缘对齐)
-        tmp_slab_obj->bmp_len = ((tmp_slab_obj->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
-        tmp_slab_obj->bmp = (ul *)kmalloc(tmp_slab_obj->bmp_len, 0);
-
-        // BUG
-        if (tmp_slab_obj->bmp == NULL)
-        {
-            kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->bmp == NULL");
-            free_pages(tmp_slab_obj->page, 1);
-            kfree(tmp_slab_obj);
-            return NULL;
-        }
-
-        memset(tmp_slab_obj->bmp, 0, tmp_slab_obj->bmp_len);
-
-        list_add(&slab_pool->cache_pool_entry->list, &tmp_slab_obj->list);
-
-        slab_pool->count_total_free += tmp_slab_obj->count_free;
-
-        slab_obj_ptr = tmp_slab_obj;
-    }
-
-    // 扩容完毕或无需扩容,开始分配内存对象
-    int tmp_md;
-    do
-    {
-        if (slab_obj_ptr->count_free == 0)
-        {
-            slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
-            continue;
-        }
-
-        for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
-        {
-            // 当前bmp对应的内存对象都已经被分配
-            if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
-            {
-                i += 63;
-                continue;
-            }
-
-            // 第i个内存对象是空闲的
-            tmp_md = i % 64;
-            if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << tmp_md)) == 0)
-            {
-                // 置位bmp
-                *(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << tmp_md);
-
-                // 更新当前slab对象的计数器
-                ++(slab_obj_ptr->count_using);
-                --(slab_obj_ptr->count_free);
-                // 更新slab内存池的计数器
-                ++(slab_pool->count_total_using);
-                --(slab_pool->count_total_free);
-
-                if (slab_pool->constructor != NULL)
-                {
-                    // 返回内存对象指针(要求构造函数返回内存对象指针)
-                    return slab_pool->constructor((char *)slab_obj_ptr->vaddr + slab_pool->size * i, arg);
-                }
-                // 返回内存对象指针
-                else
-                    return (void *)((char *)slab_obj_ptr->vaddr + slab_pool->size * i);
-            }
-        }
-
-    } while (slab_obj_ptr != slab_pool->cache_pool_entry);
-
-    // should not be here
-
-    kBUG("slab_malloc() ERROR: can't malloc");
-
-    // 释放内存
-    if (tmp_slab_obj != NULL)
-    {
-        list_del(&tmp_slab_obj->list);
-        kfree(tmp_slab_obj->bmp);
-        page_clean(tmp_slab_obj->page);
-        free_pages(tmp_slab_obj->page, 1);
-        kfree(tmp_slab_obj);
-    }
-    return NULL;
-}
-
-/**
- * @brief 回收slab内存池中的对象
- *
- * @param slab_pool 对应的内存池
- * @param addr 内存对象的虚拟地址
- * @param arg 传递给虚构函数的参数
- * @return ul
- */
-ul slab_free(struct slab *slab_pool, void *addr, ul arg)
-{
-    struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
-
-    do
-    {
-        // 虚拟地址不在当前内存池对象的管理范围内
-        if (!(slab_obj_ptr->vaddr <= addr && addr <= (slab_obj_ptr->vaddr + PAGE_2M_SIZE)))
-        {
-            slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
-        }
-        else
-        {
-
-            // 计算出给定内存对象是第几个
-            int index = (addr - slab_obj_ptr->vaddr) / slab_pool->size;
-
-            // 复位位图中对应的位
-            *(slab_obj_ptr->bmp + (index >> 6)) ^= (1UL << index % 64);
-
-            ++(slab_obj_ptr->count_free);
-            --(slab_obj_ptr->count_using);
-
-            ++(slab_pool->count_total_free);
-            --(slab_pool->count_total_using);
-
-            // 有对应的析构函数,调用析构函数
-            if (slab_pool->destructor != NULL)
-                slab_pool->destructor((char *)slab_obj_ptr->vaddr + slab_pool->size * index, arg);
-
-            // 当前内存对象池的正在使用的内存对象为0,且内存池的空闲对象大于当前对象池的2倍,则销毁当前对象池,以减轻系统内存压力
-            if ((slab_obj_ptr->count_using == 0) && ((slab_pool->count_total_free >> 1) >= slab_obj_ptr->count_free) && (slab_obj_ptr != slab_pool->cache_pool_entry))
-            {
-
-                list_del(&slab_obj_ptr->list);
-                slab_pool->count_total_free -= slab_obj_ptr->count_free;
-
-                kfree(slab_obj_ptr->bmp);
-                page_clean(slab_obj_ptr->page);
-                free_pages(slab_obj_ptr->page, 1);
-
-                kfree(slab_obj_ptr);
-            }
-        }
-
-        return 0;
-    } while (slab_obj_ptr != slab_pool->cache_pool_entry);
-
-    kwarn("slab_free(): address not in current slab");
-    return ENOT_IN_SLAB;
-}
-
-/**
- * @brief 初始化内存池组
- * 在初始化通用内存管理单元期间,尚无内存空间分配函数,需要我们手动为SLAB内存池指定存储空间
- * @return ul
- */
-ul slab_init()
-{
-    kinfo("Initializing SLAB...");
-    // 将slab的内存池空间放置在mms的后方
-    ul tmp_addr = memory_management_struct.end_of_struct;
-    for (int i = 0; i < 16; ++i)
-    {
-        io_mfence();
-        spin_init(&kmalloc_cache_group[i].lock);
-        // 将slab内存池对象的空间放置在mms的后面,并且预留4个unsigned long 的空间以防止内存越界
-        kmalloc_cache_group[i].cache_pool_entry = (struct slab_obj *)memory_management_struct.end_of_struct;
-
-        memory_management_struct.end_of_struct += sizeof(struct slab_obj) + (sizeof(ul) << 2);
-
-        list_init(&kmalloc_cache_group[i].cache_pool_entry->list);
-
-        // 初始化内存池对象
-        kmalloc_cache_group[i].cache_pool_entry->count_using = 0;
-        kmalloc_cache_group[i].cache_pool_entry->count_free = PAGE_2M_SIZE / kmalloc_cache_group[i].size;
-        kmalloc_cache_group[i].cache_pool_entry->bmp_len = (((kmalloc_cache_group[i].cache_pool_entry->count_free + sizeof(ul) * 8 - 1) >> 6) << 3);
-        kmalloc_cache_group[i].cache_pool_entry->bmp_count = kmalloc_cache_group[i].cache_pool_entry->count_free;
-
-        // 在slab对象后方放置bmp
-        kmalloc_cache_group[i].cache_pool_entry->bmp = (ul *)memory_management_struct.end_of_struct;
-
-        // bmp后方预留4个unsigned long的空间防止内存越界,且按照8byte进行对齐
-        memory_management_struct.end_of_struct = (ul)(memory_management_struct.end_of_struct + kmalloc_cache_group[i].cache_pool_entry->bmp_len + (sizeof(ul) << 2)) & (~(sizeof(ul) - 1));
-        io_mfence();
-        // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
-        memset(kmalloc_cache_group[i].cache_pool_entry->bmp, 0xff, kmalloc_cache_group[i].cache_pool_entry->bmp_len);
-        for (int j = 0; j < kmalloc_cache_group[i].cache_pool_entry->bmp_count; ++j)
-            *(kmalloc_cache_group[i].cache_pool_entry->bmp + (j >> 6)) ^= 1UL << (j % 64);
-
-        kmalloc_cache_group[i].count_total_using = 0;
-        kmalloc_cache_group[i].count_total_free = kmalloc_cache_group[i].cache_pool_entry->count_free;
-        io_mfence();
-    }
-
-    struct Page *page = NULL;
-
-    // 将上面初始化内存池组时,所占用的内存页进行初始化
-    ul tmp_page_mms_end = virt_2_phys(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT;
-
-    ul page_num = 0;
-    for (int i = PAGE_2M_ALIGN(virt_2_phys(tmp_addr)) >> PAGE_2M_SHIFT; i <= tmp_page_mms_end; ++i)
-    {
-
-        page = memory_management_struct.pages_struct + i;
-        page_num = page->addr_phys >> PAGE_2M_SHIFT;
-        *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
-        ++page->zone->count_pages_using;
-        io_mfence();
-        --page->zone->count_pages_free;
-        page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
-    }
-    io_mfence();
-
-    // 为slab内存池对象分配内存空间
-    ul *virt = NULL;
-    for (int i = 0; i < 16; ++i)
-    {
-        // 获取一个新的空页并添加到空页表,然后返回其虚拟地址
-        virt = (ul *)((memory_management_struct.end_of_struct + PAGE_2M_SIZE * i + PAGE_2M_SIZE - 1) & PAGE_2M_MASK);
-
-        page = Virt_To_2M_Page(virt);
-
-        page_num = page->addr_phys >> PAGE_2M_SHIFT;
-
-        *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
-
-        ++page->zone->count_pages_using;
-        io_mfence(); // 该位置必须加一个mfence,否则O3优化运行时会报错
-        --page->zone->count_pages_free;
-        page_init(page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
-
-        kmalloc_cache_group[i].cache_pool_entry->page = page;
-
-        kmalloc_cache_group[i].cache_pool_entry->vaddr = virt;
-    }
-
-    kinfo("SLAB initialized successfully!");
-
-    return 0;
-}
-
-/**
- * @brief 在kmalloc中创建slab_obj的函数(与slab_malloc()中的类似)
- *
- * @param size
- * @return struct slab_obj* 创建好的slab_obj
- */
-
-struct slab_obj *kmalloc_create_slab_obj(ul size)
-{
-    struct Page *page = alloc_pages(ZONE_NORMAL, 1, 0);
-
-    // BUG
-    if (page == NULL)
-    {
-        kBUG("kmalloc_create()->alloc_pages()=>page == NULL");
-        return NULL;
-    }
-
-    page_init(page, PAGE_KERNEL);
-
-    ul *vaddr = NULL;
-    ul struct_size = 0;
-    struct slab_obj *slab_obj_ptr;
-
-    // 根据size大小,选择不同的分支来处理
-    // 之所以选择512byte为分界点,是因为,此时bmp大小刚好为512byte。显而易见,选择过小的话会导致kmalloc函数与当前函数反复互相调用,最终导致栈溢出
-    switch (size)
-    {
-    // ============ 对于size<=512byte的内存池对象,将slab_obj结构体和bmp放置在物理页的内部 ========
-    // 由于这些对象的特征是,bmp占的空间大,而内存块的空间小,这样做的目的是避免再去申请一块内存来存储bmp,减少浪费。
-    case 32:
-    case 64:
-    case 128:
-    case 256:
-    case 512:
-        vaddr = phys_2_virt(page->addr_phys);
-        // slab_obj结构体的大小 (本身的大小+bmp的大小)
-        struct_size = sizeof(struct slab_obj) + PAGE_2M_SIZE / size / 8;
-        // 将slab_obj放置到物理页的末尾
-        slab_obj_ptr = (struct slab_obj *)((unsigned char *)vaddr + PAGE_2M_SIZE - struct_size);
-        slab_obj_ptr->bmp = (void *)slab_obj_ptr + sizeof(struct slab_obj);
-
-        slab_obj_ptr->count_free = (PAGE_2M_SIZE - struct_size) / size;
-        slab_obj_ptr->count_using = 0;
-        slab_obj_ptr->bmp_count = slab_obj_ptr->count_free;
-        slab_obj_ptr->vaddr = vaddr;
-        slab_obj_ptr->page = page;
-
-        list_init(&slab_obj_ptr->list);
-
-        slab_obj_ptr->bmp_len = ((slab_obj_ptr->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
-
-        // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
-        memset(slab_obj_ptr->bmp, 0xff, slab_obj_ptr->bmp_len);
-
-        for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
-            *(slab_obj_ptr->bmp + (i >> 6)) ^= 1UL << (i % 64);
-
-        break;
-    // ================= 较大的size时,slab_obj和bmp不再放置于当前物理页内部 ============
-    // 因为在这种情况下,bmp很短,继续放置在当前物理页内部则会造成可分配的对象少,加剧了内存空间的浪费
-    case 1024: // 1KB
-    case 2048:
-    case 4096: // 4KB
-    case 8192:
-    case 16384:
-    case 32768:
-    case 65536:
-    case 131072: // 128KB
-    case 262144:
-    case 524288:
-    case 1048576: // 1MB
-        slab_obj_ptr = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
-
-        slab_obj_ptr->count_free = PAGE_2M_SIZE / size;
-        slab_obj_ptr->count_using = 0;
-        slab_obj_ptr->bmp_count = slab_obj_ptr->count_free;
-
-        slab_obj_ptr->bmp_len = ((slab_obj_ptr->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
-
-        slab_obj_ptr->bmp = (ul *)kmalloc(slab_obj_ptr->bmp_len, 0);
-
-        // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
-        memset(slab_obj_ptr->bmp, 0xff, slab_obj_ptr->bmp_len);
-        for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
-            *(slab_obj_ptr->bmp + (i >> 6)) ^= 1UL << (i % 64);
-
-        slab_obj_ptr->vaddr = phys_2_virt(page->addr_phys);
-        slab_obj_ptr->page = page;
-        list_init(&slab_obj_ptr->list);
-        break;
-    // size 错误
-    default:
-        kerror("kamlloc_create(): Wrong size%d", size);
-        free_pages(page, 1);
-        return NULL;
-        break;
-    }
-
-    return slab_obj_ptr;
-}
-
-/**
- * @brief 通用内存分配函数
- *
- * @param size 要分配的内存大小
- * @param gfp 内存的flag
- * @return void* 内核内存虚拟地址
- */
-void *kmalloc(unsigned long size, gfp_t gfp)
-{
-    void *result = NULL;
-    if (size > 1048576)
-    {
-        kwarn("kmalloc(): Can't alloc such memory: %ld bytes, because it is too large.", size);
-        return NULL;
-    }
-    int index;
-    for (int i = 0; i < 16; ++i)
-    {
-        if (kmalloc_cache_group[i].size >= size)
-        {
-            index = i;
-            break;
-        }
-    }
-    // 对当前内存池加锁
-    spin_lock(&kmalloc_cache_group[index].lock);
-
-    struct slab_obj *slab_obj_ptr = kmalloc_cache_group[index].cache_pool_entry;
-
-    // 内存池没有可用的内存对象,需要进行扩容
-    if (unlikely(kmalloc_cache_group[index].count_total_free == 0))
-    {
-        // 创建slab_obj
-        slab_obj_ptr = kmalloc_create_slab_obj(kmalloc_cache_group[index].size);
-
-        // BUG
-        if (unlikely(slab_obj_ptr == NULL))
-        {
-            kBUG("kmalloc()->kmalloc_create_slab_obj()=>slab == NULL");
-            goto failed;
-        }
-
-        kmalloc_cache_group[index].count_total_free += slab_obj_ptr->count_free;
-        list_add(&kmalloc_cache_group[index].cache_pool_entry->list, &slab_obj_ptr->list);
-    }
-    else // 内存对象充足
-    {
-        do
-        {
-            // 跳转到下一个内存池对象
-            if (slab_obj_ptr->count_free == 0)
-                slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
-            else
-                break;
-        } while (slab_obj_ptr != kmalloc_cache_group[index].cache_pool_entry);
-    }
-    // 寻找一块可用的内存对象
-    int md;
-    for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
-    {
-
-        // 当前bmp全部被使用
-        if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
-        {
-            i += 63;
-            continue;
-        }
-        md = i % 64;
-        // 找到相应的内存对象
-        if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << md)) == 0)
-        {
-            *(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << md);
-            ++(slab_obj_ptr->count_using);
-            --(slab_obj_ptr->count_free);
-
-            --kmalloc_cache_group[index].count_total_free;
-            ++kmalloc_cache_group[index].count_total_using;
-            // 放锁
-            spin_unlock(&kmalloc_cache_group[index].lock);
-            // 返回内存对象
-            result = (void *)((char *)slab_obj_ptr->vaddr + kmalloc_cache_group[index].size * i);
-            goto done;
-        }
-    }
-    goto failed;
-done:;
-    if (gfp & __GFP_ZERO)
-        memset(result, 0, size);
-    return result;
-failed:;
-    spin_unlock(&kmalloc_cache_group[index].lock);
-    kerror("kmalloc(): Cannot alloc more memory: %d bytes", size);
-    return NULL;
-}
-
-/**
- * @brief 通用内存释放函数
- *
- * @param address 要释放的内存线性地址
- * @return unsigned long
- */
-unsigned long kfree(void *address)
-{
-    if (unlikely(address == NULL))
-        return 0;
-    struct slab_obj *slab_obj_ptr = NULL;
-
-    // 将线性地址按照2M物理页对齐, 获得所在物理页的起始线性地址
-    void *page_base_addr = (void *)((ul)address & PAGE_2M_MASK);
-
-    int index;
-
-    for (int i = 0; i < 16; ++i)
-    {
-        slab_obj_ptr = kmalloc_cache_group[i].cache_pool_entry;
-
-        do
-        {
-            // 不属于当前slab_obj的管理范围
-            if (likely(slab_obj_ptr->vaddr != page_base_addr))
-            {
-                slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
-            }
-            else
-            {
-                // 对当前内存池加锁
-                spin_lock(&kmalloc_cache_group[i].lock);
-                // 计算地址属于哪一个内存对象
-                index = (address - slab_obj_ptr->vaddr) / kmalloc_cache_group[i].size;
-
-                // 复位bmp
-                *(slab_obj_ptr->bmp + (index >> 6)) ^= 1UL << (index % 64);
-
-                ++(slab_obj_ptr->count_free);
-                --(slab_obj_ptr->count_using);
-                ++kmalloc_cache_group[i].count_total_free;
-                --kmalloc_cache_group[i].count_total_using;
-
-                // 回收空闲的slab_obj
-                // 条件:当前slab_obj_ptr的使用为0、总空闲内存对象>=当前slab_obj的总对象的2倍 且当前slab_pool不为起始slab_obj
-                if ((slab_obj_ptr->count_using == 0) && (kmalloc_cache_group[i].count_total_free >= ((slab_obj_ptr->bmp_count) << 1)) && (kmalloc_cache_group[i].cache_pool_entry != slab_obj_ptr))
-                {
-                    switch (kmalloc_cache_group[i].size)
-                    {
-                    case 32:
-                    case 64:
-                    case 128:
-                    case 256:
-                    case 512:
-                        // 在这种情况下,slab_obj是被安放在page内部的
-                        list_del(&slab_obj_ptr->list);
-
-                        kmalloc_cache_group[i].count_total_free -= slab_obj_ptr->bmp_count;
-                        page_clean(slab_obj_ptr->page);
-                        free_pages(slab_obj_ptr->page, 1);
-                        break;
-
-                    default:
-                        // 在这种情况下,slab_obj是被安放在额外获取的内存对象中的
-                        list_del(&slab_obj_ptr->list);
-                        kmalloc_cache_group[i].count_total_free -= slab_obj_ptr->bmp_count;
-
-                        kfree(slab_obj_ptr->bmp);
-
-                        page_clean(slab_obj_ptr->page);
-                        free_pages(slab_obj_ptr->page, 1);
-
-                        kfree(slab_obj_ptr);
-                        break;
-                    }
-                }
-                // 放锁
-                spin_unlock(&kmalloc_cache_group[i].lock);
-                return 0;
-            }
-
-        } while (slab_obj_ptr != kmalloc_cache_group[i].cache_pool_entry);
-    }
-    kBUG("kfree(): Can't free memory. address=%#018lx", address);
-    return ECANNOT_FREE_MEM;
-}

+ 4 - 109
kernel/src/mm/slab.h

@@ -1,54 +1,6 @@
 #pragma once
 
 #include "mm.h"
-#include <common/glib.h>
-#include <common/printk.h>
-#include <common/kprint.h>
-#include <common/spinlock.h>
-
-#define SIZEOF_LONG_ALIGN(size) ((size + sizeof(long) - 1) & ~(sizeof(long) - 1))
-#define SIZEOF_INT_ALIGN(size) ((size + sizeof(int) - 1) & ~(sizeof(int) - 1))
-
-// SLAB存储池count_using不为空
-#define ESLAB_NOTNULL 101
-#define ENOT_IN_SLAB 102     // 地址不在当前slab内存池中
-#define ECANNOT_FREE_MEM 103 // 无法释放内存
-
-struct slab_obj
-{
-    struct List list;
-    // 当前slab对象所使用的内存页
-    struct Page *page;
-
-    ul count_using;
-    ul count_free;
-
-    // 当前页面所在的线性地址
-    void *vaddr;
-
-    // 位图
-    ul bmp_len;   // 位图的长度(字节)
-    ul bmp_count; // 位图的有效位数
-    ul *bmp;
-};
-
-// slab内存池
-struct slab
-{
-    ul size; // 单位:byte
-    ul count_total_using;
-    ul count_total_free;
-    // 内存池对象
-    struct slab_obj *cache_pool_entry;
-    // dma内存池对象
-    struct slab_obj *cache_dma_pool_entry;
-
-    spinlock_t lock; // 当前内存池的操作锁
-
-    // 内存池的构造函数和析构函数
-    void *(*constructor)(void *vaddr, ul arg);
-    void *(*destructor)(void *vaddr, ul arg);
-};
 
 /**
  * @brief 通用内存分配函数
@@ -57,19 +9,16 @@ struct slab
  * @param gfp 内存的flag
  * @return void* 分配得到的内存的指针
  */
-void *kmalloc(unsigned long size, gfp_t gfp);
+extern void *kmalloc(unsigned long size, gfp_t gfp);
 
 /**
  * @brief 从kmalloc申请一块内存,并将这块内存清空
- * 
+ *
  * @param size 要分配的内存大小
  * @param gfp 内存的flag
  * @return void* 分配得到的内存的指针
  */
-static __always_inline void *kzalloc(size_t size, gfp_t gfp)
-{
-    return kmalloc(size, gfp | __GFP_ZERO);
-}
+extern void *kzalloc(size_t size, gfp_t gfp);
 
 /**
  * @brief 通用内存释放函数
@@ -77,58 +26,4 @@ static __always_inline void *kzalloc(size_t size, gfp_t gfp)
  * @param address 要释放的内存地址
  * @return unsigned long
  */
-unsigned long kfree(void *address);
-
-/**
- * @brief 创建一个内存池
- *
- * @param size 内存池容量大小
- * @param constructor 构造函数
- * @param destructor 析构函数
- * @param arg 参数
- * @return struct slab* 构建好的内存池对象
- */
-struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg);
-
-/**
- * @brief 销毁内存池对象
- * 只有当slab对象是空的时候才能销毁
- * @param slab_pool 要销毁的内存池对象
- * @return ul
- *
- */
-ul slab_destroy(struct slab *slab_pool);
-
-/**
- * @brief 分配SLAB内存池中的内存对象
- *
- * @param slab_pool slab内存池
- * @param arg 传递给内存对象构造函数的参数
- * @return void* 内存空间的虚拟地址
- */
-void *slab_malloc(struct slab *slab_pool, ul arg);
-
-/**
- * @brief 回收slab内存池中的对象
- *
- * @param slab_pool 对应的内存池
- * @param addr 内存对象的虚拟地址
- * @param arg 传递给虚构函数的参数
- * @return ul
- */
-ul slab_free(struct slab *slab_pool, void *addr, ul arg);
-
-/**
- * @brief 在kmalloc中创建slab_obj的函数(与slab_malloc()类似)
- *
- * @param size
- * @return struct slab_obj* 创建好的slab_obj
- */
-struct slab_obj *kmalloc_create_slab_obj(ul size);
-
-/**
- * @brief 初始化内存池组
- * 在初始化通用内存管理单元期间,尚无内存空间分配函数,需要我们手动为SLAB内存池指定存储空间
- * @return ul
- */
-ul slab_init();
+extern unsigned long kfree(void *address);

+ 202 - 26
kernel/src/mm/syscall.rs

@@ -1,43 +1,219 @@
+use core::intrinsics::unlikely;
+
+use alloc::sync::Arc;
+
 use crate::{
-    include::bindings::bindings::mm_stat_t,
+    arch::MMArch,
+    kerror,
+    libs::align::{check_aligned, page_align_up},
+    mm::MemoryManagementArch,
     syscall::{Syscall, SystemError},
 };
 
-extern "C" {
-    fn sys_do_brk(new_addr: usize) -> usize;
-    fn sys_do_sbrk(incr: isize) -> usize;
-    fn sys_do_mstat(dst: *mut mm_stat_t, from_user: bool) -> usize;
+use super::{
+    allocator::page_frame::{PageFrameCount, VirtPageFrame},
+    ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
+    verify_area, VirtAddr,
+};
+
+bitflags! {
+    /// Memory protection flags
+    pub struct ProtFlags: u64 {
+        const PROT_NONE = 0x0;
+        const PROT_READ = 0x1;
+        const PROT_WRITE = 0x2;
+        const PROT_EXEC = 0x4;
+    }
+
+    /// Memory mapping flags
+    pub struct MapFlags: u64 {
+        const MAP_NONE = 0x0;
+        /// share changes
+        const MAP_SHARED = 0x1;
+        /// changes are private
+        const MAP_PRIVATE = 0x2;
+        /// Interpret addr exactly
+        const MAP_FIXED = 0x10;
+        /// don't use a file
+        const MAP_ANONYMOUS = 0x20;
+        // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
+        /// stack-like segment
+        const MAP_GROWSDOWN = 0x100;
+        /// ETXTBSY
+        const MAP_DENYWRITE = 0x800;
+        /// Mark it as an executable
+        const MAP_EXECUTABLE = 0x1000;
+        /// Pages are locked
+        const MAP_LOCKED = 0x2000;
+        /// don't check for reservations
+        const MAP_NORESERVE = 0x4000;
+        /// populate (prefault) pagetables
+        const MAP_POPULATE = 0x8000;
+        /// do not block on IO
+        const MAP_NONBLOCK = 0x10000;
+        /// give out an address that is best suited for process/thread stacks
+        const MAP_STACK = 0x20000;
+        /// create a huge page mapping
+        const MAP_HUGETLB = 0x40000;
+        /// perform synchronous page faults for the mapping
+        const MAP_SYNC = 0x80000;
+        /// MAP_FIXED which doesn't unmap underlying mapping
+        const MAP_FIXED_NOREPLACE = 0x100000;
+
+        /// For anonymous mmap, memory could be uninitialized
+        const MAP_UNINITIALIZED = 0x4000000;
+
+    }
 }
+
 impl Syscall {
-    pub fn brk(new_addr: usize) -> Result<usize, SystemError> {
-        let ret = unsafe { sys_do_brk(new_addr) };
-        if (ret as isize) < 0 {
-            return Err(
-                SystemError::from_posix_errno(-(ret as isize) as i32).expect("brk: Invalid errno")
-            );
+    pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
+        // kdebug!("brk: new_addr={:?}", new_addr);
+        let address_space = AddressSpace::current()?;
+        let mut address_space = address_space.write();
+
+        unsafe {
+            address_space
+                .set_brk(VirtAddr::new(page_align_up(new_addr.data())))
+                .ok();
+
+            return Ok(address_space.sbrk(0).unwrap());
         }
-        return Ok(ret);
     }
 
-    pub fn sbrk(incr: isize) -> Result<usize, SystemError> {
-        let ret = unsafe { sys_do_sbrk(incr) };
-        if (ret as isize) < 0 {
-            return Err(
-                SystemError::from_posix_errno(-(ret as isize) as i32).expect("sbrk: Invalid errno")
+    pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
+        // kdebug!("pid:{}, sbrk: incr={}", current_pcb().pid, incr);
+
+        let address_space = AddressSpace::current()?;
+        let mut address_space = address_space.write();
+        let r = unsafe { address_space.sbrk(incr) };
+
+        // kdebug!("pid:{}, sbrk: r={:?}", current_pcb().pid, r);
+        return r;
+    }
+
+    /// ## mmap系统调用
+    ///
+    /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
+    ///
+    /// ## 参数
+    ///
+    /// - `start_vaddr`:映射的起始地址
+    /// - `len`:映射的长度
+    /// - `prot`:保护标志
+    /// - `flags`:映射标志
+    /// - `fd`:文件描述符(暂时不支持)
+    /// - `offset`:文件偏移量 (暂时不支持)
+    ///
+    /// ## 返回值
+    ///
+    /// 成功时返回映射的起始地址,失败时返回错误码
+    pub fn mmap(
+        start_vaddr: VirtAddr,
+        len: usize,
+        prot_flags: usize,
+        map_flags: usize,
+        _fd: i32,
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
+        let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
+
+        if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
+            && map_flags.contains(MapFlags::MAP_FIXED)
+        {
+            kerror!(
+                "mmap: MAP_FIXED is not supported for address below {}",
+                DEFAULT_MMAP_MIN_ADDR
             );
+            return Err(SystemError::EINVAL);
+        }
+        // 暂时不支持除匿名页以外的映射
+        if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
+            kerror!("mmap: not support file mapping");
+            return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+        }
+
+        // 暂时不支持巨页映射
+        if map_flags.contains(MapFlags::MAP_HUGETLB) {
+            kerror!("mmap: not support huge page mapping");
+            return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
         }
-        return Ok(ret);
+        let current_address_space = AddressSpace::current()?;
+        let start_page = current_address_space.write().map_anonymous(
+            start_vaddr,
+            len,
+            prot_flags,
+            map_flags,
+            true,
+        )?;
+        return Ok(start_page.virt_address().data());
     }
 
-    /// 获取内存统计信息
+    /// ## munmap系统调用
+    ///
+    /// ## 参数
+    ///
+    /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
+    /// - `len`:取消映射的字节数(已经对齐到页)
     ///
-    /// TODO: 该函数不是符合POSIX标准的,在将来需要删除!
-    pub fn mstat(dst: *mut mm_stat_t, from_user: bool) -> Result<usize, SystemError> {
-        let ret = unsafe { sys_do_mstat(dst, from_user) };
-        if (ret as isize) < 0 {
-            return Err(SystemError::from_posix_errno(-(ret as isize) as i32)
-                .expect("mstat: Invalid errno"));
+    /// ## 返回值
+    ///
+    /// 成功时返回0,失败时返回错误码
+    pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
+        assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
+        assert!(check_aligned(len, MMArch::PAGE_SIZE));
+
+        if unlikely(verify_area(start_vaddr, len).is_err()) {
+            return Err(SystemError::EINVAL);
+        }
+        if unlikely(len == 0) {
+            return Err(SystemError::EINVAL);
         }
-        return Ok(ret);
+
+        let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
+        let start_frame = VirtPageFrame::new(start_vaddr);
+        let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
+
+        current_address_space
+            .write()
+            .munmap(start_frame, page_count)
+            .map_err(|_| SystemError::EINVAL)?;
+        return Ok(0);
+    }
+
+    /// ## mprotect系统调用
+    ///
+    /// ## 参数
+    ///
+    /// - `start_vaddr`:起始地址(已经对齐到页)
+    /// - `len`:长度(已经对齐到页)
+    /// - `prot_flags`:保护标志
+    pub fn mprotect(
+        start_vaddr: VirtAddr,
+        len: usize,
+        prot_flags: usize,
+    ) -> Result<usize, SystemError> {
+        assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
+        assert!(check_aligned(len, MMArch::PAGE_SIZE));
+
+        if unlikely(verify_area(start_vaddr, len).is_err()) {
+            return Err(SystemError::EINVAL);
+        }
+        if unlikely(len == 0) {
+            return Err(SystemError::EINVAL);
+        }
+
+        let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
+
+        let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
+        let start_frame = VirtPageFrame::new(start_vaddr);
+        let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
+
+        current_address_space
+            .write()
+            .mprotect(start_frame, page_count, prot_flags)
+            .map_err(|_| SystemError::EINVAL)?;
+        return Ok(0);
     }
 }

+ 1319 - 0
kernel/src/mm/ucontext.rs

@@ -0,0 +1,1319 @@
+// 进程的用户空间内存管理
+
+use core::{
+    cmp,
+    hash::Hasher,
+    intrinsics::unlikely,
+    ops::Add,
+    sync::atomic::{compiler_fence, Ordering},
+};
+
+use alloc::{
+    collections::BTreeMap,
+    sync::{Arc, Weak},
+    vec::Vec,
+};
+use hashbrown::HashSet;
+
+use crate::{
+    arch::{asm::current::current_pcb, mm::PageMapper, CurrentIrqArch, MMArch},
+    exception::InterruptArch,
+    libs::{
+        align::page_align_up,
+        rwlock::{RwLock, RwLockWriteGuard},
+        spinlock::{SpinLock, SpinLockGuard},
+    },
+    syscall::SystemError,
+};
+
+use super::{
+    allocator::page_frame::{
+        deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
+    },
+    page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll},
+    syscall::{MapFlags, ProtFlags},
+    MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion,
+};
+
+/// MMAP_MIN_ADDR的默认值
+/// 以下内容来自linux-5.19:
+///  This is the portion of low virtual memory which should be protected
+//   from userspace allocation.  Keeping a user from writing to low pages
+//   can help reduce the impact of kernel NULL pointer bugs.
+//   For most ia64, ppc64 and x86 users with lots of address space
+//   a value of 65536 is reasonable and should cause no problems.
+//   On arm and other archs it should not be higher than 32768.
+//   Programs which use vm86 functionality or have some need to map
+//   this low address space will need CAP_SYS_RAWIO or disable this
+//   protection by setting the value to 0.
+pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536;
+
+#[derive(Debug)]
+pub struct AddressSpace {
+    inner: RwLock<InnerAddressSpace>,
+}
+
+impl AddressSpace {
+    pub fn new(create_stack: bool) -> Result<Arc<Self>, SystemError> {
+        let inner = InnerAddressSpace::new(create_stack)?;
+        let result = Self {
+            inner: RwLock::new(inner),
+        };
+        return Ok(Arc::new(result));
+    }
+
+    /// 从pcb中获取当前进程的地址空间结构体的Arc指针
+    pub fn current() -> Result<Arc<AddressSpace>, SystemError> {
+        let result = current_pcb()
+            .address_space()
+            .expect("Current process has no address space");
+        return Ok(result);
+    }
+
+    /// 判断某个地址空间是否为当前进程的地址空间
+    pub fn is_current(self: &Arc<Self>) -> bool {
+        let current = Self::current();
+        if let Ok(current) = current {
+            return Arc::ptr_eq(&current, self);
+        }
+        return false;
+    }
+}
+
+impl core::ops::Deref for AddressSpace {
+    type Target = RwLock<InnerAddressSpace>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+impl core::ops::DerefMut for AddressSpace {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.inner
+    }
+}
+
+/// @brief 用户地址空间结构体(每个进程都有一个)
+#[derive(Debug)]
+pub struct InnerAddressSpace {
+    pub user_mapper: UserMapper,
+    pub mappings: UserMappings,
+    pub mmap_min: VirtAddr,
+    /// 用户栈信息结构体
+    pub user_stack: Option<UserStack>,
+
+    pub elf_brk_start: VirtAddr,
+    pub elf_brk: VirtAddr,
+
+    /// 当前进程的堆空间的起始地址
+    pub brk_start: VirtAddr,
+    /// 当前进程的堆空间的结束地址(不包含)
+    pub brk: VirtAddr,
+
+    pub start_code: VirtAddr,
+    pub end_code: VirtAddr,
+    pub start_data: VirtAddr,
+    pub end_data: VirtAddr,
+}
+
+impl InnerAddressSpace {
+    pub fn new(create_stack: bool) -> Result<Self, SystemError> {
+        let mut result = Self {
+            user_mapper: MMArch::setup_new_usermapper()?,
+            mappings: UserMappings::new(),
+            mmap_min: VirtAddr(DEFAULT_MMAP_MIN_ADDR),
+            elf_brk_start: VirtAddr::new(0),
+            elf_brk: VirtAddr::new(0),
+            brk_start: MMArch::USER_BRK_START,
+            brk: MMArch::USER_BRK_START,
+            user_stack: None,
+            start_code: VirtAddr(0),
+            end_code: VirtAddr(0),
+            start_data: VirtAddr(0),
+            end_data: VirtAddr(0),
+        };
+        if create_stack {
+            // kdebug!("to create user stack.");
+            result.new_user_stack(UserStack::DEFAULT_USER_STACK_SIZE)?;
+        }
+
+        return Ok(result);
+    }
+
+    /// 尝试克隆当前进程的地址空间,包括这些映射都会被克隆
+    ///
+    /// # Returns
+    ///
+    /// 返回克隆后的,新的地址空间的Arc指针
+    pub fn try_clone(&mut self) -> Result<Arc<AddressSpace>, SystemError> {
+        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+        let new_addr_space = AddressSpace::new(false)?;
+        let mut new_guard = new_addr_space.write();
+
+        // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容)
+        unsafe {
+            new_guard.user_stack = Some(self.user_stack.as_ref().unwrap().clone_info_only());
+        }
+        let _current_stack_size = self.user_stack.as_ref().unwrap().stack_size();
+
+        let current_mapper = &mut self.user_mapper.utable;
+
+        for vma in self.mappings.vmas.iter() {
+            // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过
+
+            let vma_guard: SpinLockGuard<'_, VMA> = vma.lock();
+            let old_flags = vma_guard.flags();
+            let tmp_flags: PageFlags<MMArch> = PageFlags::new().set_write(true);
+
+            // 分配内存页并创建新的VMA
+            let new_vma = VMA::zeroed(
+                VirtPageFrame::new(vma_guard.region.start()),
+                PageFrameCount::new(vma_guard.region.size() / MMArch::PAGE_SIZE),
+                tmp_flags,
+                &mut new_guard.user_mapper.utable,
+                (),
+            )?;
+            new_guard.mappings.vmas.insert(new_vma.clone());
+            // kdebug!("new vma: {:x?}", new_vma);
+            let mut new_vma_guard = new_vma.lock();
+            for page in new_vma_guard.pages().map(|p| p.virt_address()) {
+                // kdebug!("page: {:x?}", page);
+                let current_frame = unsafe {
+                    MMArch::phys_2_virt(
+                        current_mapper
+                            .translate(page)
+                            .expect("VMA page not mapped")
+                            .0,
+                    )
+                }
+                .expect("Phys2Virt: vaddr overflow.")
+                .data() as *mut u8;
+
+                let new_frame = unsafe {
+                    MMArch::phys_2_virt(
+                        new_guard
+                            .user_mapper
+                            .utable
+                            .translate(page)
+                            .expect("VMA page not mapped")
+                            .0,
+                    )
+                }
+                .expect("Phys2Virt: vaddr overflow.")
+                .data() as *mut u8;
+
+                unsafe {
+                    // 拷贝数据
+                    new_frame.copy_from_nonoverlapping(current_frame, MMArch::PAGE_SIZE);
+                }
+            }
+            drop(vma_guard);
+
+            new_vma_guard.remap(old_flags, &mut new_guard.user_mapper.utable, ())?;
+            drop(new_vma_guard);
+        }
+        drop(new_guard);
+        drop(irq_guard);
+        return Ok(new_addr_space);
+    }
+
+    /// 判断当前的地址空间是否是当前进程的地址空间
+    #[inline]
+    pub fn is_current(&self) -> bool {
+        return self.user_mapper.utable.is_current();
+    }
+
+    /// 进行匿名页映射
+    ///
+    /// ## 参数
+    ///
+    /// - `start_vaddr`:映射的起始地址
+    /// - `len`:映射的长度
+    /// - `prot_flags`:保护标志
+    /// - `map_flags`:映射标志
+    /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界
+    pub fn map_anonymous(
+        &mut self,
+        start_vaddr: VirtAddr,
+        len: usize,
+        prot_flags: ProtFlags,
+        map_flags: MapFlags,
+        round_to_min: bool,
+    ) -> Result<VirtPageFrame, SystemError> {
+        // 用于对齐hint的函数
+        let round_hint_to_min = |hint: VirtAddr| {
+            // 先把hint向下对齐到页边界
+            let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK);
+            // kdebug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint);
+            // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR
+            if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) {
+                Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR)))
+            } else if addr == 0 {
+                None
+            } else {
+                Some(VirtAddr::new(addr))
+            }
+        };
+        // kdebug!("map_anonymous: start_vaddr = {:?}", start_vaddr);
+        // kdebug!("map_anonymous: len(no align) = {}", len);
+
+        let len = page_align_up(len);
+
+        // kdebug!("map_anonymous: len = {}", len);
+
+        let start_page: VirtPageFrame = self.mmap(
+            round_hint_to_min(start_vaddr),
+            PageFrameCount::from_bytes(len).unwrap(),
+            prot_flags,
+            map_flags,
+            move |page, count, flags, mapper, flusher| {
+                Ok(VMA::zeroed(page, count, flags, mapper, flusher)?)
+            },
+        )?;
+
+        return Ok(start_page);
+    }
+
+    /// 向进程的地址空间映射页面
+    ///
+    /// # 参数
+    ///
+    /// - `addr`:映射的起始地址,如果为`None`,则由内核自动分配
+    /// - `page_count`:映射的页面数量
+    /// - `prot_flags`:保护标志
+    /// - `map_flags`:映射标志
+    /// - `map_func`:映射函数,用于创建VMA
+    ///
+    /// # Returns
+    ///
+    /// 返回映射的起始虚拟页帧
+    ///
+    /// # Errors
+    ///
+    /// - `EINVAL`:参数错误
+    pub fn mmap<
+        F: FnOnce(
+            VirtPageFrame,
+            PageFrameCount,
+            PageFlags<MMArch>,
+            &mut PageMapper,
+            &mut dyn Flusher<MMArch>,
+        ) -> Result<Arc<LockedVMA>, SystemError>,
+    >(
+        &mut self,
+        addr: Option<VirtAddr>,
+        page_count: PageFrameCount,
+        prot_flags: ProtFlags,
+        map_flags: MapFlags,
+        map_func: F,
+    ) -> Result<VirtPageFrame, SystemError> {
+        if page_count == PageFrameCount::new(0) {
+            return Err(SystemError::EINVAL);
+        }
+        // kdebug!("mmap: addr: {addr:?}, page_count: {page_count:?}, prot_flags: {prot_flags:?}, map_flags: {map_flags:?}");
+
+        // 找到未使用的区域
+        let region = match addr {
+            Some(vaddr) => {
+                self.mappings
+                    .find_free_at(self.mmap_min, vaddr, page_count.bytes(), map_flags)?
+            }
+            None => self
+                .mappings
+                .find_free(self.mmap_min, page_count.bytes())
+                .ok_or(SystemError::ENOMEM)?,
+        };
+
+        let page = VirtPageFrame::new(region.start());
+
+        // kdebug!("mmap: page: {:?}, region={region:?}", page.virt_address());
+
+        compiler_fence(Ordering::SeqCst);
+        let (mut active, mut inactive);
+        let flusher = if self.is_current() {
+            // kdebug!("mmap: current ucontext");
+            active = PageFlushAll::new();
+            &mut active as &mut dyn Flusher<MMArch>
+        } else {
+            // kdebug!("mmap: not current ucontext");
+            inactive = InactiveFlusher::new();
+            &mut inactive as &mut dyn Flusher<MMArch>
+        };
+        compiler_fence(Ordering::SeqCst);
+        // 映射页面,并将VMA插入到地址空间的VMA列表中
+        self.mappings.insert_vma(map_func(
+            page,
+            page_count,
+            PageFlags::from_prot_flags(prot_flags, true),
+            &mut self.user_mapper.utable,
+            flusher,
+        )?);
+
+        return Ok(page);
+    }
+
+    /// 取消进程的地址空间中的映射
+    ///
+    /// # 参数
+    ///
+    /// - `start_page`:起始页帧
+    /// - `page_count`:取消映射的页帧数量
+    ///
+    /// # Errors
+    ///
+    /// - `EINVAL`:参数错误
+    /// - `ENOMEM`:内存不足
+    pub fn munmap(
+        &mut self,
+        start_page: VirtPageFrame,
+        page_count: PageFrameCount,
+    ) -> Result<(), SystemError> {
+        let to_unmap = VirtRegion::new(start_page.virt_address(), page_count.bytes());
+        let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new();
+
+        let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>();
+
+        for r in regions {
+            let r = r.lock().region;
+            let r = self.mappings.remove_vma(&r).unwrap();
+            let intersection = r.lock().region().intersect(&to_unmap).unwrap();
+            let (before, r, after) = r.extract(intersection).unwrap();
+
+            // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
+
+            if let Some(before) = before {
+                // 如果前面有VMA,则需要将前面的VMA重新插入到地址空间的VMA列表中
+                self.mappings.insert_vma(before);
+            }
+
+            if let Some(after) = after {
+                // 如果后面有VMA,则需要将后面的VMA重新插入到地址空间的VMA列表中
+                self.mappings.insert_vma(after);
+            }
+
+            r.unmap(&mut self.user_mapper.utable, &mut flusher);
+        }
+
+        // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
+
+        return Ok(());
+    }
+
+    pub fn mprotect(
+        &mut self,
+        start_page: VirtPageFrame,
+        page_count: PageFrameCount,
+        prot_flags: ProtFlags,
+    ) -> Result<(), SystemError> {
+        // kdebug!(
+        //     "mprotect: start_page: {:?}, page_count: {:?}, prot_flags:{prot_flags:?}",
+        //     start_page,
+        //     page_count
+        // );
+        let (mut active, mut inactive);
+        let mut flusher = if self.is_current() {
+            active = PageFlushAll::new();
+            &mut active as &mut dyn Flusher<MMArch>
+        } else {
+            inactive = InactiveFlusher::new();
+            &mut inactive as &mut dyn Flusher<MMArch>
+        };
+
+        let mapper = &mut self.user_mapper.utable;
+        let region = VirtRegion::new(start_page.virt_address(), page_count.bytes());
+        // kdebug!("mprotect: region: {:?}", region);
+
+        let regions = self.mappings.conflicts(region).collect::<Vec<_>>();
+        // kdebug!("mprotect: regions: {:?}", regions);
+
+        for r in regions {
+            // kdebug!("mprotect: r: {:?}", r);
+            let r = r.lock().region().clone();
+            let r = self.mappings.remove_vma(&r).unwrap();
+
+            let intersection = r.lock().region().intersect(&region).unwrap();
+            let (before, r, after) = r.extract(intersection).expect("Failed to extract VMA");
+
+            if let Some(before) = before {
+                self.mappings.insert_vma(before);
+            }
+            if let Some(after) = after {
+                self.mappings.insert_vma(after);
+            }
+
+            let mut r_guard = r.lock();
+            // 如果VMA的保护标志不允许指定的修改,则返回错误
+            if !r_guard.can_have_flags(prot_flags) {
+                drop(r_guard);
+                self.mappings.insert_vma(r.clone());
+                return Err(SystemError::EACCES);
+            }
+
+            let new_flags: PageFlags<MMArch> = r_guard
+                .flags()
+                .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
+                .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
+
+            r_guard.remap(new_flags, mapper, &mut flusher)?;
+            drop(r_guard);
+            self.mappings.insert_vma(r);
+        }
+
+        return Ok(());
+    }
+
+    /// 创建新的用户栈
+    ///
+    /// ## 参数
+    ///
+    /// - `size`:栈的大小
+    pub fn new_user_stack(&mut self, size: usize) -> Result<(), SystemError> {
+        assert!(self.user_stack.is_none(), "User stack already exists");
+        let stack = UserStack::new(self, None, size)?;
+        self.user_stack = Some(stack);
+        return Ok(());
+    }
+
+    #[inline(always)]
+    pub fn user_stack_mut(&mut self) -> Option<&mut UserStack> {
+        return self.user_stack.as_mut();
+    }
+
+    /// 取消用户空间内的所有映射
+    pub unsafe fn unmap_all(&mut self) {
+        let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new();
+        for vma in self.mappings.iter_vmas() {
+            vma.unmap(&mut self.user_mapper.utable, &mut flusher);
+        }
+    }
+
+    /// 设置进程的堆的内存空间
+    ///
+    /// ## 参数
+    ///
+    /// - `new_brk`:新的堆的结束地址。需要满足页对齐要求,并且是用户空间地址,且大于等于当前的堆的起始地址
+    ///
+    /// ## 返回值
+    ///
+    /// 返回旧的堆的结束地址
+    pub unsafe fn set_brk(&mut self, new_brk: VirtAddr) -> Result<VirtAddr, SystemError> {
+        assert!(new_brk.check_aligned(MMArch::PAGE_SIZE));
+
+        if !new_brk.check_user() || new_brk < self.brk_start {
+            return Err(SystemError::EFAULT);
+        }
+
+        let old_brk = self.brk;
+        // kdebug!("set_brk: old_brk: {:?}, new_brk: {:?}", old_brk, new_brk);
+        if new_brk > self.brk {
+            let len = new_brk - self.brk;
+            let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
+            let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED;
+            self.map_anonymous(old_brk, len, prot_flags, map_flags, true)?
+                .virt_address();
+            self.brk = new_brk;
+            return Ok(old_brk);
+        } else {
+            let unmap_len = self.brk - new_brk;
+            let unmap_start = new_brk;
+            if unmap_len == 0 {
+                return Ok(old_brk);
+            }
+            self.munmap(
+                VirtPageFrame::new(unmap_start),
+                PageFrameCount::from_bytes(unmap_len).unwrap(),
+            )?;
+            self.brk = new_brk;
+            return Ok(old_brk);
+        }
+    }
+
+    pub unsafe fn sbrk(&mut self, incr: isize) -> Result<VirtAddr, SystemError> {
+        if incr == 0 {
+            return Ok(self.brk);
+        }
+
+        let new_brk = if incr > 0 {
+            self.brk + incr as usize
+        } else {
+            self.brk - (incr.abs() as usize)
+        };
+
+        let new_brk = VirtAddr::new(page_align_up(new_brk.data()));
+
+        return self.set_brk(new_brk);
+    }
+}
+
+impl Drop for InnerAddressSpace {
+    fn drop(&mut self) {
+        unsafe {
+            self.unmap_all();
+        }
+    }
+}
+
+#[derive(Debug, Hash)]
+pub struct UserMapper {
+    pub utable: PageMapper,
+}
+
+impl UserMapper {
+    pub fn new(utable: PageMapper) -> Self {
+        return Self { utable };
+    }
+}
+
+impl Drop for UserMapper {
+    fn drop(&mut self) {
+        if self.utable.is_current() {
+            // 如果当前要被销毁的用户空间的页表是当前进程的页表,那么就切换回初始内核页表
+            unsafe { MMArch::set_table(PageTableKind::User, MMArch::initial_page_table()) }
+        }
+        // 释放用户空间顶层页表占用的页帧
+        // 请注意,在释放这个页帧之前,用户页表应该已经被完全释放,否则会产生内存泄露
+        unsafe {
+            deallocate_page_frames(
+                PhysPageFrame::new(self.utable.table().phys()),
+                PageFrameCount::new(1),
+            )
+        };
+    }
+}
+
+/// 用户空间映射信息
+#[derive(Debug)]
+pub struct UserMappings {
+    /// 当前用户空间的虚拟内存区域
+    vmas: HashSet<Arc<LockedVMA>>,
+    /// 当前用户空间的VMA空洞
+    vm_holes: BTreeMap<VirtAddr, usize>,
+}
+
+impl UserMappings {
+    pub fn new() -> Self {
+        return Self {
+            vmas: HashSet::new(),
+            vm_holes: core::iter::once((VirtAddr::new(0), MMArch::USER_END_VADDR.data()))
+                .collect::<BTreeMap<_, _>>(),
+        };
+    }
+
+    /// 判断当前进程的VMA内,是否有包含指定的虚拟地址的VMA。
+    ///
+    /// 如果有,返回包含指定虚拟地址的VMA的Arc指针,否则返回None。
+    #[allow(dead_code)]
+    pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
+        for v in self.vmas.iter() {
+            let guard = v.lock();
+            if guard.region.contains(vaddr) {
+                return Some(v.clone());
+            }
+        }
+        return None;
+    }
+
+    /// 获取当前进程的地址空间中,与给定虚拟地址范围有重叠的VMA的迭代器。
+    pub fn conflicts(&self, request: VirtRegion) -> impl Iterator<Item = Arc<LockedVMA>> + '_ {
+        let r = self
+            .vmas
+            .iter()
+            .filter(move |v| !v.lock().region.intersect(&request).is_none())
+            .cloned();
+        return r;
+    }
+
+    /// 在当前进程的地址空间中,寻找第一个符合条件的空闲的虚拟内存范围。
+    ///
+    /// @param min_vaddr 最小的起始地址
+    /// @param size 请求的大小
+    ///
+    /// @return 如果找到了,返回虚拟内存范围,否则返回None
+    pub fn find_free(&self, min_vaddr: VirtAddr, size: usize) -> Option<VirtRegion> {
+        let _vaddr = min_vaddr;
+        let mut iter = self
+            .vm_holes
+            .iter()
+            .skip_while(|(hole_vaddr, hole_size)| hole_vaddr.add(**hole_size) <= min_vaddr);
+
+        let (hole_vaddr, size) = iter.find(|(hole_vaddr, hole_size)| {
+            // 计算当前空洞的可用大小
+            let available_size: usize =
+                if hole_vaddr <= &&min_vaddr && min_vaddr <= hole_vaddr.add(**hole_size) {
+                    **hole_size - (min_vaddr - **hole_vaddr)
+                } else {
+                    **hole_size
+                };
+
+            size <= available_size
+        })?;
+
+        // 创建一个新的虚拟内存范围。
+        let region = VirtRegion::new(cmp::max(*hole_vaddr, min_vaddr), *size);
+        return Some(region);
+    }
+
+    pub fn find_free_at(
+        &self,
+        min_vaddr: VirtAddr,
+        vaddr: VirtAddr,
+        size: usize,
+        flags: MapFlags,
+    ) -> Result<VirtRegion, SystemError> {
+        // 如果没有指定地址,那么就在当前进程的地址空间中寻找一个空闲的虚拟内存范围。
+        if vaddr == VirtAddr::new(0) {
+            return self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM);
+        }
+
+        // 如果指定了地址,那么就检查指定的地址是否可用。
+
+        let requested = VirtRegion::new(vaddr, size);
+
+        if requested.end() >= MMArch::USER_END_VADDR || !vaddr.check_aligned(MMArch::PAGE_SIZE) {
+            return Err(SystemError::EINVAL);
+        }
+
+        if let Some(_x) = self.conflicts(requested).next() {
+            if flags.contains(MapFlags::MAP_FIXED_NOREPLACE) {
+                // 如果指定了 MAP_FIXED_NOREPLACE 标志,由于所指定的地址无法成功建立映射,则放弃映射,不对地址做修正
+                return Err(SystemError::EEXIST);
+            }
+
+            if flags.contains(MapFlags::MAP_FIXED) {
+                // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖
+                return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+            }
+
+            // 如果没有指定MAP_FIXED标志,那么就对地址做修正
+            let requested = self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM)?;
+            return Ok(requested);
+        }
+
+        return Ok(requested);
+    }
+
+    /// 在当前进程的地址空间中,保留一个指定大小的区域,使得该区域不在空洞中。
+    /// 该函数会修改vm_holes中的空洞信息。
+    ///
+    /// @param region 要保留的区域
+    ///
+    /// 请注意,在调用本函数之前,必须先确定region所在范围内没有VMA。
+    fn reserve_hole(&mut self, region: &VirtRegion) {
+        let prev_hole: Option<(&VirtAddr, &mut usize)> =
+            self.vm_holes.range_mut(..region.start()).next_back();
+
+        if let Some((prev_hole_vaddr, prev_hole_size)) = prev_hole {
+            let prev_hole_end = prev_hole_vaddr.add(*prev_hole_size);
+
+            if prev_hole_end > region.start() {
+                // 如果前一个空洞的结束地址大于当前空洞的起始地址,那么就需要调整前一个空洞的大小。
+                *prev_hole_size = region.start().data() - prev_hole_vaddr.data();
+            }
+
+            if prev_hole_end > region.end() {
+                // 如果前一个空洞的结束地址大于当前空洞的结束地址,那么就需要增加一个新的空洞。
+                self.vm_holes
+                    .insert(region.end(), prev_hole_end - region.end());
+            }
+        }
+    }
+
+    /// 在当前进程的地址空间中,释放一个指定大小的区域,使得该区域成为一个空洞。
+    /// 该函数会修改vm_holes中的空洞信息。
+    fn unreserve_hole(&mut self, region: &VirtRegion) {
+        // 如果将要插入的空洞与后一个空洞相邻,那么就需要合并。
+        let next_hole_size: Option<usize> = self.vm_holes.remove(&region.end());
+
+        if let Some((_prev_hole_vaddr, prev_hole_size)) = self
+            .vm_holes
+            .range_mut(..region.start())
+            .next_back()
+            .filter(|(offset, size)| offset.data() + **size == region.start().data())
+        {
+            *prev_hole_size += region.size() + next_hole_size.unwrap_or(0);
+        } else {
+            self.vm_holes
+                .insert(region.start(), region.size() + next_hole_size.unwrap_or(0));
+        }
+    }
+
+    /// 在当前进程的映射关系中,插入一个新的VMA。
+    pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
+        let region = vma.lock().region.clone();
+        // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。
+        assert!(self.conflicts(region).next().is_none());
+        self.reserve_hole(&region);
+
+        self.vmas.insert(vma);
+    }
+
+    /// @brief 删除一个VMA,并把对应的地址空间加入空洞中。
+    ///
+    /// 这里不会取消VMA对应的地址的映射
+    ///
+    /// @param region 要删除的VMA所在的地址范围
+    ///
+    /// @return 如果成功删除了VMA,则返回被删除的VMA,否则返回None
+    /// 如果没有可以删除的VMA,则不会执行删除操作,并报告失败。
+    pub fn remove_vma(&mut self, region: &VirtRegion) -> Option<Arc<LockedVMA>> {
+        // 请注意,由于这里会对每个VMA加锁,因此性能很低
+        let vma: Arc<LockedVMA> = self
+            .vmas
+            .drain_filter(|vma| vma.lock().region == *region)
+            .next()?;
+        self.unreserve_hole(region);
+
+        return Some(vma);
+    }
+
+    /// @brief Get the iterator of all VMAs in this process.
+    pub fn iter_vmas(&self) -> hashbrown::hash_set::Iter<Arc<LockedVMA>> {
+        return self.vmas.iter();
+    }
+}
+
+impl Default for UserMappings {
+    fn default() -> Self {
+        return Self::new();
+    }
+}
+
+/// 加了锁的VMA
+///
+/// 备注:进行性能测试,看看SpinLock和RwLock哪个更快。
+#[derive(Debug)]
+pub struct LockedVMA(SpinLock<VMA>);
+
+impl core::hash::Hash for LockedVMA {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.0.lock().hash(state);
+    }
+}
+
+impl PartialEq for LockedVMA {
+    fn eq(&self, other: &Self) -> bool {
+        self.0.lock().eq(&other.0.lock())
+    }
+}
+
+impl Eq for LockedVMA {}
+
+#[allow(dead_code)]
+impl LockedVMA {
+    pub fn new(vma: VMA) -> Arc<Self> {
+        let r = Arc::new(Self(SpinLock::new(vma)));
+        r.0.lock().self_ref = Arc::downgrade(&r);
+        return r;
+    }
+
+    pub fn lock(&self) -> SpinLockGuard<VMA> {
+        return self.0.lock();
+    }
+
+    /// 调整当前VMA的页面的标志位
+    ///
+    /// TODO:增加调整虚拟页映射的物理地址的功能
+    ///
+    /// @param flags 新的标志位
+    /// @param mapper 页表映射器
+    /// @param flusher 页表项刷新器
+    ///
+    pub fn remap(
+        &self,
+        flags: PageFlags<MMArch>,
+        mapper: &mut PageMapper,
+        mut flusher: impl Flusher<MMArch>,
+    ) -> Result<(), SystemError> {
+        let mut guard = self.lock();
+        assert!(guard.mapped);
+        for page in guard.region.pages() {
+            // 暂时要求所有的页帧都已经映射到页表
+            // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
+            let r = unsafe {
+                mapper
+                    .remap(page.virt_address(), flags)
+                    .expect("Failed to remap, beacuse of some page is not mapped")
+            };
+            flusher.consume(r);
+        }
+        guard.flags = flags;
+        return Ok(());
+    }
+
+    pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) {
+        let mut guard = self.lock();
+        assert!(guard.mapped);
+        for page in guard.region.pages() {
+            let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) }
+                .expect("Failed to unmap, beacuse of some page is not mapped");
+
+            // todo: 获取物理页的anon_vma的守卫
+
+            // todo: 从anon_vma中删除当前VMA
+
+            // todo: 如果物理页的anon_vma链表长度为0,则释放物理页.
+
+            // 目前由于还没有实现共享页,所以直接释放物理页也没问题。
+            // 但是在实现共享页之后,就不能直接释放物理页了,需要在anon_vma链表长度为0的时候才能释放物理页
+            unsafe { deallocate_page_frames(PhysPageFrame::new(paddr), PageFrameCount::new(1)) };
+
+            flusher.consume(flush);
+        }
+        guard.mapped = false;
+    }
+
+    pub fn mapped(&self) -> bool {
+        return self.0.lock().mapped;
+    }
+
+    /// 将当前VMA进行切分,切分成3个VMA,分别是:
+    ///
+    /// 1. 前面的VMA,如果没有则为None
+    /// 2. 中间的VMA,也就是传入的Region
+    /// 3. 后面的VMA,如果没有则为None
+    pub fn extract(
+        &self,
+        region: VirtRegion,
+    ) -> Option<(
+        Option<Arc<LockedVMA>>,
+        Arc<LockedVMA>,
+        Option<Arc<LockedVMA>>,
+    )> {
+        assert!(region.start().check_aligned(MMArch::PAGE_SIZE));
+        assert!(region.end().check_aligned(MMArch::PAGE_SIZE));
+
+        let mut guard = self.lock();
+        {
+            // 如果传入的region不在当前VMA的范围内,则直接返回None
+            if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end())
+            {
+                return None;
+            }
+
+            let intersect: Option<VirtRegion> = guard.region.intersect(&region);
+            // 如果当前VMA不包含region,则直接返回None
+            if unlikely(intersect.is_none()) {
+                return None;
+            }
+            let intersect: VirtRegion = intersect.unwrap();
+            if unlikely(intersect == guard.region) {
+                // 如果当前VMA完全包含region,则直接返回当前VMA
+                return Some((None, guard.self_ref.upgrade().unwrap(), None));
+            }
+        }
+
+        let before: Option<Arc<LockedVMA>> = guard.region.before(&region).map(|virt_region| {
+            let mut vma: VMA = unsafe { guard.clone() };
+            vma.region = virt_region;
+
+            let vma: Arc<LockedVMA> = LockedVMA::new(vma);
+            vma
+        });
+
+        let after: Option<Arc<LockedVMA>> = guard.region.after(&region).map(|virt_region| {
+            let mut vma: VMA = unsafe { guard.clone() };
+            vma.region = virt_region;
+
+            let vma: Arc<LockedVMA> = LockedVMA::new(vma);
+            vma
+        });
+
+        guard.region = region;
+
+        // TODO: 重新设置before、after这两个VMA里面的物理页的anon_vma
+
+        return Some((before, guard.self_ref.upgrade().unwrap(), after));
+    }
+}
+
+/// @brief 虚拟内存区域
+#[derive(Debug)]
+pub struct VMA {
+    /// 虚拟内存区域对应的虚拟地址范围
+    region: VirtRegion,
+    /// VMA内的页帧的标志
+    flags: PageFlags<MMArch>,
+    /// VMA内的页帧是否已经映射到页表
+    mapped: bool,
+    /// VMA所属的用户地址空间
+    user_address_space: Option<Weak<AddressSpace>>,
+    self_ref: Weak<LockedVMA>,
+}
+
+impl core::hash::Hash for VMA {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.region.hash(state);
+        self.flags.hash(state);
+        self.mapped.hash(state);
+    }
+}
+
+#[allow(dead_code)]
+impl VMA {
+    pub fn region(&self) -> &VirtRegion {
+        return &self.region;
+    }
+
+    /// # 拷贝当前VMA的内容
+    ///
+    /// ### 安全性
+    ///
+    /// 由于这样操作可能由于错误的拷贝,导致内存泄露、内存重复释放等问题,所以需要小心使用。
+    pub unsafe fn clone(&self) -> Self {
+        return Self {
+            region: self.region,
+            flags: self.flags,
+            mapped: self.mapped,
+            user_address_space: self.user_address_space.clone(),
+            self_ref: self.self_ref.clone(),
+        };
+    }
+
+    #[inline(always)]
+    pub fn flags(&self) -> PageFlags<MMArch> {
+        return self.flags;
+    }
+
+    pub fn pages(&self) -> VirtPageFrameIter {
+        return VirtPageFrameIter::new(
+            VirtPageFrame::new(self.region.start()),
+            VirtPageFrame::new(self.region.end()),
+        );
+    }
+
+    pub fn remap(
+        &mut self,
+        flags: PageFlags<MMArch>,
+        mapper: &mut PageMapper,
+        mut flusher: impl Flusher<MMArch>,
+    ) -> Result<(), SystemError> {
+        assert!(self.mapped);
+        for page in self.region.pages() {
+            // kdebug!("remap page {:?}", page.virt_address());
+            // 暂时要求所有的页帧都已经映射到页表
+            // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
+            let r = unsafe {
+                mapper
+                    .remap(page.virt_address(), flags)
+                    .expect("Failed to remap, beacuse of some page is not mapped")
+            };
+            // kdebug!("consume page {:?}", page.virt_address());
+            flusher.consume(r);
+            // kdebug!("remap page {:?} done", page.virt_address());
+        }
+        self.flags = flags;
+        return Ok(());
+    }
+
+    /// 检查当前VMA是否可以拥有指定的标志位
+    ///
+    /// ## 参数
+    ///
+    /// - `prot_flags` 要检查的标志位
+    pub fn can_have_flags(&self, prot_flags: ProtFlags) -> bool {
+        return (self.flags.has_write() || !prot_flags.contains(ProtFlags::PROT_WRITE))
+            && (self.flags.has_execute() || !prot_flags.contains(ProtFlags::PROT_EXEC));
+    }
+
+    /// 把物理地址映射到虚拟地址
+    ///
+    /// @param phys 要映射的物理地址
+    /// @param destination 要映射到的虚拟地址
+    /// @param count 要映射的页帧数量
+    /// @param flags 页面标志位
+    /// @param mapper 页表映射器
+    /// @param flusher 页表项刷新器
+    ///
+    /// @return 返回映射后的虚拟内存区域
+    pub fn physmap(
+        phys: PhysPageFrame,
+        destination: VirtPageFrame,
+        count: PageFrameCount,
+        flags: PageFlags<MMArch>,
+        mapper: &mut PageMapper,
+        mut flusher: impl Flusher<MMArch>,
+    ) -> Result<Arc<LockedVMA>, SystemError> {
+        {
+            let mut cur_phy = phys;
+            let mut cur_dest = destination;
+
+            for _ in 0..count.data() {
+                // 将物理页帧映射到虚拟页帧
+                let r = unsafe {
+                    mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags)
+                }
+                .expect("Failed to map phys, may be OOM error");
+
+                // todo: 增加OOM处理
+
+                // todo: 将VMA加入到anon_vma中
+
+                // 刷新TLB
+                flusher.consume(r);
+
+                cur_phy = cur_phy.next();
+                cur_dest = cur_dest.next();
+            }
+        }
+
+        let r: Arc<LockedVMA> = LockedVMA::new(VMA {
+            region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
+            flags,
+            mapped: true,
+            user_address_space: None,
+            self_ref: Weak::default(),
+        });
+        return Ok(r);
+    }
+
+    /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA
+    ///
+    /// @param destination 要映射到的虚拟地址
+    /// @param count 要映射的页帧数量
+    /// @param flags 页面标志位
+    /// @param mapper 页表映射器
+    /// @param flusher 页表项刷新器
+    ///
+    /// @return 返回映射后的虚拟内存区域
+    pub fn zeroed(
+        destination: VirtPageFrame,
+        page_count: PageFrameCount,
+        flags: PageFlags<MMArch>,
+        mapper: &mut PageMapper,
+        mut flusher: impl Flusher<MMArch>,
+    ) -> Result<Arc<LockedVMA>, SystemError> {
+        let mut cur_dest: VirtPageFrame = destination;
+        // kdebug!(
+        //     "VMA::zeroed: page_count = {:?}, destination={destination:?}",
+        //     page_count
+        // );
+        for _ in 0..page_count.data() {
+            // kdebug!(
+            //     "VMA::zeroed: cur_dest={cur_dest:?}, vaddr = {:?}",
+            //     cur_dest.virt_address()
+            // );
+            let r = unsafe { mapper.map(cur_dest.virt_address(), flags) }
+                .expect("Failed to map zero, may be OOM error");
+            // todo: 将VMA加入到anon_vma中
+            // todo: 增加OOM处理
+
+            // 稍后再刷新TLB,这里取消刷新
+            flusher.consume(r);
+            cur_dest = cur_dest.next();
+        }
+        let r = LockedVMA::new(VMA {
+            region: VirtRegion::new(
+                destination.virt_address(),
+                page_count.data() * MMArch::PAGE_SIZE,
+            ),
+            flags,
+            mapped: true,
+            user_address_space: None,
+            self_ref: Weak::default(),
+        });
+        drop(flusher);
+        // kdebug!("VMA::zeroed: flusher dropped");
+
+        // 清空这些内存
+        let virt_iter = VirtPageFrameIter::new(destination, destination.add(page_count));
+        for frame in virt_iter {
+            let paddr = mapper.translate(frame.virt_address()).unwrap().0;
+
+            unsafe {
+                let vaddr = MMArch::phys_2_virt(paddr).unwrap();
+                MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE);
+            }
+        }
+        // kdebug!("VMA::zeroed: done");
+        return Ok(r);
+    }
+}
+
+impl Drop for VMA {
+    fn drop(&mut self) {
+        // 当VMA被释放时,需要确保它已经被从页表中解除映射
+        assert!(!self.mapped, "VMA is still mapped");
+    }
+}
+
+impl PartialEq for VMA {
+    fn eq(&self, other: &Self) -> bool {
+        return self.region == other.region;
+    }
+}
+
+impl Eq for VMA {}
+
+impl PartialOrd for VMA {
+    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
+        return self.region.partial_cmp(&other.region);
+    }
+}
+
+impl Ord for VMA {
+    fn cmp(&self, other: &Self) -> cmp::Ordering {
+        return self.region.cmp(&other.region);
+    }
+}
+
+#[derive(Debug)]
+pub struct UserStack {
+    // 栈底地址
+    stack_bottom: VirtAddr,
+    // 当前已映射的大小
+    mapped_size: usize,
+    /// 栈顶地址(这个值需要仔细确定!因为它可能不会实时与用户栈的真实栈顶保持一致!要小心!)
+    current_sp: VirtAddr,
+}
+
+impl UserStack {
+    /// 默认的用户栈底地址
+    pub const DEFAULT_USER_STACK_BOTTOM: VirtAddr = MMArch::USER_STACK_START;
+    /// 默认的用户栈大小为8MB
+    pub const DEFAULT_USER_STACK_SIZE: usize = 8 * 1024 * 1024;
+    /// 用户栈的保护页数量
+    pub const GUARD_PAGES_NUM: usize = 4;
+
+    /// 创建一个用户栈
+    pub fn new(
+        vm: &mut InnerAddressSpace,
+        stack_bottom: Option<VirtAddr>,
+        stack_size: usize,
+    ) -> Result<Self, SystemError> {
+        let stack_bottom = stack_bottom.unwrap_or(Self::DEFAULT_USER_STACK_BOTTOM);
+        assert!(stack_bottom.check_aligned(MMArch::PAGE_SIZE));
+
+        // 分配用户栈的保护页
+        let guard_size = Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE;
+        let actual_stack_bottom = stack_bottom - guard_size;
+
+        let mut prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE;
+        let map_flags =
+            MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE;
+        // kdebug!(
+        //     "map anonymous stack: {:?} {}",
+        //     actual_stack_bottom,
+        //     guard_size
+        // );
+        vm.map_anonymous(
+            actual_stack_bottom,
+            guard_size,
+            prot_flags,
+            map_flags,
+            false,
+        )?;
+        // test_buddy();
+        // 设置保护页只读
+        prot_flags.remove(ProtFlags::PROT_WRITE);
+        // kdebug!(
+        //     "to mprotect stack guard pages: {:?} {}",
+        //     actual_stack_bottom,
+        //     guard_size
+        // );
+        vm.mprotect(
+            VirtPageFrame::new(actual_stack_bottom),
+            PageFrameCount::new(Self::GUARD_PAGES_NUM),
+            prot_flags,
+        )?;
+
+        // kdebug!(
+        //     "mprotect stack guard pages done: {:?} {}",
+        //     actual_stack_bottom,
+        //     guard_size
+        // );
+
+        let mut user_stack = UserStack {
+            stack_bottom: actual_stack_bottom,
+            mapped_size: guard_size,
+            current_sp: actual_stack_bottom - guard_size,
+        };
+
+        // kdebug!("extend user stack: {:?} {}", stack_bottom, stack_size);
+        // 分配用户栈
+        user_stack.initial_extend(vm, stack_size)?;
+        // kdebug!("user stack created: {:?} {}", stack_bottom, stack_size);
+        return Ok(user_stack);
+    }
+
+    fn initial_extend(
+        &mut self,
+        vm: &mut InnerAddressSpace,
+        mut bytes: usize,
+    ) -> Result<(), SystemError> {
+        let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
+        let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS;
+
+        bytes = page_align_up(bytes);
+        self.mapped_size += bytes;
+
+        vm.map_anonymous(
+            self.stack_bottom - self.mapped_size,
+            bytes,
+            prot_flags,
+            map_flags,
+            false,
+        )?;
+
+        return Ok(());
+    }
+
+    /// 扩展用户栈
+    ///
+    /// ## 参数
+    ///
+    /// - `vm` 用户地址空间结构体
+    /// - `bytes` 要扩展的字节数
+    ///
+    /// ## 返回值
+    ///
+    /// - **Ok(())** 扩展成功
+    /// - **Err(SystemError)** 扩展失败
+    #[allow(dead_code)]
+    pub fn extend(
+        &mut self,
+        vm: &mut RwLockWriteGuard<InnerAddressSpace>,
+        mut bytes: usize,
+    ) -> Result<(), SystemError> {
+        let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
+        let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS;
+
+        bytes = page_align_up(bytes);
+        self.mapped_size += bytes;
+
+        vm.map_anonymous(
+            self.stack_bottom - self.mapped_size,
+            bytes,
+            prot_flags,
+            map_flags,
+            false,
+        )?;
+
+        return Ok(());
+    }
+
+    /// 获取栈顶地址
+    ///
+    /// 请注意,如果用户栈的栈顶地址发生变化,这个值可能不会实时更新!
+    pub fn sp(&self) -> VirtAddr {
+        return self.current_sp;
+    }
+
+    pub unsafe fn set_sp(&mut self, sp: VirtAddr) {
+        self.current_sp = sp;
+    }
+
+    /// 仅仅克隆用户栈的信息,不会克隆用户栈的内容/映射
+    pub unsafe fn clone_info_only(&self) -> Self {
+        return Self {
+            stack_bottom: self.stack_bottom,
+            mapped_size: self.mapped_size,
+            current_sp: self.current_sp,
+        };
+    }
+
+    /// 获取当前用户栈的大小(不包括保护页)
+    pub fn stack_size(&self) -> usize {
+        return self.mapped_size - Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE;
+    }
+}

+ 0 - 109
kernel/src/mm/utils.c

@@ -1,109 +0,0 @@
-#include "internal.h"
-
-extern uint64_t mm_total_2M_pages;
-
-/**
- * @brief 获取指定虚拟地址处映射的物理地址
- *
- * @param mm 内存空间分布结构体
- * @param vaddr 虚拟地址
- * @return uint64_t 已映射的物理地址
- */
-uint64_t __mm_get_paddr(struct mm_struct *mm, uint64_t vaddr)
-{
-    ul *tmp;
-
-    tmp = phys_2_virt((ul *)(((ul)mm->pgd) & (~0xfffUL)) + ((vaddr >> PAGE_GDT_SHIFT) & 0x1ff));
-
-    // pml4页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    tmp = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + ((vaddr >> PAGE_1G_SHIFT) & 0x1ff));
-
-    // pdpt页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    // 读取pdt页表项
-    tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(vaddr) >> PAGE_2M_SHIFT) & 0x1ff)));
-
-    // pde页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    if (*tmp & (1 << 7))
-    {
-        // 当前为2M物理页
-        return (*tmp) & (~0x1fffUL);
-    }
-    else
-    {
-        // 存在4级页表
-        tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(vaddr) >> PAGE_4K_SHIFT) & 0x1ff)));
-
-        return (*tmp) & (~0x1ffUL);
-    }
-}
-
-/**
- * @brief 检测指定地址是否已经被映射
- *
- * @param page_table_phys_addr 页表的物理地址
- * @param virt_addr 要检测的地址
- * @return true 已经被映射
- * @return false
- */
-bool mm_check_mapped(ul page_table_phys_addr, uint64_t virt_addr)
-{
-    ul *tmp;
-
-    tmp = phys_2_virt((ul *)((ul)page_table_phys_addr & (~0xfffUL)) + ((virt_addr >> PAGE_GDT_SHIFT) & 0x1ff));
-
-    // pml4页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    tmp = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + ((virt_addr >> PAGE_1G_SHIFT) & 0x1ff));
-
-    // pdpt页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    // 读取pdt页表项
-    tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr) >> PAGE_2M_SHIFT) & 0x1ff)));
-
-    // pde页表项为0
-    if (*tmp == 0)
-        return 0;
-
-    if (*tmp & (1 << 7))
-    {
-        // 当前为2M物理页
-        return true;
-    }
-    else
-    {
-        // 存在4级页表
-        tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr) >> PAGE_4K_SHIFT) & 0x1ff)));
-        if (*tmp != 0)
-            return true;
-        else
-            return false;
-    }
-}
-
-/**
- * @brief 检测是否为有效的2M页(物理内存页)
- *
- * @param paddr 物理地址
- * @return int8_t 是 -> 1
- *                 否 -> 0
- */
-int8_t mm_is_2M_page(uint64_t paddr)
-{
-    if (likely((paddr >> PAGE_2M_SHIFT) < mm_total_2M_pages))
-        return 1;
-    else
-        return 0;
-}

+ 0 - 275
kernel/src/mm/vma.c

@@ -1,275 +0,0 @@
-#include "mm.h"
-#include "slab.h"
-#include "internal.h"
-
-/**
- * @brief 获取一块新的vma结构体,并将其与指定的mm进行绑定
- *
- * @param mm 与VMA绑定的内存空间分布结构体
- * @return struct vm_area_struct* 新的VMA
- */
-struct vm_area_struct *vm_area_alloc(struct mm_struct *mm)
-{
-    struct vm_area_struct *vma = (struct vm_area_struct *)kmalloc(sizeof(struct vm_area_struct), 0);
-    if (vma)
-        vma_init(vma, mm);
-    return vma;
-}
-
-/**
- * @brief 从链表中删除指定的vma结构体
- *
- * @param vma
- */
-void vm_area_del(struct vm_area_struct *vma)
-{
-    if (vma->vm_mm == NULL)
-        return;
-    __vma_unlink_list(vma->vm_mm, vma);
-}
-
-/**
- * @brief 释放vma结构体
- *
- * @param vma 待释放的vma结构体
- */
-void vm_area_free(struct vm_area_struct *vma)
-{
-    if (vma->vm_prev == NULL && vma->vm_next == NULL) // 如果当前是剩余的最后一个vma
-        vma->vm_mm->vmas = NULL;
-    kfree(vma);
-}
-
-/**
- * @brief 将vma结构体插入mm_struct的链表之中
- *
- * @param mm 内存空间分布结构体
- * @param vma 待插入的VMA结构体
- * @param prev 链表的前一个结点
- */
-void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev)
-{
-    struct vm_area_struct *next = NULL;
-    vma->vm_prev = prev;
-    if (prev) // 若指定了前一个结点,则直接连接
-    {
-        next = prev->vm_next;
-        prev->vm_next = vma;
-    }
-    else // 否则将vma直接插入到给定的mm的vma链表之中
-    {
-        next = mm->vmas;
-        mm->vmas = vma;
-    }
-
-    vma->vm_next = next;
-
-    if (next != NULL)
-        next->vm_prev = vma;
-}
-
-/**
- * @brief 将vma给定结构体从vma链表的结点之中删除
- *
- * @param mm 内存空间分布结构体
- * @param vma 待插入的VMA结构体
- */
-void __vma_unlink_list(struct mm_struct *mm, struct vm_area_struct *vma)
-{
-    struct vm_area_struct *prev, *next;
-    next = vma->vm_next;
-    prev = vma->vm_prev;
-    if (prev)
-        prev->vm_next = next;
-    else // 当前vma是链表中的第一个vma
-        mm->vmas = next;
-
-    if (next)
-        next->vm_prev = prev;
-}
-
-/**
- * @brief 查找第一个符合“addr < vm_end”条件的vma
- *
- * @param mm 内存空间分布结构体
- * @param addr 虚拟地址
- * @return struct vm_area_struct* 符合条件的vma
- */
-struct vm_area_struct *vma_find(struct mm_struct *mm, uint64_t addr)
-{
-    struct vm_area_struct *vma = mm->vmas;
-    struct vm_area_struct *result = NULL;
-    while (vma != NULL)
-    {
-        if (vma->vm_end > addr)
-        {
-            result = vma;
-            break;
-        }
-        vma = vma->vm_next;
-    }
-    return result;
-}
-
-/**
- * @brief 插入vma
- *
- * @param mm
- * @param vma
- * @return int
- */
-int vma_insert(struct mm_struct *mm, struct vm_area_struct *vma)
-{
-
-    struct vm_area_struct *prev;
-
-    prev = vma_find(mm, vma->vm_start);
-    
-    if (prev && prev->vm_start <= vma->vm_start && prev->vm_end >= vma->vm_end)
-    {
-        // 已经存在了相同的vma
-        return -EEXIST;
-    }
-    // todo: bugfix: 这里的第二种情况貌似从来不会满足
-    else if (prev && ((vma->vm_start >= prev->vm_start && vma->vm_start <= prev->vm_end) || (prev->vm_start <= vma->vm_end && prev->vm_start >= vma->vm_start)))    
-    {
-        //部分重叠
-        if ((!CROSS_2M_BOUND(vma->vm_start, prev->vm_start)) && (!CROSS_2M_BOUND(vma->vm_end, prev->vm_end))&& vma->vm_end)
-        {
-            //合并vma 并改变链表vma的范围
-            kdebug("before combining vma:vm_start = %#018lx, vm_end = %#018lx\n", vma->vm_start, vma->vm_end);
-
-            prev->vm_start = (vma->vm_start < prev->vm_start )? vma->vm_start : prev->vm_start;
-            prev->vm_end = (vma->vm_end > prev->vm_end) ? vma->vm_end : prev->vm_end;
-            // 计算page_offset
-            prev->page_offset = prev->vm_start - (prev->vm_start & PAGE_2M_MASK);
-            kdebug("combined vma:vm_start = %#018lx, vm_end = %#018lx\nprev:vm_start = %018lx, vm_end = %018lx\n", vma->vm_start, vma->vm_end, prev->vm_start, prev->vm_end);
-            kinfo("vma has same part\n");
-            return __VMA_MERGED;
-        }
-    }
-
-    // prev = vma_find(mm, vma->vm_start);
-
-    if (prev == NULL) // 要将当前vma插入到链表的尾部
-    {
-        struct vm_area_struct *ptr = mm->vmas;
-        while (ptr)
-        {
-            if (ptr->vm_next)
-                ptr = ptr->vm_next;
-            else
-            {
-                prev = ptr;
-                break;
-            }
-        }
-    }
-    else
-        prev = prev->vm_prev;
-    __vma_link_list(mm, vma, prev);
-    return 0;
-}
-
-/**
- * @brief 创建anon_vma,并将其与页面结构体进行绑定
- * 若提供的页面结构体指针为NULL,则只创建,不绑定
- *
- * @param page 页面结构体的指针
- * @param lock_page 是否将页面结构体加锁
- * @return struct anon_vma_t* 创建好的anon_vma
- */
-struct anon_vma_t *__anon_vma_create_alloc(struct Page *page, bool lock_page)
-{
-    struct anon_vma_t *anon_vma = (struct anon_vma_t *)kmalloc(sizeof(struct anon_vma_t), 0);
-    if (unlikely(anon_vma == NULL))
-        return NULL;
-    memset(anon_vma, 0, sizeof(struct anon_vma_t));
-
-    list_init(&anon_vma->vma_list);
-    semaphore_init(&anon_vma->sem, 1);
-
-    // 需要和page进行绑定
-    if (page != NULL)
-    {
-        if (lock_page == true) // 需要加锁
-        {
-            uint64_t rflags;
-            spin_lock(&page->op_lock);
-            page->anon_vma = anon_vma;
-            spin_unlock(&page->op_lock);
-        }
-        else
-            page->anon_vma = anon_vma;
-
-        anon_vma->page = page;
-    }
-    return anon_vma;
-}
-
-/**
- * @brief 将指定的vma加入到anon_vma的管理范围之中
- *
- * @param anon_vma 页面的anon_vma
- * @param vma 待加入的vma
- * @return int 返回码
- */
-int __anon_vma_add(struct anon_vma_t *anon_vma, struct vm_area_struct *vma)
-{
-    semaphore_down(&anon_vma->sem);
-    list_add(&anon_vma->vma_list, &vma->anon_vma_list);
-    vma->anon_vma = anon_vma;
-    atomic_inc(&anon_vma->ref_count);
-    semaphore_up(&anon_vma->sem);
-    return 0;
-}
-
-/**
- * @brief 释放anon vma结构体
- *
- * @param anon_vma 待释放的anon_vma结构体
- * @return int 返回码
- */
-int __anon_vma_free(struct anon_vma_t *anon_vma)
-{
-    if (anon_vma->page != NULL)
-    {
-        spin_lock(&anon_vma->page->op_lock);
-        anon_vma->page->anon_vma = NULL;
-        spin_unlock(&anon_vma->page->op_lock);
-    }
-    kfree(anon_vma);
-
-    return 0;
-}
-
-/**
- * @brief 从anon_vma的管理范围中删除指定的vma
- * (在进入这个函数之前,应该要对anon_vma加锁)
- * @param vma 将要取消对应的anon_vma管理的vma结构体
- * @return int 返回码
- */
-int __anon_vma_del(struct vm_area_struct *vma)
-{
-    // 当前vma没有绑定anon_vma
-    if (vma->anon_vma == NULL)
-        return -EINVAL;
-
-    list_del(&vma->anon_vma_list);
-    atomic_dec(&vma->anon_vma->ref_count);
-
-    // 若当前anon_vma的引用计数归零,则意味着可以释放内存页
-    if (unlikely(atomic_read(&vma->anon_vma->ref_count) == 0)) // 应当释放该anon_vma
-    {
-        // 若页面结构体是mmio创建的,则释放页面结构体
-        if (vma->anon_vma->page->attr & PAGE_DEVICE)
-            kfree(vma->anon_vma->page);
-        else
-            free_pages(vma->anon_vma->page, 1);
-        __anon_vma_free(vma->anon_vma);
-    }
-
-    // 清理当前vma的关联数据
-    vma->anon_vma = NULL;
-    list_init(&vma->anon_vma_list);
-}

+ 86 - 0
kernel/src/process/abi.rs

@@ -0,0 +1,86 @@
+/// An enumeration of the possible values for the `AT_*` constants.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub enum AtType {
+    /// End of vector.
+    Null,
+    /// Entry should be ignored.
+    Ignore,
+    /// File descriptor of program.
+    ExecFd,
+    /// Program headers for program.
+    Phdr,
+    /// Size of program header entry.
+    PhEnt,
+    /// Number of program headers.
+    PhNum,
+    /// System page size.
+    PageSize,
+    /// Base address of interpreter.
+    Base,
+    /// Flags.
+    Flags,
+    /// Entry point of program.
+    Entry,
+    /// Program is not ELF.
+    NotElf,
+    /// Real uid.
+    Uid,
+    /// Effective uid.
+    EUid,
+    /// Real gid.
+    Gid,
+    /// Effective gid.
+    EGid,
+    /// String identifying CPU for optimizations.
+    Platform,
+    /// Arch dependent hints at CPU capabilities.
+    HwCap,
+    /// Frequency at which times() increments.
+    ClkTck,
+    /// Secure mode boolean.
+    Secure,
+    /// String identifying real platform, may differ from AT_PLATFORM.
+    BasePlatform,
+    /// Address of 16 random bytes.
+    Random,
+    /// Extension of AT_HWCAP.
+    HwCap2,
+    /// Filename of program.
+    ExecFn,
+    /// Minimal stack size for signal delivery.
+    MinSigStackSize,
+}
+
+impl TryFrom<u32> for AtType {
+    type Error = &'static str;
+
+    fn try_from(value: u32) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(AtType::Null),
+            1 => Ok(AtType::Ignore),
+            2 => Ok(AtType::ExecFd),
+            3 => Ok(AtType::Phdr),
+            4 => Ok(AtType::PhEnt),
+            5 => Ok(AtType::PhNum),
+            6 => Ok(AtType::PageSize),
+            7 => Ok(AtType::Base),
+            8 => Ok(AtType::Flags),
+            9 => Ok(AtType::Entry),
+            10 => Ok(AtType::NotElf),
+            11 => Ok(AtType::Uid),
+            12 => Ok(AtType::EUid),
+            13 => Ok(AtType::Gid),
+            14 => Ok(AtType::EGid),
+            15 => Ok(AtType::Platform),
+            16 => Ok(AtType::HwCap),
+            17 => Ok(AtType::ClkTck),
+            23 => Ok(AtType::Secure),
+            24 => Ok(AtType::BasePlatform),
+            25 => Ok(AtType::Random),
+            26 => Ok(AtType::HwCap2),
+            31 => Ok(AtType::ExecFn),
+            51 => Ok(AtType::MinSigStackSize),
+            _ => Err("Invalid value for AtType"),
+        }
+    }
+}

+ 115 - 0
kernel/src/process/c_adapter.rs

@@ -0,0 +1,115 @@
+use core::{ffi::c_void, ptr::null_mut};
+
+use alloc::boxed::Box;
+
+use crate::{
+    arch::{asm::current::current_pcb, fpu::FpState},
+    include::bindings::bindings::process_control_block,
+    syscall::SystemError,
+};
+
+use super::{fork::copy_mm, process::init_stdio, process_init};
+
+#[no_mangle]
+pub extern "C" fn rs_process_init() {
+    process_init();
+}
+
+#[no_mangle]
+pub extern "C" fn rs_process_copy_mm(clone_vm: bool, new_pcb: &mut process_control_block) -> usize {
+    return copy_mm(clone_vm, new_pcb)
+        .map(|_| 0)
+        .unwrap_or_else(|err| err.to_posix_errno() as usize);
+}
+
+/// @brief 初始化当前进程的文件描述符数组
+/// 请注意,如果当前进程已经有文件描述符数组,那么本操作将被禁止
+#[no_mangle]
+pub extern "C" fn process_init_files() -> i32 {
+    let r = current_pcb().init_files();
+    if r.is_ok() {
+        return 0;
+    } else {
+        return r.unwrap_err().to_posix_errno();
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_drop_address_space(pcb: &'static mut process_control_block) -> i32 {
+    unsafe {
+        pcb.drop_address_space();
+    }
+    return 0;
+}
+
+/// @brief 拷贝当前进程的文件描述符信息
+///
+/// @param clone_flags 克隆标志位
+/// @param pcb 新的进程的pcb
+#[no_mangle]
+pub extern "C" fn process_copy_files(
+    clone_flags: u64,
+    from: &'static process_control_block,
+) -> i32 {
+    let r = current_pcb().copy_files(clone_flags, from);
+    if r.is_ok() {
+        return 0;
+    } else {
+        return r.unwrap_err().to_posix_errno();
+    }
+}
+
+/// @brief 回收进程的文件描述符数组
+///
+/// @param pcb 要被回收的进程的pcb
+///
+/// @return i32
+#[no_mangle]
+pub extern "C" fn process_exit_files(pcb: &'static mut process_control_block) -> i32 {
+    let r: Result<(), SystemError> = pcb.exit_files();
+    if r.is_ok() {
+        return 0;
+    } else {
+        return r.unwrap_err().to_posix_errno();
+    }
+}
+
+/// @brief 复制当前进程的浮点状态
+#[allow(dead_code)]
+#[no_mangle]
+pub extern "C" fn rs_dup_fpstate() -> *mut c_void {
+    // 如果当前进程没有浮点状态,那么就返回一个默认的浮点状态
+    if current_pcb().fp_state == null_mut() {
+        return Box::leak(Box::new(FpState::default())) as *mut FpState as usize as *mut c_void;
+    } else {
+        // 如果当前进程有浮点状态,那么就复制一个新的浮点状态
+        let state = current_pcb().fp_state as usize as *mut FpState;
+        unsafe {
+            let s = state.as_ref().unwrap();
+            let state: &mut FpState = Box::leak(Box::new(s.clone()));
+
+            return state as *mut FpState as usize as *mut c_void;
+        }
+    }
+}
+
+/// @brief 释放进程的浮点状态所占用的内存
+#[no_mangle]
+pub extern "C" fn rs_process_exit_fpstate(pcb: &'static mut process_control_block) {
+    if pcb.fp_state != null_mut() {
+        let state = pcb.fp_state as usize as *mut FpState;
+        unsafe {
+            drop(Box::from_raw(state));
+        }
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_init_stdio() -> i32 {
+    let r = init_stdio();
+    if r.is_ok() {
+        return 0;
+    } else {
+        return r.unwrap_err().to_posix_errno();
+    }
+}

+ 288 - 0
kernel/src/process/exec.rs

@@ -0,0 +1,288 @@
+use core::{fmt::Debug, ptr::null};
+
+use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
+
+use crate::{
+    filesystem::vfs::{
+        file::{File, FileMode},
+        ROOT_INODE,
+    },
+    io::SeekFrom,
+    libs::elf::ELF_LOADER,
+    mm::{
+        ucontext::{AddressSpace, UserStack},
+        VirtAddr,
+    },
+    syscall::SystemError,
+};
+
+/// 系统支持的所有二进制文件加载器的列表
+const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER];
+
+pub trait BinaryLoader: 'static + Debug {
+    /// 检查二进制文件是否为当前加载器支持的格式
+    fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
+
+    fn load(
+        self: &'static Self,
+        param: &mut ExecParam,
+        head_buf: &[u8],
+    ) -> Result<BinaryLoaderResult, ExecError>;
+}
+
+/// 二进制文件加载结果
+#[derive(Debug)]
+pub struct BinaryLoaderResult {
+    /// 程序入口地址
+    entry_point: VirtAddr,
+}
+
+impl BinaryLoaderResult {
+    pub fn new(entry_point: VirtAddr) -> Self {
+        Self { entry_point }
+    }
+
+    pub fn entry_point(&self) -> VirtAddr {
+        self.entry_point
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Debug)]
+pub enum ExecError {
+    /// 二进制文件不可执行
+    NotExecutable,
+    /// 二进制文件不是当前架构的
+    WrongArchitecture,
+    /// 访问权限不足
+    PermissionDenied,
+    /// 不支持的操作
+    NotSupported,
+    /// 解析文件本身的时候出现错误(比如一些字段本身不合法)
+    ParseError,
+    /// 内存不足
+    OutOfMemory,
+    /// 参数错误
+    InvalidParemeter,
+    /// 无效的地址
+    BadAddress(Option<VirtAddr>),
+    Other(String),
+}
+
+impl Into<SystemError> for ExecError {
+    fn into(self) -> SystemError {
+        match self {
+            ExecError::NotExecutable => SystemError::ENOEXEC,
+            ExecError::WrongArchitecture => SystemError::EOPNOTSUPP_OR_ENOTSUP,
+            ExecError::PermissionDenied => SystemError::EACCES,
+            ExecError::NotSupported => SystemError::EOPNOTSUPP_OR_ENOTSUP,
+            ExecError::ParseError => SystemError::ENOEXEC,
+            ExecError::OutOfMemory => SystemError::ENOMEM,
+            ExecError::InvalidParemeter => SystemError::EINVAL,
+            ExecError::BadAddress(_addr) => SystemError::EFAULT,
+            ExecError::Other(_msg) => SystemError::ENOEXEC,
+        }
+    }
+}
+
+bitflags! {
+    pub struct ExecParamFlags: u32 {
+        // 是否以可执行文件的形式加载
+        const EXEC = 1 << 0;
+    }
+}
+
+#[derive(Debug)]
+pub struct ExecParam<'a> {
+    file_path: &'a str,
+    file: Option<File>,
+    vm: Arc<AddressSpace>,
+    /// 一些标志位
+    flags: ExecParamFlags,
+    /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
+    init_info: ProcInitInfo,
+}
+
+#[derive(Debug, Eq, PartialEq)]
+pub enum ExecLoadMode {
+    /// 以可执行文件的形式加载
+    Exec,
+    /// 以动态链接库的形式加载
+    DSO,
+}
+
+#[allow(dead_code)]
+impl<'a> ExecParam<'a> {
+    pub fn new(file_path: &'a str, vm: Arc<AddressSpace>, flags: ExecParamFlags) -> Self {
+        Self {
+            file_path,
+            file: None,
+            vm,
+            flags,
+            init_info: ProcInitInfo::new(),
+        }
+    }
+
+    pub fn file_path(&self) -> &'a str {
+        self.file_path
+    }
+
+    pub fn vm(&self) -> &Arc<AddressSpace> {
+        &self.vm
+    }
+
+    pub fn flags(&self) -> &ExecParamFlags {
+        &self.flags
+    }
+
+    pub fn init_info(&self) -> &ProcInitInfo {
+        &self.init_info
+    }
+
+    pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
+        &mut self.init_info
+    }
+
+    /// 获取加载模式
+    pub fn load_mode(&self) -> ExecLoadMode {
+        if self.flags.contains(ExecParamFlags::EXEC) {
+            ExecLoadMode::Exec
+        } else {
+            ExecLoadMode::DSO
+        }
+    }
+
+    pub fn file_mut(&mut self) -> &mut File {
+        self.file.as_mut().unwrap()
+    }
+}
+
+/// ## 加载二进制文件
+pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
+    let inode = ROOT_INODE().lookup(param.file_path)?;
+
+    // 读取文件头部,用于判断文件类型
+    let file = File::new(inode, FileMode::O_RDONLY)?;
+    param.file = Some(file);
+    let mut head_buf = [0u8; 512];
+    param.file_mut().lseek(SeekFrom::SeekSet(0))?;
+    let _bytes = param.file_mut().read(512, &mut head_buf)?;
+    // kdebug!("load_binary_file: read {} bytes", _bytes);
+
+    let mut loader = None;
+    for bl in BINARY_LOADERS.iter() {
+        let probe_result = bl.probe(param, &head_buf);
+        if probe_result.is_ok() {
+            loader = Some(bl);
+            break;
+        }
+    }
+    // kdebug!("load_binary_file: loader: {:?}", loader);
+    if loader.is_none() {
+        return Err(SystemError::ENOEXEC);
+    }
+
+    let loader: &&dyn BinaryLoader = loader.unwrap();
+    assert!(param.vm().is_current());
+    // kdebug!("load_binary_file: to load with param: {:?}", param);
+
+    let result: BinaryLoaderResult = loader
+        .load(param, &head_buf)
+        .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
+
+    // kdebug!("load_binary_file: load success");
+    return Ok(result);
+}
+
+/// 程序初始化信息,这些信息会被压入用户栈中
+#[derive(Debug)]
+pub struct ProcInitInfo {
+    pub args: Vec<String>,
+    pub envs: Vec<String>,
+    pub auxv: BTreeMap<u8, usize>,
+}
+
+impl ProcInitInfo {
+    pub fn new() -> Self {
+        Self {
+            args: Vec::new(),
+            envs: Vec::new(),
+            auxv: BTreeMap::new(),
+        }
+    }
+
+    /// 把程序初始化信息压入用户栈中
+    /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
+    ///
+    /// ## 返回值
+    ///
+    /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址     
+    pub unsafe fn push_at(
+        &self,
+        ustack: &mut UserStack,
+    ) -> Result<(VirtAddr, VirtAddr), SystemError> {
+        // 先把程序的名称压入栈中
+        self.push_str(ustack, self.args[0].as_str())?;
+
+        // 然后把环境变量压入栈中
+        let envps = self
+            .envs
+            .iter()
+            .map(|s| {
+                self.push_str(ustack, s.as_str()).expect("push_str failed");
+                ustack.sp()
+            })
+            .collect::<Vec<_>>();
+
+        // 然后把参数压入栈中
+        let argps = self
+            .args
+            .iter()
+            .map(|s| {
+                self.push_str(ustack, s.as_str()).expect("push_str failed");
+                ustack.sp()
+            })
+            .collect::<Vec<_>>();
+
+        // 压入auxv
+        self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
+        for (&k, &v) in self.auxv.iter() {
+            self.push_slice(ustack, &[k as usize, v])?;
+        }
+
+        // 把环境变量指针压入栈中
+        self.push_slice(ustack, &[null::<u8>()])?;
+        self.push_slice(ustack, envps.as_slice())?;
+
+        // 把参数指针压入栈中
+        self.push_slice(ustack, &[null::<u8>()])?;
+        self.push_slice(ustack, argps.as_slice())?;
+
+        let argv_ptr = ustack.sp();
+
+        // 把argc压入栈中
+        self.push_slice(ustack, &[self.args.len()])?;
+
+        return Ok((ustack.sp(), argv_ptr));
+    }
+
+    fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
+        let mut sp = ustack.sp();
+        sp -= slice.len() * core::mem::size_of::<T>();
+        sp -= sp.data() % core::mem::align_of::<T>();
+
+        unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
+            .copy_from_slice(slice);
+        unsafe {
+            ustack.set_sp(sp);
+        }
+
+        return Ok(());
+    }
+
+    fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
+        self.push_slice(ustack, &[b'\0'])?;
+        self.push_slice(ustack, s.as_bytes())?;
+        return Ok(());
+    }
+}

+ 5 - 83
kernel/src/process/fork.c

@@ -10,6 +10,7 @@ extern void kernel_thread_func(void);
 extern uint64_t rs_procfs_register_pid(uint64_t);
 extern uint64_t rs_procfs_unregister_pid(uint64_t);
 extern void *rs_dup_fpstate();
+extern uint64_t rs_process_copy_mm(bool clone_vm, struct process_control_block *new_pcb);
 
 extern int process_copy_files(uint64_t clone_flags, struct process_control_block *pcb);
 int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb);
@@ -137,7 +138,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
 
     // 创建对应procfs文件
     rs_procfs_register_pid(tsk->pid);
-
+    // kdebug("Fork ok. pid: %d\n", tsk->pid);
     // 唤醒进程
     process_wakeup(tsk);
 
@@ -185,88 +186,9 @@ int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb)
  */
 int process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb)
 {
-    int retval = 0;
-    // 与父进程共享内存空间
-    if (clone_flags & CLONE_VM)
-    {
-        pcb->mm = current_pcb->mm;
-
-        return retval;
-    }
-
-    // 分配新的内存空间分布结构体
-    struct mm_struct *new_mms = (struct mm_struct *)kmalloc(sizeof(struct mm_struct), 0);
-    memset(new_mms, 0, sizeof(struct mm_struct));
-
-    memcpy(new_mms, current_pcb->mm, sizeof(struct mm_struct));
-    new_mms->vmas = NULL;
-    pcb->mm = new_mms;
-
-    // 分配顶层页表, 并设置顶层页表的物理地址
-    new_mms->pgd = (pml4t_t *)virt_2_phys(kmalloc(PAGE_4K_SIZE, 0));
-    // 由于高2K部分为内核空间,在接下来需要覆盖其数据,因此不用清零
-    memset(phys_2_virt(new_mms->pgd), 0, PAGE_4K_SIZE / 2);
-
-    // 拷贝内核空间的页表指针
-    memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]->mm->pgd) + 256,
-           PAGE_4K_SIZE / 2);
-
-    uint64_t *current_pgd = (uint64_t *)phys_2_virt(current_pcb->mm->pgd);
-
-    uint64_t *new_pml4t = (uint64_t *)phys_2_virt(new_mms->pgd);
-
-    // 拷贝用户空间的vma
-    struct vm_area_struct *vma = current_pcb->mm->vmas;
-    while (vma != NULL)
-    {
-        if (vma->vm_end > USER_MAX_LINEAR_ADDR || vma->vm_flags & VM_DONTCOPY)
-        {
-            vma = vma->vm_next;
-            continue;
-        }
-
-        int64_t vma_size = vma->vm_end - vma->vm_start;
-        // kdebug("vma_size=%ld, vm_start=%#018lx", vma_size, vma->vm_start);
-        if (vma_size > PAGE_2M_SIZE / 2)
-        {
-            int page_to_alloc = (PAGE_2M_ALIGN(vma_size)) >> PAGE_2M_SHIFT;
-            for (int i = 0; i < page_to_alloc; ++i)
-            {
-                uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
-
-                struct vm_area_struct *new_vma = NULL;
-                int ret = mm_create_vma(new_mms, vma->vm_start + i * PAGE_2M_SIZE, PAGE_2M_SIZE, vma->vm_flags,
-                                        vma->vm_ops, &new_vma);
-                // 防止内存泄露
-                if (unlikely(ret == -EEXIST))
-                    free_pages(Phy_to_2M_Page(pa), 1);
-                else
-                    mm_map_vma(new_vma, pa, 0, PAGE_2M_SIZE);
-
-                memcpy((void *)phys_2_virt(pa), (void *)(vma->vm_start + i * PAGE_2M_SIZE),
-                       (vma_size >= PAGE_2M_SIZE) ? PAGE_2M_SIZE : vma_size);
-                vma_size -= PAGE_2M_SIZE;
-            }
-        }
-        else
-        {
-            uint64_t map_size = PAGE_4K_ALIGN(vma_size);
-            uint64_t va = (uint64_t)kmalloc(map_size, 0);
-
-            struct vm_area_struct *new_vma = NULL;
-            int ret = mm_create_vma(new_mms, vma->vm_start, map_size, vma->vm_flags, vma->vm_ops, &new_vma);
-            // 防止内存泄露
-            if (unlikely(ret == -EEXIST))
-                kfree((void *)va);
-            else
-                mm_map_vma(new_vma, virt_2_phys(va), 0, map_size);
-
-            memcpy((void *)va, (void *)vma->vm_start, vma_size);
-        }
-        vma = vma->vm_next;
-    }
-
-    return retval;
+    pcb->address_space = NULL;
+    bool clone_vm = (clone_flags & CLONE_VM);
+    return (int)rs_process_copy_mm(clone_vm, pcb);
 }
 
 /**

+ 38 - 2
kernel/src/process/fork.rs

@@ -44,7 +44,7 @@ pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_contr
     // kdebug!("DEFAULT_SIGACTION.sa_flags={}", DEFAULT_SIGACTION.sa_flags);
 
     // 拷贝sigaction
-    let mut flags: u64 = 0;
+    let mut flags: usize = 0;
 
     spin_lock_irqsave(unsafe { &mut (*current_pcb().sighand).siglock }, &mut flags);
     compiler_fence(core::sync::atomic::Ordering::SeqCst);
@@ -64,7 +64,7 @@ pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_contr
     }
     compiler_fence(core::sync::atomic::Ordering::SeqCst);
 
-    spin_unlock_irqrestore(unsafe { &mut (*current_pcb().sighand).siglock }, &flags);
+    spin_unlock_irqrestore(unsafe { &mut (*current_pcb().sighand).siglock }, flags);
     compiler_fence(core::sync::atomic::Ordering::SeqCst);
 
     // 将信号的处理函数设置为default(除了那些被手动屏蔽的)
@@ -131,3 +131,39 @@ pub extern "C" fn process_exit_sighand(pcb: *mut process_control_block) {
         (*pcb).signal = 0 as *mut crate::include::bindings::bindings::signal_struct;
     }
 }
+
+/// 拷贝进程的地址空间
+///
+/// ## 参数
+///
+/// - `clone_vm`: 是否与父进程共享地址空间。true表示共享
+/// - `new_pcb`: 新进程的pcb
+///
+/// ## 返回值
+///
+/// - 成功:返回Ok(())
+/// - 失败:返回Err(SystemError)
+///
+/// ## Panic
+///
+/// - 如果当前进程没有用户地址空间,则panic
+pub fn copy_mm(clone_vm: bool, new_pcb: &mut process_control_block) -> Result<(), SystemError> {
+    // kdebug!("copy_mm, clone_vm: {}", clone_vm);
+    let old_address_space = current_pcb()
+        .address_space()
+        .expect("copy_mm: Failed to get address space of current process.");
+
+    if clone_vm {
+        unsafe { new_pcb.set_address_space(old_address_space) };
+        return Ok(());
+    }
+
+    let new_address_space = old_address_space.write().try_clone().unwrap_or_else(|e| {
+        panic!(
+            "copy_mm: Failed to clone address space of current process, current pid: [{}], new pid: [{}]. Error: {:?}",
+            current_pcb().pid, new_pcb.pid, e
+        )
+    });
+    unsafe { new_pcb.set_address_space(new_address_space) };
+    return Ok(());
+}

+ 32 - 0
kernel/src/process/mod.rs

@@ -1,6 +1,38 @@
+use core::{
+    ptr::null_mut,
+    sync::atomic::{compiler_fence, Ordering},
+};
+
+use crate::{
+    arch::asm::current::current_pcb,
+    kdebug,
+    mm::{
+        set_INITIAL_PROCESS_ADDRESS_SPACE, ucontext::AddressSpace, INITIAL_PROCESS_ADDRESS_SPACE,
+    },
+};
+
+pub mod abi;
+pub mod c_adapter;
+pub mod exec;
 pub mod fork;
 pub mod initial_proc;
 pub mod pid;
 pub mod preempt;
 pub mod process;
 pub mod syscall;
+
+pub fn process_init() {
+    unsafe {
+        compiler_fence(Ordering::SeqCst);
+        current_pcb().address_space = null_mut();
+        kdebug!("To create address space for INIT process.");
+        // test_buddy();
+        set_INITIAL_PROCESS_ADDRESS_SPACE(
+            AddressSpace::new(true).expect("Failed to create address space for INIT process."),
+        );
+        kdebug!("INIT process address space created.");
+        compiler_fence(Ordering::SeqCst);
+        current_pcb().set_address_space(INITIAL_PROCESS_ADDRESS_SPACE());
+        compiler_fence(Ordering::SeqCst);
+    };
+}

+ 15 - 14
kernel/src/process/proc-types.h

@@ -61,14 +61,14 @@ struct thread_struct
 
 // ========= pcb->flags =========
 // 进程标志位
-#define PF_KTHREAD (1UL << 0)    // 内核线程
-#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
-#define PF_VFORK (1UL << 2)      // 标志进程是否由于vfork而存在资源共享
-#define PF_KFORK (1UL << 3)    // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
-#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
-#define PF_EXITING (1UL << 5)  // 进程正在退出
-#define PF_WAKEKILL (1UL << 6) // 进程由于接收到终止信号唤醒
-#define PF_SIGNALED (1UL << 7) // 进程由于接收到信号而退出
+#define PF_KTHREAD (1UL << 0)      // 内核线程
+#define PF_NEED_SCHED (1UL << 1)   // 进程需要被调度
+#define PF_VFORK (1UL << 2)        // 标志进程是否由于vfork而存在资源共享
+#define PF_KFORK (1UL << 3)        // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
+#define PF_NOFREEZE (1UL << 4)     // 当前进程不能被冻结
+#define PF_EXITING (1UL << 5)      // 进程正在退出
+#define PF_WAKEKILL (1UL << 6)     // 进程由于接收到终止信号唤醒
+#define PF_SIGNALED (1UL << 7)     // 进程由于接收到信号而退出
 #define PF_NEED_MIGRATE (1UL << 8) // 进程需要迁移到其他的核心
 
 /**
@@ -87,9 +87,6 @@ struct process_control_block
     // pcb的名字
     char name[PCB_NAME_LEN];
 
-    // 内存空间分布结构体, 记录内存页表和程序段信息
-    struct mm_struct *mm;
-
     // 进程切换时保存的状态信息
     struct thread_struct *thread;
 
@@ -111,7 +108,7 @@ struct process_control_block
     int64_t rt_time_slice;   // 由实时调度器管理的时间片
 
     // 进程拥有的文件描述符的指针数组(由Rust进行管理)
-    void * fds;
+    void *fds;
 
     // 链表中的下一个pcb
     struct process_control_block *prev_pcb, *next_pcb;
@@ -136,11 +133,15 @@ struct process_control_block
     // 如果当前进程等待被迁移到另一个cpu核心上(也就是flags中的PF_NEED_MIGRATE被置位),
     // 该字段存储要被迁移到的目标处理器核心号
     uint32_t migrate_to;
-    void* fp_state;//Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
+    // Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
+    void *fp_state;
+    // 指向进程的地址空间的arc指针.
+    void *address_space;
 };
 
 // 将进程的pcb和内核栈融合到一起,8字节对齐
-union proc_union {
+union proc_union
+{
     struct process_control_block pcb;
     ul stack[STACK_SIZE / sizeof(ul)];
 } __attribute__((aligned(8)));

+ 38 - 445
kernel/src/process/process.c

@@ -38,7 +38,6 @@ extern void kernel_thread_func(void);
 extern void rs_procfs_unregister_pid(uint64_t);
 
 ul _stack_start; // initial proc的栈基地址(虚拟地址)
-extern struct mm_struct initial_mm;
 extern struct signal_struct INITIAL_SIGNALS;
 extern struct sighand_struct INITIAL_SIGHAND;
 
@@ -46,17 +45,20 @@ extern void process_exit_sighand(struct process_control_block *pcb);
 extern void process_exit_signal(struct process_control_block *pcb);
 extern void initial_proc_init_signal(struct process_control_block *pcb);
 extern void rs_process_exit_fpstate(struct process_control_block *pcb);
+extern void rs_drop_address_space(struct process_control_block *pcb);
 extern int process_init_files();
 extern int rs_init_stdio();
+extern uint64_t rs_do_execve(const char *filename, const char *const argv[], const char *const envp[], struct pt_regs *regs);
+extern uint64_t rs_exec_init_process(struct pt_regs *regs);
 
 // 设置初始进程的PCB
-#define INITIAL_PROC(proc)                                                                                             \
-    {                                                                                                                  \
-        .state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0,              \
-        .mm = &initial_mm, .thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2,       \
-        .virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .prev_pcb = &proc, .parent_pcb = &proc, .exit_code = 0,   \
-        .wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL, .sig_blocked = 0,                   \
-        .signal = &INITIAL_SIGNALS, .sighand = &INITIAL_SIGHAND,                                                       \
+#define INITIAL_PROC(proc)                                                                                           \
+    {                                                                                                                \
+        .state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0,            \
+        .thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2,                        \
+        .virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .prev_pcb = &proc, .parent_pcb = &proc, .exit_code = 0, \
+        .wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL, .sig_blocked = 0,                 \
+        .signal = &INITIAL_SIGNALS, .sighand = &INITIAL_SIGHAND, .address_space = NULL                               \
     }
 
 struct thread_struct initial_thread = {
@@ -113,8 +115,10 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
     //           initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5,
     //           initial_tss[0].ist6, initial_tss[0].ist7);
 
-    __asm__ __volatile__("movq	%%fs,	%0 \n\t" : "=a"(prev->thread->fs));
-    __asm__ __volatile__("movq	%%gs,	%0 \n\t" : "=a"(prev->thread->gs));
+    __asm__ __volatile__("movq	%%fs,	%0 \n\t"
+                         : "=a"(prev->thread->fs));
+    __asm__ __volatile__("movq	%%gs,	%0 \n\t"
+                         : "=a"(prev->thread->gs));
 
     __asm__ __volatile__("movq	%0,	%%fs \n\t" ::"a"(next->thread->fs));
     __asm__ __volatile__("movq	%0,	%%gs \n\t" ::"a"(next->thread->gs));
@@ -145,359 +149,6 @@ int process_open_exec_file(char *path)
     return fd;
 }
 
-/**
- * @brief 加载elf格式的程序文件到内存中,并设置regs
- *
- * @param regs 寄存器
- * @param path 文件路径
- * @return int
- */
-static int process_load_elf_file(struct pt_regs *regs, char *path)
-{
-    int retval = 0;
-    int fd = process_open_exec_file(path);
-
-    if ((long)fd < 0)
-    {
-        kdebug("(long)fd=%ld", (long)fd);
-        return (unsigned long)fd;
-    }
-
-    void *buf = kzalloc(PAGE_4K_SIZE, 0);
-    uint64_t pos = 0;
-
-    retval = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_SET, 0, 0, 0, 0, 0);
-
-    // 读取 Elf64_Ehdr
-    retval = enter_syscall_int(SYS_READ, fd, (uint64_t)buf, sizeof(Elf64_Ehdr), 0, 0, 0, 0, 0);
-
-    pos = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_CUR, 0, 0, 0, 0, 0);
-
-    if (retval != sizeof(Elf64_Ehdr))
-    {
-        kerror("retval=%d, not equal to sizeof(Elf64_Ehdr):%d", retval, sizeof(Elf64_Ehdr));
-    }
-    retval = 0;
-    if (!elf_check(buf))
-    {
-        kerror("Not an ELF file: %s", path);
-        retval = -ENOTSUP;
-        goto load_elf_failed;
-    }
-
-#if ARCH(X86_64)
-    // 暂时只支持64位的文件
-    if (((Elf32_Ehdr *)buf)->e_ident[EI_CLASS] != ELFCLASS64)
-    {
-        kdebug("((Elf32_Ehdr *)buf)->e_ident[EI_CLASS]=%d", ((Elf32_Ehdr *)buf)->e_ident[EI_CLASS]);
-        retval = -EUNSUPPORTED;
-        goto load_elf_failed;
-    }
-    Elf64_Ehdr ehdr = *(Elf64_Ehdr *)buf;
-    // 暂时只支持AMD64架构
-    if (ehdr.e_machine != EM_AMD64)
-    {
-        kerror("e_machine=%d", ehdr.e_machine);
-        retval = -EUNSUPPORTED;
-        goto load_elf_failed;
-    }
-#else
-#error Unsupported architecture!
-#endif
-    if (ehdr.e_type != ET_EXEC)
-    {
-        kerror("Not executable file! filename=%s\tehdr->e_type=%d", path, ehdr.e_type);
-        retval = -EUNSUPPORTED;
-        goto load_elf_failed;
-    }
-    // kdebug("filename=%s:\te_entry=%#018lx", path, ehdr.e_entry);
-    regs->rip = ehdr.e_entry;
-    current_pcb->mm->code_addr_start = ehdr.e_entry;
-
-    // kdebug("ehdr.e_phoff=%#018lx\t ehdr.e_phentsize=%d, ehdr.e_phnum=%d", ehdr.e_phoff, ehdr.e_phentsize,
-    // ehdr.e_phnum); 将指针移动到program header处
-
-    // 读取所有的phdr
-    pos = ehdr.e_phoff;
-
-    pos = enter_syscall_int(SYS_LSEEK, fd, pos, SEEK_SET, 0, 0, 0, 0, 0);
-
-    memset(buf, 0, PAGE_4K_SIZE);
-
-    enter_syscall_int(SYS_READ, fd, (uint64_t)buf, (uint64_t)ehdr.e_phentsize * (uint64_t)ehdr.e_phnum, 0, 0, 0, 0, 0);
-
-    pos = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_CUR, 0, 0, 0, 0, 0);
-
-    if ((long)retval < 0)
-    {
-        kdebug("(unsigned long)filp=%d", (long)retval);
-        retval = -ENOEXEC;
-        goto load_elf_failed;
-    }
-
-    Elf64_Phdr *phdr = buf;
-    // 将程序加载到内存中
-    for (int i = 0; i < ehdr.e_phnum; ++i, ++phdr)
-    {
-        // kdebug("phdr[%d] phdr->p_offset=%#018lx phdr->p_vaddr=%#018lx phdr->p_memsz=%ld phdr->p_filesz=%ld
-        // phdr->p_type=%d", i, phdr->p_offset, phdr->p_vaddr, phdr->p_memsz, phdr->p_filesz, phdr->p_type);
-
-        // 不是可加载的段
-        if (phdr->p_type != PT_LOAD)
-            continue;
-
-        int64_t remain_mem_size = phdr->p_memsz;
-        int64_t remain_file_size = phdr->p_filesz;
-        pos = phdr->p_offset;
-
-        uint64_t virt_base = 0;
-        uint64_t beginning_offset = 0; // 由于页表映射导致的virtbase与实际的p_vaddr之间的偏移量
-
-        if (remain_mem_size >= PAGE_2M_SIZE) // 接下来存在映射2M页的情况,因此将vaddr按2M向下对齐
-            virt_base = phdr->p_vaddr & PAGE_2M_MASK;
-        else // 接下来只有4K页的映射
-            virt_base = phdr->p_vaddr & PAGE_4K_MASK;
-
-        beginning_offset = phdr->p_vaddr - virt_base;
-        remain_mem_size += beginning_offset;
-
-        while (remain_mem_size > 0)
-        {
-            // kdebug("loading...");
-            int64_t map_size = 0;
-            if (remain_mem_size >= PAGE_2M_SIZE)
-            {
-                uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
-                struct vm_area_struct *vma = NULL;
-                int ret =
-                    mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
-
-                // 防止内存泄露
-                if (ret == -EEXIST)
-                    free_pages(Phy_to_2M_Page(pa), 1);
-                else
-                    mm_map(current_pcb->mm, virt_base, PAGE_2M_SIZE, pa);
-                // mm_map_vma(vma, pa, 0, PAGE_2M_SIZE);
-                io_mfence();
-                memset((void *)virt_base, 0, PAGE_2M_SIZE);
-                map_size = PAGE_2M_SIZE;
-            }
-            else
-            {
-                // todo: 使用4K、8K、32K大小内存块混合进行分配,提高空间利用率(减少了bmp的大小)
-                map_size = ALIGN(remain_mem_size, PAGE_4K_SIZE);
-                // 循环分配4K大小内存块
-                for (uint64_t off = 0; off < map_size; off += PAGE_4K_SIZE)
-                {
-                    uint64_t paddr = virt_2_phys((uint64_t)kmalloc(PAGE_4K_SIZE, 0));
-
-                    struct vm_area_struct *vma = NULL;
-                    int val = mm_create_vma(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, VM_USER | VM_ACCESS_FLAGS,
-                                            NULL, &vma);
-                    // kdebug("virt_base=%#018lx", virt_base + off);
-                    if (val == -EEXIST)
-                        kfree(phys_2_virt(paddr));
-                    else
-                        mm_map(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, paddr);
-                    // mm_map_vma(vma, paddr, 0, PAGE_4K_SIZE);
-                    io_mfence();
-                    memset((void *)(virt_base + off), 0, PAGE_4K_SIZE);
-                }
-            }
-
-            pos = enter_syscall_int(SYS_LSEEK, fd, pos, SEEK_SET, 0, 0, 0, 0, 0);
-
-            int64_t val = 0;
-            if (remain_file_size > 0)
-            {
-                int64_t to_trans = (remain_file_size > PAGE_2M_SIZE) ? PAGE_2M_SIZE : remain_file_size;
-
-                void *buf3 = kzalloc(PAGE_4K_SIZE, 0);
-                while (to_trans > 0)
-                {
-                    int64_t x = 0;
-
-                    x = enter_syscall_int(SYS_READ, fd, (uint64_t)buf3, to_trans, 0, 0, 0, 0, 0);
-                    memcpy(virt_base + beginning_offset + val, buf3, x);
-                    val += x;
-                    to_trans -= x;
-
-                    pos = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_CUR, 0, 0, 0, 0, 0);
-                }
-                kfree(buf3);
-
-                // kdebug("virt_base + beginning_offset=%#018lx, val=%d, to_trans=%d", virt_base + beginning_offset,
-                // val,
-                //        to_trans);
-                // kdebug("to_trans=%d", to_trans);
-            }
-
-            if (val < 0)
-                goto load_elf_failed;
-
-            remain_mem_size -= map_size;
-            remain_file_size -= val;
-            virt_base += map_size;
-        }
-    }
-
-    // 分配2MB的栈内存空间
-    regs->rsp = current_pcb->mm->stack_start;
-    regs->rbp = current_pcb->mm->stack_start;
-
-    {
-        struct vm_area_struct *vma = NULL;
-        uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
-        int val = mm_create_vma(current_pcb->mm, current_pcb->mm->stack_start - PAGE_2M_SIZE, PAGE_2M_SIZE,
-                                VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
-        if (val == -EEXIST)
-            free_pages(Phy_to_2M_Page(pa), 1);
-        else
-            mm_map_vma(vma, pa, 0, PAGE_2M_SIZE);
-    }
-
-    // 清空栈空间
-    memset((void *)(current_pcb->mm->stack_start - PAGE_2M_SIZE), 0, PAGE_2M_SIZE);
-
-load_elf_failed:;
-    {
-        enter_syscall_int(SYS_CLOSE, fd, 0, 0, 0, 0, 0, 0, 0);
-    }
-
-    if (buf != NULL)
-        kfree(buf);
-    return retval;
-}
-/**
- * @brief 使当前进程去执行新的代码
- *
- * @param regs 当前进程的寄存器
- * @param path 可执行程序的路径
- * @param argv 参数列表
- * @param envp 环境变量
- * @return ul 错误码
- */
-#pragma GCC push_options
-#pragma GCC optimize("O0")
-ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
-{
-
-    // 当前进程正在与父进程共享地址空间,需要创建
-    // 独立的地址空间才能使新程序正常运行
-    if (current_pcb->flags & PF_VFORK)
-    {
-        // kdebug("proc:%d  creating new mem space", current_pcb->pid);
-        // 分配新的内存空间分布结构体
-        struct mm_struct *new_mms = (struct mm_struct *)kmalloc(sizeof(struct mm_struct), 0);
-        memset(new_mms, 0, sizeof(struct mm_struct));
-        current_pcb->mm = new_mms;
-
-        // 分配顶层页表, 并设置顶层页表的物理地址
-        new_mms->pgd = (pml4t_t *)virt_2_phys(kmalloc(PAGE_4K_SIZE, 0));
-
-        // 由于高2K部分为内核空间,在接下来需要覆盖其数据,因此不用清零
-        memset(phys_2_virt(new_mms->pgd), 0, PAGE_4K_SIZE / 2);
-
-        // 拷贝内核空间的页表指针
-        memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]) + 256, PAGE_4K_SIZE / 2);
-    }
-
-    // 设置用户栈和用户堆的基地址
-    unsigned long stack_start_addr = 0x6ffff0a00000UL;
-    const uint64_t brk_start_addr = 0x700000000000UL;
-
-    process_switch_mm(current_pcb);
-
-    // 为用户态程序设置地址边界
-    if (!(current_pcb->flags & PF_KTHREAD))
-        current_pcb->addr_limit = USER_MAX_LINEAR_ADDR;
-
-    current_pcb->mm->code_addr_end = 0;
-    current_pcb->mm->data_addr_start = 0;
-    current_pcb->mm->data_addr_end = 0;
-    current_pcb->mm->rodata_addr_start = 0;
-    current_pcb->mm->rodata_addr_end = 0;
-    current_pcb->mm->bss_start = 0;
-    current_pcb->mm->bss_end = 0;
-    current_pcb->mm->brk_start = brk_start_addr;
-    current_pcb->mm->brk_end = brk_start_addr;
-    current_pcb->mm->stack_start = stack_start_addr;
-
-    // 清除进程的vfork标志位
-    current_pcb->flags &= ~PF_VFORK;
-
-    // 加载elf格式的可执行文件
-    int tmp = process_load_elf_file(regs, path);
-
-    if (tmp < 0)
-        goto exec_failed;
-
-    int argc = 0;
-    char **dst_argv = NULL;
-    // kdebug("stack_start_addr=%#018lx", stack_start_addr);
-    // 拷贝参数列表
-    if (argv != NULL)
-    {
-
-        // 目标程序的argv基地址指针,最大8个参数
-        dst_argv = (char **)(stack_start_addr - (sizeof(char **) << 3));
-        uint64_t str_addr = (uint64_t)dst_argv;
-
-        for (argc = 0; argc < 8 && argv[argc] != NULL; ++argc)
-        {
-
-            if (*argv[argc] == NULL)
-                break;
-
-            // 测量参数的长度(最大1023)
-            int argv_len = strnlen_user(argv[argc], 1023) + 1;
-            strncpy((char *)(str_addr - argv_len), argv[argc], argv_len - 1);
-            str_addr -= argv_len;
-            dst_argv[argc] = (char *)str_addr;
-            // 字符串加上结尾字符
-            ((char *)str_addr)[argv_len] = '\0';
-        }
-
-        // 重新设定栈基址,并预留空间防止越界
-
-        stack_start_addr = str_addr - 8;
-    }
-
-    // kdebug("stack_start_addr=%#018lx", stack_start_addr);
-    // ==== 生成relibc所需的Stack结构体
-    {
-        uint64_t *ptr_stack = (uint64_t *)(stack_start_addr - 8);
-        if (argc == 0)
-            *ptr_stack = 0;
-        else
-            *ptr_stack = (uint64_t)dst_argv;
-        ptr_stack--;
-        *ptr_stack = argc;
-        stack_start_addr -= 16;
-    }
-
-    // 传递参数(旧版libc)
-    regs->rdi = argc;
-    regs->rsi = (uint64_t)dst_argv;
-    // 设置用户栈基地址
-    current_pcb->mm->stack_start = stack_start_addr;
-    regs->rsp = regs->rbp = stack_start_addr;
-    // kdebug("execve ok");
-    // 设置进程的段选择子为用户态可访问
-    regs->cs = USER_CS | 3;
-    regs->ds = USER_DS | 3;
-    regs->ss = USER_DS | 0x3;
-    regs->rflags = 0x200246;
-    regs->rax = 1;
-    regs->es = 0;
-
-    return 0;
-
-exec_failed:;
-    process_do_exit(tmp);
-}
-#pragma GCC pop_options
-
 /**
  * @brief 初始化实时进程rt_pcb
  *
@@ -527,43 +178,24 @@ ul initial_kernel_thread(ul arg)
     kinfo("initial proc running...\targ:%#018lx, vruntime=%d", arg, current_pcb->virtual_runtime);
     int val = 0;
     val = scm_enable_double_buffer();
-
+    io_mfence();
     rs_init_stdio();
+    io_mfence();
     // block_io_scheduler_init();
     ahci_init();
     mount_root_fs();
+    io_mfence();
     rs_virtio_probe();
+    io_mfence();
+
     // 使用单独的内核线程来初始化usb驱动程序
     // 注释:由于目前usb驱动程序不完善,因此先将其注释掉
     // int usb_pid = kernel_thread(usb_init, 0, 0);
 
     kinfo("LZ4 lib Version=%s", LZ4_versionString());
+    io_mfence();
     __rust_demo_func();
-    // while (1)
-    // {
-    //     /* code */
-    // }
-
-    // 对completion完成量进行测试
-    // __test_completion();
-
-    // // 对一些组件进行单元测试
-    uint64_t tpid[] = {
-        // ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_mutex, 0),
-        // ktest_start(ktest_test_idr, 0),
-        // usb_pid,
-    };
-
-    // kinfo("Waiting test thread exit...");
-    // // 等待测试进程退出
-    // for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i)
-    //     waitpid(tpid[i], NULL, NULL);
-    // kinfo("All test done.");
-
-    // 测试实时进程
-
-    // struct process_control_block *test_rt1 = kthread_run_rt(&test, NULL, "test rt");
-    // kdebug("process:rt test kthread is created!!!!");
+    io_mfence();
 
     // 准备切换到用户态
     struct pt_regs *regs;
@@ -588,8 +220,8 @@ ul initial_kernel_thread(ul arg)
     // 这里的设计思路和switch_to类似 加载用户态程序:shell.elf
     __asm__ __volatile__("movq %1, %%rsp   \n\t"
                          "pushq %2    \n\t"
-                         "jmp do_execve  \n\t" ::"D"(current_pcb->thread->rsp),
-                         "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "S"("/bin/shell.elf"), "c"(NULL),
+                         "jmp rs_exec_init_process  \n\t" ::"D"(current_pcb->thread->rsp),
+                         "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "c"(NULL),
                          "d"(NULL)
                          : "memory");
 
@@ -678,9 +310,15 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
  * @brief 初始化进程模块
  * ☆前置条件:已完成系统调用模块的初始化
  */
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 void process_init()
 {
     kinfo("Initializing process...");
+    // rs_test_buddy();
+    io_mfence();
+    rs_process_init();
+    io_mfence();
 
     initial_tss[proc_current_cpu_id].rsp0 = initial_thread.rbp;
 
@@ -692,18 +330,23 @@ void process_init()
     list_init(&initial_proc_union.pcb.list);
     wait_queue_init(&initial_proc_union.pcb.wait_child_proc_exit, NULL);
 
+    io_mfence();
     // 初始化init进程的signal相关的信息
     initial_proc_init_signal(current_pcb);
     kdebug("Initial process to init files");
+    io_mfence();
     process_init_files();
     kdebug("Initial process init files ok");
+    io_mfence();
 
     // 临时设置IDLE进程的的虚拟运行时间为0,防止下面的这些内核线程的虚拟运行时间出错
     current_pcb->virtual_runtime = 0;
+
     barrier();
     kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核线程
     barrier();
     kthread_mechanism_init(); // 初始化kthread机制
+    barrier();
 
     initial_proc_union.pcb.state = PROC_RUNNING;
     initial_proc_union.pcb.preempt_count = 0;
@@ -712,6 +355,7 @@ void process_init()
     // 将IDLE进程的虚拟运行时间设置为一个很大的数值
     current_pcb->virtual_runtime = (1UL << 60);
 }
+#pragma GCC pop_options
 
 /**
  * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL
@@ -786,57 +430,7 @@ int process_wakeup_immediately(struct process_control_block *pcb)
  */
 uint64_t process_exit_mm(struct process_control_block *pcb)
 {
-    if (pcb->flags & CLONE_VM)
-        return 0;
-    if (pcb->mm == NULL)
-    {
-        kdebug("pcb->mm==NULL");
-        return 0;
-    }
-    if (pcb->mm->pgd == NULL)
-    {
-        kdebug("pcb->mm->pgd==NULL");
-        return 0;
-    }
-
-    // // 获取顶层页表
-    pml4t_t *current_pgd = (pml4t_t *)phys_2_virt(pcb->mm->pgd);
-
-    // 循环释放VMA中的内存
-    struct vm_area_struct *vma = pcb->mm->vmas;
-    while (vma != NULL)
-    {
-
-        struct vm_area_struct *cur_vma = vma;
-        vma = cur_vma->vm_next;
-
-        uint64_t pa;
-        mm_unmap_vma(pcb->mm, cur_vma, &pa);
-
-        uint64_t size = (cur_vma->vm_end - cur_vma->vm_start);
-
-        // 释放内存
-        switch (size)
-        {
-        case PAGE_4K_SIZE:
-            kfree(phys_2_virt(pa));
-            break;
-        default:
-            break;
-        }
-        vm_area_del(cur_vma);
-        vm_area_free(cur_vma);
-    }
-
-    // 释放顶层页表
-    kfree(current_pgd);
-    if (unlikely(pcb->mm->vmas != NULL))
-    {
-        kwarn("pcb.mm.vmas!=NULL");
-    }
-    // 释放内存空间分布结构体
-    kfree(pcb->mm);
-
+    rs_drop_address_space(pcb);
     return 0;
 }
 
@@ -857,9 +451,6 @@ void process_exit_thread(struct process_control_block *pcb)
  */
 int process_release_pcb(struct process_control_block *pcb)
 {
-    // 释放子进程的页表
-    // BUG 暂时注释process_exit_mm
-    // process_exit_mm(pcb);
     if ((pcb->flags & PF_KTHREAD)) // 释放内核线程的worker private结构体
         free_kthread_struct(pcb);
 
@@ -871,6 +462,8 @@ int process_release_pcb(struct process_control_block *pcb)
     process_exit_signal(pcb);
     rs_process_exit_fpstate(pcb);
     rs_procfs_unregister_pid(pcb->pid);
+    // 释放进程的地址空间
+    process_exit_mm(pcb);
     // 释放当前pcb
     kfree(pcb);
     return 0;

+ 32 - 42
kernel/src/process/process.h

@@ -31,18 +31,18 @@ extern int process_exit_files(struct process_control_block *pcb);
  */
 
 // 设置初始进程的tss
-#define INITIAL_TSS                                                                                                    \
-    {                                                                                                                  \
-        .reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                              \
-        .rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                                              \
-        .rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00,  \
-        .ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00,                            \
-        .ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0,            \
-        .reserved3 = 0, .io_map_base_addr = 0                                                                          \
+#define INITIAL_TSS                                                                                                   \
+    {                                                                                                                 \
+        .reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                             \
+        .rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                                             \
+        .rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \
+        .ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00,                           \
+        .ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0,           \
+        .reserved3 = 0, .io_map_base_addr = 0                                                                         \
     }
 
-#define GET_CURRENT_PCB                                                                                                \
-    "movq %rsp, %rbx \n\t"                                                                                             \
+#define GET_CURRENT_PCB    \
+    "movq %rsp, %rbx \n\t" \
     "andq $-32768, %rbx\n\t"
 
 /**
@@ -51,23 +51,23 @@ extern int process_exit_files(struct process_control_block *pcb);
  * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
  */
 
-#define switch_to(prev, next)                                                                                          \
-    do                                                                                                                 \
-    {                                                                                                                  \
-        __asm__ __volatile__("pushq	%%rbp	\n\t"                                                                        \
-                             "pushq	%%rax	\n\t"                                                                        \
-                             "movq	%%rsp,	%0	\n\t"                                                                     \
-                             "movq	%2,	%%rsp	\n\t"                                                                     \
-                             "leaq	2f(%%rip),	%%rax	\n\t"                                                              \
-                             "movq	%%rax,	%1	\n\t"                                                                     \
-                             "pushq	%3		\n\t"                                                                          \
-                             "jmp	__switch_to	\n\t"                                                                    \
-                             "2:	\n\t"                                                                                 \
-                             "popq	%%rax	\n\t"                                                                         \
-                             "popq	%%rbp	\n\t"                                                                         \
-                             : "=m"(prev->thread->rsp), "=m"(prev->thread->rip)                                        \
-                             : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next)                    \
-                             : "memory", "rax");                                                                       \
+#define switch_to(prev, next)                                                                       \
+    do                                                                                              \
+    {                                                                                               \
+        __asm__ __volatile__("pushq	%%rbp	\n\t"                                                     \
+                             "pushq	%%rax	\n\t"                                                     \
+                             "movq	%%rsp,	%0	\n\t"                                                  \
+                             "movq	%2,	%%rsp	\n\t"                                                  \
+                             "leaq	2f(%%rip),	%%rax	\n\t"                                           \
+                             "movq	%%rax,	%1	\n\t"                                                  \
+                             "pushq	%3		\n\t"                                                       \
+                             "jmp	__switch_to	\n\t"                                                 \
+                             "2:	\n\t"                                                              \
+                             "popq	%%rax	\n\t"                                                      \
+                             "popq	%%rbp	\n\t"                                                      \
+                             : "=m"(prev->thread->rsp), "=m"(prev->thread->rip)                     \
+                             : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
+                             : "memory", "rax");                                                    \
     } while (0)
 
 /**
@@ -112,17 +112,6 @@ int process_wakeup(struct process_control_block *pcb);
  */
 int process_wakeup_immediately(struct process_control_block *pcb);
 
-/**
- * @brief 使当前进程去执行新的代码
- *
- * @param regs 当前进程的寄存器
- * @param path 可执行程序的路径
- * @param argv 参数列表
- * @param envp 环境变量
- * @return ul 错误码
- */
-ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]);
-
 /**
  * @brief 释放进程的页表
  *
@@ -166,10 +155,11 @@ int process_release_pcb(struct process_control_block *pcb);
  * @param next 下一个进程的pcb
  *
  */
-#define process_switch_mm(next_pcb)                                                                                    \
-    do                                                                                                                 \
-    {                                                                                                                  \
-        asm volatile("movq %0, %%cr3	\n\t" ::"r"(next_pcb->mm->pgd) : "memory");                                    \
+#define process_switch_mm(next_pcb)                                    \
+    do                                                                 \
+    {                                                                  \
+        asm volatile("movq %0, %%cr3	\n\t" ::"r"(next_pcb->mm->pgd) \
+                     : "memory");                                      \
     } while (0)
 // flush_tlb();
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels