Skip to content
Merged

Fpu #212

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DragonOS
Submodule DragonOS added at 45b837
4 changes: 4 additions & 0 deletions kernel/src/arch/x86_64/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
147 changes: 147 additions & 0 deletions kernel/src/arch/x86_64/fpu.rs
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions kernel/src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub mod cpu;
pub mod interrupt;
pub mod mm;
pub mod sched;
pub mod fpu;
44 changes: 28 additions & 16 deletions kernel/src/driver/keyboard/ps2_keyboard.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::sync::atomic::AtomicI32;

use alloc::sync::{Arc, Weak};

use crate::{
Expand All @@ -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 {
Expand Down Expand Up @@ -53,16 +54,19 @@ 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;
}
}

impl DeviceINode for LockedPS2KeyBoardInode {
fn set_fs(&self, fs: Weak<DevFS>) {
self.0.lock().fs = fs;
self.0.write().fs = fs;
}
}

Expand All @@ -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(
Expand Down Expand Up @@ -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(());
}

Expand All @@ -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;
Expand All @@ -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 {
Expand Down
11 changes: 3 additions & 8 deletions kernel/src/exception/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
Loading