浏览代码

增加x87FPU支持 (#212)

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

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>
Gou Ngai 2 年之前
父节点
当前提交
64aea4b349

+ 1 - 0
DragonOS

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

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

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

+ 147 - 0
kernel/src/arch/x86_64/fpu.rs

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

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

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

+ 28 - 16
kernel/src/driver/keyboard/ps2_keyboard.rs

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

+ 3 - 8
kernel/src/exception/entry.S

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

+ 76 - 40
kernel/src/exception/irq.c

@@ -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,
 };
 
 /**

+ 2 - 2
kernel/src/exception/trap.c

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

+ 38 - 3
kernel/src/filesystem/vfs/file.rs

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

+ 22 - 1
kernel/src/ipc/signal.rs

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

+ 2 - 0
kernel/src/ipc/signal_types.rs

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

+ 1 - 0
kernel/src/mm/mmio_buddy.rs

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

+ 10 - 8
kernel/src/process/fork.c

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

+ 1 - 0
kernel/src/process/proc-types.h

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

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

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

+ 36 - 4
kernel/src/process/process.rs

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

+ 1 - 1
kernel/src/sched/core.rs

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

+ 1 - 0
kernel/src/sched/rt.rs

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

+ 3 - 16
kernel/src/syscall/syscall.c

@@ -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; // 返回码
 }

+ 0 - 2
kernel/src/syscall/syscall.h

@@ -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];
 
 // 判断系统调用是否来自用户态

+ 0 - 1
tools/run-qemu.sh

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

+ 1 - 2
user/apps/about/about.c

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

+ 3 - 4
user/apps/shell/cmd.c

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

+ 2 - 1
user/apps/test_signal/main.c

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