Files
DragonOS/kernel/src/arch/x86_64/process/mod.rs
LoGin 1496ba7b24 进程管理模块重构完成 (#380)
* 添加新版pcb的数据结构 (#273)

* 将pcb中的内容分类,分别加锁 (#305)

* 进程管理重构:完成fork的主体逻辑 (#309)

1.完成fork的主体逻辑
2.将文件系统接到新的pcb上
3.经过思考,暂时弃用signal机制,待进程管理重构完成后,重写signal机制.原因是原本的signal机制太烂了

* chdir getcwd pid pgid ppid (#310)


---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* 删除旧的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<ProcessControlBlock>,把调度器队列锁从 RwSpinLock 替换为了 SpinLock (#336)

* 把调度器的pcb替换为新的Arc<ProcessControlBlock>

* 把调度器队列锁从 RwSpinLock 替换为了 SpinLock ,修改了签名以通过编译

* 修正一些双重加锁、细节问题

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* 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 <longjin@RinGoTek.cn>

* 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 <longjin@RinGoTek.cn>

* 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 <longjin@RinGoTek.cn>

* 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 <longjin@RinGoTek.cn>

* 消除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 <zhouhanjie@dragonos.org>
Co-authored-by: GnoCiYeH <118462160+GnoCiYeH@users.noreply.github.com>
Co-authored-by: houmkh <1119644616@qq.com>
2023-09-15 14:58:19 +08:00

497 lines
15 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<FpState>,
}
#[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::<usize>();
*(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::<usize>();
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<Self> {
// 获取栈指针
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<Arc<ProcessControlBlock>> =
ManuallyDrop::new(Arc::from_raw(*p));
let new_arc: Arc<ProcessControlBlock> = Arc::clone(&arc_wrapper);
return new_arc;
}
}
}
impl ProcessManager {
pub fn arch_init() {
{
// 初始化进程切换结果 per cpu变量
let mut switch_res_vec: Vec<SwitchResult> = 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<ProcessControlBlock>,
new_pcb: &Arc<ProcessControlBlock>,
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::<TrapFrame>();
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<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
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<String>, envp: Vec<String>) -> ! {
// 以下代码不能发生中断
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::<TrapFrame>(),
);
// 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!()
}