diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index cf178c977d..46fd99b4fe 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -108,6 +108,8 @@ void i386_fnsave(void *fpu_state); void i386_fxsave(void *fpu_state); void i386_frstor(const void *fpu_state); void i386_fxrstor(const void *fpu_state); +void i386_fnsave_swap(void *old_fpu_state, const void *new_fpu_state); +void i386_fxsave_swap(void *old_fpu_state, const void *new_fpu_state); uint32 x86_read_ebp(); uint32 x86_read_cr0(); void x86_write_cr0(uint32 value); diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index 8a5802b6a5..19cd41e5a2 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -10,7 +10,6 @@ #include -#include #include #include @@ -25,9 +24,6 @@ typedef union cpu_ent { int preempted; timer quantum_timer; - // tells which thread's fpu state we hold - struct thread *fpu_state_thread; - // keeping track of CPU activity bigtime_t active_time; bigtime_t last_kernel_time; diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 5c9c8d006e..b7dd401425 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -139,7 +139,6 @@ struct thread { int32 state; int32 next_state; union cpu_ent *cpu; - union cpu_ent *fpu_cpu; /* this cpu holds our fpu state */ sigset_t sig_pending; sigset_t sig_block_mask; diff --git a/src/system/kernel/arch/x86/arch_cpu.c b/src/system/kernel/arch/x86/arch_cpu.c index 1ffb9ada23..b4aab754f5 100644 --- a/src/system/kernel/arch/x86/arch_cpu.c +++ b/src/system/kernel/arch/x86/arch_cpu.c @@ -43,8 +43,7 @@ struct set_mtrr_parameter { extern void reboot(void); // from arch_x86.S -void (*gX86SaveFPUFunc)(void *state); -void (*gX86RestoreFPUFunc)(const void *state); +void (*gX86SwapFPUFunc)(void *oldState, const void *newState); bool gHasSSE = false; static struct tss **sTSS; @@ -184,9 +183,9 @@ init_sse(void) // enable OS support for SSE x86_write_cr4(x86_read_cr4() | CR4_OS_FXSR | CR4_OS_XMM_EXCEPTION); + x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU)); - gX86SaveFPUFunc = i386_fxsave; - gX86RestoreFPUFunc = i386_fxrstor; + gX86SwapFPUFunc = i386_fxsave_swap; gHasSSE = true; } @@ -237,8 +236,9 @@ status_t arch_cpu_preboot_init(kernel_args *args) { write_dr3(0); - gX86SaveFPUFunc = i386_fnsave; - gX86RestoreFPUFunc = i386_frstor; + + x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU)); + gX86SwapFPUFunc = i386_fnsave_swap; return B_OK; } @@ -333,9 +333,6 @@ arch_cpu_init_post_vm(kernel_args *args) DT_DATA_WRITEABLE, DPL_USER); } - // enable lazy FPU state - x86_write_cr0((x86_read_cr0() & ~CR0_FPU_EMULATION) | CR0_MONITOR_FPU); - // setup SSE2/3 support init_sse(); diff --git a/src/system/kernel/arch/x86/arch_int.c b/src/system/kernel/arch/x86/arch_int.c index 2b4180afcd..3ce42e4115 100644 --- a/src/system/kernel/arch/x86/arch_int.c +++ b/src/system/kernel/arch/x86/arch_int.c @@ -6,7 +6,6 @@ * Distributed under the terms of the NewOS License. */ -#include #include #include #include @@ -37,10 +36,6 @@ # define TRACE(x) ; #endif -// from arch_cpu.c -extern void (*gX86SaveFPUFunc)(void *state); -extern void (*gX86RestoreFPUFunc)(const void *state); - // Definitions for the PIC 8259 controller // (this is not a complete list, only what we're actually using) @@ -360,6 +355,7 @@ i386_handle_trap(struct iframe frame) case 2: // NMI Interrupt case 9: // Coprocessor Segment Overrun + case 7: // Device Not Available Exception (#NM) case 10: // Invalid TSS Exception (#TS) case 11: // Segment Not Present (#NP) case 12: // Stack Fault Exception (#SS) @@ -367,25 +363,6 @@ i386_handle_trap(struct iframe frame) fatal_exception(&frame); break; - case 7: // Device Not Available Exception (#NM) - { - // raised to lazily save and restore FPU states - cpu_ent *cpu = get_cpu_struct(); - - asm volatile ("clts;"); - if (cpu->info.fpu_state_thread != thread) { - if (cpu->info.fpu_state_thread) { - gX86SaveFPUFunc(cpu->info.fpu_state_thread->arch_info.fpu_state); - cpu->info.fpu_state_thread->fpu_cpu = NULL; - } - - gX86RestoreFPUFunc(thread->arch_info.fpu_state); - cpu->info.fpu_state_thread = thread; - thread->fpu_cpu = cpu; - } - break; - } - case 8: // Double Fault Exception (#DF) { struct tss *tss = x86_get_main_tss(); diff --git a/src/system/kernel/arch/x86/arch_thread.c b/src/system/kernel/arch/x86/arch_thread.c index 7f1f78345c..d66f5b8b42 100644 --- a/src/system/kernel/arch/x86/arch_thread.c +++ b/src/system/kernel/arch/x86/arch_thread.c @@ -28,13 +28,12 @@ #endif -#define CR0_TASK_SWITCHED (1UL << 3) - // from arch_interrupts.S extern void i386_stack_init(struct farcall *interrupt_stack_offset); extern void i386_restore_frame_from_syscall(struct iframe frame); // from arch_cpu.c +extern void (*gX86SwapFPUFunc)(void *oldState, const void *newState); extern bool gHasSSE; static struct arch_thread sInitialState _ALIGNED(16); @@ -286,7 +285,7 @@ arch_thread_context_switch(struct thread *from, struct thread *to) if (to->team->address_space != NULL) i386_reinit_user_debug_after_context_switch(to); - x86_write_cr0(x86_read_cr0() | CR0_TASK_SWITCHED); + gX86SwapFPUFunc(from->arch_info.fpu_state, to->arch_info.fpu_state); i386_context_switch(&from->arch_info, &to->arch_info, newPageDirectory); } diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/arch_x86.S index 8ae47882c4..af5688f0bf 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/arch_x86.S @@ -45,6 +45,22 @@ FUNCTION(i386_fxrstor): fxrstor (%eax) ret +/* void i386_fsave_swap(void *old_fpu_state, const void *new_fpu_state); */ +FUNCTION(i386_fnsave_swap): + movl 4(%esp),%eax + fnsave (%eax) + movl 8(%esp),%eax + frstor (%eax) + ret + +/* void i386_fxsave_swap(void *old_fpu_state, const void *new_fpu_state); */ +FUNCTION(i386_fxsave_swap): + movl 4(%esp),%eax + fxsave (%eax) + movl 8(%esp),%eax + fxrstor (%eax) + ret + /* uint32 x86_read_ebp(); */ FUNCTION(x86_read_ebp): movl %ebp, %eax diff --git a/src/system/kernel/thread.c b/src/system/kernel/thread.c index d590da6f34..ee68543538 100644 --- a/src/system/kernel/thread.c +++ b/src/system/kernel/thread.c @@ -872,12 +872,6 @@ thread_exit2(void *_args) user_debug_thread_deleted(args.original_team_id, args.thread->id); } - // remove us as the fpu state owner if we are one - if (args.thread->fpu_cpu) { - args.thread->fpu_cpu->info.fpu_state_thread = NULL; - args.thread->fpu_cpu = NULL; - } - // return the death stack and reschedule one last time put_death_stack_and_reschedule(args.death_stack);