Enable hardware floats and save on every context switch
This commit is contained in:
parent
c0d0ad5a1e
commit
cc18a3f7f0
20
src/main.rs
20
src/main.rs
@ -86,7 +86,7 @@ mod start;
|
|||||||
mod tasking;
|
mod tasking;
|
||||||
mod virtual_memory;
|
mod virtual_memory;
|
||||||
|
|
||||||
use core::{ptr, slice};
|
use core::{arch::asm, ptr, slice};
|
||||||
|
|
||||||
use bootinfo::BOOTINFO;
|
use bootinfo::BOOTINFO;
|
||||||
use cast::usize;
|
use cast::usize;
|
||||||
@ -105,7 +105,10 @@ use tar_no_std::TarArchiveRef;
|
|||||||
use tasking::{SleepReason, TASKING};
|
use tasking::{SleepReason, TASKING};
|
||||||
use virtual_memory::{ACTIVE_SPACE, KERNEL_SPACE};
|
use virtual_memory::{ACTIVE_SPACE, KERNEL_SPACE};
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
registers::rflags::{self, RFlags},
|
registers::{
|
||||||
|
control::{Cr0, Cr0Flags, Cr4, Cr4Flags},
|
||||||
|
rflags::{self, RFlags},
|
||||||
|
},
|
||||||
structures::paging::{Page, PageTableFlags},
|
structures::paging::{Page, PageTableFlags},
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
};
|
};
|
||||||
@ -129,6 +132,19 @@ pub fn main() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
rflags::write(rflags_data);
|
rflags::write(rflags_data);
|
||||||
}
|
}
|
||||||
|
// Enable the FPU
|
||||||
|
unsafe {
|
||||||
|
Cr0::update(|cr0| {
|
||||||
|
cr0.remove(Cr0Flags::EMULATE_COPROCESSOR);
|
||||||
|
cr0.insert(Cr0Flags::MONITOR_COPROCESSOR);
|
||||||
|
});
|
||||||
|
Cr4::update(|cr4| {
|
||||||
|
cr4.insert(Cr4Flags::OSFXSR);
|
||||||
|
cr4.insert(Cr4Flags::OSXMMEXCPT_ENABLE);
|
||||||
|
});
|
||||||
|
asm!("FNINIT");
|
||||||
|
tasking::store_initial_fpu_state();
|
||||||
|
}
|
||||||
gdt::init();
|
gdt::init();
|
||||||
Lazy::force(&PHYSICAL_MEMORY);
|
Lazy::force(&PHYSICAL_MEMORY);
|
||||||
Lazy::force(&KERNEL_SPACE);
|
Lazy::force(&KERNEL_SPACE);
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
gdt,
|
gdt, interrupts::{send_ipc_to, REGISTERD_PIDS}, pit, println, virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE}
|
||||||
interrupts::{send_ipc_to, REGISTERD_PIDS},
|
|
||||||
pit, println,
|
|
||||||
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE},
|
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
|
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
|
||||||
use cast::{u64, usize};
|
use cast::{u64, usize};
|
||||||
use core::{
|
use core::{
|
||||||
arch::naked_asm,
|
arch::{asm, naked_asm}, ptr::{addr_of, addr_of_mut}, sync::atomic::{AtomicBool, Ordering}
|
||||||
ptr::{addr_of, addr_of_mut},
|
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
|
||||||
};
|
};
|
||||||
use crossbeam_queue::SegQueue;
|
use crossbeam_queue::SegQueue;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use spin::{Lazy, Mutex, RwLock};
|
use spin::{Lazy, Mutex, Once, RwLock};
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
structures::paging::{Page, PageTableFlags},
|
structures::paging::{Page, PageTableFlags},
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
@ -88,6 +83,36 @@ pub enum SleepReason {
|
|||||||
TimeSleep,
|
TimeSleep,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INITIAL_FPU_STATE: Once<FpuState> = Once::new();
|
||||||
|
|
||||||
|
pub fn store_initial_fpu_state() {
|
||||||
|
let mut state = FpuState::new();
|
||||||
|
state.save();
|
||||||
|
INITIAL_FPU_STATE.call_once(|| state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(align(16))]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct FpuState {
|
||||||
|
state: [u8; 512]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FpuState {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: [0; 512],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save(&mut self) {
|
||||||
|
unsafe { asm!("fxsave [rax]", in("rax") &mut self.state) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self) {
|
||||||
|
unsafe { asm!("fxrstor [rax]", in("rax") &self.state) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
address_space: Option<AddressSpace>,
|
address_space: Option<AddressSpace>,
|
||||||
@ -176,6 +201,7 @@ impl Process {
|
|||||||
kernel_stack,
|
kernel_stack,
|
||||||
sleeping: RwLock::new(sleeping),
|
sleeping: RwLock::new(sleeping),
|
||||||
tls_values: Mutex::new(vec![0; self.num_tls]),
|
tls_values: Mutex::new(vec![0; self.num_tls]),
|
||||||
|
fpu_state: Mutex::new(*INITIAL_FPU_STATE.get().unwrap()),
|
||||||
};
|
};
|
||||||
let idx = self.threads.write().insert(thread);
|
let idx = self.threads.write().insert(thread);
|
||||||
self.num_threads += 1;
|
self.num_threads += 1;
|
||||||
@ -194,6 +220,7 @@ pub struct Thread {
|
|||||||
kernel_esp: *mut usize,
|
kernel_esp: *mut usize,
|
||||||
kernel_esp_top: VirtAddr,
|
kernel_esp_top: VirtAddr,
|
||||||
tls_values: Mutex<Vec<u64>>,
|
tls_values: Mutex<Vec<u64>>,
|
||||||
|
fpu_state: Mutex<FpuState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IpcMessage {
|
pub struct IpcMessage {
|
||||||
@ -351,9 +378,11 @@ impl Tasking {
|
|||||||
if self.current_thread(|thread| thread.sleeping.read().is_none()) {
|
if self.current_thread(|thread| thread.sleeping.read().is_none()) {
|
||||||
self.ready_to_run.lock().push_back((current_pid, self.current_tid().unwrap()));
|
self.ready_to_run.lock().push_back((current_pid, self.current_tid().unwrap()));
|
||||||
}
|
}
|
||||||
|
self.current_thread(|thread| thread.fpu_state.lock().save());
|
||||||
let curr_stack = self.current_thread_mut(|thread| addr_of_mut!(thread.kernel_esp));
|
let curr_stack = self.current_thread_mut(|thread| addr_of_mut!(thread.kernel_esp));
|
||||||
*self.current_pid.write() = Some(next_process_pid);
|
*self.current_pid.write() = Some(next_process_pid);
|
||||||
*self.current_tid.write() = Some(next_process_tid);
|
*self.current_tid.write() = Some(next_process_tid);
|
||||||
|
self.current_thread(|thread| thread.fpu_state.lock().load());
|
||||||
let kernel_esp = self.current_thread(|thread| {
|
let kernel_esp = self.current_thread(|thread| {
|
||||||
gdt::set_tss_stack(thread.kernel_esp_top);
|
gdt::set_tss_stack(thread.kernel_esp_top);
|
||||||
thread.kernel_esp
|
thread.kernel_esp
|
||||||
@ -437,6 +466,7 @@ impl Tasking {
|
|||||||
.expect("Non-current process has active page table")
|
.expect("Non-current process has active page table")
|
||||||
.activate();
|
.activate();
|
||||||
});
|
});
|
||||||
|
self.current_thread(|thread| thread.fpu_state.lock().load());
|
||||||
let kernel_esp = self.current_thread_mut(|thread| {
|
let kernel_esp = self.current_thread_mut(|thread| {
|
||||||
gdt::set_tss_stack(thread.kernel_esp_top);
|
gdt::set_tss_stack(thread.kernel_esp_top);
|
||||||
thread.kernel_esp
|
thread.kernel_esp
|
||||||
@ -493,6 +523,7 @@ impl Tasking {
|
|||||||
}
|
}
|
||||||
*self.current_pid.write() = Some(next_process_pid);
|
*self.current_pid.write() = Some(next_process_pid);
|
||||||
*self.current_tid.write() = Some(next_process_tid);
|
*self.current_tid.write() = Some(next_process_tid);
|
||||||
|
self.current_thread(|thread| thread.fpu_state.lock().load());
|
||||||
let kernel_esp = self.current_thread_mut(|thread| {
|
let kernel_esp = self.current_thread_mut(|thread| {
|
||||||
gdt::set_tss_stack(thread.kernel_esp_top);
|
gdt::set_tss_stack(thread.kernel_esp_top);
|
||||||
thread.kernel_esp
|
thread.kernel_esp
|
||||||
|
Loading…
x
Reference in New Issue
Block a user