瀏覽代碼

Revert "新的内存管理模块 (#301)" (#302)

This reverts commit d8ad0a5e7724469abd5cc3cf271993538878033e.
LoGin 1 年之前
父節點
當前提交
bb5f098a86
共有 100 個文件被更改,包括 4857 次插入7905 次删除
  1. 1 2
      .vscode/settings.json
  2. 1 11
      Makefile
  3. 5 10
      README.md
  4. 4 4
      README_EN.md
  5. 二進制
      docs/Multiboot2 Specification version 2.0.pdf
  6. 1 39
      docs/community/contact/index.rst
  7. 1 4
      docs/introduction/build_system.md
  8. 6 18
      docs/introduction/features.md
  9. 1 3
      docs/introduction/index.rst
  10. 15 0
      docs/kernel/core_api/allocate-memory.md
  11. 13 0
      docs/kernel/core_api/index.rst
  12. 267 0
      docs/kernel/core_api/mm-api.md
  13. 0 29
      docs/kernel/memory_management/allocate-memory.md
  14. 4 4
      docs/kernel/memory_management/index.rst
  15. 0 20
      docs/kernel/memory_management/intro.md
  16. 1 2
      docs/kernel/process_management/index.rst
  17. 0 15
      docs/kernel/process_management/load_binary.md
  18. 0 7
      kernel/Cargo.toml
  19. 2 3
      kernel/src/Makefile
  20. 2 2
      kernel/src/arch/mod.rs
  21. 2 3
      kernel/src/arch/x86_64/asm/irqflags.rs
  22. 0 8
      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. 0 1
      kernel/src/arch/x86_64/libs/mod.rs
  26. 19 618
      kernel/src/arch/x86_64/mm/mod.rs
  27. 0 6
      kernel/src/arch/x86_64/mod.rs
  28. 1 1
      kernel/src/arch/x86_64/msi.rs
  29. 22 176
      kernel/src/arch/x86_64/syscall.rs
  30. 0 8
      kernel/src/common/atomic.h
  31. 14 20
      kernel/src/driver/acpi/acpi.c
  32. 5 5
      kernel/src/driver/base/char/mod.rs
  33. 1 2
      kernel/src/driver/base/device/mod.rs
  34. 1 1
      kernel/src/driver/disk/ahci/ahci.c
  35. 4 6
      kernel/src/driver/interrupt/apic/apic.c
  36. 1 1
      kernel/src/driver/pci/msi.c
  37. 20 44
      kernel/src/driver/pci/pci.rs
  38. 6 4
      kernel/src/driver/pci/pci_irq.rs
  39. 1 1
      kernel/src/driver/uart/uart.rs
  40. 11 6
      kernel/src/driver/video/video.c
  41. 27 69
      kernel/src/driver/virtio/virtio_impl.rs
  42. 3 3
      kernel/src/exception/mod.rs
  43. 0 1
      kernel/src/exception/softirq.rs
  44. 6 9
      kernel/src/filesystem/procfs/mod.rs
  45. 29 15
      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. 64 53
      kernel/src/head.S
  49. 1 2
      kernel/src/include/bindings/wrapper.h
  50. 4 4
      kernel/src/ipc/signal.rs
  51. 5 10
      kernel/src/lib.rs
  52. 1 27
      kernel/src/libs/align.rs
  53. 0 785
      kernel/src/libs/elf.rs
  54. 5 33
      kernel/src/libs/libUI/screen_manager.c
  55. 1 3
      kernel/src/libs/libUI/screen_manager.h
  56. 1 25
      kernel/src/libs/libUI/textui.c
  57. 1 5
      kernel/src/libs/libUI/textui.h
  58. 0 1
      kernel/src/libs/mod.rs
  59. 0 4
      kernel/src/libs/printk.c
  60. 10 92
      kernel/src/libs/printk.rs
  61. 5 43
      kernel/src/libs/rwlock.rs
  62. 16 16
      kernel/src/libs/spinlock.rs
  63. 22 28
      kernel/src/main.c
  64. 27 0
      kernel/src/mm/Makefile
  65. 55 0
      kernel/src/mm/allocator.rs
  66. 0 667
      kernel/src/mm/allocator/buddy.rs
  67. 0 112
      kernel/src/mm/allocator/bump.rs
  68. 0 101
      kernel/src/mm/allocator/kernel_allocator.rs
  69. 0 5
      kernel/src/mm/allocator/mod.rs
  70. 0 338
      kernel/src/mm/allocator/page_frame.rs
  71. 0 123
      kernel/src/mm/allocator/slab.rs
  72. 0 135
      kernel/src/mm/c_adapter.rs
  73. 79 0
      kernel/src/mm/internal.h
  74. 0 145
      kernel/src/mm/kernel_mapper.rs
  75. 196 0
      kernel/src/mm/mm-stat.c
  76. 175 0
      kernel/src/mm/mm-types.h
  77. 686 0
      kernel/src/mm/mm.c
  78. 365 14
      kernel/src/mm/mm.h
  79. 582 0
      kernel/src/mm/mmap.c
  80. 9 0
      kernel/src/mm/mmio.c
  81. 3 1
      kernel/src/mm/mmio.h
  82. 219 160
      kernel/src/mm/mmio_buddy.rs
  83. 4 609
      kernel/src/mm/mod.rs
  84. 0 79
      kernel/src/mm/no_init.rs
  85. 0 924
      kernel/src/mm/page.rs
  86. 713 0
      kernel/src/mm/slab.c
  87. 109 4
      kernel/src/mm/slab.h
  88. 26 202
      kernel/src/mm/syscall.rs
  89. 0 1319
      kernel/src/mm/ucontext.rs
  90. 109 0
      kernel/src/mm/utils.c
  91. 275 0
      kernel/src/mm/vma.c
  92. 0 86
      kernel/src/process/abi.rs
  93. 0 115
      kernel/src/process/c_adapter.rs
  94. 0 288
      kernel/src/process/exec.rs
  95. 83 5
      kernel/src/process/fork.c
  96. 2 38
      kernel/src/process/fork.rs
  97. 0 32
      kernel/src/process/mod.rs
  98. 14 15
      kernel/src/process/proc-types.h
  99. 445 38
      kernel/src/process/process.c
  100. 42 32
      kernel/src/process/process.h

+ 1 - 2
.vscode/settings.json

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

+ 1 - 11
Makefile

@@ -61,24 +61,14 @@ 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:
-	rust-gdb -n -x tools/.gdbinit
+	gdb -n -x tools/.gdbinit
 
 # 写入磁盘镜像
 write_diskimage:

+ 5 - 10
README.md

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

+ 4 - 4
README_EN.md

@@ -12,7 +12,6 @@
 
 - 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**
@@ -32,7 +31,7 @@
 
 ## How to join DragonOS ?
 
-  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)
+  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.
 
   Or, you can also bring your ideas, discuss with community members, and create some new functions for DragonOS.
 
@@ -42,8 +41,9 @@
 
   Or join our development exchange QQ group: **115763565**
 
-  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.
+  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.
 
+  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
 
-  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!
+  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?
 

二進制
docs/Multiboot2 Specification version 2.0.pdf


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

@@ -3,50 +3,12 @@
 与社区建立联系
 ====================================
 
-联系方式
--------------------------
-
 社区公共邮箱:[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
-
-

+ 1 - 4
docs/introduction/build_system.md

@@ -233,10 +233,7 @@ 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`
-:::
+:::

+ 6 - 18
docs/introduction/features.md

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

+ 1 - 3
docs/introduction/index.rst

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

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

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

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

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

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

@@ -0,0 +1,267 @@
+(_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缓冲区) |

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

@@ -1,29 +0,0 @@
-# 内存分配指南
-
-&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

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

@@ -1,20 +0,0 @@
-# 内存管理模块简介
-
-## 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代码能够正常运行。
-

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

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

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

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

+ 0 - 7
kernel/Cargo.toml

@@ -22,9 +22,6 @@ 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]
@@ -37,8 +34,4 @@ version = "1.4.0"
 features = ["spin_no_std"]
 
 
-# The release profile, used for `cargo build --release`
-[profile.release]
-debug = false
-
 

+ 2 - 3
kernel/src/Makefile

@@ -17,7 +17,7 @@ export ASFLAGS := --64
 LD_LIST := head.o
 
 
-kernel_subdirs := common driver process debug arch exception smp sched syscall ktest libs ipc io time
+kernel_subdirs := common driver process debug arch exception mm smp sched syscall ktest libs ipc io time
 	
 
 
@@ -58,8 +58,7 @@ 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  kernel ../../bin/kernel/kernel.elf
-# $(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 -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端口实现

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

@@ -3,9 +3,8 @@ 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(nomem, preserves_flags));
+        asm!("pushfq ; pop {} ; cli", out(reg) x, options(nostack));
     }
     x
 }
@@ -14,6 +13,6 @@ pub fn local_irq_save() -> usize {
 // 恢复先前保存的rflags的值x
 pub fn local_irq_restore(x: usize) {
     unsafe {
-        asm!("push {}; popfq", in(reg) x, options(nomem, preserves_flags));
+        asm!("push {} ; popfq", in(reg) x, options(nostack));
     }
 }

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

@@ -16,15 +16,7 @@ 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: usize = local_irq_save();
+    let rflags = 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, options(nomem, preserves_flags));
+            asm!("pushfq; pop {}", out(reg) rflags);
         }
         return rflags & (1 << 9) != 0;
     }
 
     unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
         compiler_fence(Ordering::SeqCst);
-        let rflags = local_irq_save();
+        let rflags = local_irq_save() as u64;
         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());
+        local_irq_restore(flags.flags() as usize);
         compiler_fence(Ordering::SeqCst);
     }
 }

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

@@ -1 +0,0 @@
-

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

@@ -1,627 +1,28 @@
 pub mod barrier;
-
-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 crate::include::bindings::bindings::process_control_block;
 
 use core::arch::asm;
-use core::ffi::c_void;
-use core::fmt::{Debug, Write};
-use core::mem::{self};
-
-use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
-
-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);
+use core::ptr::read_volatile;
 
-    /// @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);
-    }
-}
+use self::barrier::mfence;
 
-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 {
-        video_reinitialize(false);
-    }
-
-    // 打开显示输出
-    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);
-}
-
-/// 低地址重映射的管理器
+/// @brief 切换进程的页表
 ///
-/// 低地址重映射的管理器,在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();
-        }
-    }
+/// @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 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();
-            }
-        }
+    unsafe {
+        asm!("mov cr3, {}", in(reg) pml4t);
     }
-}
-#[no_mangle]
-pub extern "C" fn rs_mm_init() {
-    mm_init();
+    mfence();
+    return next_pcb;
 }

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

@@ -4,7 +4,6 @@ pub mod context;
 pub mod cpu;
 pub mod fpu;
 pub mod interrupt;
-pub mod libs;
 pub mod mm;
 pub mod msi;
 pub mod pci;
@@ -12,9 +11,4 @@ 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 {

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

@@ -1,27 +1,24 @@
-use core::{ffi::c_void, panic};
-
-use alloc::{string::String, vec::Vec};
+use core::ffi::c_void;
 
 use crate::{
-    arch::{asm::current::current_pcb, CurrentIrqArch},
-    exception::InterruptArch,
-    filesystem::vfs::MAX_PATHLEN,
     include::bindings::bindings::{
-        pt_regs, set_system_trap_gate, CLONE_FS, CLONE_SIGNAL, CLONE_VM, USER_CS, USER_DS,
+        pt_regs, set_system_trap_gate, verify_area, CLONE_FS, CLONE_SIGNAL, CLONE_VM, PAGE_4K_SIZE,
     },
     ipc::signal::sys_rt_sigreturn,
-    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,
-    },
+    kinfo,
+    syscall::{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();
 }
@@ -74,34 +71,23 @@ pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () {
 
             // 权限校验
             if from_user
-                && (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())
+                && (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) }
             {
                 syscall_return!(SystemError::EFAULT.to_posix_errno() as u64, regs);
             } else {
-                unsafe {
-                    // kdebug!("syscall: execve\n");
-                    syscall_return!(
-                        rs_do_execve(
+                syscall_return!(
+                    unsafe {
+                        c_sys_execve(
                             path_ptr as *const u8,
                             argv_ptr as *const *const u8,
                             env_ptr as *const *const u8,
-                            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
-                    // )
-                }
+                            regs,
+                        )
+                    },
+                    regs
+                );
             }
         }
 
@@ -118,147 +104,7 @@ 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(());
-}

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

@@ -9,7 +9,6 @@
  *
  */
 #pragma once
-#include <arch/x86_64/include/asm/cmpxchg.h>
 
 #define atomic_read(atomic)	((atomic)->value)   // 读取原子变量
 #define atomic_set(atomic,val)	(((atomic)->value) = (val)) // 设置原子变量的初始值
@@ -98,10 +97,3 @@ 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;
-}

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

@@ -44,8 +44,7 @@ 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);
-            rs_map_phys(acpi_description_header_base + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
+            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);
             sdt_header = (struct acpi_system_description_table_header_t *)((ul)(acpi_description_header_base + PAGE_2M_SIZE * i));
 
             if (_fun(sdt_header, _data) == true)
@@ -174,14 +173,13 @@ 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);
-        rs_map_phys(acpi_rsdt_virt_addr_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
+        mm_map(&initial_mm, acpi_rsdt_virt_addr_base, PAGE_2M_SIZE, paddr);
 
         // rsdt表虚拟地址
         rsdt = (struct acpi_RSDT_Structure_t *)(acpi_rsdt_virt_addr_base + acpi_RSDT_offset);
@@ -194,7 +192,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的物理地址
@@ -203,27 +201,23 @@ 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);
-        rs_map_phys(acpi_description_header_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
+        mm_map(&initial_mm, acpi_description_header_base, PAGE_2M_SIZE, paddr);
     }
     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);
-        rs_map_phys(acpi_rsdt_virt_addr_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
+        mm_map(&initial_mm, acpi_rsdt_virt_addr_base, PAGE_2M_SIZE, paddr);
         // rsdt表虚拟地址
         rsdt = (struct acpi_RSDT_Structure_t *)(acpi_rsdt_virt_addr_base + acpi_RSDT_offset);
         kdebug("RSDT mapped!");
@@ -237,7 +231,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的物理地址
@@ -246,9 +240,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);
-        rs_map_phys(acpi_description_header_base, paddr, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
-        kinfo("entry mapped!");
+        mm_map(&initial_mm, acpi_description_header_base, PAGE_2M_SIZE, paddr);
+        // 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,

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

@@ -1,5 +1,3 @@
-use alloc::{collections::BTreeMap, string::String, sync::Arc};
-
 use crate::{
     filesystem::{
         sysfs::{
@@ -11,6 +9,7 @@ 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;
-    rs_map_phys(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
+    mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
 
     kinfo("ABAR mapped!");
 }

+ 4 - 6
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);
     // 填写页表,完成地址映射
-    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);
+    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);
 
     // 设置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 寄存器地址
-    // todo: 
-    rs_map_phys(APIC_LOCAL_APIC_VIRT_BASE_ADDR, (ia32_apic_base & 0x1FFFFFFFFFF000), PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
+    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);
     uint a, b, c, d;
 
     cpu_cpuid(1, 0, &a, &b, &c, &d);
@@ -357,7 +357,6 @@ 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]);
@@ -397,7 +396,6 @@ 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映射到页表
-    rs_map_phys(pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_mmio_size, PAGE_KERNEL_PAGE);
+    mm_map(&initial_mm, pci_dev->msix_mmio_vaddr, pci_dev->msix_mmio_size, bar);
     return 0;
 }
 

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

@@ -3,17 +3,15 @@
 
 use super::pci_irq::{IrqType, PciIrqError};
 use crate::arch::{PciArch, TraitPciArch};
-use crate::include::bindings::bindings::{PAGE_2M_SIZE, VM_DONTCOPY, VM_IO};
+use crate::include::bindings::bindings::{
+    initial_mm, mm_map, mm_struct, PAGE_2M_SIZE, VM_DONTCOPY, VM_IO,
+};
 use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
-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::mm::mmio_buddy::MMIO_POOL;
 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},
@@ -634,27 +632,20 @@ impl PciRoot {
         let virtsize_ptr = &mut virtsize as *mut u64;
         let size = bus_number_double * PAGE_2M_SIZE;
         unsafe {
-            if let Err(_) = mmio_pool().create_mmio(
-                size as usize,
-                (VM_IO | VM_DONTCOPY) as u64,
-                vaddr_ptr,
-                virtsize_ptr,
-            ) {
+            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)
+            {
                 kerror!("Create mmio failed when initing ecam");
                 return Err(PciError::CreateMmioError);
             };
-
             //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
-            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);
+            mm_map(
+                initial_mm_ptr,
+                virtaddress,
+                size as u64,
+                self.physical_address_base,
+            );
         }
         self.mmio_base = Some(virtaddress as *mut u32);
         Ok(0)
@@ -1311,9 +1302,8 @@ impl Display for BarInfo {
         }
     }
 }
-// todo 增加对桥的bar的支持
+//todo 增加对桥的bar的支持
 pub trait PciDeviceBar {}
-
 ///一个普通PCI设备(非桥)有6个BAR寄存器,PciStandardDeviceBar存储其全部信息
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct PciStandardDeviceBar {
@@ -1419,11 +1409,10 @@ 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 size_want = size as usize;
-
-                if let Err(_) = mmio_pool().create_mmio(
-                    size_want,
+                let initial_mm_ptr = &mut initial_mm as *mut mm_struct;
+                //kdebug!("size want={:#x}", size);
+                if let Err(_) = MMIO_POOL.create_mmio(
+                    size,
                     (VM_IO | VM_DONTCOPY) as u64,
                     vaddr_ptr,
                     virtsize_ptr,
@@ -1432,20 +1421,7 @@ pub fn pci_bar_init(
                     return Err(PciError::CreateMmioError);
                 };
                 //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
-                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);
+                mm_map(initial_mm_ptr, virtaddress, size as u64, address);
             }
             bar_info = BarInfo::Memory {
                 address_type,

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

@@ -6,14 +6,16 @@ use core::ptr::NonNull;
 use alloc::ffi::CString;
 use alloc::vec::Vec;
 
-use super::pci::{PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
+use super::pci::{HeaderType, 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, Volatile, VolatileReadable, VolatileWritable};
-
+use crate::libs::volatile::{
+    volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
+};
+use crate::{kdebug, kerror, kinfo, kwarn};
 /// MSIX表的一项
 #[repr(C)]
 struct MsixEntry {
@@ -266,7 +268,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,
         },

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

@@ -34,10 +34,16 @@ void init_frame_buffer()
 {
     kinfo("Re-mapping VBE frame buffer...");
 
-    video_frame_buffer_info.vaddr = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + FRAME_BUFFER_MAPPING_OFFSET;
+    uint64_t global_CR3 = (uint64_t)get_CR3();
 
-    rs_map_phys(video_frame_buffer_info.vaddr, __fb_info.framebuffer_addr, video_frame_buffer_info.size, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
+    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();
     kinfo("VBE frame buffer successfully Re-mapped!");
 }
 
@@ -113,6 +119,7 @@ int video_reinitialize(bool level) // 这个函数会在main.c调用, 保证 vid
         // 启用屏幕刷新软中断
         rs_register_softirq_video();
         rs_raise_softirq(VIDEO_REFRESH_SIRQ);
+
     }
     return 0;
 }
@@ -182,10 +189,8 @@ 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;
-    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);
+    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);
 
     io_mfence();
     char init_text2[] = "Video driver initialized.\n";

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

@@ -1,101 +1,59 @@
-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,
+/// 为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::mm::virt_2_phys;
+use core::mem::size_of;
 use core::ptr::NonNull;
-use virtio_drivers::{BufferDirection, Hal, PAGE_SIZE};
-
+use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE};
 pub struct HalImpl;
 unsafe impl Hal for HalImpl {
     /// @brief 申请用于DMA的内存页
     /// @param pages 页数(4k一页)
     /// @return PhysAddr 获得的内存页的初始物理地址
-    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(),
-        );
+    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;
         unsafe {
-            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(),
-            );
+            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(),
+            )
         }
     }
     /// @brief 释放用于DMA的内存页
     /// @param paddr 起始物理地址 pages 页数(4k一页)
     /// @return i32 0表示成功
-    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 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 {
-            deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
+            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);
         }
         return 0;
     }
     /// @brief mmio物理地址转换为虚拟地址,不需要使用
     /// @param paddr 起始物理地址
     /// @return NonNull<u8> 虚拟地址的指针
-    unsafe fn mmio_phys_to_virt(_paddr: virtio_drivers::PhysAddr, _size: usize) -> NonNull<u8> {
+    unsafe fn mmio_phys_to_virt(_paddr: 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,
-    ) -> virtio_drivers::PhysAddr {
-        let vaddr = VirtAddr::new(buffer.as_ptr() as *mut u8 as usize);
+    unsafe fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
+        let vaddr = buffer.as_ptr() as *mut u8 as usize;
         //kdebug!("virt:{:x}", vaddr);
         // Nothing to do, as the host already has access to all memory.
-        return MMArch::virt_2_phys(vaddr).unwrap().data();
+        virt_2_phys(vaddr)
     }
     /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做)
-    unsafe fn unshare(
-        _paddr: virtio_drivers::PhysAddr,
-        _buffer: NonNull<[u8]>,
-        _direction: BufferDirection,
-    ) {
+    unsafe fn unshare(_paddr: 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: usize,
+    flags: u64,
 }
 
 impl IrqFlags {
-    pub fn new(flags: usize) -> Self {
+    pub fn new(flags: u64) -> Self {
         IrqFlags { flags }
     }
 
-    pub fn flags(&self) -> usize {
+    pub fn flags(&self) -> u64 {
         self.flags
     }
 }

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

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

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

@@ -10,7 +10,6 @@ use alloc::{
 };
 
 use crate::{
-    arch::asm::current::current_pcb,
     filesystem::vfs::{
         core::{generate_inode_id, ROOT_INODE},
         FileType,
@@ -169,15 +168,13 @@ impl ProcFSInode {
                 .to_owned(),
         );
 
-        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 hiwater_vm: u64 =
+            unsafe { *(*pcb.mm).vmas }.vm_end - unsafe { *(*pcb.mm).vmas }.vm_start;
         // 进程数据段的大小
-        let data = (address_space_guard.end_data - address_space_guard.start_data) / 1024;
-        drop(address_space_guard);
+        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;
 
         pdata.append(
             &mut format!("\nVmPeak:\t{} kB", hiwater_vm)

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

@@ -1,5 +1,9 @@
 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下生成文件夹
@@ -54,15 +58,20 @@ 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),
@@ -73,15 +82,20 @@ pub fn bus_driver_register(bus_name: &str, name: &str) -> Result<Arc<dyn IndexNo
 /// @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 4096
+#define VFS_MAX_PATHLEN 1024
 
 /**
  * @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()?.file_type;
+        let file_type = self.inode.metadata().unwrap().file_type;
         match file_type {
             FileType::Pipe | FileType::CharDevice => {
                 return Err(SystemError::ESPIPE);

+ 64 - 53
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_apu_cr3
+	jnc	load_cr3
 
     // 2. 设置临时页表
     // 最高级
@@ -263,11 +263,7 @@ ENTRY(_start64)
     mov $__PDPTE, %ebx
     or $0x3, %ebx
     mov %ebx, 0(%eax)
-
-    mov $__PML4E, %eax
-    // 加256个表项, 映射高地址
-    add $2048, %eax
-    mov %ebx, 0(%eax)
+    mov %ebx, 256(%eax)
 
     // 次级
     mov $__PDPTE, %eax
@@ -275,28 +271,6 @@ 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寄存器
 
@@ -305,20 +279,7 @@ 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!
@@ -520,23 +481,73 @@ ENTRY(head_stack_start)
 
 // 初始化页表
 .align 0x1000 //设置为4k对齐
+//.org 0x1000 //设置页表位置为内核执行头程序的0x1000处
+
 __PML4E:
-    .skip 0x1000
+    .quad 0x103007 // 用户访问,可读写,已存在, 地址在31~12位
+    .fill	255,8,0
+	.quad 0x103003
+	.fill	255,8,0
+
+.org	0x2000
+
 __PDPTE:
-	.skip 0x1000
 
-// 三级页表
-__PDE:
-    .skip 0x1000
+	.quad	0x104003 // 用户访问,可读写,已存在
+	.fill	511,8,0
+
+.org	0x3000
 
-// 预留50个四级页表,总共表示100M的内存空间。这50个页表占用200KB的空间
-__PT_S:
-    .skip 0x32000
+__PDE:
 
+	.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表
 

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

@@ -32,7 +32,6 @@
 #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>
@@ -50,4 +49,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: usize = 0;
+    let mut flags: u64 = 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 usize,
+    flags: &mut u64,
 ) -> 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: usize) {
+fn unlock_process_sighand(pcb: &mut process_control_block, flags: u64) {
     let lock = unsafe { &mut (*pcb.sighand).siglock };
 
-    spin_unlock_irqrestore(lock, flags);
+    spin_unlock_irqrestore(lock, &flags);
 }
 
 /// @brief 判断是否需要强制发送信号,然后发送信号

+ 5 - 10
kernel/src/lib.rs

@@ -1,18 +1,13 @@
 #![no_std] // <1>
 #![no_main] // <1>
 #![feature(alloc_error_handler)]
-#![feature(allocator_api)]
-#![feature(arbitrary_self_types)]
 #![feature(const_mut_refs)]
-#![feature(core_intrinsics)]
+#![feature(core_intrinsics)] // <2>
 #![feature(c_void_variant)]
-#![feature(drain_filter)]
+#![feature(drain_filter)] // 允许Vec的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)]
@@ -42,7 +37,6 @@ mod time;
 extern crate alloc;
 #[macro_use]
 extern crate bitflags;
-extern crate elf;
 #[macro_use]
 extern crate lazy_static;
 extern crate num;
@@ -50,10 +44,11 @@ extern crate num;
 extern crate num_derive;
 extern crate smoltcp;
 extern crate thingbuf;
+
 #[cfg(target_arch = "x86_64")]
 extern crate x86;
 
-use crate::mm::allocator::kernel_allocator::KernelAllocator;
+use mm::allocator::KernelAllocator;
 
 // <3>
 use crate::{
@@ -64,7 +59,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]

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

@@ -3,7 +3,7 @@
 
 use core::{alloc::GlobalAlloc, fmt::Debug, ptr::Unique};
 
-use crate::{arch::MMArch, mm::MemoryManagementArch, syscall::SystemError, KERNEL_ALLOCATOR};
+use crate::{syscall::SystemError, KERNEL_ALLOCATOR};
 
 /// # AlignedBox
 ///
@@ -112,29 +112,3 @@ 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;
-}

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

@@ -1,785 +0,0 @@
-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)))
-    }
-}

+ 5 - 33
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;
 
-    void* buf_vaddr = kzalloc(video_frame_buffer_info.size, 0);
-    if (buf_vaddr == NULL)
+    struct Page *p = alloc_pages(ZONE_NORMAL, PAGE_2M_ALIGN(video_frame_buffer_info.size) / PAGE_2M_SIZE, 0);
+    if (p == NULL)
         goto failed;
-    buf->vaddr = buf_vaddr;
+    buf->vaddr = (uint64_t)phys_2_virt(p->addr_phys);
     return buf;
 failed:;
     kfree(buf);
@@ -74,7 +74,7 @@ static int __destroy_buffer(struct scm_buffer_info_t *buf)
         return -EINVAL;
 
     // 释放内存页
-    kfree((void*)buf->vaddr);
+    free_pages(Phy_to_2M_Page(virt_2_phys(buf->vaddr)), PAGE_2M_ALIGN(video_frame_buffer_info.size) / PAGE_2M_SIZE);
     return 0;
 }
 
@@ -295,35 +295,7 @@ 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;
 }
@@ -335,7 +307,7 @@ int scm_framework_disable(struct scm_ui_framework_t *ui)
 void scm_reinit()
 {
     scm_enable_alloc();
-    // video_reinitialize(false);
+    video_reinitialize(false);
 
     // 遍历当前所有使用帧缓冲区的框架,更新地址
     // 逐个检查已经注册了的ui框架,将其缓冲区更改为双缓冲

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

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

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

@@ -21,9 +21,6 @@ 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对象
  *
@@ -72,7 +69,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\n");
+    c_uart_send_str(COM1, "textui_install_handler");
     return 0;
 }
 
@@ -84,14 +81,11 @@ 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;
 }
 
@@ -221,13 +215,6 @@ 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
@@ -359,14 +346,3 @@ 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);
-}

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

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

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

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

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

@@ -594,9 +594,7 @@ 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()的缓冲区
@@ -612,9 +610,7 @@ 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;
 }
 

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

@@ -1,15 +1,8 @@
 #![allow(unused)]
-use crate::{
-    driver::uart::uart::c_uart_send_str,
-    include::bindings::bindings::{printk_color, BLACK, WHITE},
-};
+use crate::include::bindings::bindings::{printk_color, BLACK, WHITE};
 use ::core::ffi::c_char;
 use alloc::vec::Vec;
-use core::{
-    fmt::{self, Write},
-    intrinsics::{likely, unlikely},
-    sync::atomic::{AtomicBool, Ordering},
-};
+use core::fmt;
 
 // ====== 定义颜色 ======
 /// 白色
@@ -59,15 +52,15 @@ macro_rules! printk_color {
 #[macro_export]
 macro_rules! kdebug {
     ($($arg:tt)*) => {
-        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)))
-
+        $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())
     }
 }
 
 #[macro_export]
 macro_rules! kinfo {
     ($($arg:tt)*) => {
-        $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)))
+        $crate::libs::printk::PrintkWriter.__write_string((alloc::string::String::from("[ INFO ] ")+ alloc::fmt::format(format_args!($($arg)*)).as_str() + "\n").as_str())
     }
 }
 
@@ -75,7 +68,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_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
+        $crate::libs::printk::PrintkWriter.__write_string((alloc::fmt::format(format_args!($($arg)*)) + "\n").as_str())
     }
 }
 
@@ -83,7 +76,8 @@ 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_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
+        $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())
     }
 }
 
@@ -91,29 +85,17 @@ 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_fmt(format_args!("({}:{})\t{}\n", file!(), line!(),format_args!($($arg)*)));
+        $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())
     }
 }
 
 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);
@@ -121,36 +103,12 @@ 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字符串
@@ -167,46 +125,6 @@ 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自带的格式化组件,格式化字符并输出

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

@@ -7,10 +7,7 @@ use core::{
     sync::atomic::{AtomicU32, Ordering},
 };
 
-use crate::{
-    process::preempt::{preempt_disable, preempt_enable},
-    syscall::SystemError,
-};
+use crate::syscall::SystemError;
 
 ///RwLock读写锁
 
@@ -113,15 +110,6 @@ 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;
@@ -177,18 +165,6 @@ 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)
@@ -202,7 +178,7 @@ impl<T> RwLock<T> {
         } else {
             return None;
         }
-    }
+    } //当架构为arm时,有些代码需要作出调整compare_exchange=>compare_exchange_weak
 
     #[allow(dead_code)]
     #[inline]
@@ -220,18 +196,8 @@ impl<T> RwLock<T> {
     #[inline]
     /// @brief 尝试获得UPGRADER守卫
     pub fn try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<T>> {
-        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的原子操作
+        //获得UPGRADER守卫不需要查看读者位
+        //如果获得读者锁失败,不需要撤回fetch_or的原子操作
         if self.lock.fetch_or(UPGRADED, Ordering::Acquire) & (WRITER | UPGRADED) == 0 {
             return Some(RwLockUpgradableGuard {
                 inner: self,
@@ -352,7 +318,7 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
 
         let inner: &RwLock<T> = self.inner;
 
-        // 自动移去UPGRADED比特位
+        //自动移去UPGRADED比特位
         mem::drop(self);
 
         RwLockReadGuard {
@@ -456,7 +422,6 @@ 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();
     }
 }
 
@@ -467,7 +432,6 @@ impl<'rwlock, T> Drop for RwLockUpgradableGuard<'rwlock, T> {
             UPGRADED
         );
         self.inner.lock.fetch_sub(UPGRADED, Ordering::AcqRel);
-        preempt_enable();
         //这里为啥要AcqRel? Release应该就行了?
     }
 }
@@ -478,7 +442,5 @@ 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 usize) {
-    *flags = local_irq_save();
+pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
+    *flags = local_irq_save() as u64;
     unsafe {
         spin_lock(lock);
     }
@@ -22,11 +22,12 @@ pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut usize) {
 
 /// @brief 恢复rflags以及中断状态并解锁自旋锁
 #[inline]
-pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: usize) {
+pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
     unsafe {
         spin_unlock(lock);
     }
-    local_irq_restore(flags);
+    // kdebug!("123");
+    local_irq_restore(*flags as usize);
 }
 
 /// 判断一个自旋锁是否已经被加锁
@@ -128,27 +129,27 @@ impl RawSpinlock {
     }
 
     /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
-    pub fn lock_irqsave(&self, flags: &mut usize) {
-        *flags = local_irq_save();
+    pub fn lock_irqsave(&self, flags: &mut u64) {
+        *flags = local_irq_save() as u64;
         self.lock();
     }
 
     /// @brief 恢复rflags以及中断状态并解锁自旋锁
-    pub fn unlock_irqrestore(&self, flags: usize) {
+    pub fn unlock_irqrestore(&self, flags: &u64) {
         self.unlock();
-        local_irq_restore(flags);
+        local_irq_restore(*flags as usize);
     }
 
     /// @brief 尝试保存中断状态到flags中,关闭中断,并对自旋锁加锁
     /// @return 加锁成功->true
     ///         加锁失败->false
     #[inline(always)]
-    pub fn try_lock_irqsave(&self, flags: &mut usize) -> bool {
-        *flags = local_irq_save();
+    pub fn try_lock_irqsave(&self, flags: &mut u64) -> bool {
+        *flags = local_irq_save() as u64;
         if self.try_lock() {
             return true;
         }
-        local_irq_restore(*flags);
+        local_irq_restore(*flags as usize);
         return false;
     }
 }
@@ -167,7 +168,7 @@ pub struct SpinLock<T> {
 #[derive(Debug)]
 pub struct SpinLockGuard<'a, T: 'a> {
     lock: &'a SpinLock<T>,
-    flag: usize,
+    flag: u64,
 }
 
 /// 向编译器保证,SpinLock在线程之间是安全的.
@@ -193,8 +194,7 @@ impl<T> SpinLock<T> {
     }
 
     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
-        let mut flags: usize = 0;
-
+        let mut flags: u64 = 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: usize = 0;
+        let mut flags: u64 = 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();
         }

+ 22 - 28
kernel/src/main.c

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

+ 27 - 0
kernel/src/mm/Makefile

@@ -0,0 +1,27 @@
+
+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
+

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

@@ -0,0 +1,55 @@
+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);
+}

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

@@ -1,667 +0,0 @@
-/// @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;
-}

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

@@ -1,112 +0,0 @@
-/// @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;
-    }
-}

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

@@ -1,101 +0,0 @@
-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);
-}

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

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

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

@@ -1,338 +0,0 @@
-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);
-    }
-}

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

@@ -1,123 +0,0 @@
-//! 当前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;
-    }
-}

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

@@ -1,135 +0,0 @@
-//! 这是暴露给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;
-}

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

@@ -0,0 +1,79 @@
+#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))

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

@@ -1,145 +0,0 @@
-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();
-    }
-}

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

@@ -0,0 +1,196 @@
+/**
+ * @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;
+}

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

@@ -4,4 +4,179 @@
 #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;
+};

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

@@ -0,0 +1,686 @@
+#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;
+}

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

@@ -6,9 +6,9 @@
 #include <mm/mm-types.h>
 #include <process/process.h>
 
-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();
+// 每个页表的项数
+// 64位下,每个页表4k,每条页表项8B,故一个页表有512条
+#define PTRS_PER_PGT 512
 
 // 内核层的起始地址
 #define PAGE_OFFSET 0xffff800000000000UL
@@ -39,6 +39,9 @@ extern uint64_t rs_unmap_at_low_addr();
 // 虚拟地址与物理地址转换
 #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
@@ -46,6 +49,7 @@ extern uint64_t rs_unmap_at_low_addr();
 #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区域
@@ -134,21 +138,59 @@ extern uint64_t rs_unmap_at_low_addr();
 
 #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;
@@ -161,6 +203,26 @@ 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寄存器的值(存储了页目录的基地址)
  *
@@ -169,11 +231,70 @@ extern char _end;
 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
@@ -191,3 +312,233 @@ unsigned long *get_CR3()
 
 /* 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);

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

@@ -0,0 +1,582 @@
+#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;
+}

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

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

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

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

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

@@ -1,19 +1,16 @@
 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::{vm_flags_t, PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
-    kdebug,
-    mm::{MMArch, MemoryManagementArch},
+    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,
 };
-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;
+use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
+use core::{mem, ptr::null_mut};
 
 // 最大的伙伴块的幂
 const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT;
@@ -22,15 +19,8 @@ const MMIO_BUDDY_MIN_EXP: u32 = PAGE_4K_SHIFT;
 // 内存池数组的范围
 const MMIO_BUDDY_REGION_COUNT: u32 = MMIO_BUDDY_MAX_EXP - MMIO_BUDDY_MIN_EXP + 1;
 
-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() }
+lazy_static! {
+    pub static ref MMIO_POOL: MmioBuddyMemPool = MmioBuddyMemPool::new();
 }
 
 pub enum MmioResult {
@@ -42,49 +32,25 @@ pub enum MmioResult {
 }
 
 /// @brief buddy内存池
-#[derive(Debug)]
 pub struct MmioBuddyMemPool {
-    pool_start_addr: VirtAddr,
-    pool_size: usize,
+    pool_start_addr: u64,
+    pool_size: u64,
     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 {
-        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,
+        return MmioBuddyMemPool {
+            ..Default::default()
         };
-        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 创建新的地址区域结构体
@@ -92,12 +58,9 @@ impl MmioBuddyMemPool {
     /// @param vaddr 虚拟地址
     ///
     /// @return 创建好的地址区域结构体
-    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!!!");
+    fn create_region(&self, vaddr: u64) -> Box<MmioBuddyAddrRegion> {
+        let mut region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion::new());
+        region.vaddr = vaddr;
         return region;
     }
 
@@ -112,16 +75,16 @@ impl MmioBuddyMemPool {
     /// @return Ok(i32) 返回0
     ///
     /// @return Err(SystemError) 返回错误码
-    fn give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError> {
+    fn give_back_block(&self, vaddr: u64, exp: u32) -> Result<i32, SystemError> {
         // 确保内存对齐,低位都要为0
-        if (vaddr.data() & ((1 << exp) - 1)) != 0 {
+        if (vaddr & ((1 << exp) - 1)) != 0 {
             return Err(SystemError::EINVAL);
         }
-        let region: MmioBuddyAddrRegion = self.create_region(vaddr);
+        let region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
         // 加入buddy
-        let mut list_guard = self.free_regions[exp2index(exp)].lock();
-
-        self.push_block(region, &mut list_guard);
+        let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
+            &mut self.free_regions[exp2index(exp)].lock();
+        self.push_block(region, list_guard);
         return Ok(0);
     }
 
@@ -134,12 +97,12 @@ impl MmioBuddyMemPool {
     /// @param list_guard 【exp-1】对应的链表
     fn split_block(
         &self,
-        region: MmioBuddyAddrRegion,
+        region: Box<MmioBuddyAddrRegion>,
         exp: u32,
         low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
     ) {
-        let vaddr = self.calculate_block_vaddr(region.vaddr, exp - 1);
-        let new_region: MmioBuddyAddrRegion = self.create_region(vaddr);
+        let vaddr: u64 = self.calculate_block_vaddr(region.vaddr, exp - 1);
+        let new_region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
         self.push_block(region, low_list_guard);
         self.push_block(new_region, low_list_guard);
     }
@@ -150,7 +113,7 @@ impl MmioBuddyMemPool {
     ///
     /// @param list_guard exp对应的链表
     ///
-    /// @return Ok(MmioBuddyAddrRegion) 符合要求的内存区域。
+    /// @return Ok(Box<MmioBuddyAddrRegion>) 符合要求的内存区域。
     ///
     /// @return Err(MmioResult)
     /// - 没有满足要求的内存块时,返回ENOFOUND
@@ -160,7 +123,7 @@ impl MmioBuddyMemPool {
         &self,
         exp: u32,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
-    ) -> Result<MmioBuddyAddrRegion, MmioResult> {
+    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
         // 申请范围错误
         if exp < MMIO_BUDDY_MIN_EXP || exp > MMIO_BUDDY_MAX_EXP {
             kdebug!("query_addr_region: exp wrong");
@@ -293,9 +256,12 @@ impl MmioBuddyMemPool {
     ///
     /// @param exp 内存区域的大小(2^exp)
     ///
-    /// @return Ok(MmioBuddyAddrRegion)符合要求的内存块信息结构体。
+    /// @return Ok(Box<MmioBuddyAddrRegion>)符合要求的内存块信息结构体。
     /// @return Err(MmioResult) 没有满足要求的内存块时,返回__query_addr_region的错误码。
-    fn mmio_buddy_query_addr_region(&self, exp: u32) -> Result<MmioBuddyAddrRegion, MmioResult> {
+    fn mmio_buddy_query_addr_region(
+        &self,
+        exp: u32,
+    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
         let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
             &mut self.free_regions[exp2index(exp)].lock();
         match self.query_addr_region(exp, list_guard) {
@@ -313,7 +279,7 @@ impl MmioBuddyMemPool {
     /// @param list_guard 目标链表
     fn push_block(
         &self,
-        region: MmioBuddyAddrRegion,
+        region: Box<MmioBuddyAddrRegion>,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
     ) {
         list_guard.list.push_back(region);
@@ -322,8 +288,8 @@ impl MmioBuddyMemPool {
 
     /// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
     #[inline(always)]
-    fn calculate_block_vaddr(&self, vaddr: VirtAddr, exp: u32) -> VirtAddr {
-        return VirtAddr::new(vaddr.data() ^ (1 << exp as usize));
+    fn calculate_block_vaddr(&self, vaddr: u64, exp: u32) -> u64 {
+        return vaddr ^ (1 << exp);
     }
 
     /// @brief 寻找并弹出指定内存块的伙伴块
@@ -340,10 +306,10 @@ impl MmioBuddyMemPool {
     /// - 没有找到伙伴块,返回ENOFOUND
     fn pop_buddy_block(
         &self,
-        vaddr: VirtAddr,
+        vaddr: u64,
         exp: u32,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
-    ) -> Result<MmioBuddyAddrRegion, MmioResult> {
+    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
         if list_guard.list.len() == 0 {
             return Err(MmioResult::ISEMPTY);
         } else {
@@ -351,7 +317,7 @@ impl MmioBuddyMemPool {
             let buddy_vaddr = self.calculate_block_vaddr(vaddr, exp);
 
             // element 只会有一个元素
-            let mut element: Vec<MmioBuddyAddrRegion> = list_guard
+            let mut element: Vec<Box<MmioBuddyAddrRegion>> = list_guard
                 .list
                 .drain_filter(|x| x.vaddr == buddy_vaddr)
                 .collect();
@@ -369,13 +335,13 @@ impl MmioBuddyMemPool {
     ///
     /// @param list_guard 【exp】对应的链表
     ///
-    /// @return Ok(MmioBuddyAddrRegion) 内存块信息结构体的引用。
+    /// @return Ok(Box<MmioBuddyAddrRegion>) 内存块信息结构体的引用。
     ///
     /// @return Err(MmioResult) 当链表为空,无法删除时,返回ISEMPTY
     fn pop_block(
         &self,
         list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
-    ) -> Result<MmioBuddyAddrRegion, MmioResult> {
+    ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
         if !list_guard.list.is_empty() {
             list_guard.num_free -= 1;
             return Ok(list_guard.list.pop_back().unwrap());
@@ -411,15 +377,17 @@ impl MmioBuddyMemPool {
                 break;
             }
             // 获取内存块
-            let vaddr: VirtAddr = list_guard.list.back().unwrap().vaddr;
+            let vaddr: u64 = 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: MmioBuddyAddrRegion = list_guard.list.pop_back().unwrap();
-                    let copy_region = region.clone();
+                    let region: Box<MmioBuddyAddrRegion> = list_guard.list.pop_back().unwrap();
+                    let copy_region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion {
+                        vaddr: region.vaddr,
+                    });
                     // 在两块内存都被取出之后才进行合并
                     match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
                         Err(err) => {
@@ -447,8 +415,8 @@ impl MmioBuddyMemPool {
     /// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL
     fn merge_blocks(
         &self,
-        region_1: MmioBuddyAddrRegion,
-        region_2: MmioBuddyAddrRegion,
+        region_1: Box<MmioBuddyAddrRegion>,
+        region_2: Box<MmioBuddyAddrRegion>,
         exp: u32,
         high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
     ) -> Result<MmioResult, MmioResult> {
@@ -476,43 +444,102 @@ impl MmioBuddyMemPool {
     /// @return Err(SystemError) 失败返回错误码
     pub fn create_mmio(
         &self,
-        size: usize,
-        _vm_flags: vm_flags_t,
+        size: u32,
+        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 retval: i32 = 0;
+        let mut retval: i32 = 0;
         // 计算前导0
-        #[cfg(target_arch = "x86_64")]
-        let mut size_exp: u32 = 63 - size.leading_zeros();
+        let mut size_exp: u32 = 31 - size.leading_zeros();
         // 记录最终申请的空间大小
-        let mut new_size = size;
+        let mut new_size: u32 = size;
         // 对齐要申请的空间大小
         // 如果要申请的空间大小小于4k,则分配4k
         if size_exp < PAGE_4K_SHIFT {
-            new_size = PAGE_4K_SIZE as usize;
+            new_size = PAGE_4K_SIZE;
             size_exp = PAGE_4K_SHIFT;
         } else if (new_size & (!(1 << size_exp))) != 0 {
             // 向左对齐空间大小
             size_exp += 1;
             new_size = 1 << size_exp;
         }
-        match self.mmio_buddy_query_addr_region(size_exp) {
+        match MMIO_POOL.mmio_buddy_query_addr_region(size_exp) {
             Ok(region) => {
-                // 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 };
+                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;
+                }
             }
             Err(_) => {
-                kerror!("failed to create mmio. pid = {:?}", current_pcb().pid);
+                kdebug!("failed to create mmio vma.pid = {:?}", current_pcb().pid);
                 return Err(SystemError::ENOMEM);
             }
         }
@@ -528,62 +555,83 @@ impl MmioBuddyMemPool {
     /// @return Ok(i32) 成功返回0
     ///
     /// @return Err(SystemError) 失败返回错误码
-    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);
-        }
-        // 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);
+    pub fn release_mmio(&self, vaddr: u64, length: u64) -> Result<i32, SystemError> {
+        //先将要释放的空间取消映射
+        unsafe {
+            mm_unmap(&mut initial_mm, vaddr, length, false);
         }
-
-        for i in 0..page_count {
-            unsafe {
-                kernel_mapper
-                    .as_mut()
-                    .unwrap()
-                    .unmap(vaddr + i * MMArch::PAGE_SIZE, true)
-            };
+        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: 归还到buddy
-
         return Ok(0);
     }
 }
 
 /// @brief mmio伙伴系统内部的地址区域结构体
-#[derive(Debug, Clone)]
-struct MmioBuddyAddrRegion {
-    vaddr: VirtAddr,
+pub struct MmioBuddyAddrRegion {
+    vaddr: u64,
 }
 impl MmioBuddyAddrRegion {
-    pub fn new(vaddr: VirtAddr) -> Self {
-        return MmioBuddyAddrRegion { vaddr };
+    pub fn new() -> Self {
+        return MmioBuddyAddrRegion {
+            ..Default::default()
+        };
     }
-
-    #[allow(dead_code)]
-    pub fn vaddr(&self) -> VirtAddr {
-        return self.vaddr;
+}
+impl Default for MmioBuddyAddrRegion {
+    fn default() -> Self {
+        MmioBuddyAddrRegion {
+            vaddr: Default::default(),
+        }
     }
 }
 
 /// @brief 空闲页数组结构体
-#[derive(Debug)]
 pub struct MmioFreeRegionList {
     /// 存储mmio_buddy的地址链表
-    list: LinkedList<MmioBuddyAddrRegion>,
+    list: LinkedList<Box<MmioBuddyAddrRegion>>,
     /// 空闲块的数量
     num_free: i64,
 }
@@ -604,6 +652,25 @@ 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内存大小
@@ -614,15 +681,6 @@ 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区域的大小(字节)
@@ -641,8 +699,7 @@ pub extern "C" fn mmio_create(
     res_vaddr: *mut u64,
     res_length: *mut u64,
 ) -> i32 {
-    // kdebug!("mmio_create");
-    if let Err(err) = mmio_pool().create_mmio(size as usize, vm_flags, res_vaddr, res_length) {
+    if let Err(err) = MMIO_POOL.create_mmio(size, vm_flags, res_vaddr, res_length) {
         return err.to_posix_errno();
     } else {
         return 0;
@@ -660,7 +717,9 @@ pub extern "C" fn mmio_create(
 /// @return Err(i32) 失败返回错误码
 #[no_mangle]
 pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
-    return mmio_pool()
-        .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
-        .unwrap_or_else(|err| err.to_posix_errno());
+    if let Err(err) = MMIO_POOL.release_mmio(vaddr, length) {
+        return err.to_posix_errno();
+    } else {
+        return 0;
+    }
 }

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

@@ -1,63 +1,9 @@
-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},
-};
+use crate::include::bindings::bindings::{mm_struct, process_control_block, PAGE_OFFSET};
 
 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)]
@@ -71,561 +17,10 @@ pub fn phys_2_virt(addr: usize) -> usize {
     addr + PAGE_OFFSET as usize
 }
 
-#[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 ======
+// ====== 重构内存管理后,请删除18-24行 ======
 //BUG pcb问题
 unsafe impl Send for process_control_block {}
 unsafe impl Sync for process_control_block {}
 
-// ====== 重构内存管理后,请删除这几行 END =======
+unsafe impl Send for mm_struct {}
+unsafe impl Sync for mm_struct {}

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

@@ -1,79 +0,0 @@
-//! 该文件用于系统启动早期,内存管理器初始化之前,提供一些简单的内存映射功能
-//!
-//! 这里假设在内核引导文件中,已经填写了前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();
-}

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

@@ -1,924 +0,0 @@
-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)
-}

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

@@ -0,0 +1,713 @@
+#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;
+}

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

@@ -1,6 +1,54 @@
 #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 通用内存分配函数
@@ -9,16 +57,19 @@
  * @param gfp 内存的flag
  * @return void* 分配得到的内存的指针
  */
-extern void *kmalloc(unsigned long size, gfp_t gfp);
+void *kmalloc(unsigned long size, gfp_t gfp);
 
 /**
  * @brief 从kmalloc申请一块内存,并将这块内存清空
- *
+ * 
  * @param size 要分配的内存大小
  * @param gfp 内存的flag
  * @return void* 分配得到的内存的指针
  */
-extern void *kzalloc(size_t size, gfp_t gfp);
+static __always_inline void *kzalloc(size_t size, gfp_t gfp)
+{
+    return kmalloc(size, gfp | __GFP_ZERO);
+}
 
 /**
  * @brief 通用内存释放函数
@@ -26,4 +77,58 @@ extern void *kzalloc(size_t size, gfp_t gfp);
  * @param address 要释放的内存地址
  * @return unsigned long
  */
-extern unsigned long kfree(void *address);
+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();

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

@@ -1,219 +1,43 @@
-use core::intrinsics::unlikely;
-
-use alloc::sync::Arc;
-
 use crate::{
-    arch::MMArch,
-    kerror,
-    libs::align::{check_aligned, page_align_up},
-    mm::MemoryManagementArch,
+    include::bindings::bindings::mm_stat_t,
     syscall::{Syscall, SystemError},
 };
 
-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;
-
-    }
+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;
 }
-
 impl Syscall {
-    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());
-        }
-    }
-
-    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
+    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")
             );
-            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);
         }
-        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());
+        return Ok(ret);
     }
 
-    /// ## munmap系统调用
-    ///
-    /// ## 参数
-    ///
-    /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
-    /// - `len`:取消映射的字节数(已经对齐到页)
-    ///
-    /// ## 返回值
-    ///
-    /// 成功时返回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);
+    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")
+            );
         }
-
-        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);
+        return Ok(ret);
     }
 
-    /// ## 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);
+    /// 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"));
         }
-
-        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);
+        return Ok(ret);
     }
 }

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

@@ -1,1319 +0,0 @@
-// 进程的用户空间内存管理
-
-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;
-    }
-}

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

@@ -0,0 +1,109 @@
+#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;
+}

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

@@ -0,0 +1,275 @@
+#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);
+}

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

@@ -1,86 +0,0 @@
-/// 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"),
-        }
-    }
-}

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

@@ -1,115 +0,0 @@
-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();
-    }
-}

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

@@ -1,288 +0,0 @@
-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(());
-    }
-}

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

@@ -10,7 +10,6 @@ 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);
@@ -138,7 +137,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);
 
@@ -186,9 +185,88 @@ 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)
 {
-    pcb->address_space = NULL;
-    bool clone_vm = (clone_flags & CLONE_VM);
-    return (int)rs_process_copy_mm(clone_vm, 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;
 }
 
 /**

+ 2 - 38
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: usize = 0;
+    let mut flags: u64 = 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,39 +131,3 @@ 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(());
-}

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

@@ -1,38 +1,6 @@
-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);
-    };
-}

+ 14 - 15
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,6 +87,9 @@ struct process_control_block
     // pcb的名字
     char name[PCB_NAME_LEN];
 
+    // 内存空间分布结构体, 记录内存页表和程序段信息
+    struct mm_struct *mm;
+
     // 进程切换时保存的状态信息
     struct thread_struct *thread;
 
@@ -108,7 +111,7 @@ struct process_control_block
     int64_t rt_time_slice;   // 由实时调度器管理的时间片
 
     // 进程拥有的文件描述符的指针数组(由Rust进行管理)
-    void *fds;
+    void * fds;
 
     // 链表中的下一个pcb
     struct process_control_block *prev_pcb, *next_pcb;
@@ -133,15 +136,11 @@ struct process_control_block
     // 如果当前进程等待被迁移到另一个cpu核心上(也就是flags中的PF_NEED_MIGRATE被置位),
     // 该字段存储要被迁移到的目标处理器核心号
     uint32_t migrate_to;
-    // Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
-    void *fp_state;
-    // 指向进程的地址空间的arc指针.
-    void *address_space;
+    void* fp_state;//Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
 };
 
 // 将进程的pcb和内核栈融合到一起,8字节对齐
-union proc_union
-{
+union proc_union {
     struct process_control_block pcb;
     ul stack[STACK_SIZE / sizeof(ul)];
 } __attribute__((aligned(8)));

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

@@ -38,6 +38,7 @@ 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;
 
@@ -45,20 +46,17 @@ 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,            \
-        .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                               \
+#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,                                                       \
     }
 
 struct thread_struct initial_thread = {
@@ -115,10 +113,8 @@ 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));
@@ -149,6 +145,359 @@ 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
  *
@@ -178,24 +527,43 @@ 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();
-    io_mfence();
+    // 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!!!!");
 
     // 准备切换到用户态
     struct pt_regs *regs;
@@ -220,8 +588,8 @@ ul initial_kernel_thread(ul arg)
     // 这里的设计思路和switch_to类似 加载用户态程序:shell.elf
     __asm__ __volatile__("movq %1, %%rsp   \n\t"
                          "pushq %2    \n\t"
-                         "jmp rs_exec_init_process  \n\t" ::"D"(current_pcb->thread->rsp),
-                         "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "c"(NULL),
+                         "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),
                          "d"(NULL)
                          : "memory");
 
@@ -310,15 +678,9 @@ 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;
 
@@ -330,23 +692,18 @@ 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;
@@ -355,7 +712,6 @@ void process_init()
     // 将IDLE进程的虚拟运行时间设置为一个很大的数值
     current_pcb->virtual_runtime = (1UL << 60);
 }
-#pragma GCC pop_options
 
 /**
  * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL
@@ -430,7 +786,57 @@ int process_wakeup_immediately(struct process_control_block *pcb)
  */
 uint64_t process_exit_mm(struct process_control_block *pcb)
 {
-    rs_drop_address_space(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);
+
     return 0;
 }
 
@@ -451,6 +857,9 @@ 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);
 
@@ -462,8 +871,6 @@ 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;

+ 42 - 32
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,6 +112,17 @@ 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 释放进程的页表
  *
@@ -155,11 +166,10 @@ 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();
 

Some files were not shown because too many files changed in this diff