diff --git a/kernel/src/cpu/cpu.rs b/kernel/src/cpu/cpu.rs index 738c4f5..cb9f56a 100644 --- a/kernel/src/cpu/cpu.rs +++ b/kernel/src/cpu/cpu.rs @@ -23,9 +23,9 @@ extern "C" fn ap_main() -> ! { setup_gdt(); setup_idt(); setup_lapic(0); + set_cpu_flags(); // TODO: Also calibrate other cores setup_lapic_timer(false); - set_cpu_flags(); unsafe { sti(); } @@ -37,8 +37,10 @@ pub fn set_cpu_flags() { let features = cpuid.get_feature_info().unwrap(); let extended_features = cpuid.get_extended_feature_info().unwrap(); unsafe { - // Time Stamp Disable, SMEP and SMAP - asm!("mov rax, cr4; bts rax, 2; bts rax, 20; bts rax, 21; mov cr4, rax", out("rax") _); + // Numeric Error + asm!("mov rax, cr0; bts rax, 5; mov cr0, rax", out("rax") _); + // Time Stamp Disable, OSFXSR, OSXMMEXCPT, SMEP and SMAP + asm!("mov rax, cr4; bts rax, 2; bts rax, 9; bts rax, 10; bts rax, 20; bts rax, 21; mov cr4, rax", out("rax") _); if features.has_mce() { asm!("mov rax, cr4; bts rax, 6; mov cr4, rax", out("rax") _); } diff --git a/kernel/src/cpu/usermode.s b/kernel/src/cpu/usermode.s index 81944ba..46c46f2 100644 --- a/kernel/src/cpu/usermode.s +++ b/kernel/src/cpu/usermode.s @@ -30,4 +30,5 @@ jump_usermode: xor %r13, %r13 xor %r14, %r14 xor %r15, %r15 + fninit iretq diff --git a/kernel/src/main.rs b/kernel/src/main.rs index be4cc28..72e3d04 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -95,12 +95,12 @@ extern "C" fn early_main(temp_loader_struct: *const LoaderStruct) -> ! { } parse_madt(&early_acpi_tables); setup_hpet(&early_acpi_tables); + set_cpu_flags(); setup_lapic_timer(true); setup_multitasking(); } fn main() { info!("Starting main kernel task..."); - set_cpu_flags(); let mut status = unsafe { AcpiInitializeSubsystem() }; assert_eq!(status, AE_OK); status = unsafe { AcpiInitializeTables(null_mut(), 0, 0) }; diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index d29b329..d1e9c4a 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -1,6 +1,9 @@ -use core::sync::atomic::{AtomicBool, AtomicI64, AtomicU64, AtomicUsize, Ordering}; +use core::{ + arch::x86_64::{_fxrstor64, _fxsave64}, + sync::atomic::{AtomicBool, AtomicI64, AtomicU64, AtomicUsize, Ordering}, +}; -use alloc::{sync::Arc, vec, vec::Vec}; +use alloc::{boxed::Box, sync::Arc, vec, vec::Vec}; use kernel_common::instructions::{cli, get_rflags, hlt, pause, sti}; use crate::{ @@ -30,6 +33,9 @@ pub enum TaskState { SemaphoreBlocked, } +#[repr(align(16))] +struct FXSaveRegion([u8; 512]); + pub struct Task { pub id: usize, pub process: Arc>, @@ -41,6 +47,7 @@ pub struct Task { pub block_on_semaphore: Option>, pub semaphore_requested_count: usize, user_stack: u64, + fxsave_region: Box, } #[repr(C)] @@ -69,6 +76,9 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { if let Some(mut current_task) = current_tasks[lapic_id].take() { current_task.state = *current_state; current_task.user_stack = cpu_data.user_stack; + unsafe { + _fxsave64(current_task.fxsave_region.0.as_mut_ptr()); + } if current_task.task_state == TaskState::Terminated { unsafe { get_kernel_process().lock().address_space.switch(); @@ -95,6 +105,9 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { let kernel_stack = new_task.kernel_stack.as_ptr() as u64 + STACK_SIZE as u64; cpu_data.kernel_stack = kernel_stack; cpu_data.user_stack = new_task.user_stack; + unsafe { + _fxrstor64(new_task.fxsave_region.0.as_ptr()); + } current_tasks[get_current_lapic_id()] = Some(new_task); schedule_timer_interrupt(); } @@ -135,6 +148,7 @@ pub fn create_task(process: Arc>, func: fn()) -> Task { block_on_semaphore: None, semaphore_requested_count: 0, user_stack: 0, + fxsave_region: Box::new(FXSaveRegion([0; 512])), } } fn create_idle_task() { diff --git a/loader/src/main.rs b/loader/src/main.rs index bd88d9a..2772ba6 100644 --- a/loader/src/main.rs +++ b/loader/src/main.rs @@ -58,6 +58,7 @@ fn main() -> Status { let extended_features = cpuid.get_extended_feature_info().unwrap(); assert!(extended_features.has_smap()); assert!(extended_features.has_smep()); + assert!(features.has_sse42()); assert!(cpuid.get_extended_processor_and_feature_identifiers().unwrap().has_syscall_sysret()); let (kernel_start, kernel_entry) = load_kernel(KERNEL); let heap_start = allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, KERNEL_HEAP_INITIAL_SIZE / 0x1000).unwrap().as_ptr() as u64; diff --git a/qemu.sh b/qemu.sh index 71b5b1a..cd5acb8 100755 --- a/qemu.sh +++ b/qemu.sh @@ -2,4 +2,4 @@ # shellcheck disable=SC2068 set -euo pipefail ./build.py -qemu-system-x86_64 -M q35 -accel kvm -cpu qemu64,rdrand,smap,smep,umip -smp 4 -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@ +qemu-system-x86_64 -M q35 -accel kvm -cpu host -smp 4 -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@