Commit cb3d8a9c authored by Nifou's avatar Nifou

Better context switch

*  Save the SSE state by saving the FX register
*  Save the RDX register
parent d6542fc2
Pipeline #168246771 passed with stages
in 8 minutes and 51 seconds
......@@ -82,7 +82,7 @@ dependencies = [
[[package]]
name = "obsidianos-kernel"
version = "0.0.1"
version = "0.0.2"
dependencies = [
"bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
......
......@@ -31,6 +31,7 @@ use crate::{
tasking::{
memory::MemoryArea,
scheduler::{FIRST_TIME, PROCESSES, SCHEDULER},
context::Fx,
},
};
......@@ -65,7 +66,8 @@ pub extern "x86-interrupt" fn timer_interrupt_handler(_: &mut InterruptStackFram
llvm_asm!("
sub rsp, 16
push rdi
push rsi"
push rsi
push rdx"
: : : : "intel", "volatile");
}
......@@ -90,6 +92,7 @@ pub extern "x86-interrupt" fn timer_interrupt_handler(_: &mut InterruptStackFram
mov r15, rdi
// Restore the saved registers
pop rdx
pop rsi
pop rdi
......@@ -118,6 +121,10 @@ pub extern "x86-interrupt" fn timer_interrupt_handler(_: &mut InterruptStackFram
:
: "intel", "volatile");
}
// Save the SSE state
let save_fx = || Fx::save(SCHEDULER.get().current().unwrap().fx);
save_fx();
} else {
FIRST_TIME.store(false, Ordering::Relaxed);
}
......
......@@ -15,7 +15,10 @@
* along with this program. If not, see https://www.gnu.org/licenses.
*/
//! A trait which make the addition of other scheduler algorithms easier
use super::thread::{Thread, Tid};
use super::{
thread::{Thread, Tid},
context::Fx,
};
/// A trait which defines the common functions used in a scheduler algorithm
pub trait SchedulerAlgo {
......@@ -47,6 +50,14 @@ pub trait SchedulerAlgo {
fn switch(&mut self) {
// Choose the next thread
if let Some(thread) = self.choose() {
if thread.first_time {
// Init the SSE state
Fx::init();
self.current_mut().unwrap().first_time = false;
} else {
Fx::restore(thread.fx);
}
unsafe {
// Change the stack to use the new context
llvm_asm!("mov rsp, rax" : : "{rax}"(thread.kstack) : : "intel", "volatile");
......
......@@ -112,3 +112,23 @@ impl core::default::Default for Registers {
}
}
}
/// The FX register which saves the SSE state
pub struct Fx;
impl Fx {
/// Init the SSE state
pub fn init() {
unsafe { llvm_asm!("fninit" : : : : "intel", "volatile"); }
}
/// Save the SSE state
pub fn save(addr: u64) {
unsafe { llvm_asm!("fxsave [$0]" : : "r"(addr) : : "intel", "volatile"); }
}
/// Restore the SSE state
pub fn restore(addr: u64) {
unsafe { llvm_asm!("fxrstor [$0]" : : "r"(addr) : : "intel", "volatile"); }
}
}
......@@ -44,6 +44,7 @@ use crate::{
pub static NEXT_TID: AtomicUsize = AtomicUsize::new(0);
const KSTACK_SIZE: usize = 4096;
const FX_SIZE: usize = 512;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// A thread ID
......@@ -63,6 +64,9 @@ pub struct Thread {
/// Kernel stack used to store the thread's context
pub kstack: usize,
/// The save of the SSE state
pub fx: u64,
}
impl Thread {
......@@ -70,6 +74,8 @@ impl Thread {
pub fn new(process: Pid, rip: usize, cr3: usize) -> Self {
let kstack_pointer =
Box::into_raw(unsafe { Box::from_raw(HEAP_ALLOCATOR.alloc(Layout::from_size_align_unchecked(KSTACK_SIZE, 4096)) as *mut [u8; KSTACK_SIZE]) }) as u64 + KSTACK_SIZE as u64;
let fx =
Box::into_raw(unsafe { Box::from_raw(HEAP_ALLOCATOR.alloc(Layout::from_size_align_unchecked(FX_SIZE, 16)) as *mut [u8; KSTACK_SIZE]) }) as u64;
// Create a new set of registers
let mut regs = Registers::default();
......@@ -95,6 +101,7 @@ impl Thread {
first_time: true,
process,
kstack: sp,
fx,
}
}
......@@ -107,6 +114,8 @@ impl Thread {
pub fn fork(process: Pid, mut regs: Registers) -> (Self, Mappings) {
let kstack_pointer =
Box::into_raw(unsafe { Box::from_raw(HEAP_ALLOCATOR.alloc(Layout::from_size_align_unchecked(KSTACK_SIZE, 4096)) as *mut [u8; KSTACK_SIZE]) }) as u64 + KSTACK_SIZE as u64;
let fx =
Box::into_raw(unsafe { Box::from_raw(HEAP_ALLOCATOR.alloc(Layout::from_size_align_unchecked(FX_SIZE, 16)) as *mut [u8; KSTACK_SIZE]) }) as u64;
// Set 0 in rax (return value of the `fork` syscall in the child process)
regs.rax = 0;
......@@ -137,6 +146,7 @@ impl Thread {
first_time: true,
process,
kstack: sp,
fx,
},
mapping,
)
......
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