增加x87FPU支持 (#212)

* remove `ret_from_syscall`
*修复ps2键盘驱动程序inode在进程fork的时候导致死锁的问题.
*更新: VFS每次拷贝文件描述符的时候,都会去调用inode的open函数

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
Gou Ngai 2023-03-28 20:44:26 +08:00 committed by GitHub
parent 2286eda652
commit 64aea4b349
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 388 additions and 114 deletions

1
DragonOS Submodule

@ -0,0 +1 @@
Subproject commit 45b8371173b070028457f7ee64be33f68b4f9ada

View File

@ -2,6 +2,8 @@ use crate::include::bindings::bindings::{process_control_block, switch_proc};
use core::sync::atomic::compiler_fence;
use super::fpu::{fp_state_save, fp_state_restore};
/// @brief 切换进程的上下文(没有切换页表的动作)
///
/// @param next 下一个进程的pcb
@ -11,6 +13,8 @@ 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);
unsafe {
switch_proc(prev, next);

View File

@ -0,0 +1,147 @@
use core::{
arch::{
asm,
x86_64::{_fxrstor64, _fxsave64},
},
ffi::c_void,
ptr::null_mut,
};
use alloc::boxed::Box;
use crate::include::bindings::bindings::process_control_block;
use super::asm::irqflags::{local_irq_restore, local_irq_save};
/// https://www.felixcloutier.com/x86/fxsave#tbl-3-47
#[repr(C, align(16))]
#[derive(Debug, Copy, Clone)]
pub struct FpState {
//0
fcw: u16,
fsw: u16,
ftw: u16,
fop: u16,
word2: u64,
//16
word3: u64,
mxcsr: u32,
mxcsr_mask: u32,
//32
mm: [u64; 16],
//160
xmm: [u64; 32],
//416
rest: [u64; 12],
}
impl Default for FpState {
fn default() -> Self {
Self {
fcw: 0x037f,
fsw: Default::default(),
ftw: Default::default(),
fop: Default::default(),
word2: Default::default(),
word3: Default::default(),
mxcsr: 0x1f80,
mxcsr_mask: Default::default(),
mm: Default::default(),
xmm: Default::default(),
rest: Default::default(),
}
}
}
impl FpState {
#[allow(dead_code)]
pub fn new() -> Self {
assert!(core::mem::size_of::<Self>() == 512);
return Self::default();
}
#[allow(dead_code)]
pub fn save(&mut self) {
unsafe {
_fxsave64(self as *mut FpState as *mut u8);
}
}
#[allow(dead_code)]
pub fn restore(&self) {
unsafe {
_fxrstor64(self as *const FpState as *const u8);
}
}
/// @brief 清空fp_state
pub fn clear(&mut self) {
*self = Self::default();
}
}
/// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能
pub fn fp_state_save(pcb: &mut process_control_block) {
// 该过程中不允许中断
let mut rflags: u64 = 0;
local_irq_save(&mut rflags);
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" */
)
}
local_irq_restore(&rflags);
}
/// @brief 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能
pub fn fp_state_restore(pcb: &mut process_control_block) {
// 该过程中不允许中断
let mut rflags: u64 = 0;
local_irq_save(&mut rflags);
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();
local_irq_restore(&rflags);
}

View File

@ -5,3 +5,4 @@ pub mod cpu;
pub mod interrupt;
pub mod mm;
pub mod sched;
pub mod fpu;

View File

@ -1,3 +1,5 @@
use core::sync::atomic::AtomicI32;
use alloc::sync::{Arc, Weak};
use crate::{
@ -6,13 +8,12 @@ use crate::{
vfs::{core::generate_inode_id, file::FileMode, FileType, IndexNode, Metadata, PollStatus},
},
include::bindings::bindings::{vfs_file_operations_t, vfs_file_t, vfs_index_node_t, ENOTSUP},
kdebug,
libs::spinlock::SpinLock,
libs::rwlock::RwLock,
time::TimeSpec,
};
#[derive(Debug)]
pub struct LockedPS2KeyBoardInode(SpinLock<PS2KeyBoardInode>);
pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>, AtomicI32); // self.1 用来记录有多少个文件打开了这个inode
#[derive(Debug)]
pub struct PS2KeyBoardInode {
@ -53,8 +54,11 @@ impl LockedPS2KeyBoardInode {
},
};
let result = Arc::new(LockedPS2KeyBoardInode(SpinLock::new(inode)));
result.0.lock().self_ref = Arc::downgrade(&result);
let result = Arc::new(LockedPS2KeyBoardInode(
RwLock::new(inode),
AtomicI32::new(0),
));
result.0.write().self_ref = Arc::downgrade(&result);
return result;
}
@ -62,7 +66,7 @@ impl LockedPS2KeyBoardInode {
impl DeviceINode for LockedPS2KeyBoardInode {
fn set_fs(&self, fs: Weak<DevFS>) {
self.0.lock().fs = fs;
self.0.write().fs = fs;
}
}
@ -80,7 +84,7 @@ impl IndexNode for LockedPS2KeyBoardInode {
buf: &mut [u8],
_data: &mut crate::filesystem::vfs::FilePrivateData,
) -> Result<usize, i32> {
let guard = self.0.lock();
let guard = self.0.read();
let func = guard.f_ops.read.unwrap();
let r = unsafe {
func(
@ -108,16 +112,24 @@ impl IndexNode for LockedPS2KeyBoardInode {
_data: &mut crate::filesystem::vfs::FilePrivateData,
_mode: &FileMode,
) -> Result<(), i32> {
let guard = self.0.lock();
let func = guard.f_ops.open.unwrap();
let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };
let prev_ref_count = self.1.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
if prev_ref_count == 0 {
// 第一次打开,需要初始化
let guard = self.0.write();
let func = guard.f_ops.open.unwrap();
let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };
}
return Ok(());
}
fn close(&self, _data: &mut crate::filesystem::vfs::FilePrivateData) -> Result<(), i32> {
let guard = self.0.lock();
let func = guard.f_ops.close.unwrap();
let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };
let prev_ref_count = self.1.fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
if prev_ref_count == 1 {
// 最后一次关闭,需要释放
let guard = self.0.write();
let func = guard.f_ops.close.unwrap();
let _ = unsafe { func(0 as *mut vfs_index_node_t, 0 as *mut vfs_file_t) };
}
return Ok(());
}
@ -128,11 +140,11 @@ impl IndexNode for LockedPS2KeyBoardInode {
}
fn metadata(&self) -> Result<Metadata, i32> {
return Ok(self.0.lock().metadata.clone());
return Ok(self.0.read().metadata.clone());
}
fn set_metadata(&self, metadata: &Metadata) -> Result<(), i32> {
let mut inode = self.0.lock();
let mut inode = self.0.write();
inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime;
@ -144,7 +156,7 @@ impl IndexNode for LockedPS2KeyBoardInode {
}
fn fs(&self) -> alloc::sync::Arc<dyn crate::filesystem::vfs::FileSystem> {
return self.0.lock().fs.upgrade().unwrap();
return self.0.read().fs.upgrade().unwrap();
}
fn as_any_ref(&self) -> &dyn core::any::Any {

View File

@ -64,17 +64,18 @@ ENTRY(ret_from_intr)
//
cli
// do_signal
movq %rsp, %rdi
callq do_signal
//
jmp Restore_all
Err_Code:
// =====
// =====
pushq %rax
movq %es, %rax
pushq %rax
@ -108,16 +109,10 @@ Err_Code:
movq %rsp, %rdi // rdi
callq *%rdx // *
jmp ret_from_exception
//
ENTRY(ret_from_system_call)
jmp Restore_all
// 0 #DE
ENTRY(divide_error)

View File

@ -18,31 +18,31 @@ extern void ignore_int();
#pragma GCC push_options
#pragma GCC optimize("O0")
// 保存函数调用现场的寄存器
#define SAVE_ALL_REGS \
"cld; \n\t" \
"pushq %rax; \n\t" \
"pushq %rax; \n\t" \
"movq %es, %rax; \n\t" \
"pushq %rax; \n\t" \
"movq %ds, %rax; \n\t" \
"pushq %rax; \n\t" \
"xorq %rax, %rax;\n\t" \
"pushq %rbp; \n\t" \
"pushq %rdi; \n\t" \
"pushq %rsi; \n\t" \
"pushq %rdx; \n\t" \
"pushq %rcx; \n\t" \
"pushq %rbx; \n\t" \
"pushq %r8 ; \n\t" \
"pushq %r9 ; \n\t" \
"pushq %r10; \n\t" \
"pushq %r11; \n\t" \
"pushq %r12; \n\t" \
"pushq %r13; \n\t" \
"pushq %r14; \n\t" \
"pushq %r15; \n\t" \
"movq $0x10, %rdx;\n\t" \
"movq %rdx, %ds; \n\t" \
#define SAVE_ALL_REGS \
"cld; \n\t" \
"pushq %rax; \n\t" \
"pushq %rax; \n\t" \
"movq %es, %rax; \n\t" \
"pushq %rax; \n\t" \
"movq %ds, %rax; \n\t" \
"pushq %rax; \n\t" \
"xorq %rax, %rax;\n\t" \
"pushq %rbp; \n\t" \
"pushq %rdi; \n\t" \
"pushq %rsi; \n\t" \
"pushq %rdx; \n\t" \
"pushq %rcx; \n\t" \
"pushq %rbx; \n\t" \
"pushq %r8 ; \n\t" \
"pushq %r9 ; \n\t" \
"pushq %r10; \n\t" \
"pushq %r11; \n\t" \
"pushq %r12; \n\t" \
"pushq %r13; \n\t" \
"pushq %r14; \n\t" \
"pushq %r15; \n\t" \
"movq $0x10, %rdx;\n\t" \
"movq %rdx, %ds; \n\t" \
"movq %rdx, %es; \n\t"
// 定义IRQ处理函数的名字格式IRQ+中断号+interrupt
@ -52,13 +52,13 @@ extern void ignore_int();
// 构造中断entry
// 为了复用返回函数的代码需要压入一个错误码0
// todo: 将这里改为volatile也许能解决编译选项为O1时系统崩溃的问题
#define Build_IRQ(number) \
void IRQ_NAME(number); \
__asm__(SYMBOL_NAME_STR(IRQ) #number "interrupt: \n\t" \
"pushq $0x00 \n\t" SAVE_ALL_REGS "movq %rsp, %rdi \n\t" \
"leaq ret_from_intr(%rip), %rax \n\t" \
"pushq %rax \n\t" \
"movq $" #number ", %rsi \n\t" \
#define Build_IRQ(number) \
void IRQ_NAME(number); \
__asm__(SYMBOL_NAME_STR(IRQ) #number "interrupt: \n\t" \
"pushq $0x00 \n\t" SAVE_ALL_REGS "movq %rsp, %rdi \n\t" \
"leaq ret_from_intr(%rip), %rax \n\t" \
"pushq %rax \n\t" \
"movq $" #number ", %rsi \n\t" \
"jmp do_IRQ \n\t");
// 构造中断入口
@ -89,10 +89,30 @@ Build_IRQ(0x37);
// 初始化中断数组
void (*interrupt_table[24])(void) = {
IRQ0x20interrupt, IRQ0x21interrupt, IRQ0x22interrupt, IRQ0x23interrupt, IRQ0x24interrupt, IRQ0x25interrupt,
IRQ0x26interrupt, IRQ0x27interrupt, IRQ0x28interrupt, IRQ0x29interrupt, IRQ0x2ainterrupt, IRQ0x2binterrupt,
IRQ0x2cinterrupt, IRQ0x2dinterrupt, IRQ0x2einterrupt, IRQ0x2finterrupt, IRQ0x30interrupt, IRQ0x31interrupt,
IRQ0x32interrupt, IRQ0x33interrupt, IRQ0x34interrupt, IRQ0x35interrupt, IRQ0x36interrupt, IRQ0x37interrupt,
IRQ0x20interrupt,
IRQ0x21interrupt,
IRQ0x22interrupt,
IRQ0x23interrupt,
IRQ0x24interrupt,
IRQ0x25interrupt,
IRQ0x26interrupt,
IRQ0x27interrupt,
IRQ0x28interrupt,
IRQ0x29interrupt,
IRQ0x2ainterrupt,
IRQ0x2binterrupt,
IRQ0x2cinterrupt,
IRQ0x2dinterrupt,
IRQ0x2einterrupt,
IRQ0x2finterrupt,
IRQ0x30interrupt,
IRQ0x31interrupt,
IRQ0x32interrupt,
IRQ0x33interrupt,
IRQ0x34interrupt,
IRQ0x35interrupt,
IRQ0x36interrupt,
IRQ0x37interrupt,
};
/**
@ -118,8 +138,16 @@ void (*syscall_intr_table[1])(void) = {IRQ0x80interrupt};
// 初始化IPI中断服务程序数组
void (*SMP_interrupt_table[SMP_IRQ_NUM])(void) = {
IRQ0xc8interrupt, IRQ0xc9interrupt, IRQ0xcainterrupt, IRQ0xcbinterrupt, IRQ0xccinterrupt,
IRQ0xcdinterrupt, IRQ0xceinterrupt, IRQ0xcfinterrupt, IRQ0xd0interrupt, IRQ0xd1interrupt,
IRQ0xc8interrupt,
IRQ0xc9interrupt,
IRQ0xcainterrupt,
IRQ0xcbinterrupt,
IRQ0xccinterrupt,
IRQ0xcdinterrupt,
IRQ0xceinterrupt,
IRQ0xcfinterrupt,
IRQ0xd0interrupt,
IRQ0xd1interrupt,
};
// 初始化local apic中断服务程序数组
@ -134,8 +162,16 @@ Build_IRQ(0x9d);
Build_IRQ(0x9e);
Build_IRQ(0x9f);
void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void) = {
IRQ0x96interrupt, IRQ0x97interrupt, IRQ0x98interrupt, IRQ0x99interrupt, IRQ0x9ainterrupt,
IRQ0x9binterrupt, IRQ0x9cinterrupt, IRQ0x9dinterrupt, IRQ0x9einterrupt, IRQ0x9finterrupt,
IRQ0x96interrupt,
IRQ0x97interrupt,
IRQ0x98interrupt,
IRQ0x99interrupt,
IRQ0x9ainterrupt,
IRQ0x9binterrupt,
IRQ0x9cinterrupt,
IRQ0x9dinterrupt,
IRQ0x9einterrupt,
IRQ0x9finterrupt,
};
/**

View File

@ -96,8 +96,8 @@ void do_undefined_opcode(struct pt_regs *regs, unsigned long error_code)
void do_dev_not_avaliable(struct pt_regs *regs, unsigned long error_code)
{
kerror("do_dev_not_avaliable(7),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d\n", error_code, regs->rsp,
regs->rip, proc_current_cpu_id);
kerror("do_dev_not_avaliable(7),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\t CPU:%d, pid=%d\n", error_code, regs->rsp,
regs->rip, proc_current_cpu_id, current_pcb->pid);
current_pcb->state = PROC_STOPPED;
sched();

View File

@ -4,12 +4,13 @@ use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
use crate::{
arch::asm::current::current_pcb,
driver::tty::TtyFilePrivateData,
filesystem::procfs::ProcfsFilePrivateData,
include::bindings::bindings::{
process_control_block, EINVAL, ENOBUFS, EOVERFLOW, EPERM, ESPIPE,
},
io::SeekFrom,
kerror, driver::tty::TtyFilePrivateData,
kerror,
};
use super::{Dirent, FileType, IndexNode, Metadata};
@ -79,7 +80,7 @@ bitflags! {
}
/// @brief 抽象文件结构体
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct File {
inode: Arc<dyn IndexNode>,
/// 对于文件,表示字节偏移量;对于文件夹,表示当前操作的子目录项偏移量
@ -262,9 +263,30 @@ impl File {
return Ok((name_bytes.len() + ::core::mem::size_of::<Dirent>()
- ::core::mem::size_of_val(&dirent.d_name)) as u64);
}
pub fn inode(&self) -> Arc<dyn IndexNode> {
return self.inode.clone();
}
/// @brief 尝试克隆一个文件
///
/// @return Option<Box<File>> 克隆后的文件结构体。如果克隆失败返回None
pub fn try_clone(&self) -> Option<Box<File>> {
let mut res: Box<File> = Box::new(Self {
inode: self.inode.clone(),
offset: self.offset.clone(),
mode: self.mode.clone(),
file_type: self.file_type.clone(),
readdir_subdirs_name: self.readdir_subdirs_name.clone(),
private_data: self.private_data.clone(),
});
// 调用inode的open方法让inode知道有新的文件打开了这个inode
if self.inode.open(&mut res.private_data, &res.mode).is_err() {
return None;
}
return Some(res);
}
}
impl Drop for File {
@ -283,7 +305,7 @@ impl Drop for File {
}
/// @brief pcb里面的文件描述符数组
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct FileDescriptorVec {
/// 当前进程打开的文件描述符
pub fds: [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD],
@ -310,6 +332,19 @@ impl FileDescriptorVec {
return Box::new(FileDescriptorVec { fds: data });
}
/// @brief 克隆一个文件描述符数组
///
/// @return Box<FileDescriptorVec> 克隆后的文件描述符数组
pub fn clone(&self) -> Box<FileDescriptorVec> {
let mut res: Box<FileDescriptorVec> = FileDescriptorVec::new();
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
if let Some(file) = &self.fds[i] {
res.fds[i] = file.try_clone();
}
}
return res;
}
/// @brief 从pcb的fds字段获取文件描述符数组的可变引用
#[inline]
pub fn from_pcb(pcb: &'static process_control_block) -> Option<&'static mut FileDescriptorVec> {

View File

@ -1,8 +1,14 @@
use core::{ffi::c_void, intrinsics::size_of, ptr::read_volatile, sync::atomic::compiler_fence};
use core::{
ffi::c_void,
intrinsics::size_of,
ptr::{null_mut, read_volatile},
sync::atomic::compiler_fence,
};
use crate::{
arch::{
asm::{bitops::ffz, current::current_pcb, ptrace::user_mode},
fpu::FpState,
interrupt::sti,
},
include::bindings::bindings::{
@ -658,6 +664,17 @@ fn setup_frame(
(*frame).handler = ka._u._sa_handler as usize as *mut c_void;
}
// 将当前进程的fp_state拷贝到用户栈
if current_pcb().fp_state != null_mut() {
unsafe {
let fp_state: &mut FpState = (current_pcb().fp_state as usize as *mut FpState)
.as_mut()
.unwrap();
(*frame).context.sc_stack.fpstate = *fp_state;
// 保存完毕后清空fp_state以免下次save的时候出现SIMD exception
fp_state.clear();
}
}
// 将siginfo拷贝到用户栈
err |= copy_siginfo_to_user(unsafe { &mut (*frame).info }, info).unwrap_or(1);
@ -768,7 +785,11 @@ fn restore_sigcontext(context: *const sigcontext, regs: &mut pt_regs) -> bool {
(*current_thread).trap_num = (*context).trap_num;
(*current_thread).cr2 = (*context).cr2;
(*current_thread).err_code = (*context).err_code;
// 如果当前进程有fpstate则将其恢复到pcb的fp_state中
*(current_pcb().fp_state as usize as *mut FpState) = (*context).sc_stack.fpstate;
}
return true;
}

View File

@ -6,6 +6,7 @@ use core::fmt::Debug;
use alloc::vec::Vec;
use crate::arch::fpu::FpState;
use crate::include::bindings::bindings::NULL;
// todo: 将这里更换为手动编写的ffi绑定
use crate::include::bindings::bindings::atomic_t;
@ -664,4 +665,5 @@ pub struct signal_stack {
pub sp: *mut c_void,
pub flags: u32,
pub size: u32,
pub fpstate:FpState,
}

View File

@ -635,6 +635,7 @@ pub struct MmioFreeRegionList {
num_free: i64,
}
impl MmioFreeRegionList {
#[allow(dead_code)]
fn new() -> Self {
return MmioFreeRegionList {
..Default::default()

View File

@ -9,6 +9,7 @@ extern long process_global_pid;
extern void kernel_thread_func(void);
extern uint64_t rs_procfs_register_pid(uint64_t);
extern uint64_t rs_procfs_unregister_pid(uint64_t);
extern void *rs_dup_fpstate();
extern int process_copy_files(uint64_t clone_flags, struct process_control_block *pcb);
int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb);
@ -134,12 +135,12 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
tsk->flags &= ~PF_KFORK;
// 唤醒进程
process_wakeup(tsk);
// 创建对应procfs文件
rs_procfs_register_pid(tsk->pid);
// 唤醒进程
process_wakeup(tsk);
return retval;
copy_thread_failed:;
@ -175,7 +176,6 @@ int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb)
return 0;
}
/**
* @brief
*
@ -334,6 +334,7 @@ int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb,
child_regs = (struct pt_regs *)(((uint64_t)pcb) + STACK_SIZE - size);
memcpy(child_regs, (void *)current_regs, size);
barrier();
// 然后重写新的栈中每个栈帧的rbp值
process_rewrite_rbp(child_regs, pcb);
@ -349,8 +350,7 @@ int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb,
// 设置子进程的返回值为0
child_regs->rax = 0;
if (pcb->flags & PF_KFORK)
thd->rbp =
(uint64_t)(child_regs + 1); // 设置新的内核线程开始执行时的rbp也就是进入ret_from_system_call时的rbp
thd->rbp = (uint64_t)(child_regs + 1); // 设置新的内核线程开始执行时的rbp也就是进入ret_from_intr时的rbp
else
thd->rbp = (uint64_t)pcb + STACK_SIZE;
@ -361,11 +361,13 @@ int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb,
// 根据是否为内核线程、是否在内核态fork设置进程的开始执行的地址
if (pcb->flags & PF_KFORK)
thd->rip = (uint64_t)ret_from_system_call;
thd->rip = (uint64_t)ret_from_intr;
else if (pcb->flags & PF_KTHREAD && (!(pcb->flags & PF_KFORK)))
thd->rip = (uint64_t)kernel_thread_func;
else
thd->rip = (uint64_t)ret_from_system_call;
thd->rip = (uint64_t)ret_from_intr;
pcb->fp_state = rs_dup_fpstate();
return 0;
}

View File

@ -136,6 +136,7 @@ struct process_control_block
// 如果当前进程等待被迁移到另一个cpu核心上也就是flags中的PF_NEED_MIGRATE被置位
// 该字段存储要被迁移到的目标处理器核心号
uint32_t migrate_to;
void* fp_state;//Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
};
// 将进程的pcb和内核栈融合到一起,8字节对齐

View File

@ -19,6 +19,7 @@
#include <driver/disk/ahci/ahci.h>
#include <driver/usb/usb.h>
#include <driver/video/video.h>
#include <driver/virtio/virtio.h>
#include <exception/gate.h>
#include <ktest/ktest.h>
#include <mm/mmio.h>
@ -26,7 +27,6 @@
#include <sched/sched.h>
#include <syscall/syscall.h>
#include <syscall/syscall_num.h>
#include <driver/virtio/virtio.h>
extern int __rust_demo_func();
// #pragma GCC push_options
// #pragma GCC optimize("O0")
@ -46,6 +46,7 @@ extern struct sighand_struct INITIAL_SIGHAND;
extern void process_exit_sighand(struct process_control_block *pcb);
extern void process_exit_signal(struct process_control_block *pcb);
extern void initial_proc_init_signal(struct process_control_block *pcb);
extern void rs_process_exit_fpstate(struct process_control_block *pcb);
extern int process_init_files();
// 设置初始进程的PCB
@ -410,8 +411,6 @@ load_elf_failed:;
ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
{
// kdebug("do_execve is running...");
// 当前进程正在与父进程共享地址空间,需要创建
// 独立的地址空间才能使新程序正常运行
if (current_pcb->flags & PF_VFORK)
@ -584,7 +583,7 @@ ul initial_kernel_thread(ul arg)
// 若在后面这段代码中触发中断return时会导致段选择子错误从而触发#GP因此这里需要cli
cli();
current_pcb->thread->rip = (ul)ret_from_system_call;
current_pcb->thread->rip = (ul)ret_from_intr;
current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs);
current_pcb->thread->fs = USER_DS | 0x3;
barrier();
@ -616,9 +615,9 @@ ul initial_kernel_thread(ul arg)
*/
void process_exit_notify()
{
wait_queue_wakeup(&current_pcb->parent_pcb->wait_child_proc_exit, PROC_INTERRUPTIBLE);
}
/**
* @brief 退
*
@ -882,6 +881,7 @@ int process_release_pcb(struct process_control_block *pcb)
pcb->next_pcb->prev_pcb = pcb->prev_pcb;
process_exit_sighand(pcb);
process_exit_signal(pcb);
rs_process_exit_fpstate(pcb);
rs_procfs_unregister_pid(pcb->pid);
// 释放当前pcb
kfree(pcb);

View File

@ -6,7 +6,7 @@ use core::{
use alloc::boxed::Box;
use crate::{
arch::asm::current::current_pcb,
arch::{asm::current::current_pcb, fpu::FpState},
filesystem::vfs::file::{File, FileDescriptorVec},
include::bindings::bindings::{
process_control_block, CLONE_FS, EBADF, EFAULT, ENFILE, EPERM, PROC_INTERRUPTIBLE,
@ -151,7 +151,7 @@ impl process_control_block {
};
// 拷贝文件描述符数组
let new_fd_vec: &mut FileDescriptorVec = Box::leak(Box::new(old_fds.clone()));
let new_fd_vec: &mut FileDescriptorVec = Box::leak(old_fds.clone());
self.fds = new_fd_vec as *mut FileDescriptorVec as usize as *mut c_void;
@ -259,7 +259,8 @@ impl process_control_block {
/// 当我们要把一个进程,交给其他机制管理时,那么就应该调用本函数。
///
/// 由于本函数可能造成进程不再被调度因此标记为unsafe
pub unsafe fn mark_sleep_interruptible(&mut self){
#[allow(dead_code)]
pub unsafe fn mark_sleep_interruptible(&mut self) {
self.state = PROC_INTERRUPTIBLE as u64;
}
@ -267,7 +268,8 @@ impl process_control_block {
/// 当我们要把一个进程,交给其他机制管理时,那么就应该调用本函数
///
/// 由于本函数可能造成进程不再被调度因此标记为unsafe
pub unsafe fn mark_sleep_uninterruptible(&mut self){
#[allow(dead_code)]
pub unsafe fn mark_sleep_uninterruptible(&mut self) {
self.state = PROC_UNINTERRUPTIBLE as u64;
}
}
@ -318,4 +320,34 @@ pub extern "C" fn process_exit_files(pcb: &'static mut process_control_block) ->
}
}
/// @brief 复制当前进程的浮点状态
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn rs_dup_fpstate() -> *mut c_void {
// 如果当前进程没有浮点状态,那么就返回一个默认的浮点状态
if current_pcb().fp_state == null_mut() {
return Box::leak(Box::new(FpState::default())) as *mut FpState as usize as *mut c_void;
} else {
// 如果当前进程有浮点状态,那么就复制一个新的浮点状态
let state = current_pcb().fp_state as usize as *mut FpState;
unsafe {
let s = state.as_ref().unwrap();
let state: &mut FpState = Box::leak(Box::new(s.clone()));
return state as *mut FpState as usize as *mut c_void;
}
}
}
/// @brief 释放进程的浮点状态所占用的内存
#[no_mangle]
pub extern "C" fn rs_process_exit_fpstate(pcb: &'static mut process_control_block) {
if pcb.fp_state != null_mut() {
let state = pcb.fp_state as usize as *mut FpState;
unsafe {
drop(Box::from_raw(state));
}
}
}
// =========== 以上为导出到C的函数在将来进程管理模块被完全重构之后需要删掉他们 END ============

View File

@ -11,7 +11,7 @@ use crate::{
process_control_block, pt_regs, EINVAL, EPERM, MAX_CPU_NUM, PF_NEED_MIGRATE, PROC_RUNNING,
SCHED_FIFO, SCHED_NORMAL, SCHED_RR,
},
process::process::process_cpu
process::process::process_cpu,
};
use super::cfs::{sched_cfs_init, SchedulerCFS, __get_cfs_scheduler};

View File

@ -154,6 +154,7 @@ impl SchedulerRT {
return sum as usize;
}
#[allow(dead_code)]
#[inline]
pub fn load_list_len(&mut self, cpu_id: u32) -> usize {
return self.load_list[cpu_id as usize].len();

View File

@ -89,17 +89,6 @@ ul system_call_not_exists(struct pt_regs *regs)
*/
#define SYSCALL_COMMON(syscall_num, symbol) [syscall_num] = symbol,
/**
* @brief sysenter的系统调用函数entry.S中跳转到这里
*
* @param regs 3,rax存储系统调用号
* @return ul
*/
ul system_call_function(struct pt_regs *regs)
{
return system_call_table[regs->rax](regs);
}
/**
* @brief
*
@ -298,13 +287,12 @@ extern uint64_t sys_getdents(struct pt_regs *regs);
*/
uint64_t sys_execve(struct pt_regs *regs)
{
// kdebug("sys_execve");
char *user_path = (char *)regs->r8;
char **argv = (char **)regs->r9;
int path_len = strnlen_user(user_path, PAGE_4K_SIZE);
// kdebug("path_len=%d", path_len);
if (path_len >= PAGE_4K_SIZE)
return -ENAMETOOLONG;
else if (path_len <= 0)
@ -316,12 +304,10 @@ uint64_t sys_execve(struct pt_regs *regs)
memset(path, 0, path_len + 1);
// kdebug("before copy file path from user");
// 拷贝文件路径
strncpy_from_user(path, user_path, path_len);
path[path_len] = '\0';
// kdebug("before do_execve, path = %s", path);
// 执行新的程序
uint64_t retval = do_execve(regs, path, argv, NULL);
@ -362,6 +348,8 @@ uint64_t sys_wait4(struct pt_regs *regs)
return -EINVAL;
// 如果子进程没有退出,则等待其退出
// BUG: 这里存在问题,由于未对进程管理模块加锁,因此可能会出现子进程退出后,父进程还在等待的情况
// 子进程退出后process_exit_notify消息丢失
while (child_proc->state != PROC_ZOMBIE)
wait_queue_sleep_on_interriptible(&current_pcb->wait_child_proc_exit);
@ -402,7 +390,6 @@ ul sys_ahci_end_req(struct pt_regs *regs)
// 系统调用的内核入口程序
void do_syscall_int(struct pt_regs *regs, unsigned long error_code)
{
ul ret = system_call_table[regs->rax](regs);
regs->rax = ret; // 返回码
}

View File

@ -12,8 +12,6 @@
typedef unsigned long (*system_call_t)(struct pt_regs *regs);
extern void ret_from_system_call(void); // 导出从系统调用返回的函数定义在entry.S
extern system_call_t system_call_table[MAX_SYSTEM_CALL_NUM];
// 判断系统调用是否来自用户态

View File

@ -35,7 +35,6 @@ QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot or
QEMU_ARGUMENT+="-s -S -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}"
if [ $flag_can_run -eq 1 ]; then
case "$1" in
--bios)

View File

@ -36,9 +36,8 @@ void print_copyright()
}
int main()
{
{
print_ascii_logo();
print_copyright();
return 0;

View File

@ -486,6 +486,7 @@ int shell_cmd_exec(int argc, char **argv)
char *file_path = get_target_filepath(argv[1], &path_len);
// printf("before execv, path=%s, argc=%d\n", file_path, argc);
execv(file_path, argv);
// printf("after execv, path=%s, argc=%d\n", file_path, argc);
free(argv);
free(file_path);
@ -497,10 +498,8 @@ int shell_cmd_exec(int argc, char **argv)
if (strcmp(argv[argc - 1], "&") != 0)
waitpid(pid, &retval, 0);
else
{
// 输出子进程的pid
printf("[1] %d\n", pid);
}
printf("[1] %d\n", pid); // 输出子进程的pid
free(argv);
}
}

View File

@ -18,11 +18,11 @@
*/
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
bool handle_ok = false;
@ -39,6 +39,7 @@ int main()
printf("registered.\n");
clock_t last = clock();
while (1)
{
if ((clock() - last) / CLOCKS_PER_SEC >= 1)