mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 20:36:48 +00:00
增加x87FPU支持 (#212)
* remove `ret_from_syscall` *修复ps2键盘驱动程序inode在进程fork的时候导致死锁的问题. *更新: VFS每次拷贝文件描述符的时候,都会去调用inode的open函数 --------- Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
parent
2286eda652
commit
64aea4b349
1
DragonOS
Submodule
1
DragonOS
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 45b8371173b070028457f7ee64be33f68b4f9ada
|
@ -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
kernel/src/arch/x86_64/fpu.rs
Normal file
147
kernel/src/arch/x86_64/fpu.rs
Normal 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);
|
||||
}
|
@ -5,3 +5,4 @@ pub mod cpu;
|
||||
pub mod interrupt;
|
||||
pub mod mm;
|
||||
pub mod sched;
|
||||
pub mod fpu;
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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> {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -635,6 +635,7 @@ pub struct MmioFreeRegionList {
|
||||
num_free: i64,
|
||||
}
|
||||
impl MmioFreeRegionList {
|
||||
#[allow(dead_code)]
|
||||
fn new() -> Self {
|
||||
return MmioFreeRegionList {
|
||||
..Default::default()
|
||||
|
@ -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;
|
||||
}
|
@ -136,6 +136,7 @@ struct process_control_block
|
||||
// 如果当前进程等待被迁移到另一个cpu核心上(也就是flags中的PF_NEED_MIGRATE被置位),
|
||||
// 该字段存储要被迁移到的目标处理器核心号
|
||||
uint32_t migrate_to;
|
||||
void* fp_state;//Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
|
||||
};
|
||||
|
||||
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
||||
|
@ -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(¤t_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);
|
||||
|
@ -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 ============
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
|
@ -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(¤t_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; // 返回码
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
// 判断系统调用是否来自用户态
|
||||
|
@ -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)
|
||||
|
@ -36,9 +36,8 @@ void print_copyright()
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
print_ascii_logo();
|
||||
|
||||
print_copyright();
|
||||
|
||||
return 0;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user