mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:08:11 +00:00
Kernel: Implement lazy FPU state restore.
This commit is contained in:
parent
2279f5eaa6
commit
dfdca9d2a7
8 changed files with 50 additions and 9 deletions
|
@ -258,6 +258,9 @@ Process* Process::fork(RegisterDump& regs)
|
||||||
child->m_tss.gs = regs.gs;
|
child->m_tss.gs = regs.gs;
|
||||||
child->m_tss.ss = regs.ss_if_crossRing;
|
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
|
#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);
|
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
|
#endif
|
||||||
|
@ -588,6 +591,8 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring
|
||||||
, m_tty(tty)
|
, m_tty(tty)
|
||||||
, m_ppid(ppid)
|
, m_ppid(ppid)
|
||||||
{
|
{
|
||||||
|
memset(&m_fpu_state, 0, sizeof(FPUState));
|
||||||
|
|
||||||
m_gids.set(m_gid);
|
m_gids.set(m_gid);
|
||||||
|
|
||||||
if (fork_parent) {
|
if (fork_parent) {
|
||||||
|
@ -698,6 +703,9 @@ Process::~Process()
|
||||||
ProcFS::the().remove_process(*this);
|
ProcFS::the().remove_process(*this);
|
||||||
system.nprocess--;
|
system.nprocess--;
|
||||||
|
|
||||||
|
if (g_last_fpu_process == this)
|
||||||
|
g_last_fpu_process = nullptr;
|
||||||
|
|
||||||
if (selector())
|
if (selector())
|
||||||
gdt_free_entry(selector());
|
gdt_free_entry(selector());
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,10 @@ public:
|
||||||
bool wakeup_requested() { return m_wakeup_requested; }
|
bool wakeup_requested() { return m_wakeup_requested; }
|
||||||
void request_wakeup() { m_wakeup_requested = true; }
|
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:
|
private:
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
friend class Scheduler;
|
friend class Scheduler;
|
||||||
|
@ -303,6 +307,7 @@ private:
|
||||||
dword m_wakeupTime { 0 };
|
dword m_wakeupTime { 0 };
|
||||||
TSS32 m_tss;
|
TSS32 m_tss;
|
||||||
TSS32 m_tss_to_resume_kernel;
|
TSS32 m_tss_to_resume_kernel;
|
||||||
|
FPUState m_fpu_state;
|
||||||
struct FileDescriptorAndFlags {
|
struct FileDescriptorAndFlags {
|
||||||
operator bool() const { return !!descriptor; }
|
operator bool() const { return !!descriptor; }
|
||||||
void clear() { descriptor = nullptr; flags = 0; }
|
void clear() { descriptor = nullptr; flags = 0; }
|
||||||
|
@ -372,6 +377,7 @@ private:
|
||||||
int m_next_window_id { 1 };
|
int m_next_window_id { 1 };
|
||||||
|
|
||||||
dword m_wakeup_requested { false };
|
dword m_wakeup_requested { false };
|
||||||
|
bool m_has_used_fpu { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Process* current;
|
extern Process* current;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
static const dword time_slice = 5; // *10 = 50ms
|
static const dword time_slice = 5; // *10 = 50ms
|
||||||
|
|
||||||
Process* current;
|
Process* current;
|
||||||
|
Process* g_last_fpu_process;
|
||||||
static Process* s_colonel_process;
|
static Process* s_colonel_process;
|
||||||
static bool s_in_yield;
|
static bool s_in_yield;
|
||||||
|
|
||||||
|
@ -299,6 +300,7 @@ void Scheduler::initialize()
|
||||||
initialize_redirection();
|
initialize_redirection();
|
||||||
s_colonel_process = Process::create_kernel_process("colonel", nullptr);
|
s_colonel_process = Process::create_kernel_process("colonel", nullptr);
|
||||||
current = nullptr;
|
current = nullptr;
|
||||||
|
g_last_fpu_process = nullptr;
|
||||||
s_in_yield = false;
|
s_in_yield = false;
|
||||||
load_task_register(s_redirection.selector);
|
load_task_register(s_redirection.selector);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ class Process;
|
||||||
struct RegisterDump;
|
struct RegisterDump;
|
||||||
|
|
||||||
extern Process* current;
|
extern Process* current;
|
||||||
|
extern Process* g_last_fpu_process;
|
||||||
|
|
||||||
class Scheduler {
|
class Scheduler {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
#include "IRQHandler.h"
|
#include "IRQHandler.h"
|
||||||
#include "PIC.h"
|
#include "PIC.h"
|
||||||
|
#include "Scheduler.h"
|
||||||
|
|
||||||
//#define PAGE_FAULT_DEBUG
|
//#define PAGE_FAULT_DEBUG
|
||||||
|
|
||||||
|
@ -150,13 +151,31 @@ void exception_6_handler(RegisterDump& regs)
|
||||||
current->crash();
|
current->crash();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7: FPU exception
|
// 7: FPU not available exception
|
||||||
EH_ENTRY_NO_CODE(7);
|
EH_ENTRY_NO_CODE(7);
|
||||||
void exception_7_handler(RegisterDump& regs)
|
void exception_7_handler(RegisterDump& regs)
|
||||||
{
|
{
|
||||||
(void)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
|
#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;
|
word ss;
|
||||||
dword esp;
|
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("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);
|
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME: Do stuff.
|
|
||||||
asm volatile("clts");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,17 @@ struct RegisterDumpWithExceptionCode {
|
||||||
word ss_if_crossRing;
|
word ss_if_crossRing;
|
||||||
} PACKED;
|
} 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)
|
inline constexpr dword pageBaseOf(dword address)
|
||||||
{
|
{
|
||||||
return address & 0xfffff000;
|
return address & 0xfffff000;
|
||||||
|
|
|
@ -138,10 +138,6 @@ void init()
|
||||||
gdt_init();
|
gdt_init();
|
||||||
idt_init();
|
idt_init();
|
||||||
|
|
||||||
#ifndef NO_FPU
|
|
||||||
asm volatile("fninit");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VFS::initialize_globals();
|
VFS::initialize_globals();
|
||||||
vfs = new VFS;
|
vfs = new VFS;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ void GButton::paint_event(GPaintEvent&)
|
||||||
} else {
|
} else {
|
||||||
// Base
|
// Base
|
||||||
painter.fill_rect({ 3, 3, width() - 5, height() - 5 }, button_color);
|
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
|
// White highlight
|
||||||
painter.draw_line({ 1, 1 }, { width() - 2, 1 }, highlight_color);
|
painter.draw_line({ 1, 1 }, { width() - 2, 1 }, highlight_color);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue