diff options
-rw-r--r-- | Kernel/Process.cpp | 8 | ||||
-rw-r--r-- | Kernel/Process.h | 6 | ||||
-rw-r--r-- | Kernel/Scheduler.cpp | 2 | ||||
-rw-r--r-- | Kernel/Scheduler.h | 1 | ||||
-rw-r--r-- | Kernel/i386.cpp | 26 | ||||
-rw-r--r-- | Kernel/i386.h | 11 | ||||
-rw-r--r-- | Kernel/init.cpp | 4 | ||||
-rw-r--r-- | LibGUI/GButton.cpp | 1 |
8 files changed, 50 insertions, 9 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 2582637591..37fdd3a226 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -258,6 +258,9 @@ Process* Process::fork(RegisterDump& regs) child->m_tss.gs = regs.gs; child->m_tss.ss = regs.ss_if_crossRing; + child->m_fpu_state = m_fpu_state; + child->m_has_used_fpu = m_has_used_fpu; + #ifdef FORK_DEBUG dbgprintf("fork: child will begin executing at %w:%x with stack %w:%x\n", child->m_tss.cs, child->m_tss.eip, child->m_tss.ss, child->m_tss.esp); #endif @@ -588,6 +591,8 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring , m_tty(tty) , m_ppid(ppid) { + memset(&m_fpu_state, 0, sizeof(FPUState)); + m_gids.set(m_gid); if (fork_parent) { @@ -698,6 +703,9 @@ Process::~Process() ProcFS::the().remove_process(*this); system.nprocess--; + if (g_last_fpu_process == this) + g_last_fpu_process = nullptr; + if (selector()) gdt_free_entry(selector()); diff --git a/Kernel/Process.h b/Kernel/Process.h index 87321a6660..1949ba08d0 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -268,6 +268,10 @@ public: bool wakeup_requested() { return m_wakeup_requested; } void request_wakeup() { m_wakeup_requested = true; } + FPUState& fpu_state() { return m_fpu_state; } + bool has_used_fpu() const { return m_has_used_fpu; } + void set_has_used_fpu(bool b) { m_has_used_fpu = b; } + private: friend class MemoryManager; friend class Scheduler; @@ -303,6 +307,7 @@ private: dword m_wakeupTime { 0 }; TSS32 m_tss; TSS32 m_tss_to_resume_kernel; + FPUState m_fpu_state; struct FileDescriptorAndFlags { operator bool() const { return !!descriptor; } void clear() { descriptor = nullptr; flags = 0; } @@ -372,6 +377,7 @@ private: int m_next_window_id { 1 }; dword m_wakeup_requested { false }; + bool m_has_used_fpu { false }; }; extern Process* current; diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 54d137421b..444c7d50ae 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -8,6 +8,7 @@ static const dword time_slice = 5; // *10 = 50ms Process* current; +Process* g_last_fpu_process; static Process* s_colonel_process; static bool s_in_yield; @@ -299,6 +300,7 @@ void Scheduler::initialize() initialize_redirection(); s_colonel_process = Process::create_kernel_process("colonel", nullptr); current = nullptr; + g_last_fpu_process = nullptr; s_in_yield = false; load_task_register(s_redirection.selector); } diff --git a/Kernel/Scheduler.h b/Kernel/Scheduler.h index 466de2bbe4..813939f5bb 100644 --- a/Kernel/Scheduler.h +++ b/Kernel/Scheduler.h @@ -6,6 +6,7 @@ class Process; struct RegisterDump; extern Process* current; +extern Process* g_last_fpu_process; class Scheduler { public: diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index 4a0d1faeb8..5b7268fc85 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -6,6 +6,7 @@ #include "MemoryManager.h" #include "IRQHandler.h" #include "PIC.h" +#include "Scheduler.h" //#define PAGE_FAULT_DEBUG @@ -150,13 +151,31 @@ void exception_6_handler(RegisterDump& regs) current->crash(); } -// 7: FPU exception +// 7: FPU not available exception EH_ENTRY_NO_CODE(7); void exception_7_handler(RegisterDump& regs) { (void)regs; + + asm volatile("clts"); + if (g_last_fpu_process == current) + return; + if (g_last_fpu_process) { + asm volatile("fnsave %0":"=m"(g_last_fpu_process->fpu_state())); + } else { + asm volatile("fnclex"); + } + g_last_fpu_process = current; + + if (current->has_used_fpu()) { + asm volatile("frstor %0"::"m"(current->fpu_state())); + } else { + asm volatile("fninit"); + current->set_has_used_fpu(true); + } + #ifdef FPU_EXCEPTION_DEBUG - kprintf("%s FPU exception: %u(%s)\n", current->isRing0() ? "Kernel" : "Process", current->pid(), current->name().characters()); + kprintf("%s FPU not available exception: %u(%s)\n", current->isRing0() ? "Kernel" : "Process", current->pid(), current->name().characters()); word ss; dword esp; @@ -173,9 +192,6 @@ void exception_7_handler(RegisterDump& regs) kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx); kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi); #endif - - // FIXME: Do stuff. - asm volatile("clts"); } diff --git a/Kernel/i386.h b/Kernel/i386.h index d48c7b481e..0b7ff5dbeb 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -202,6 +202,17 @@ struct RegisterDumpWithExceptionCode { word ss_if_crossRing; } PACKED; +struct FPUState { + dword cwd; + dword swd; + dword twd; + dword fip; + dword fcs; + dword foo; + dword fos; + dword st[20]; +}; + inline constexpr dword pageBaseOf(dword address) { return address & 0xfffff000; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 0e1f835d8f..4df345664e 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -138,10 +138,6 @@ void init() gdt_init(); idt_init(); -#ifndef NO_FPU - asm volatile("fninit"); -#endif - VFS::initialize_globals(); vfs = new VFS; diff --git a/LibGUI/GButton.cpp b/LibGUI/GButton.cpp index 3eea022f3a..cee19019d0 100644 --- a/LibGUI/GButton.cpp +++ b/LibGUI/GButton.cpp @@ -42,6 +42,7 @@ void GButton::paint_event(GPaintEvent&) } else { // Base painter.fill_rect({ 3, 3, width() - 5, height() - 5 }, button_color); + painter.fill_rect_with_gradient({ 3, 3, width() - 5, height() - 5 }, button_color, Color::White); // White highlight painter.draw_line({ 1, 1 }, { width() - 2, 1 }, highlight_color); |