进程管理模块重构完成 (#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>
This commit is contained in:
LoGin
2023-09-15 14:58:19 +08:00
committed by GitHub
parent b087521e07
commit 1496ba7b24
153 changed files with 4895 additions and 8190 deletions

View File

@ -1,3 +1,4 @@
#![allow(dead_code)]
use core::arch::x86_64::_popcnt64;
/// @brief ffz - 寻找u64中的第一个0所在的位从第0位开始寻找

View File

@ -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;
}

View File

@ -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()
}

View File

@ -1,6 +1,2 @@
pub mod irqflags;
#[macro_use]
pub mod current;
pub mod bitops;
pub mod cmpxchg;
pub mod ptrace;
pub mod irqflags;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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() -> ! {
// 重启计算机

View File

@ -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::<Self>() == 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);
}

View File

@ -1,21 +0,0 @@
#pragma once
#include <common/glib.h>
#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

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -389,7 +389,6 @@ unsafe fn allocator_init() {
// 初始化buddy_allocator
let buddy_allocator = unsafe { BuddyAllocator::<X86_64MMArch>::new(bump_allocator).unwrap() };
// 设置全局的页帧分配器
unsafe { set_inner_allocator(buddy_allocator) };
kinfo!("Successfully initialized buddy allocator");

View File

@ -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;

View File

@ -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();
}

View File

@ -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<KernelThreadCreateInfo>,
clone_flags: CloneFlags,
) -> Result<Pid, SystemError> {
// 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<KernelThreadClosure>的指针将传入到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)
)
}

View File

@ -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<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!()
}

View File

@ -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<String>,
envp: Vec<String>,
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(());
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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<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 {
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<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(());
}