From 1496ba7b24a5e6954291ca9643b9f3cec567479a Mon Sep 17 00:00:00 2001 From: LoGin Date: Fri, 15 Sep 2023 14:58:19 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E7=AE=A1=E7=90=86=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E9=87=8D=E6=9E=84=E5=AE=8C=E6=88=90=20(#380)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加新版pcb的数据结构 (#273) * 将pcb中的内容分类,分别加锁 (#305) * 进程管理重构:完成fork的主体逻辑 (#309) 1.完成fork的主体逻辑 2.将文件系统接到新的pcb上 3.经过思考,暂时弃用signal机制,待进程管理重构完成后,重写signal机制.原因是原本的signal机制太烂了 * chdir getcwd pid pgid ppid (#310) --------- Co-authored-by: longjin * 删除旧的fork以及signal的代码,并调整fork/vfork/execve系统调用 (#325) 1.删除旧的fork 2.删除signal相关代码,等进程管理重构结束之后,再重新写. 3.调整了fork/vfork/execve系统调用 * 实现切换进程的代码 (#331) * 实现切换进程的代码 * Patch modify preempt (#332) * 修改设置preempt的代码 * 删除rust的list和refcount * 为每个核心初始化idle进程 (#333) * 为每个核心初始化idle进程 * 完成了新的内核线程机制 (#335) * 调度器的pcb替换为新的Arc,把调度器队列锁从 RwSpinLock 替换为了 SpinLock (#336) * 把调度器的pcb替换为新的Arc * 把调度器队列锁从 RwSpinLock 替换为了 SpinLock ,修改了签名以通过编译 * 修正一些双重加锁、细节问题 --------- Co-authored-by: longjin * github workflow自动检查代码是否格式化 * cache toolchain yml * 调整rust版本的waitqueue中的pcb为新版的pcb (#343) * 解决设置rust workspace带来的“工具链不一致”的问题 (#344) * 解决设置rust workspace带来的“工具链不一致”的问题 更改workflow * 调整pcb的sched_info和rwlock,以避免调度器死锁问题 (#341) * 调整pcb的sched_info和rwlock,以避免调度器死锁问题 * 修改为在 WriterGuard 中维护 Irq_guard * 修正了 write_irqsave方法 * 优化了代码 * 把 set state 操作从 wakup 移动到 sched_enqueue 中 * 修正为在 wakeup 中设置 running ,以保留 set_state 的私有性 * 移除了 process_wakeup * 实现进程退出的逻辑 (#340) 实现进程退出的逻辑 * 标志进程sleep * 修复wakeup的问题 --------- Co-authored-by: longjin * rust 重构 completion (#350) * 完成了completion的基本结构,待完善上级调用 * 用SpinLock保护结构体并发安全 * 修改原子变量为u32,修复符号错误 * irq guard * 修改为具有内部可变性的结构体 * temp fix * 修复了由于进程持有自旋锁导致的不被调度的问题 * 对 complete 系列方法上锁,保护 done 数据并发安全 * 移除了未使用的依赖 * 重写显示刷新驱动 (#363) * 重构显示刷新驱动 * Patch refactor process management (#366) * 维护进程树 * 维护进程树 * 更改代码结构 * 新建进程时,设置cwd * 调整adopt childern函数,降低开销 --------- Co-authored-by: longjin * waitqueue兼容C部分 (#351) * PATH * safe init * waitqueue兼容C部分 * waitqueue兼容C部分 * 删除semaphore.c,在ps2_keyboard中使用waitqueue * 删除semaphore.c,在ps2_keyboard中使用waitqueue * current_pcb的C兼容 * current_pcb的C兼容 * current_pcb的C兼容 * fmt * current_pcb的兼容 * 针对修改 * 调整代码 * fmt * 删除pcb的set flags * 更改函数名 --------- Co-authored-by: longjin * merge master * Patch debug process management refactor (#372) * 能够调通,执行完textui_init * 能跑到initial kernel thread * fmt * 能够正常初始化所有服务(尚未能切换到用户程序) * 删除部分无用的extern * 存在问题:ap处理器启动后,bsp的smp_init函数return之后就出错了,怀疑是栈损坏 * 解决smp启动由于未换栈导致的内存访问错误 * debug * 1 * 1 * lock no preempt * 调通 * 优化代码,删除一些调试日志 * fix * 使用rust重写wait4 (#377) * 维护进程树 * 维护进程树 * 更改代码结构 * 新建进程时,设置cwd * 调整adopt childern函数,降低开销 * wait4 * 删除c_sys_wait4 * 使用userbuffer保护裸指针 --------- Co-authored-by: longjin * 消除warning * 1. 修正未设置cpu executing的问题 * 修正kthread机制可能存在的内存泄露问题 * 删除pcb文档 * 删除C的tss struct --------- Co-authored-by: Bullet <93781792+GP-Bullet@users.noreply.github.com> Co-authored-by: Chiichen <39649411+Chiichen@users.noreply.github.com> Co-authored-by: hanjiezhou Co-authored-by: GnoCiYeH <118462160+GnoCiYeH@users.noreply.github.com> Co-authored-by: houmkh <1119644616@qq.com> --- .gitignore | 2 +- .vscode/settings.json | 6 +- docs/kernel/process_management/index.rst | 1 - docs/kernel/process_management/kthread.md | 130 +-- docs/kernel/process_management/pcb.md | 27 - kernel/Cargo.toml | 1 + kernel/src/Makefile | 9 +- kernel/src/arch/x86_64/asm/bitops.rs | 1 + kernel/src/arch/x86_64/asm/cmpxchg.rs | 12 - kernel/src/arch/x86_64/asm/current.rs | 19 - kernel/src/arch/x86_64/asm/mod.rs | 6 +- kernel/src/arch/x86_64/asm/ptrace.rs | 12 - kernel/src/arch/x86_64/asm/spinlock.c | 10 +- kernel/src/arch/x86_64/context.rs | 31 - kernel/src/arch/x86_64/cpu.rs | 9 - kernel/src/arch/x86_64/fpu.rs | 94 +- kernel/src/arch/x86_64/include/asm/current.h | 21 - kernel/src/arch/x86_64/interrupt/mod.rs | 75 ++ kernel/src/arch/x86_64/ipc/mod.rs | 10 + kernel/src/arch/x86_64/mm/mod.rs | 1 - kernel/src/arch/x86_64/mod.rs | 4 +- kernel/src/arch/x86_64/process/c_adapter.rs | 13 + kernel/src/arch/x86_64/process/kthread.rs | 98 ++ kernel/src/arch/x86_64/process/mod.rs | 496 +++++++++ kernel/src/arch/x86_64/process/syscall.rs | 116 +++ kernel/src/arch/x86_64/process/table.rs | 75 ++ kernel/src/arch/x86_64/sched.rs | 4 +- kernel/src/arch/x86_64/smp/mod.rs | 61 ++ kernel/src/arch/x86_64/syscall.rs | 235 +---- kernel/src/common/blk_types.h | 3 - kernel/src/common/completion.h | 47 - kernel/src/common/cpu.h | 1 - kernel/src/common/elf.h | 7 - kernel/src/common/kthread.h | 125 --- kernel/src/common/mutex.h | 69 -- kernel/src/common/semaphore.h | 47 - kernel/src/common/stddef.h | 2 +- kernel/src/common/user_namespace.h | 7 - kernel/src/common/wait_queue.h | 118 --- kernel/src/debug/traceback/traceback.c | 4 +- kernel/src/driver/Makefile | 2 +- kernel/src/driver/base/device/mod.rs | 7 - kernel/src/driver/disk/ahci/ahci.h | 7 - kernel/src/driver/disk/ahci/mod.rs | 18 +- kernel/src/driver/interrupt/apic/apic.c | 20 +- kernel/src/driver/interrupt/apic/apic2rust.h | 2 + kernel/src/driver/interrupt/apic/apic_timer.c | 11 +- kernel/src/driver/keyboard/ps2_keyboard.c | 21 +- kernel/src/driver/timers/HPET/HPET.c | 17 +- kernel/src/driver/video/Makefile | 10 - kernel/src/driver/video/mod.rs | 337 +++++- kernel/src/driver/video/video.c | 213 ---- kernel/src/driver/video/video.h | 35 - kernel/src/driver/virtio/transport_pci.rs | 4 +- kernel/src/driver/virtio/virtio.h | 5 - kernel/src/driver/virtio/virtio.rs | 6 - kernel/src/exception/softirq.rs | 14 +- kernel/src/exception/trap.c | 90 +- kernel/src/filesystem/procfs/mod.rs | 129 ++- kernel/src/filesystem/vfs/VFS.h | 1 - kernel/src/filesystem/vfs/core.rs | 5 +- kernel/src/filesystem/vfs/file.rs | 122 ++- kernel/src/filesystem/vfs/io/Makefile | 17 - kernel/src/filesystem/vfs/io/block/Makefile | 17 - kernel/src/filesystem/vfs/io/block/mod.rs | 1 - kernel/src/filesystem/vfs/mount.rs | 23 +- kernel/src/filesystem/vfs/syscall.rs | 454 +++++---- kernel/src/head.S | 48 +- kernel/src/include/DragonOS/signal.h | 1 - kernel/src/include/bindings/wrapper.h | 6 +- kernel/src/ipc/Makefile | 10 - kernel/src/ipc/mod.rs | 2 - kernel/src/ipc/pipe.rs | 22 +- kernel/src/ipc/signal.rs | 922 ----------------- kernel/src/ipc/signal_types.rs | 669 ------------ kernel/src/ipc/syscall.rs | 179 +--- kernel/src/ktest/Makefile | 2 +- kernel/src/ktest/ktest.c | 3 +- kernel/src/ktest/test-mutex.c | 93 -- kernel/src/lib.rs | 28 +- kernel/src/libs/align.rs | 6 + kernel/src/libs/elf.rs | 7 +- kernel/src/libs/int_like.rs | 14 + kernel/src/libs/lib_ui/screen_manager.h | 45 - kernel/src/libs/lib_ui/screen_manager.rs | 302 +++--- kernel/src/libs/lib_ui/textui.rs | 142 ++- kernel/src/libs/lib_ui/textui_no_alloc.rs | 18 +- kernel/src/libs/list.rs | 18 - kernel/src/libs/lockref.rs | 352 ------- kernel/src/libs/mod.rs | 3 - kernel/src/libs/mutex.c | 121 --- kernel/src/libs/mutex.rs | 33 +- kernel/src/libs/printk.rs | 10 +- kernel/src/libs/refcount.rs | 67 -- kernel/src/libs/rwlock.rs | 43 +- kernel/src/libs/semaphore.c | 40 - kernel/src/libs/semaphore.rs | 6 +- kernel/src/libs/spinlock.rs | 270 ++--- kernel/src/libs/wait_queue.c | 84 -- kernel/src/libs/wait_queue.rs | 137 ++- kernel/src/libs/wait_queue_head.c | 82 -- kernel/src/main.c | 64 +- kernel/src/mm/mm-types.h | 1 - kernel/src/mm/mm.h | 1 - kernel/src/mm/mmio_buddy.rs | 7 +- kernel/src/mm/mod.rs | 12 +- kernel/src/mm/syscall.rs | 4 +- kernel/src/mm/ucontext.rs | 23 +- kernel/src/net/net_core.rs | 4 +- kernel/src/net/syscall.rs | 37 +- kernel/src/process/Makefile | 22 - kernel/src/process/c_adapter.rs | 139 +-- kernel/src/process/fork.c | 295 ------ kernel/src/process/fork.rs | 331 +++--- kernel/src/process/idle.rs | 79 ++ kernel/src/process/init.rs | 44 + kernel/src/process/initial_proc.rs | 45 - kernel/src/process/kthread.c | 341 ------- kernel/src/process/kthread.rs | 460 +++++++++ kernel/src/process/mod.rs | 961 +++++++++++++++++- kernel/src/process/pid.rs | 18 - kernel/src/process/preempt.h | 23 +- kernel/src/process/preempt.rs | 13 - kernel/src/process/proc-types.h | 144 --- kernel/src/process/proc.S | 36 - kernel/src/process/process.c | 495 --------- kernel/src/process/process.h | 187 +--- kernel/src/process/process.rs | 378 +------ kernel/src/process/syscall.rs | 174 +++- kernel/src/sched/cfs.rs | 152 +-- kernel/src/sched/completion.c | 338 ------ kernel/src/sched/completion.rs | 153 +++ kernel/src/sched/core.c | 14 - kernel/src/sched/core.rs | 165 ++- kernel/src/sched/mod.rs | 40 + kernel/src/sched/rt.rs | 182 ++-- kernel/src/sched/sched.h | 5 - kernel/src/sched/syscall.rs | 9 +- kernel/src/smp/c_adapter.rs | 8 +- kernel/src/smp/core.rs | 5 - kernel/src/smp/mod.rs | 12 +- kernel/src/smp/smp.c | 81 +- kernel/src/smp/smp.h | 7 +- kernel/src/syscall/mod.rs | 87 +- kernel/src/syscall/syscall.c | 50 - kernel/src/time/clocksource.c | 10 +- kernel/src/time/clocksource.h | 1 - kernel/src/time/sleep.h | 2 +- kernel/src/time/sleep.rs | 10 +- kernel/src/time/timer.h | 2 +- kernel/src/time/timer.rs | 19 +- tools/.gdbinit | 2 +- user/libs/libc/src/malloc.c | 11 +- 153 files changed, 4895 insertions(+), 8190 deletions(-) delete mode 100644 docs/kernel/process_management/pcb.md delete mode 100644 kernel/src/arch/x86_64/asm/cmpxchg.rs delete mode 100644 kernel/src/arch/x86_64/asm/current.rs delete mode 100644 kernel/src/arch/x86_64/asm/ptrace.rs delete mode 100644 kernel/src/arch/x86_64/context.rs delete mode 100644 kernel/src/arch/x86_64/include/asm/current.h create mode 100644 kernel/src/arch/x86_64/ipc/mod.rs create mode 100644 kernel/src/arch/x86_64/process/c_adapter.rs create mode 100644 kernel/src/arch/x86_64/process/kthread.rs create mode 100644 kernel/src/arch/x86_64/process/mod.rs create mode 100644 kernel/src/arch/x86_64/process/syscall.rs create mode 100644 kernel/src/arch/x86_64/process/table.rs create mode 100644 kernel/src/arch/x86_64/smp/mod.rs delete mode 100644 kernel/src/common/completion.h delete mode 100644 kernel/src/common/kthread.h delete mode 100644 kernel/src/common/mutex.h delete mode 100644 kernel/src/common/semaphore.h delete mode 100644 kernel/src/common/user_namespace.h delete mode 100644 kernel/src/common/wait_queue.h delete mode 100644 kernel/src/driver/disk/ahci/ahci.h create mode 100644 kernel/src/driver/interrupt/apic/apic2rust.h delete mode 100644 kernel/src/driver/video/Makefile delete mode 100644 kernel/src/driver/video/video.c delete mode 100644 kernel/src/driver/video/video.h delete mode 100644 kernel/src/driver/virtio/virtio.h delete mode 100644 kernel/src/filesystem/vfs/io/Makefile delete mode 100644 kernel/src/filesystem/vfs/io/block/Makefile delete mode 100644 kernel/src/filesystem/vfs/io/block/mod.rs delete mode 100644 kernel/src/ipc/Makefile delete mode 100644 kernel/src/ipc/signal.rs delete mode 100644 kernel/src/ipc/signal_types.rs delete mode 100644 kernel/src/ktest/test-mutex.c delete mode 100644 kernel/src/libs/list.rs delete mode 100644 kernel/src/libs/lockref.rs delete mode 100644 kernel/src/libs/mutex.c delete mode 100644 kernel/src/libs/refcount.rs delete mode 100644 kernel/src/libs/semaphore.c delete mode 100644 kernel/src/libs/wait_queue.c delete mode 100644 kernel/src/libs/wait_queue_head.c delete mode 100644 kernel/src/process/Makefile delete mode 100644 kernel/src/process/fork.c create mode 100644 kernel/src/process/idle.rs create mode 100644 kernel/src/process/init.rs delete mode 100644 kernel/src/process/initial_proc.rs delete mode 100644 kernel/src/process/kthread.c create mode 100644 kernel/src/process/kthread.rs delete mode 100644 kernel/src/process/pid.rs delete mode 100644 kernel/src/process/preempt.rs delete mode 100644 kernel/src/process/proc.S delete mode 100644 kernel/src/process/process.c delete mode 100644 kernel/src/sched/completion.c create mode 100644 kernel/src/sched/completion.rs delete mode 100644 kernel/src/sched/core.c diff --git a/.gitignore b/.gitignore index d9faba48..8edf414e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,4 @@ docs/_build draft cppcheck.xml /target/ -Cargo.lock \ No newline at end of file +Cargo.lock diff --git a/.vscode/settings.json b/.vscode/settings.json index c21797a6..a2c7109f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -96,7 +96,6 @@ "math.h": "c", "ipi.h": "c", "arch.h": "c", - "elf.h": "c", "stdio.h": "c", "wait_queue.h": "c", "stddef.h": "c", @@ -154,7 +153,6 @@ "err.h": "c", "rtc.h": "c", "list.h": "c", - "completion.h": "c", "fat32.h": "c", "irqflags.h": "c", "dirent.h": "c", @@ -169,13 +167,13 @@ "assert.h": "c", "sys_version.h": "c", "cmd.h": "c", - "user_namespace.h": "c", "sleep.h": "c", "net.h": "c", "lz4.h": "c", "cmd_test.h": "c", "cmpxchg.h": "c", - "mman.h": "c" + "mman.h": "c", + "clocksource.h": "c" }, "C_Cpp.errorSquiggles": "enabled", "esbonio.sphinx.confDir": "", diff --git a/docs/kernel/process_management/index.rst b/docs/kernel/process_management/index.rst index c25eb3ef..ad685729 100644 --- a/docs/kernel/process_management/index.rst +++ b/docs/kernel/process_management/index.rst @@ -5,5 +5,4 @@ :maxdepth: 1 kthread - pcb load_binary diff --git a/docs/kernel/process_management/kthread.md b/docs/kernel/process_management/kthread.md index 58042e80..4e69ca82 100644 --- a/docs/kernel/process_management/kthread.md +++ b/docs/kernel/process_management/kthread.md @@ -1,134 +1,14 @@ # kthread 内核线程 -  内核线程模块定义在`common/kthread.h`中,提供对内核线程的及支持功能。内核线程作为内核的“分身”,能够提升系统的并行化程度以及故障容错能力。 +  内核线程模块实现在`process/kthread.rs`中,提供对内核线程的及支持功能。内核线程作为内核的“分身”,能够提升系统的并行化程度以及故障容错能力。 ## 原理   每个内核线程都运行在内核态,执行其特定的任务。 -  内核线程的创建是通过调用`kthread_create()`或者`kthread_run()`宏,向`kthreadd`守护线程发送创建任务来实现的。也就是说,内核线程的创建,最终是由`kthreadd`来完成。 +  内核线程的创建是通过调用`KernelThreadMechanism::create()`或者`KernelThreadMechanism::create_and_run()`函数,向`kthreadd`守护线程发送创建任务来实现的。也就是说,内核线程的创建,最终是由`kthread_daemon`来完成。 -  当内核线程被创建后,虽然会加入调度队列,但是当其被第一次调度,执行引导程序`kthread()`后,将进入休眠状态。直到其他模块使用`process_wakeup()`,它才会真正开始运行。 +  当内核线程被创建后,默认处于睡眠状态,要使用`ProcessManager::wakeup`函数将其唤醒。 +  当内核其他模块想要停止一个内核线程的时候,可以调用`KernelThreadMechanism::stop()`函数,等待内核线程的退出,然后获得返回值并清理内核线程的pcb。 -  当内核其他模块想要停止一个内核线程的时候,可以调用`kthread_stop()`函数。该函数将会置位内核线程的`worker_private`中的`KTHREAD_SHOULD_STOP`标志位,并等待内核线程的退出,然后获得返回值并清理内核线程的pcb。 - -  内核线程应当经常检查`KTHREAD_SHOULD_STOP`标志位,以确定其是否要退出。当检测到该标志位被置位时,内核线程应当完成数据清理工作,并调用`kthread_exit()`或直接返回一个返回码,以退出内核线程。 - -## 创建内核线程 - -### kthread_create() - -#### 原型 - -  `kthread_create(thread_fn, data, name_fmt, arg...)` - -#### 简介 - -  在当前NUMA结点上创建一个内核线程(DragonOS目前暂不支持NUMA,因此node可忽略。) - -  请注意,该宏会创建一个内核线程,并将其设置为停止状态. - -#### 参数 - -**thread_fn** - -  该内核线程要执行的函数 - -**data** - -  传递给 *thread_fn* 的参数数据 - -**name_fmt** - -  printf-style format string for the thread name - -**arg** - -  name_fmt的参数 - -#### 返回值 - -  创建好的内核线程的pcb - -### kthread_run() - -#### 原型 - -  `kthread_run(thread_fn, data, name_fmt, ...)` - -#### 简介 - -  创建内核线程并加入调度队列。 - -  该宏定义是`kthread_create()`的简单封装,提供创建了内核线程后,立即运行的功能。 - -### kthread_run_rt() - -#### 原型 - -  `kthread_run_rt(thread_fn, data, name_fmt, ...)` - -#### 简介 - -  创建内核实时线程并加入调度队列。 - -  类似`kthread_run()`,该宏定义也是`kthread_create()`的简单封装,提供创建了内核实时线程后,在设置实时进程的参数后,立即运行的功能。 - -## 停止内核线程 - -### kthread_stop() - -#### 原型 - -  `int kthread_stop(struct process_control_block * pcb)` - -#### 简介 - -  当外部模块希望停止一个内核线程时,调用该函数,向kthread发送停止消息,请求其结束。并等待其退出,返回内核线程的退出返回值。 - -#### 参数 - -**pcb** - -  内核线程的pcb - -#### 返回值 - -  内核线程的退出返回码。 - -### kthread_should_stop() - - -#### 原型 - -  `bool kthread_should_stop(void)` - -#### 简介 - -  内核线程可以调用该函数得知是否有其他进程请求结束当前内核线程。 - -#### 返回值 - -  一个bool变量 - - -| 值 | 解释 | -| ---------- | ----------------------- | -| true | 有其他进程请求结束该内核线程 | -| false | 该内核线程没有收到停止消息 | - -### kthread_exit() - -#### 原型 - -  `void kthread_exit(long result)` - -#### 简介 - -  让当前内核线程退出,并返回result参数给kthread_stop()函数。 - -#### 参数 - -**result** - -  内核线程的退出返回码 +  内核线程应当经常检查`KernelThreadMechanism::should_stop()`的结果,以确定其是否要退出。当检测到需要退出时,内核线程返回一个返回码,即可退出。(注意资源的清理) diff --git a/docs/kernel/process_management/pcb.md b/docs/kernel/process_management/pcb.md deleted file mode 100644 index 9bea41e4..00000000 --- a/docs/kernel/process_management/pcb.md +++ /dev/null @@ -1,27 +0,0 @@ -# PCB 进程控制块 - -PCB的全称为process control block, 它是每个进程/线程的核心控制结构。定义于`kernel/src/process/proc-types.h`中。 - -## PCB详解 - -Todo: - -## 与PCB的管理相关的API - -### 根据pid寻找pcb - -**process_find_pcb_by_pid** - -该API提供了根据pid寻找pcb的功能,定义在`kernel/src/process/process.h`中。 - -当找到目标的pcb时,返回对应的pcb,否则返回NULL。 - -#### 参数 - -**pid** - 进程id - -#### 返回值 - -**struct process_control_block** - 目标pcb \ No newline at end of file diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 625a6d96..d9e93509 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -25,6 +25,7 @@ num-derive = "0.3" # 一个no_std的hashmap、hashset hashbrown = "0.13.2" elf = { version = "0.7.2", default-features = false } +memoffset = "0.9.0" atomic_enum = "0.2.0" # 构建时依赖项 diff --git a/kernel/src/Makefile b/kernel/src/Makefile index 841c40a4..eb71a9b5 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -10,15 +10,14 @@ LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_ PIC := _INTR_APIC_ -CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include +CFLAGS = $(GLOBAL_CFLAGS) -fno-pie -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include export ASFLAGS := --64 LD_LIST := head.o -kernel_subdirs := common driver process debug arch exception smp sched syscall ktest libs ipc time - +kernel_subdirs := common driver debug arch exception smp sched syscall ktest libs time head.o: head.S @@ -38,7 +37,7 @@ kernel_rust: all: kernel @echo "Linking 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 -T link.lds + $(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 -T link.lds --no-relax # 生成kallsyms current_dir=$(pwd) @@ -52,7 +51,7 @@ all: kernel # 重新链接 @echo "Re-Linking kernel..." @echo $(shell find . -name "*.o") - $(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 + $(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 --no-relax @echo "Generating kernel ELF file..." # 生成内核文件 $(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 kernel ../../bin/kernel/kernel.elf diff --git a/kernel/src/arch/x86_64/asm/bitops.rs b/kernel/src/arch/x86_64/asm/bitops.rs index 7eb7c06c..bd74c4ef 100644 --- a/kernel/src/arch/x86_64/asm/bitops.rs +++ b/kernel/src/arch/x86_64/asm/bitops.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use core::arch::x86_64::_popcnt64; /// @brief ffz - 寻找u64中的第一个0所在的位(从第0位开始寻找) diff --git a/kernel/src/arch/x86_64/asm/cmpxchg.rs b/kernel/src/arch/x86_64/asm/cmpxchg.rs deleted file mode 100644 index 306e1863..00000000 --- a/kernel/src/arch/x86_64/asm/cmpxchg.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 该函数在cmpxchg.c中实现 -extern "C" { - fn __try_cmpxchg_q(ptr: *mut u64, old_ptr: *mut u64, new_ptr: *mut u64) -> bool; -} - -/// @brief 封装lock cmpxchg指令 -/// 由于Rust实现这部分的内联汇编比较麻烦(实在想不出办法),因此使用C的实现。 -#[inline] -pub unsafe fn try_cmpxchg_q(ptr: *mut u64, old_ptr: *mut u64, new_ptr: *mut u64) -> bool { - let retval = __try_cmpxchg_q(ptr, old_ptr, new_ptr); - return retval; -} diff --git a/kernel/src/arch/x86_64/asm/current.rs b/kernel/src/arch/x86_64/asm/current.rs deleted file mode 100644 index 87afcec0..00000000 --- a/kernel/src/arch/x86_64/asm/current.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::include::bindings::bindings::process_control_block; - -use core::{arch::asm, sync::atomic::compiler_fence}; - -/// @brief 获取指向当前进程的pcb的可变引用 -#[inline] -pub fn current_pcb() -> &'static mut process_control_block { - let ret: Option<&mut process_control_block>; - - unsafe { - let mut tmp: u64 = !(32767u64); - compiler_fence(core::sync::atomic::Ordering::SeqCst); - asm!("and {0}, rsp", inout(reg)(tmp),); - compiler_fence(core::sync::atomic::Ordering::SeqCst); - ret = (tmp as *mut process_control_block).as_mut(); - } - - ret.unwrap() -} diff --git a/kernel/src/arch/x86_64/asm/mod.rs b/kernel/src/arch/x86_64/asm/mod.rs index dae9eda1..37094b0e 100644 --- a/kernel/src/arch/x86_64/asm/mod.rs +++ b/kernel/src/arch/x86_64/asm/mod.rs @@ -1,6 +1,2 @@ -pub mod irqflags; -#[macro_use] -pub mod current; pub mod bitops; -pub mod cmpxchg; -pub mod ptrace; +pub mod irqflags; diff --git a/kernel/src/arch/x86_64/asm/ptrace.rs b/kernel/src/arch/x86_64/asm/ptrace.rs deleted file mode 100644 index 1a9fed17..00000000 --- a/kernel/src/arch/x86_64/asm/ptrace.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![allow(dead_code)] -use crate::include::bindings::bindings::pt_regs; - -/// @brief 判断给定的栈帧是否来自用户态 -/// 判断方法为:根据代码段选择子是否具有ring3的访问权限(低2bit均为1) -pub fn user_mode(regs: *const pt_regs) -> bool { - if (unsafe { (*regs).cs } & 0x3) != 0 { - return true; - } else { - return false; - } -} diff --git a/kernel/src/arch/x86_64/asm/spinlock.c b/kernel/src/arch/x86_64/asm/spinlock.c index 7b4cb73d..aaafe482 100644 --- a/kernel/src/arch/x86_64/asm/spinlock.c +++ b/kernel/src/arch/x86_64/asm/spinlock.c @@ -13,13 +13,13 @@ void __arch_spin_lock(spinlock_t *lock) "jmp 1b \n\t" // 尝试加锁 "3:" : "=m"(lock->lock)::"memory"); - preempt_disable(); + rs_preempt_disable(); } void __arch_spin_unlock(spinlock_t *lock) { - preempt_enable(); __asm__ __volatile__("movb $1, %0 \n\t" : "=m"(lock->lock)::"memory"); + rs_preempt_enable(); } void __arch_spin_lock_no_preempt(spinlock_t *lock) @@ -44,13 +44,13 @@ void __arch_spin_unlock_no_preempt(spinlock_t *lock) long __arch_spin_trylock(spinlock_t *lock) { uint64_t tmp_val = 0; - preempt_disable(); + rs_preempt_disable(); // 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功 asm volatile("lock xchg %%bx, %1 \n\t" // 确保只有1个进程能得到锁 : "=q"(tmp_val), "=m"(lock->lock) : "b"(0) : "memory"); if (!tmp_val) - preempt_enable(); + rs_preempt_enable(); return tmp_val; -} \ No newline at end of file +} diff --git a/kernel/src/arch/x86_64/context.rs b/kernel/src/arch/x86_64/context.rs deleted file mode 100644 index b52a0b9b..00000000 --- a/kernel/src/arch/x86_64/context.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::include::bindings::bindings::{process_control_block, switch_proc}; - -use core::sync::atomic::compiler_fence; - -use super::fpu::{fp_state_restore, fp_state_save}; - -/// @brief 切换进程的上下文(没有切换页表的动作) -/// -/// @param next 下一个进程的pcb -/// @param trap_frame 中断上下文的栈帧 -#[inline(always)] -pub fn switch_process( - prev: &'static mut process_control_block, - next: &'static mut process_control_block, -) { - 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); -} diff --git a/kernel/src/arch/x86_64/cpu.rs b/kernel/src/arch/x86_64/cpu.rs index ac1be208..96ad425d 100644 --- a/kernel/src/arch/x86_64/cpu.rs +++ b/kernel/src/arch/x86_64/cpu.rs @@ -1,5 +1,3 @@ -use core::arch::asm; - use x86::cpuid::{cpuid, CpuIdResult}; /// @brief 获取当前cpu的apic id @@ -10,13 +8,6 @@ pub fn current_cpu_id() -> u32 { return cpu_id; } -/// @brief 通过pause指令,让cpu休息一会儿。降低空转功耗 -pub fn cpu_relax() { - unsafe { - asm!("pause"); - } -} - /// 重置cpu pub fn cpu_reset() -> ! { // 重启计算机 diff --git a/kernel/src/arch/x86_64/fpu.rs b/kernel/src/arch/x86_64/fpu.rs index d2fb71bf..7d54551a 100644 --- a/kernel/src/arch/x86_64/fpu.rs +++ b/kernel/src/arch/x86_64/fpu.rs @@ -1,17 +1,4 @@ -use core::{ - arch::{ - asm, - x86_64::{_fxrstor64, _fxsave64}, - }, - ffi::c_void, - ptr::null_mut, -}; - -use alloc::boxed::Box; - -use crate::{exception::InterruptArch, include::bindings::bindings::process_control_block}; - -use crate::arch::CurrentIrqArch; +use core::arch::x86_64::{_fxrstor64, _fxsave64}; /// https://www.felixcloutier.com/x86/fxsave#tbl-3-47 #[repr(C, align(16))] @@ -53,94 +40,29 @@ impl Default for FpState { } } impl FpState { - #[allow(dead_code)] + #[inline] pub fn new() -> Self { assert!(core::mem::size_of::() == 512); return Self::default(); } - #[allow(dead_code)] + + #[inline] pub fn save(&mut self) { unsafe { _fxsave64(self as *mut FpState as *mut u8); } } - #[allow(dead_code)] + + #[inline] pub fn restore(&self) { unsafe { _fxrstor64(self as *const FpState as *const u8); } } - /// @brief 清空fp_state + /// 清空fp_state + #[allow(dead_code)] pub fn clear(&mut self) { *self = Self::default(); } } - -/// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能 -pub fn fp_state_save(pcb: &mut process_control_block) { - // 该过程中不允许中断 - let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; - - let fp: &mut FpState = if pcb.fp_state == null_mut() { - let f = Box::leak(Box::new(FpState::default())); - pcb.fp_state = f as *mut FpState as usize as *mut c_void; - f - } else { - unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() } - }; - - // 保存浮点寄存器 - fp.save(); - - // 关闭浮点功能 - unsafe { - asm!( - "mov rax, cr4", - "and ax,~(3<<9)", //[9][10]->0 - "mov cr4,rax", - "mov rax, cr0", - "and ax,~(02h)", //[1]->0 - "or ax, ~(0FFFBh)", //[2]->1 - "mov cr0, rax" /* - "mov rax, cr0", - "and ax, 0xFFFB", - "or ax,0x2", - "mov cr0,rax", - "mov rax, cr4", - "or ax,3<<9", - "mov cr4, rax" */ - ) - } - drop(guard); -} - -/// @brief 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能 -pub fn fp_state_restore(pcb: &mut process_control_block) { - // 该过程中不允许中断 - let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; - - if pcb.fp_state == null_mut() { - panic!("fp_state_restore: fp_state is null. pid={}", pcb.pid); - } - - unsafe { - asm! { - "mov rax, cr0", - "and ax, 0FFFBh",//[2]->0 - "or ax,02h",//[1]->1 - "mov cr0,rax", - "mov rax, cr4", - "or ax,3<<9", - "mov cr4, rax", - "clts", - "fninit" - } - } - - let fp = unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() }; - fp.restore(); - fp.clear(); - - drop(guard); -} diff --git a/kernel/src/arch/x86_64/include/asm/current.h b/kernel/src/arch/x86_64/include/asm/current.h deleted file mode 100644 index 81a8dd6a..00000000 --- a/kernel/src/arch/x86_64/include/asm/current.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include - -#pragma GCC push_options -#pragma GCC optimize("O0") -struct process_control_block; -// 获取当前的pcb -struct process_control_block *get_current_pcb() -{ - struct process_control_block *current = NULL; - // 利用了当前pcb和栈空间总大小为32k大小对齐,将rsp低15位清空,即可获得pcb的起始地址 - barrier(); - __asm__ __volatile__("andq %%rsp, %0 \n\t" - : "=r"(current) - : "0"(~32767UL)); - barrier(); - - return current; -}; -#define current_pcb get_current_pcb() -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/arch/x86_64/interrupt/mod.rs b/kernel/src/arch/x86_64/interrupt/mod.rs index c8292658..44e18635 100644 --- a/kernel/src/arch/x86_64/interrupt/mod.rs +++ b/kernel/src/arch/x86_64/interrupt/mod.rs @@ -61,3 +61,78 @@ impl InterruptArch for X86_64InterruptArch { compiler_fence(Ordering::SeqCst); } } + +/// 中断栈帧结构体 +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TrapFrame { + pub r15: ::core::ffi::c_ulong, + pub r14: ::core::ffi::c_ulong, + pub r13: ::core::ffi::c_ulong, + pub r12: ::core::ffi::c_ulong, + pub r11: ::core::ffi::c_ulong, + pub r10: ::core::ffi::c_ulong, + pub r9: ::core::ffi::c_ulong, + pub r8: ::core::ffi::c_ulong, + pub rbx: ::core::ffi::c_ulong, + pub rcx: ::core::ffi::c_ulong, + pub rdx: ::core::ffi::c_ulong, + pub rsi: ::core::ffi::c_ulong, + pub rdi: ::core::ffi::c_ulong, + pub rbp: ::core::ffi::c_ulong, + pub ds: ::core::ffi::c_ulong, + pub es: ::core::ffi::c_ulong, + pub rax: ::core::ffi::c_ulong, + pub func: ::core::ffi::c_ulong, + pub errcode: ::core::ffi::c_ulong, + pub rip: ::core::ffi::c_ulong, + pub cs: ::core::ffi::c_ulong, + pub rflags: ::core::ffi::c_ulong, + pub rsp: ::core::ffi::c_ulong, + pub ss: ::core::ffi::c_ulong, +} + +impl TrapFrame { + pub fn new() -> Self { + Self { + r15: 0, + r14: 0, + r13: 0, + r12: 0, + r11: 0, + r10: 0, + r9: 0, + r8: 0, + rbx: 0, + rcx: 0, + rdx: 0, + rsi: 0, + rdi: 0, + rbp: 0, + ds: 0, + es: 0, + rax: 0, + func: 0, + errcode: 0, + rip: 0, + cs: 0, + rflags: 0, + rsp: 0, + ss: 0, + } + } + + /// 设置中断栈帧返回值 + pub fn set_return_value(&mut self, value: usize) { + self.rax = value as u64; + } + + /// 判断当前中断是否来自用户模式 + pub fn from_user(&self) -> bool { + if (self.cs & 0x3) != 0 { + return true; + } else { + return false; + } + } +} diff --git a/kernel/src/arch/x86_64/ipc/mod.rs b/kernel/src/arch/x86_64/ipc/mod.rs new file mode 100644 index 00000000..c872dd7b --- /dev/null +++ b/kernel/src/arch/x86_64/ipc/mod.rs @@ -0,0 +1,10 @@ +use super::interrupt::TrapFrame; + +use crate::{arch::CurrentIrqArch, exception::InterruptArch}; + +#[no_mangle] +pub unsafe extern "C" fn do_signal(_frame: &mut TrapFrame) { + CurrentIrqArch::interrupt_enable(); + // todo: 处理信号 + return; +} diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 21e239b4..612571dc 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -389,7 +389,6 @@ unsafe fn allocator_init() { // 初始化buddy_allocator let buddy_allocator = unsafe { BuddyAllocator::::new(bump_allocator).unwrap() }; - // 设置全局的页帧分配器 unsafe { set_inner_allocator(buddy_allocator) }; kinfo!("Successfully initialized buddy allocator"); diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 2bb4724b..6fa338cd 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,15 +1,17 @@ #[macro_use] pub mod asm; -pub mod context; pub mod cpu; pub mod fpu; pub mod interrupt; +pub mod ipc; pub mod libs; pub mod mm; pub mod msi; pub mod pci; +pub mod process; pub mod rand; pub mod sched; +pub mod smp; pub mod syscall; pub use self::pci::pci::X86_64PciArch as PciArch; diff --git a/kernel/src/arch/x86_64/process/c_adapter.rs b/kernel/src/arch/x86_64/process/c_adapter.rs new file mode 100644 index 00000000..c315d991 --- /dev/null +++ b/kernel/src/arch/x86_64/process/c_adapter.rs @@ -0,0 +1,13 @@ +use super::table::TSSManager; + +#[no_mangle] +unsafe extern "C" fn set_current_core_tss(stack_start: usize, ist0: usize) { + let current_tss = TSSManager::current_tss(); + current_tss.set_rsp(x86::Ring::Ring0, stack_start as u64); + current_tss.set_ist(0, ist0 as u64); +} + +#[no_mangle] +unsafe extern "C" fn rs_load_current_core_tss() { + TSSManager::load_tr(); +} diff --git a/kernel/src/arch/x86_64/process/kthread.rs b/kernel/src/arch/x86_64/process/kthread.rs new file mode 100644 index 00000000..3744b11f --- /dev/null +++ b/kernel/src/arch/x86_64/process/kthread.rs @@ -0,0 +1,98 @@ +use core::arch::asm; + +use alloc::sync::Arc; + +use crate::{ + arch::{ + interrupt::TrapFrame, + process::table::{KERNEL_CS, KERNEL_DS}, + }, + process::{ + fork::CloneFlags, + kthread::{kernel_thread_bootstrap_stage2, KernelThreadCreateInfo, KernelThreadMechanism}, + Pid, ProcessManager, + }, + syscall::SystemError, +}; + +impl KernelThreadMechanism { + /// 伪造trapframe,创建内核线程 + /// + /// ## 返回值 + /// + /// 返回创建的内核线程的pid + pub fn __inner_create( + info: &Arc, + clone_flags: CloneFlags, + ) -> Result { + // WARNING: If create failed, we must drop the info manually or it will cause memory leak. (refcount will not decrease when create failed) + let create_info: *const KernelThreadCreateInfo = + KernelThreadCreateInfo::generate_unsafe_arc_ptr(info.clone()); + + let mut frame = TrapFrame::new(); + frame.rbx = create_info as usize as u64; + frame.ds = KERNEL_DS.bits() as u64; + frame.es = KERNEL_DS.bits() as u64; + frame.cs = KERNEL_CS.bits() as u64; + frame.ss = KERNEL_DS.bits() as u64; + + // 使能中断 + frame.rflags |= 1 << 9; + + frame.rip = kernel_thread_bootstrap_stage1 as usize as u64; + + // fork失败的话,子线程不会执行。否则将导致内存安全问题。 + let pid = ProcessManager::fork(&mut frame, clone_flags).map_err(|e| { + unsafe { KernelThreadCreateInfo::parse_unsafe_arc_ptr(create_info) }; + e + })?; + + ProcessManager::find(pid) + .unwrap() + .set_name(info.name().clone()); + + return Ok(pid); + } +} + +/// 内核线程引导函数的第一阶段 +/// +/// 当内核线程开始执行时,会先执行这个函数,这个函数会将伪造的trapframe中的数据弹出,然后跳转到第二阶段 +/// +/// 跳转之后,指向Box的指针将传入到stage2的函数 +#[naked] +pub(super) unsafe extern "sysv64" fn kernel_thread_bootstrap_stage1() { + asm!( + concat!( + " + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbx + pop rcx + pop rdx + pop rsi + pop rdi + pop rbp + pop rax + mov ds, ax + pop rax + mov es, ax + pop rax + add rsp, 0x20 + popfq + add rsp, 0x10 + mov rdi, rbx + jmp {stage2_func} + " + ), + stage2_func = sym kernel_thread_bootstrap_stage2, + options(noreturn) + ) +} diff --git a/kernel/src/arch/x86_64/process/mod.rs b/kernel/src/arch/x86_64/process/mod.rs new file mode 100644 index 00000000..75fb1409 --- /dev/null +++ b/kernel/src/arch/x86_64/process/mod.rs @@ -0,0 +1,496 @@ +use core::{ + arch::asm, + intrinsics::unlikely, + mem::ManuallyDrop, + sync::atomic::{compiler_fence, Ordering}, +}; + +use alloc::{string::String, sync::Arc, vec::Vec}; + +use memoffset::offset_of; +use x86::{controlregs::Cr4, segmentation::SegmentSelector}; + +use crate::{ + arch::process::table::TSSManager, + exception::InterruptArch, + libs::spinlock::SpinLockGuard, + mm::{ + percpu::{PerCpu, PerCpuVar}, + VirtAddr, + }, + process::{ + fork::CloneFlags, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, + SwitchResult, SWITCH_RESULT, + }, + syscall::{Syscall, SystemError}, +}; + +use self::{ + kthread::kernel_thread_bootstrap_stage1, + table::{switch_fs_and_gs, KERNEL_DS, USER_DS}, +}; + +use super::{fpu::FpState, interrupt::TrapFrame, CurrentIrqArch}; + +mod c_adapter; +pub mod kthread; +pub mod syscall; +pub mod table; + +extern "C" { + /// 从中断返回 + fn ret_from_intr(); +} + +/// PCB中与架构相关的信息 +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub struct ArchPCBInfo { + rflags: usize, + rbx: usize, + r12: usize, + r13: usize, + r14: usize, + r15: usize, + rbp: usize, + rsp: usize, + rip: usize, + cr2: usize, + fsbase: usize, + gsbase: usize, + fs: u16, + gs: u16, + + /// 浮点寄存器的状态 + fp_state: Option, +} + +#[allow(dead_code)] +impl ArchPCBInfo { + /// 创建一个新的ArchPCBInfo + /// + /// ## 参数 + /// + /// - `kstack`:内核栈的引用,如果为None,则不会设置rsp和rbp。如果为Some,则会设置rsp和rbp为内核栈的最高地址。 + /// + /// ## 返回值 + /// + /// 返回一个新的ArchPCBInfo + pub fn new(kstack: Option<&KernelStack>) -> Self { + let mut r = Self { + rflags: 0, + rbx: 0, + r12: 0, + r13: 0, + r14: 0, + r15: 0, + rbp: 0, + rsp: 0, + rip: 0, + cr2: 0, + fsbase: 0, + gsbase: 0, + fs: KERNEL_DS.bits(), + gs: KERNEL_DS.bits(), + fp_state: None, + }; + + if kstack.is_some() { + let kstack = kstack.unwrap(); + r.rsp = kstack.stack_max_address().data(); + r.rbp = kstack.stack_max_address().data(); + } + + return r; + } + + pub fn set_stack(&mut self, stack: VirtAddr) { + self.rsp = stack.data(); + } + + pub fn set_stack_base(&mut self, stack_base: VirtAddr) { + self.rbp = stack_base.data(); + } + + pub fn rbp(&self) -> usize { + self.rbp + } + + pub unsafe fn push_to_stack(&mut self, value: usize) { + self.rsp -= core::mem::size_of::(); + *(self.rsp as *mut usize) = value; + } + + pub unsafe fn pop_from_stack(&mut self) -> usize { + let value = *(self.rsp as *const usize); + self.rsp += core::mem::size_of::(); + value + } + + pub fn save_fp_state(&mut self) { + if self.fp_state.is_none() { + self.fp_state = Some(FpState::new()); + } + + self.fp_state.as_mut().unwrap().save(); + } + + pub fn restore_fp_state(&mut self) { + if unlikely(self.fp_state.is_none()) { + return; + } + + self.fp_state.as_mut().unwrap().restore(); + } + + pub unsafe fn save_fsbase(&mut self) { + if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) { + self.fsbase = x86::current::segmentation::rdfsbase() as usize; + } else { + self.fsbase = 0; + } + } + + pub unsafe fn save_gsbase(&mut self) { + if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) { + self.gsbase = x86::current::segmentation::rdgsbase() as usize; + } else { + self.gsbase = 0; + } + } + + pub unsafe fn restore_fsbase(&mut self) { + if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) { + x86::current::segmentation::wrfsbase(self.fsbase as u64); + } + } + + pub unsafe fn restore_gsbase(&mut self) { + if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) { + x86::current::segmentation::wrgsbase(self.gsbase as u64); + } + } + + pub fn fsbase(&self) -> usize { + self.fsbase + } + + pub fn gsbase(&self) -> usize { + self.gsbase + } +} + +impl ProcessControlBlock { + /// 获取当前进程的pcb + pub fn arch_current_pcb() -> Arc { + // 获取栈指针 + let ptr = VirtAddr::new(x86::current::registers::rsp() as usize); + let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1))); + // 从内核栈的最低地址处取出pcb的地址 + let p = stack_base.data() as *const *const ProcessControlBlock; + if unlikely((unsafe { *p }).is_null()) { + panic!("current_pcb is null"); + } + unsafe { + // 为了防止内核栈的pcb指针被释放,这里需要将其包装一下,使得Arc的drop不会被调用 + let arc_wrapper: ManuallyDrop> = + ManuallyDrop::new(Arc::from_raw(*p)); + + let new_arc: Arc = Arc::clone(&arc_wrapper); + return new_arc; + } + } +} + +impl ProcessManager { + pub fn arch_init() { + { + // 初始化进程切换结果 per cpu变量 + let mut switch_res_vec: Vec = Vec::new(); + for _ in 0..PerCpu::MAX_CPU_NUM { + switch_res_vec.push(SwitchResult::new()); + } + unsafe { + SWITCH_RESULT = Some(PerCpuVar::new(switch_res_vec).unwrap()); + } + } + } + /// fork的过程中复制线程 + /// + /// 由于这个过程与具体的架构相关,所以放在这里 + pub fn copy_thread( + _clone_flags: &CloneFlags, + current_pcb: &Arc, + new_pcb: &Arc, + current_trapframe: &TrapFrame, + ) -> Result<(), SystemError> { + let mut child_trapframe = current_trapframe.clone(); + + // 子进程的返回值为0 + child_trapframe.set_return_value(0); + + // 设置子进程的栈基址(开始执行中断返回流程时的栈基址) + let mut new_arch_guard = new_pcb.arch_info(); + let kernel_stack_guard = new_pcb.kernel_stack(); + + // 设置子进程在内核态开始执行时的rsp、rbp + new_arch_guard.set_stack_base(kernel_stack_guard.stack_max_address()); + + let trap_frame_vaddr: VirtAddr = + kernel_stack_guard.stack_max_address() - core::mem::size_of::(); + new_arch_guard.set_stack(trap_frame_vaddr); + + // 拷贝栈帧 + unsafe { + let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame; + *trap_frame_ptr = child_trapframe; + } + + let current_arch_guard = current_pcb.arch_info_irqsave(); + new_arch_guard.fsbase = current_arch_guard.fsbase; + new_arch_guard.gsbase = current_arch_guard.gsbase; + new_arch_guard.fs = current_arch_guard.fs; + new_arch_guard.gs = current_arch_guard.gs; + new_arch_guard.fp_state = current_arch_guard.fp_state.clone(); + + // 拷贝浮点寄存器的状态 + if let Some(fp_state) = current_arch_guard.fp_state.as_ref() { + new_arch_guard.fp_state = Some(*fp_state); + } + drop(current_arch_guard); + + // 设置返回地址(子进程开始执行的指令地址) + + if new_pcb.flags().contains(ProcessFlags::KTHREAD) { + let kthread_bootstrap_stage1_func_addr = kernel_thread_bootstrap_stage1 as usize; + + new_arch_guard.rip = kthread_bootstrap_stage1_func_addr; + } else { + new_arch_guard.rip = ret_from_intr as usize; + } + + return Ok(()); + } + + /// 切换进程 + /// + /// ## 参数 + /// + /// - `prev`:上一个进程的pcb + /// - `next`:下一个进程的pcb + pub unsafe fn switch_process(prev: Arc, next: Arc) { + assert!(CurrentIrqArch::is_irq_enabled() == false); + + // 保存浮点寄存器 + prev.arch_info().save_fp_state(); + // 切换浮点寄存器 + next.arch_info().restore_fp_state(); + + // 切换fsbase + prev.arch_info().save_fsbase(); + next.arch_info().restore_fsbase(); + + // 切换gsbase + prev.arch_info().save_gsbase(); + next.arch_info().restore_gsbase(); + + // 切换地址空间 + let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone(); + compiler_fence(Ordering::SeqCst); + + next_addr_space.read().user_mapper.utable.make_current(); + compiler_fence(Ordering::SeqCst); + // 切换内核栈 + + // 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁) + let next_arch = SpinLockGuard::leak(next.arch_info()); + let prev_arch = SpinLockGuard::leak(prev.arch_info()); + + prev_arch.rip = switch_back as usize; + + // 恢复当前的 preempt count*2 + ProcessManager::current_pcb().preempt_enable(); + ProcessManager::current_pcb().preempt_enable(); + SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev.clone()); + SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next.clone()); + + // 切换tss + TSSManager::current_tss().set_rsp( + x86::Ring::Ring0, + next.kernel_stack().stack_max_address().data() as u64, + ); + // kdebug!("switch tss ok"); + + // 正式切换上下文 + switch_to_inner(prev_arch, next_arch); + } +} + +/// 保存上下文,然后切换进程,接着jmp到`switch_finish_hook`钩子函数 +#[naked] +unsafe extern "sysv64" fn switch_to_inner(prev: &mut ArchPCBInfo, next: &mut ArchPCBInfo) { + asm!( + // As a quick reminder for those who are unfamiliar with the System V ABI (extern "C"): + // + // - the current parameters are passed in the registers `rdi`, `rsi`, + // - we can modify scratch registers, e.g. rax + // - we cannot change callee-preserved registers arbitrarily, e.g. rbx, which is why we + // store them here in the first place. + concat!(" + // Save old registers, and load new ones + mov [rdi + {off_rbx}], rbx + mov rbx, [rsi + {off_rbx}] + + mov [rdi + {off_r12}], r12 + mov r12, [rsi + {off_r12}] + + mov [rdi + {off_r13}], r13 + mov r13, [rsi + {off_r13}] + + mov [rdi + {off_r14}], r14 + mov r14, [rsi + {off_r14}] + + mov [rdi + {off_r15}], r15 + mov r15, [rsi + {off_r15}] + + // switch segment registers (这些寄存器只能通过接下来的switch_hook的return来切换) + mov [rdi + {off_fs}], fs + mov [rdi + {off_gs}], gs + + push rbp + push rax + + mov [rdi + {off_rbp}], rbp + mov rbp, [rsi + {off_rbp}] + + mov [rdi + {off_rsp}], rsp + mov rsp, [rsi + {off_rsp}] + + // // push RFLAGS (can only be modified via stack) + pushfq + // // pop RFLAGS into `self.rflags` + pop QWORD PTR [rdi + {off_rflags}] + + // // push `next.rflags` + push QWORD PTR [rsi + {off_rflags}] + // // pop into RFLAGS + popfq + + // push next rip to stack + push QWORD PTR [rsi + {off_rip}] + + + // When we return, we cannot even guarantee that the return address on the stack, points to + // the calling function. Thus, we have to execute this Rust hook by + // ourselves, which will unlock the contexts before the later switch. + + // Note that switch_finish_hook will be responsible for executing `ret`. + jmp {switch_hook} + "), + + off_rflags = const(offset_of!(ArchPCBInfo, rflags)), + + off_rbx = const(offset_of!(ArchPCBInfo, rbx)), + off_r12 = const(offset_of!(ArchPCBInfo, r12)), + off_r13 = const(offset_of!(ArchPCBInfo, r13)), + off_r14 = const(offset_of!(ArchPCBInfo, r14)), + off_rbp = const(offset_of!(ArchPCBInfo, rbp)), + off_rsp = const(offset_of!(ArchPCBInfo, rsp)), + off_r15 = const(offset_of!(ArchPCBInfo, r15)), + off_rip = const(offset_of!(ArchPCBInfo, rip)), + off_fs = const(offset_of!(ArchPCBInfo, fs)), + off_gs = const(offset_of!(ArchPCBInfo, gs)), + + switch_hook = sym crate::process::switch_finish_hook, + options(noreturn), + ); +} + +/// 从`switch_to_inner`返回后,执行这个函数 +/// +/// 也就是说,当进程再次被调度时,会从这里开始执行 +#[inline(never)] +unsafe extern "sysv64" fn switch_back() { + asm!(concat!( + " + pop rax + pop rbp + " + )) +} + +pub unsafe fn arch_switch_to_user(path: String, argv: Vec, envp: Vec) -> ! { + // 以下代码不能发生中断 + CurrentIrqArch::interrupt_disable(); + + let current_pcb = ProcessManager::current_pcb(); + let trap_frame_vaddr = VirtAddr::new( + current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::(), + ); + // kdebug!("trap_frame_vaddr: {:?}", trap_frame_vaddr); + let new_rip = VirtAddr::new(ret_from_intr as usize); + + assert!( + (x86::current::registers::rsp() as usize) < trap_frame_vaddr.data(), + "arch_switch_to_user(): current_rsp >= fake trap + frame vaddr, this may cause some illegal access to memory! + rsp: {:#x}, trap_frame_vaddr: {:#x}", + x86::current::registers::rsp() as usize, + trap_frame_vaddr.data() + ); + + let mut arch_guard = current_pcb.arch_info_irqsave(); + arch_guard.rsp = trap_frame_vaddr.data(); + + arch_guard.fs = USER_DS.bits(); + arch_guard.gs = USER_DS.bits(); + + switch_fs_and_gs( + SegmentSelector::from_bits_truncate(arch_guard.fs), + SegmentSelector::from_bits_truncate(arch_guard.gs), + ); + arch_guard.rip = new_rip.data(); + + drop(arch_guard); + + // 删除kthread的标志 + current_pcb.flags().remove(ProcessFlags::KTHREAD); + current_pcb.worker_private().take(); + + let mut trap_frame = TrapFrame::new(); + + compiler_fence(Ordering::SeqCst); + Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| { + panic!( + "arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}", + pid = current_pcb.pid(), + e = e + ); + }); + compiler_fence(Ordering::SeqCst); + + // 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题! + + drop(current_pcb); + + compiler_fence(Ordering::SeqCst); + ready_to_switch_to_user(trap_frame, trap_frame_vaddr.data(), new_rip.data()); +} + +/// 由于需要依赖ret来切换到用户态,所以不能inline +#[inline(never)] +unsafe extern "sysv64" fn ready_to_switch_to_user( + trap_frame: TrapFrame, + trapframe_vaddr: usize, + new_rip: usize, +) -> ! { + *(trapframe_vaddr as *mut TrapFrame) = trap_frame; + asm!( + "mov rsp, {trapframe_vaddr}", + "push {new_rip}", + "ret", + trapframe_vaddr = in(reg) trapframe_vaddr, + new_rip = in(reg) new_rip + ); + unreachable!() +} diff --git a/kernel/src/arch/x86_64/process/syscall.rs b/kernel/src/arch/x86_64/process/syscall.rs new file mode 100644 index 00000000..ee13d8b6 --- /dev/null +++ b/kernel/src/arch/x86_64/process/syscall.rs @@ -0,0 +1,116 @@ +use alloc::{string::String, vec::Vec}; + +use crate::{ + arch::{ + interrupt::TrapFrame, + process::table::{USER_CS, USER_DS}, + CurrentIrqArch, + }, + exception::InterruptArch, + mm::ucontext::AddressSpace, + process::{ + exec::{load_binary_file, ExecParam, ExecParamFlags}, + ProcessManager, + }, + syscall::{Syscall, SystemError}, +}; + +impl Syscall { + pub fn do_execve( + path: String, + argv: Vec, + envp: Vec, + regs: &mut TrapFrame, + ) -> Result<(), SystemError> { + // kdebug!( + // "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n", + // path, + // argv, + // envp + // ); + // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + let pcb = ProcessManager::current_pcb(); + + let mut basic_info = pcb.basic_mut(); + // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free) + let old_address_space = basic_info.user_vm(); + + // 在pcb中原来的用户地址空间 + unsafe { + basic_info.set_user_vm(None); + } + // 创建新的地址空间并设置为当前地址空间 + let address_space = AddressSpace::new(true).expect("Failed to create new address space"); + unsafe { + basic_info.set_user_vm(Some(address_space.clone())); + } + + // to avoid deadlock + drop(basic_info); + + 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"); + // kdebug!("argv: {:?}, envp: {:?}", argv, envp); + 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.bits() as u64; + regs.ds = USER_DS.bits() as u64; + regs.ss = USER_DS.bits() as u64; + 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(()); + } +} diff --git a/kernel/src/arch/x86_64/process/table.rs b/kernel/src/arch/x86_64/process/table.rs new file mode 100644 index 00000000..db252cb3 --- /dev/null +++ b/kernel/src/arch/x86_64/process/table.rs @@ -0,0 +1,75 @@ +use x86::{current::task::TaskStateSegment, segmentation::SegmentSelector, Ring}; + +use crate::{ + mm::{percpu::PerCpu, VirtAddr}, + smp::core::smp_get_processor_id, +}; + +// === 段选择子在GDT中的索引 === +/// kernel code segment selector +pub const KERNEL_CS: SegmentSelector = SegmentSelector::new(1, Ring::Ring0); +/// kernel data segment selector +pub const KERNEL_DS: SegmentSelector = SegmentSelector::new(2, Ring::Ring0); +/// user code segment selector +pub const USER_CS: SegmentSelector = SegmentSelector::new(5, Ring::Ring3); +/// user data segment selector +pub const USER_DS: SegmentSelector = SegmentSelector::new(6, Ring::Ring3); + +static mut TSS_MANAGER: TSSManager = TSSManager::new(); + +extern "C" { + static mut GDT_Table: [u64; 512]; +} +/// 切换fs和gs段寄存器 +/// +/// 由于需要return使得它生效,所以不能inline +#[inline(never)] +pub unsafe fn switch_fs_and_gs(fs: SegmentSelector, gs: SegmentSelector) { + x86::segmentation::load_fs(fs); + x86::segmentation::load_gs(gs); +} + +#[derive(Debug)] +pub struct TSSManager { + tss: [TaskStateSegment; PerCpu::MAX_CPU_NUM], +} + +impl TSSManager { + const fn new() -> Self { + return Self { + tss: [TaskStateSegment::new(); PerCpu::MAX_CPU_NUM], + }; + } + + /// 获取当前CPU的TSS + pub unsafe fn current_tss() -> &'static mut TaskStateSegment { + &mut TSS_MANAGER.tss[smp_get_processor_id() as usize] + } + + /// 加载当前CPU的TSS + pub unsafe fn load_tr() { + let index = (10 + smp_get_processor_id() * 2) as u16; + let selector = SegmentSelector::new(index, Ring::Ring0); + + Self::set_tss_descriptor( + index, + VirtAddr::new(Self::current_tss() as *mut TaskStateSegment as usize), + ); + x86::task::load_tr(selector); + } + + unsafe fn set_tss_descriptor(index: u16, vaddr: VirtAddr) { + const LIMIT: u64 = 103; + let gdt_vaddr = VirtAddr::new(&GDT_Table as *const _ as usize); + + let gdt: &mut [u64] = core::slice::from_raw_parts_mut(gdt_vaddr.data() as *mut u64, 512); + + let vaddr = vaddr.data() as u64; + gdt[index as usize] = (LIMIT & 0xffff) + | ((vaddr & 0xffff) << 16) + | (((vaddr >> 16) & 0xff) << 32) + | (0x89 << 40) + | (((vaddr >> 24) & 0xff) << 56); + gdt[index as usize + 1] = ((vaddr >> 32) & 0xffffffff) | 0; + } +} diff --git a/kernel/src/arch/x86_64/sched.rs b/kernel/src/arch/x86_64/sched.rs index e723f571..54c9f93e 100644 --- a/kernel/src/arch/x86_64/sched.rs +++ b/kernel/src/arch/x86_64/sched.rs @@ -1,10 +1,10 @@ -use crate::include::bindings::bindings::{enter_syscall_int, SYS_SCHED}; +use crate::{include::bindings::bindings::enter_syscall_int, syscall::SYS_SCHED}; /// @brief 若内核代码不处在中断上下文中,那么将可以使用本函数,发起一个sys_sched系统调用,然后运行调度器。 /// 由于只能在中断上下文中进行进程切换,因此需要发起一个系统调用SYS_SCHED。 #[no_mangle] pub extern "C" fn sched() { unsafe { - enter_syscall_int(SYS_SCHED.into(), 0, 0, 0, 0, 0, 0, 0, 0); + enter_syscall_int(SYS_SCHED as u64, 0, 0, 0, 0, 0, 0, 0, 0); } } diff --git a/kernel/src/arch/x86_64/smp/mod.rs b/kernel/src/arch/x86_64/smp/mod.rs new file mode 100644 index 00000000..78900621 --- /dev/null +++ b/kernel/src/arch/x86_64/smp/mod.rs @@ -0,0 +1,61 @@ +use core::{arch::asm, hint::spin_loop, sync::atomic::compiler_fence}; + +use memoffset::offset_of; + +use crate::{ + arch::process::table::TSSManager, exception::InterruptArch, + include::bindings::bindings::cpu_core_info, kdebug, process::ProcessManager, + smp::core::smp_get_processor_id, +}; + +use super::CurrentIrqArch; + +extern "C" { + fn smp_ap_start_stage2(); +} + +#[repr(C)] +struct ApStartStackInfo { + vaddr: usize, +} + +/// AP处理器启动时执行 +#[no_mangle] +unsafe extern "C" fn smp_ap_start() -> ! { + CurrentIrqArch::interrupt_disable(); + let vaddr = cpu_core_info[smp_get_processor_id() as usize].stack_start as usize; + compiler_fence(core::sync::atomic::Ordering::SeqCst); + let v = ApStartStackInfo { vaddr }; + smp_init_switch_stack(&v); +} + +#[naked] +unsafe extern "sysv64" fn smp_init_switch_stack(st: &ApStartStackInfo) -> ! { + asm!(concat!(" + mov rsp, [rdi + {off_rsp}] + mov rbp, [rdi + {off_rsp}] + jmp {stage1} + "), + off_rsp = const(offset_of!(ApStartStackInfo, vaddr)), + stage1 = sym smp_ap_start_stage1, + options(noreturn)); +} + +unsafe extern "C" fn smp_ap_start_stage1() -> ! { + let id = smp_get_processor_id(); + kdebug!("smp_ap_start_stage1: id: {}\n", id); + let current_idle = ProcessManager::idle_pcb()[smp_get_processor_id() as usize].clone(); + + let tss = TSSManager::current_tss(); + + tss.set_rsp( + x86::Ring::Ring0, + current_idle.kernel_stack().stack_max_address().data() as u64, + ); + TSSManager::load_tr(); + + smp_ap_start_stage2(); + loop { + spin_loop(); + } +} diff --git a/kernel/src/arch/x86_64/syscall.rs b/kernel/src/arch/x86_64/syscall.rs index 24ce3754..d64b17d2 100644 --- a/kernel/src/arch/x86_64/syscall.rs +++ b/kernel/src/arch/x86_64/syscall.rs @@ -1,28 +1,15 @@ -use core::{ffi::c_void, panic}; +use core::ffi::c_void; -use alloc::{string::String, vec::Vec}; +use alloc::string::String; 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, - }, - 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, - }, + include::bindings::bindings::set_system_trap_gate, + syscall::{Syscall, SystemError, SYS_RT_SIGRETURN}, }; -use super::{asm::ptrace::user_mode, mm::barrier::mfence}; +use super::{interrupt::TrapFrame, mm::barrier::mfence}; extern "C" { - fn do_fork(regs: *mut pt_regs, clone_flags: u64, stack_start: u64, stack_size: u64) -> u64; - fn syscall_int(); } @@ -35,85 +22,28 @@ macro_rules! syscall_return { } #[no_mangle] -pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () { - let syscall_num = regs.rax as usize; +pub extern "C" fn syscall_handler(frame: &mut TrapFrame) -> () { + let syscall_num = frame.rax as usize; let args = [ - regs.r8 as usize, - regs.r9 as usize, - regs.r10 as usize, - regs.r11 as usize, - regs.r12 as usize, - regs.r13 as usize, - regs.r14 as usize, - regs.r15 as usize, + frame.r8 as usize, + frame.r9 as usize, + frame.r10 as usize, + frame.r11 as usize, + frame.r12 as usize, + frame.r13 as usize, + frame.r14 as usize, + frame.r15 as usize, ]; mfence(); - mfence(); - let from_user = user_mode(regs); // 由于进程管理未完成重构,有些系统调用需要在这里临时处理,以后这里的特殊处理要删掉。 match syscall_num { - SYS_FORK => unsafe { - syscall_return!(do_fork(regs, 0, regs.rsp, 0), regs); - }, - SYS_VFORK => unsafe { - syscall_return!( - do_fork( - regs, - (CLONE_VM | CLONE_FS | CLONE_SIGNAL) as u64, - regs.rsp, - 0, - ), - regs - ); - }, - SYS_EXECVE => { - let path_ptr = args[0]; - let argv_ptr = args[1]; - let env_ptr = args[2]; - - // 权限校验 - 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()) - { - syscall_return!(SystemError::EFAULT.to_posix_errno() as u64, regs); - } else { - unsafe { - // kdebug!("syscall: execve\n"); - syscall_return!( - rs_do_execve( - path_ptr as *const u8, - argv_ptr as *const *const u8, - env_ptr as *const *const u8, - regs - ), - regs - ); - // 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 - // ) - } - } - } - SYS_RT_SIGRETURN => { - syscall_return!(sys_rt_sigreturn(regs), regs); + syscall_return!(SystemError::ENOSYS.to_posix_errno() as usize, frame); } - // SYS_SCHED => { - // syscall_return!(sched(from_user) as u64, regs); - // } _ => {} } - syscall_return!(Syscall::handle(syscall_num, &args, from_user) as u64, regs); + syscall_return!(Syscall::handle(syscall_num, &args, frame) as u64, frame); } /// 系统调用初始化 @@ -123,142 +53,15 @@ pub fn arch_syscall_init() -> Result<(), SystemError> { 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 = check_and_clone_cstr_array(argv)?; - let envp: Vec = check_and_clone_cstr_array(envp)?; - Ok((path, argv, envp)) - }; - let r: Result<(String, Vec, Vec), 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 { +pub extern "C" fn rs_exec_init_process(frame: &mut TrapFrame) -> 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); + let r = Syscall::do_execve(path, argv, envp, frame); // 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, - envp: Vec, - 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(()); -} diff --git a/kernel/src/common/blk_types.h b/kernel/src/common/blk_types.h index b1c1cc4b..6bcb18a0 100644 --- a/kernel/src/common/blk_types.h +++ b/kernel/src/common/blk_types.h @@ -2,8 +2,6 @@ #include #include -#include -#include #define BLK_TYPE_AHCI 0 @@ -83,5 +81,4 @@ struct blk_gendisk struct block_device *partition; // 磁盘分区数组 const struct block_device_operation *fops; // 磁盘操作 void *private_data; - mutex_t open_mutex; // open()/close()操作的互斥锁 }; \ No newline at end of file diff --git a/kernel/src/common/completion.h b/kernel/src/common/completion.h deleted file mode 100644 index 0cf58118..00000000 --- a/kernel/src/common/completion.h +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include -#include