diff --git a/kernel/arch/sse.S b/kernel/arch/sse.S new file mode 100644 index 0000000..1d6e0ad --- /dev/null +++ b/kernel/arch/sse.S @@ -0,0 +1,45 @@ +#include + +.intel_syntax noprefix + +.global sse_init +sse_init: + mov rax, cr0 + and ax, 0xFFFF-CR0_EM + or ax, CR0_MP + mov cr0, rax + + mov rax, cr4 + or ax, CR4_OSFXSR + or ax, CR4_OSXMMEXCPT + mov cr4, rax + + ret + +.global sse_save +sse_save: + movabs rax, offset _sse_buffer + fxsave [rax] + movabs rsi, offset _sse_buffer + mov rdx, 512 + call memcpy + ret + +.global sse_restore +sse_restore: + mov rsi, rdi + movabs rdi, offset _sse_buffer + mov rdx, 512 + call memcpy + movabs rax, offset _sse_buffer + fxrstor [rax] + ret + + +.section .data +.align 16 +_sse_buffer: + .rept 512 + .byte 0 + .endr + diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index aa6efa6..4163b16 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -9,6 +9,7 @@ #include #include #include +#include void thread_function() { @@ -36,6 +37,7 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) acpi_init(); apic_init(); ioapic_init(); + sse_init(); process_t *p1 = process_spawn(0); diff --git a/kernel/include/registers.h b/kernel/include/registers.h index b350030..e250a9f 100644 --- a/kernel/include/registers.h +++ b/kernel/include/registers.h @@ -1,8 +1,16 @@ #pragma once +#ifndef __ASSEMBLER__ void load_idt(void *); uint64_t read_cr0(); uint64_t read_cr2(); uint64_t read_cr3(); void write_cr3(uint64_t); uint64_t read_cr4(); +#endif + +#define CR0_MP (1<<1) +#define CR0_EM (1<<2) + +#define CR4_OSFXSR (1<<9) +#define CR4_OSXMMEXCPT (1<<10) diff --git a/kernel/include/sse.h b/kernel/include/sse.h new file mode 100644 index 0000000..ec15b66 --- /dev/null +++ b/kernel/include/sse.h @@ -0,0 +1,6 @@ +#pragma once + +void sse_init(); + +void sse_save(uint8_t *addr); +void sse_restore(uint8_t *addr); diff --git a/kernel/include/thread.h b/kernel/include/thread.h index abee69c..75d321a 100644 --- a/kernel/include/thread.h +++ b/kernel/include/thread.h @@ -11,6 +11,7 @@ typedef struct thread_st uint64_t stack_pointer; // Top of the kernel stack for thread uint64_t tid; uint64_t state; + uint8_t sse_registers[512]; process_t *process; LIST(struct thread_st, process_threads); LIST(struct thread_st, ready_queue); diff --git a/kernel/interrupts/ioapic.c b/kernel/interrupts/ioapic.c index 44dc1ba..c4ef50b 100644 --- a/kernel/interrupts/ioapic.c +++ b/kernel/interrupts/ioapic.c @@ -86,6 +86,4 @@ void ioapic_init() vmm_set_page(0, (uintptr_t)P2V(IOAPIC_BASE), IOAPIC_BASE, PAGE_PRESENT | PAGE_WRITE); for(int i = 0; i < 24; i++) ioapic_route(i, IOAPIC_DEST_LOGICAL | IOAPIC_DELIVERY_LOWEST, 0xFF, INT_IRQ0+i); - - IRQ_UNMASK(IRQ_KEYBOARD); } diff --git a/kernel/proc/scheduler.c b/kernel/proc/scheduler.c index d0d2363..1c78bf8 100644 --- a/kernel/proc/scheduler.c +++ b/kernel/proc/scheduler.c @@ -1,6 +1,7 @@ #include #include #include +#include LIST(thread_t, ready_queue); @@ -60,6 +61,7 @@ void scheduler() new->state = THREAD_STATE_RUNNING; set_last_thread(new); switch_process(new->process); + sse_restore(new->sse_registers); switch_thread(scheduler_th, new); } } @@ -70,6 +72,11 @@ void schedule() thread_t *old = get_current_thread(); + if(old) + { + sse_save(old->sse_registers); + } + switch_process(0); switch_thread(old, scheduler_th); }