Maintain fsbase and gsbase as per-thread registers.
Note: This is an incompatible ABI change.
This commit is contained in:
parent
92d7c1807e
commit
1f72c1637c
|
@ -50,7 +50,8 @@ extern "C" __attribute__((noreturn))
|
||||||
void BootstrapKernelThread(void* user, ThreadEntry entry);
|
void BootstrapKernelThread(void* user, ThreadEntry entry);
|
||||||
|
|
||||||
// These functions create a new kernel process but doesn't start it.
|
// These functions create a new kernel process but doesn't start it.
|
||||||
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs);
|
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
||||||
|
unsigned long fsbase, unsigned long gsbase);
|
||||||
Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user,
|
Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user,
|
||||||
size_t stacksize = 0);
|
size_t stacksize = 0);
|
||||||
Thread* CreateKernelThread(ThreadEntry entry, void* user, size_t stacksize = 0);
|
Thread* CreateKernelThread(ThreadEntry entry, void* user, size_t stacksize = 0);
|
||||||
|
@ -74,7 +75,8 @@ typedef void (*sighandler_t)(int);
|
||||||
class Thread
|
class Thread
|
||||||
{
|
{
|
||||||
friend Thread* CreateKernelThread(Process* process,
|
friend Thread* CreateKernelThread(Process* process,
|
||||||
CPU::InterruptRegisters* regs);
|
CPU::InterruptRegisters* regs,
|
||||||
|
unsigned long fsbase, unsigned long gsbase);
|
||||||
friend void KernelInit(unsigned long magic, multiboot_info_t* bootinfo);
|
friend void KernelInit(unsigned long magic, multiboot_info_t* bootinfo);
|
||||||
friend void Thread__OnSigKill(Thread* thread);
|
friend void Thread__OnSigKill(Thread* thread);
|
||||||
|
|
||||||
|
@ -111,6 +113,12 @@ public:
|
||||||
size_t kernelstacksize;
|
size_t kernelstacksize;
|
||||||
bool kernelstackmalloced;
|
bool kernelstackmalloced;
|
||||||
|
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
public:
|
||||||
|
unsigned long fsbase;
|
||||||
|
unsigned long gsbase;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CPU::InterruptRegisters registers;
|
CPU::InterruptRegisters registers;
|
||||||
Signal::Queue signalqueue;
|
Signal::Queue signalqueue;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
struct tforkregs_x64
|
struct tforkregs_x64
|
||||||
|
@ -49,6 +51,8 @@ struct tforkregs_x64
|
||||||
uint64_t r14;
|
uint64_t r14;
|
||||||
uint64_t r15;
|
uint64_t r15;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
|
uint64_t fsbase;
|
||||||
|
uint64_t gsbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
struct tforkregs_x86
|
struct tforkregs_x86
|
||||||
|
@ -41,6 +43,8 @@ struct tforkregs_x86
|
||||||
uint32_t esp;
|
uint32_t esp;
|
||||||
uint32_t ebp;
|
uint32_t ebp;
|
||||||
uint32_t eflags;
|
uint32_t eflags;
|
||||||
|
uint32_t fsbase;
|
||||||
|
uint32_t gsbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#include <msr.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sortix/keycodes.h>
|
#include <sortix/keycodes.h>
|
||||||
|
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
|
@ -36,6 +40,10 @@
|
||||||
#include <sortix/kernel/keyboard.h>
|
#include <sortix/kernel/keyboard.h>
|
||||||
#include <sortix/kernel/thread.h>
|
#include <sortix/kernel/thread.h>
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
#include "../x86-family/gdt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ps2.h"
|
#include "ps2.h"
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
@ -97,7 +105,15 @@ void PS2Keyboard::OnInterrupt(CPU::InterruptRegisters* regs)
|
||||||
uint8_t scancode = PopScancode();
|
uint8_t scancode = PopScancode();
|
||||||
if ( scancode == KBKEY_F10 )
|
if ( scancode == KBKEY_F10 )
|
||||||
{
|
{
|
||||||
CurrentThread()->SaveRegisters(regs);
|
Thread* thread = CurrentThread();
|
||||||
|
#if defined(__i386__)
|
||||||
|
thread->fsbase = (unsigned long) GDT::GetFSBase();
|
||||||
|
thread->gsbase = (unsigned long) GDT::GetGSBase();
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
thread->fsbase = (unsigned long) rdmsr(MSRID_FSBASE);
|
||||||
|
thread->gsbase = (unsigned long) rdmsr(MSRID_GSBASE);
|
||||||
|
#endif
|
||||||
|
thread->SaveRegisters(regs);
|
||||||
Debugger::Run();
|
Debugger::Run();
|
||||||
}
|
}
|
||||||
PS2KeyboardWork work;
|
PS2KeyboardWork work;
|
||||||
|
|
|
@ -995,7 +995,8 @@ static pid_t sys_tfork(int flags, tforkregs_t* user_regs)
|
||||||
|
|
||||||
// If the thread could not be created, make the process commit suicide
|
// If the thread could not be created, make the process commit suicide
|
||||||
// in a manner such that we don't wait for its zombie.
|
// in a manner such that we don't wait for its zombie.
|
||||||
Thread* thread = CreateKernelThread(clone, &cpuregs);
|
Thread* thread = CreateKernelThread(clone, &cpuregs, regs.fsbase,
|
||||||
|
regs.gsbase);
|
||||||
if ( !thread )
|
if ( !thread )
|
||||||
{
|
{
|
||||||
clone->AbortConstruction();
|
clone->AbortConstruction();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <msr.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <timespec.h>
|
#include <timespec.h>
|
||||||
|
@ -130,6 +131,18 @@ static void DoActualSwitch(CPU::InterruptRegisters* regs)
|
||||||
assert(stacklower && stacksize && stackhigher);
|
assert(stacklower && stacksize && stackhigher);
|
||||||
GDT::SetKernelStack(stacklower, stacksize, stackhigher);
|
GDT::SetKernelStack(stacklower, stacksize, stackhigher);
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
current->fsbase = (unsigned long) rdmsr(MSRID_FSBASE);
|
||||||
|
current->gsbase = (unsigned long) rdmsr(MSRID_GSBASE);
|
||||||
|
wrmsr(MSRID_FSBASE, (uint64_t) next->fsbase);
|
||||||
|
wrmsr(MSRID_GSBASE, (uint64_t) next->gsbase);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
current->fsbase = (unsigned long) GDT::GetFSBase();
|
||||||
|
current->gsbase = (unsigned long) GDT::GetGSBase();
|
||||||
|
GDT::SetFSBase((uint32_t) next->fsbase);
|
||||||
|
GDT::SetGSBase((uint32_t) next->gsbase);
|
||||||
|
#endif
|
||||||
|
|
||||||
LogEndSwitch(next, regs);
|
LogEndSwitch(next, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ Thread::Thread()
|
||||||
schedulerlistnext = NULL;
|
schedulerlistnext = NULL;
|
||||||
state = NONE;
|
state = NONE;
|
||||||
memset(®isters, 0, sizeof(registers));
|
memset(®isters, 0, sizeof(registers));
|
||||||
|
fsbase = 0;
|
||||||
|
gsbase = 0;
|
||||||
kernelstackpos = 0;
|
kernelstackpos = 0;
|
||||||
kernelstacksize = 0;
|
kernelstacksize = 0;
|
||||||
kernelstackmalloced = false;
|
kernelstackmalloced = false;
|
||||||
|
@ -96,8 +98,16 @@ extern "C" void BootstrapKernelThread(void* user, ThreadEntry entry)
|
||||||
kthread_exit();
|
kthread_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs)
|
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
||||||
|
unsigned long fsbase, unsigned long gsbase)
|
||||||
{
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
if ( fsbase >> 48 != 0x0000 && fsbase >> 48 != 0xFFFF )
|
||||||
|
return errno = EINVAL, (Thread*) NULL;
|
||||||
|
if ( gsbase >> 48 != 0x0000 && gsbase >> 48 != 0xFFFF )
|
||||||
|
return errno = EINVAL, (Thread*) NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(process && regs && process->addrspace);
|
assert(process && regs && process->addrspace);
|
||||||
Thread* thread = new Thread;
|
Thread* thread = new Thread;
|
||||||
if ( !thread )
|
if ( !thread )
|
||||||
|
@ -105,6 +115,8 @@ Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs)
|
||||||
|
|
||||||
thread->addrspace = process->addrspace;
|
thread->addrspace = process->addrspace;
|
||||||
thread->SaveRegisters(regs);
|
thread->SaveRegisters(regs);
|
||||||
|
thread->fsbase = fsbase;
|
||||||
|
thread->gsbase = gsbase;
|
||||||
|
|
||||||
kthread_mutex_lock(&process->threadlock);
|
kthread_mutex_lock(&process->threadlock);
|
||||||
|
|
||||||
|
@ -134,7 +146,7 @@ Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user,
|
||||||
CPU::InterruptRegisters regs;
|
CPU::InterruptRegisters regs;
|
||||||
SetupKernelThreadRegs(®s, entry, user, (addr_t) stack, stacksize);
|
SetupKernelThreadRegs(®s, entry, user, (addr_t) stack, stacksize);
|
||||||
|
|
||||||
Thread* thread = CreateKernelThread(process, ®s);
|
Thread* thread = CreateKernelThread(process, ®s, 0, 0);
|
||||||
if ( !thread ) { delete[] stack; return NULL; }
|
if ( !thread ) { delete[] stack; return NULL; }
|
||||||
|
|
||||||
thread->kernelstackpos = (addr_t) stack;
|
thread->kernelstackpos = (addr_t) stack;
|
||||||
|
@ -156,7 +168,7 @@ void StartKernelThread(Thread* thread)
|
||||||
|
|
||||||
Thread* RunKernelThread(Process* process, CPU::InterruptRegisters* regs)
|
Thread* RunKernelThread(Process* process, CPU::InterruptRegisters* regs)
|
||||||
{
|
{
|
||||||
Thread* thread = CreateKernelThread(process, regs);
|
Thread* thread = CreateKernelThread(process, regs, 0, 0);
|
||||||
if ( !thread )
|
if ( !thread )
|
||||||
return NULL;
|
return NULL;
|
||||||
StartKernelThread(thread);
|
StartKernelThread(thread);
|
||||||
|
|
|
@ -371,8 +371,6 @@ interrupt_handler_prepare:
|
||||||
movw $0x10, %bp
|
movw $0x10, %bp
|
||||||
movl %ebp, %ds
|
movl %ebp, %ds
|
||||||
movl %ebp, %es
|
movl %ebp, %es
|
||||||
movl %ebp, %fs
|
|
||||||
movl %ebp, %gs
|
|
||||||
|
|
||||||
# Push CR2 in case of page faults
|
# Push CR2 in case of page faults
|
||||||
movq %cr2, %rbp
|
movq %cr2, %rbp
|
||||||
|
@ -406,8 +404,6 @@ load_interrupted_registers:
|
||||||
popq %rbp
|
popq %rbp
|
||||||
movl %ebp, %ds
|
movl %ebp, %ds
|
||||||
movl %ebp, %es
|
movl %ebp, %es
|
||||||
movl %ebp, %fs
|
|
||||||
movl %ebp, %gs
|
|
||||||
|
|
||||||
popq %rdi
|
popq %rdi
|
||||||
popq %rsi
|
popq %rsi
|
||||||
|
|
|
@ -110,7 +110,13 @@ struct tss_entry
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
const size_t GDT_NUM_ENTRIES = 9;
|
||||||
|
const size_t GDT_FS_ENTRY = 7;
|
||||||
|
const size_t GDT_GS_ENTRY = 8;
|
||||||
|
#else
|
||||||
const size_t GDT_NUM_ENTRIES = 7;
|
const size_t GDT_NUM_ENTRIES = 7;
|
||||||
|
#endif
|
||||||
static struct gdt_entry gdt_entries[GDT_NUM_ENTRIES];
|
static struct gdt_entry gdt_entries[GDT_NUM_ENTRIES];
|
||||||
|
|
||||||
static struct tss_entry tss_entry;
|
static struct tss_entry tss_entry;
|
||||||
|
@ -166,6 +172,11 @@ void Init()
|
||||||
|
|
||||||
WriteTSS(5, 0x10, 0x0);
|
WriteTSS(5, 0x10, 0x0);
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
SetGate(GDT_FS_ENTRY, 0, 0xFFFFFFFF, 0xF2, gran);
|
||||||
|
SetGate(GDT_GS_ENTRY, 0, 0xFFFFFFFF, 0xF2, gran);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reload the Global Descriptor Table.
|
// Reload the Global Descriptor Table.
|
||||||
volatile struct gdt_ptr gdt_ptr;
|
volatile struct gdt_ptr gdt_ptr;
|
||||||
gdt_ptr.limit = (sizeof(struct gdt_entry) * GDT_NUM_ENTRIES) - 1;
|
gdt_ptr.limit = (sizeof(struct gdt_entry) * GDT_NUM_ENTRIES) - 1;
|
||||||
|
@ -175,11 +186,17 @@ void Init()
|
||||||
// Switch the current data segment.
|
// Switch the current data segment.
|
||||||
asm volatile ("mov %0, %%ds\n"
|
asm volatile ("mov %0, %%ds\n"
|
||||||
"mov %0, %%es\n"
|
"mov %0, %%es\n"
|
||||||
"mov %0, %%fs\n"
|
|
||||||
"mov %0, %%gs\n"
|
|
||||||
"mov %0, %%ss\n" : :
|
"mov %0, %%ss\n" : :
|
||||||
"r"(KDS));
|
"r"(KDS));
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
asm volatile ("mov %0, %%fs" : : "r"(GDT_FS_ENTRY << 3 | URPL));
|
||||||
|
asm volatile ("mov %0, %%gs" : : "r"(GDT_GS_ENTRY << 3 | URPL));
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
asm volatile ("mov %0, %%fs" : : "r"(UDS | URPL));
|
||||||
|
asm volatile ("mov %0, %%gs" : : "r"(UDS | URPL));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Switch the current code segment.
|
// Switch the current code segment.
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
asm volatile ("push %0\n"
|
asm volatile ("push %0\n"
|
||||||
|
@ -250,5 +267,41 @@ void SetKernelStack(uintptr_t stacklower, size_t stacksize, uintptr_t stackhighe
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__i386__)
|
||||||
|
uint32_t GetFSBase()
|
||||||
|
{
|
||||||
|
struct gdt_entry* entry = gdt_entries + GDT_FS_ENTRY;
|
||||||
|
return (uint32_t) entry->base_low << 0 |
|
||||||
|
(uint32_t) entry->base_middle << 16 |
|
||||||
|
(uint32_t) entry->base_high << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetGSBase()
|
||||||
|
{
|
||||||
|
struct gdt_entry* entry = gdt_entries + GDT_GS_ENTRY;
|
||||||
|
return (uint32_t) entry->base_low << 0 |
|
||||||
|
(uint32_t) entry->base_middle << 16 |
|
||||||
|
(uint32_t) entry->base_high << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFSBase(uint32_t fsbase)
|
||||||
|
{
|
||||||
|
struct gdt_entry* entry = gdt_entries + GDT_FS_ENTRY;
|
||||||
|
entry->base_low = fsbase >> 0 & 0xFFFF;
|
||||||
|
entry->base_middle = fsbase >> 16 & 0xFF;
|
||||||
|
entry->base_high = fsbase >> 24 & 0xFF;
|
||||||
|
asm volatile ("mov %0, %%fs" : : "r"(GDT_FS_ENTRY << 3 | URPL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetGSBase(uint32_t gsbase)
|
||||||
|
{
|
||||||
|
struct gdt_entry* entry = gdt_entries + GDT_GS_ENTRY;
|
||||||
|
entry->base_low = gsbase >> 0 & 0xFFFF;
|
||||||
|
entry->base_middle = gsbase >> 16 & 0xFF;
|
||||||
|
entry->base_high = gsbase >> 24 & 0xFF;
|
||||||
|
asm volatile ("mov %0, %%gs" : : "r"(GDT_GS_ENTRY << 3 | URPL));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace GDT
|
} // namespace GDT
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -25,12 +25,20 @@
|
||||||
#ifndef SORTIX_X86_FAMILY_GDT_H
|
#ifndef SORTIX_X86_FAMILY_GDT_H
|
||||||
#define SORTIX_X86_FAMILY_GDT_H
|
#define SORTIX_X86_FAMILY_GDT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
namespace GDT {
|
namespace GDT {
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void WriteTSS(int32_t num, uint16_t ss0, uintptr_t stack0);
|
void WriteTSS(int32_t num, uint16_t ss0, uintptr_t stack0);
|
||||||
void SetKernelStack(uintptr_t stacklower, size_t stacksize, uintptr_t stackhigher);
|
void SetKernelStack(uintptr_t stacklower, size_t stacksize, uintptr_t stackhigher);
|
||||||
|
#if defined(__i386__)
|
||||||
|
uint32_t GetFSBase();
|
||||||
|
uint32_t GetGSBase();
|
||||||
|
void SetFSBase(uint32_t fsbase);
|
||||||
|
void SetGSBase(uint32_t gsbase);
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace GDT
|
} // namespace GDT
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <msr.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
#include <sortix/kernel/syscall.h>
|
#include <sortix/kernel/syscall.h>
|
||||||
#include <sortix/kernel/thread.h>
|
#include <sortix/kernel/thread.h>
|
||||||
|
|
||||||
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
|
|
||||||
|
@ -272,7 +274,15 @@ void CrashCalltrace(const CPU::InterruptRegisters* regs)
|
||||||
__attribute__((noreturn))
|
__attribute__((noreturn))
|
||||||
void KernelCrashHandler(CPU::InterruptRegisters* regs)
|
void KernelCrashHandler(CPU::InterruptRegisters* regs)
|
||||||
{
|
{
|
||||||
CurrentThread()->SaveRegisters(regs);
|
Thread* thread = CurrentThread();
|
||||||
|
#if defined(__i386__)
|
||||||
|
thread->fsbase = (unsigned long) GDT::GetFSBase();
|
||||||
|
thread->gsbase = (unsigned long) GDT::GetGSBase();
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
thread->fsbase = (unsigned long) rdmsr(MSRID_FSBASE);
|
||||||
|
thread->gsbase = (unsigned long) rdmsr(MSRID_GSBASE);
|
||||||
|
#endif
|
||||||
|
thread->SaveRegisters(regs);
|
||||||
|
|
||||||
// Walk and print the stack frames if this is a debug build.
|
// Walk and print the stack frames if this is a debug build.
|
||||||
if ( CALLTRACE_KERNEL )
|
if ( CALLTRACE_KERNEL )
|
||||||
|
@ -290,7 +300,15 @@ void KernelCrashHandler(CPU::InterruptRegisters* regs)
|
||||||
|
|
||||||
void UserCrashHandler(CPU::InterruptRegisters* regs)
|
void UserCrashHandler(CPU::InterruptRegisters* regs)
|
||||||
{
|
{
|
||||||
CurrentThread()->SaveRegisters(regs);
|
Thread* thread = CurrentThread();
|
||||||
|
#if defined(__i386__)
|
||||||
|
thread->fsbase = (unsigned long) GDT::GetFSBase();
|
||||||
|
thread->gsbase = (unsigned long) GDT::GetGSBase();
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
thread->fsbase = (unsigned long) rdmsr(MSRID_FSBASE);
|
||||||
|
thread->gsbase = (unsigned long) rdmsr(MSRID_GSBASE);
|
||||||
|
#endif
|
||||||
|
thread->SaveRegisters(regs);
|
||||||
|
|
||||||
// Execute this crash handler with preemption on.
|
// Execute this crash handler with preemption on.
|
||||||
Interrupt::Enable();
|
Interrupt::Enable();
|
||||||
|
|
|
@ -368,8 +368,6 @@ fixup_relocate_stack_complete:
|
||||||
movw $0x10, %bp
|
movw $0x10, %bp
|
||||||
movl %ebp, %ds
|
movl %ebp, %ds
|
||||||
movl %ebp, %es
|
movl %ebp, %es
|
||||||
movl %ebp, %fs
|
|
||||||
movl %ebp, %gs
|
|
||||||
|
|
||||||
# Push CR2 in case of page faults
|
# Push CR2 in case of page faults
|
||||||
movl %cr2, %ebp
|
movl %cr2, %ebp
|
||||||
|
@ -404,8 +402,6 @@ load_interrupted_registers:
|
||||||
popl %ebp
|
popl %ebp
|
||||||
movl %ebp, %ds
|
movl %ebp, %ds
|
||||||
movl %ebp, %es
|
movl %ebp, %es
|
||||||
movl %ebp, %fs
|
|
||||||
movl %ebp, %gs
|
|
||||||
|
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
|
|
|
@ -37,8 +37,6 @@ syscall_handler:
|
||||||
movw $0x10, %bp
|
movw $0x10, %bp
|
||||||
movl %ebp, %ds
|
movl %ebp, %ds
|
||||||
movl %ebp, %es
|
movl %ebp, %es
|
||||||
movl %ebp, %fs
|
|
||||||
movl %ebp, %gs
|
|
||||||
|
|
||||||
# Make sure the requested system call is valid.
|
# Make sure the requested system call is valid.
|
||||||
cmp SYSCALL_MAX, %eax
|
cmp SYSCALL_MAX, %eax
|
||||||
|
@ -66,8 +64,6 @@ valid_syscall:
|
||||||
popl %ebp
|
popl %ebp
|
||||||
movl %ebp, %ds
|
movl %ebp, %ds
|
||||||
movl %ebp, %es
|
movl %ebp, %es
|
||||||
movl %ebp, %fs
|
|
||||||
movl %ebp, %gs
|
|
||||||
|
|
||||||
# Return to user-space, system call result in %eax:%edx, errno in %ecx.
|
# Return to user-space, system call result in %eax:%edx, errno in %ecx.
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MSRID_FSBASE __UINT32_C(0xC0000100)
|
||||||
|
#define MSRID_GSBASE __UINT32_C(0xC0000101)
|
||||||
|
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
static __inline uint64_t rdmsr(uint32_t msrid)
|
static __inline uint64_t rdmsr(uint32_t msrid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#define MSRID_FSBASE 0xC0000100
|
||||||
|
#define MSRID_GSBASE 0xC0000101
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
.globl __call_tfork_with_regs
|
.globl __call_tfork_with_regs
|
||||||
|
@ -30,10 +33,16 @@ __call_tfork_with_regs:
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
|
|
||||||
|
# Save the flags parameter so rdmsr won't trash it and align stack.
|
||||||
|
pushq %rdi
|
||||||
|
sub $8, %rsp
|
||||||
|
|
||||||
# The actual system call expects a struct tforkregs_x64 containing the state
|
# The actual system call expects a struct tforkregs_x64 containing the state
|
||||||
# of each register in the child. Since we create an identical copy, we
|
# of each register in the child. Since we create an identical copy, we
|
||||||
# simply set each member of the structure to our own state. Note that since
|
# simply set each member of the structure to our own state. Note that since
|
||||||
# the stack goes downwards, we create it in the reverse order.
|
# the stack goes downwards, we create it in the reverse order.
|
||||||
|
pushq $0 # gsbase
|
||||||
|
pushq $0 # fsbase
|
||||||
pushfq
|
pushfq
|
||||||
pushq %r15
|
pushq %r15
|
||||||
pushq %r14
|
pushq %r14
|
||||||
|
@ -53,8 +62,7 @@ __call_tfork_with_regs:
|
||||||
pushq $0 # rax, result of sfork is 0 for the child.
|
pushq $0 # rax, result of sfork is 0 for the child.
|
||||||
pushq $.Lafter_fork # rip, child will start execution from here.
|
pushq $.Lafter_fork # rip, child will start execution from here.
|
||||||
|
|
||||||
# Call tfork with a nice pointer to our structure. Note that %rdi contains
|
# Call tfork with a nice pointer to our structure.
|
||||||
# the flag parameter that this function accepted.
|
|
||||||
movq %rsp, %rsi
|
movq %rsp, %rsi
|
||||||
call tfork
|
call tfork
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#define MSRID_FSBASE 0xC0000100
|
||||||
|
#define MSRID_GSBASE 0xC0000101
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
.globl __call_tfork_with_regs
|
.globl __call_tfork_with_regs
|
||||||
|
@ -30,12 +33,12 @@ __call_tfork_with_regs:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
|
|
||||||
movl 8(%ebp), %edx # flags parameter, edx need not be preserved.
|
|
||||||
|
|
||||||
# The actual system call expects a struct tforkregs_x86 containing the state
|
# The actual system call expects a struct tforkregs_x86 containing the state
|
||||||
# of each register in the child. Since we create an identical copy, we
|
# of each register in the child. Since we create an identical copy, we
|
||||||
# simply set each member of the structure to our own state. Note that since
|
# simply set each member of the structure to our own state. Note that since
|
||||||
# the stack goes downwards, we create it in the reverse order.
|
# the stack goes downwards, we create it in the reverse order.
|
||||||
|
pushl $0 # gsbase
|
||||||
|
pushl $0 # fsbase
|
||||||
pushfl
|
pushfl
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
pushl %esp
|
pushl %esp
|
||||||
|
@ -49,6 +52,7 @@ __call_tfork_with_regs:
|
||||||
|
|
||||||
# Call tfork with a nice pointer to our structure. Note that %edi contains
|
# Call tfork with a nice pointer to our structure. Note that %edi contains
|
||||||
# the flag parameter that this function accepted.
|
# the flag parameter that this function accepted.
|
||||||
|
movl 8(%ebp), %edx # flags parameter, edx need not be preserved.
|
||||||
pushl %esp
|
pushl %esp
|
||||||
pushl %edx
|
pushl %edx
|
||||||
call tfork
|
call tfork
|
||||||
|
|
Loading…
Reference in New Issue