Commit 1d914fce authored by Nifou's avatar Nifou

Save the state of SSE registers

parent 59825c88
......@@ -28,7 +28,6 @@
#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#[macro_use]
extern crate alloc;
......
......@@ -26,7 +26,7 @@ const STDERR: usize = 2;
impl<'a> Syscall<'a> {
/// Write to the corresponding file descriptor
pub fn write(&self, fd: usize, buf: usize, count: usize) -> usize {
pub fn write(&mut self, fd: usize, buf: usize, count: usize) -> usize {
match fd {
STDIN | STDOUT | STDERR => {
let content = unsafe { from_utf8(from_raw_parts(buf as *const u8, count)) }
......
......@@ -162,7 +162,6 @@ const WRITE: usize = 1;
const EXIT: usize = 60;
/// A structure used to call the right handler for each syscall
#[derive(Debug)]
pub struct Syscall<'a> {
stack: &'a mut SyscallStack,
process: &'a mut Process,
......
......@@ -14,14 +14,25 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses.
*/
//! The context of a process (its registers and its stack).
//! The context of a process (its registers, its stack, the SSE state, ...).
//! See [OSDEV](https://wiki.osdev.org/Context_Switching)
use alloc::{
prelude::v1::Box,
alloc::Layout,
};
use core::alloc::GlobalAlloc;
use crate::memory::heap::HEAP_ALLOCATOR;
use super::registers::*;
#[derive(PartialEq, Clone, Copy, Debug)]
/// The size of SSE, x87 FPU, and MMX states in memory (in the FX register)
pub const FX_AREA_SIZE: usize = 512;
#[derive(Clone)]
/// The context of a process (its registers and its stack).
pub struct Context {
regs: Registers,
sse_state: Box<[u8; FX_AREA_SIZE]>,
}
impl Context {
......@@ -31,7 +42,12 @@ impl Context {
regs.rsp = rsp; // Set stack
regs.rip = rip; // Set entry
Self { regs }
Self {
regs,
sse_state: unsafe {
Box::from_raw(HEAP_ALLOCATOR.alloc(Layout::from_size_align_unchecked(512, 16)) as *mut [u8; 512])
},
}
}
/// Save the current registers in this context
......@@ -58,10 +74,13 @@ impl Context {
self.regs.r14 = R14::get();
self.regs.r15 = R15::get();
self.regs.rflags = Rflags::get();
// Save the SSE state
Fx::save(self.sse_state.as_ptr() as u64);
}
/// Load the registers of this context to the registers of the CPU
pub fn load(&self) {
pub fn load(&self, first_time: bool) {
Rax::set(self.regs.rax);
Rbx::set(self.regs.rbx);
Rcx::set(self.regs.rcx);
......@@ -79,6 +98,13 @@ impl Context {
R14::set(self.regs.r14);
R15::set(self.regs.r15);
Rflags::set(self.regs.rflags);
// Load the SSE state
if first_time {
Fx::init();
} else {
Fx::restore(self.sse_state.as_ptr() as u64);
}
}
/// Get the rip register (which indicates the next address which will be executed)
......
......@@ -39,7 +39,7 @@ pub enum ProcessState {
}
/// The representation of a process with its memory, its registers, ...
#[derive(PartialEq, Debug, Clone)]
#[derive(Clone)]
pub struct Process {
/// The context of this process
pub ctx: Context,
......@@ -52,6 +52,9 @@ pub struct Process {
/// Info about the process (arguments, environment, ...)
pub info: ProcessInfo,
/// Whether or not this process was already chosen by the scheduler
pub first_time: bool,
}
impl Process {
......@@ -67,6 +70,7 @@ impl Process {
state: ProcessState::Alive,
memory: ProcessMemory::new(),
info,
first_time: true,
};
// Add the mappings in the process' page table
......
......@@ -447,3 +447,35 @@ impl Rflags {
value
}
}
#[derive(Debug)]
/// Fx register
pub struct Fx();
impl Fx {
/// Restore the SSE state
pub fn restore(addr: u64) {
unsafe {
llvm_asm!("fxrstor [$0]"
:
: "r"(addr)
: "memory"
: "intel", "volatile");
}
}
/// Save the SSE state
pub fn save(addr: u64) {
unsafe {
llvm_asm!("fxsave [$0]"
:
: "r"(addr)
: "memory"
: "intel", "volatile");
}
}
/// Init the SSE state
pub fn init() {
unsafe { llvm_asm!("fninit") }
}
}
......@@ -27,7 +27,6 @@ lazy_static! {
pub static ref SCHEDULER: Mutex<Scheduler> = Mutex::new(Scheduler::new());
}
#[derive(Debug)]
/// A Round Robin scheduler which chooses the next process to be running
pub struct Scheduler {
current_thread: Option<usize>,
......@@ -75,9 +74,10 @@ impl Scheduler {
// After switch
let current_thread = self.current_thread.unwrap();
let first_time = self.threads[current_thread].first_time;
// Load new context
self.threads[current_thread].ctx.load();
self.threads[current_thread].ctx.load(first_time);
// Switch to the process' page table
let rip = self.threads[current_thread].ctx.get_rip();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment