[haiku-commits] BRANCH xyzzy-github.x86_64 - src/system/kernel/arch/x86 src/system/kernel/arch/x86/32 src/system/kernel/arch/x86/64 headers/private/kernel/arch/x86

  • From: xyzzy-github.x86_64 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 9 Jul 2012 17:49:12 +0200 (CEST)

added 4 changesets to branch 'refs/remotes/xyzzy-github/x86_64'
old head: ee7aba5117fea8aa4d292fb9c105dc483c67a2e2
new head: b5c9d24abcc3599375153ed310b495ea944d46a0

----------------------------------------------------------------------------

5e9bb17: Renamed remaining i386_* functions to x86_* for consistency.

8c5e747: Don't need to shift the factor in system_time(), just store the 
already shifted value.

85d4a8b: Fixed compilation of C code using ELF headers.

b5c9d24: Implemented threading for x86_64.
  
  * Thread creation and switching is working fine, however threads do not yet
    get interrupted because I've not implemented hardware interrupt handling
    yet (I'll do that next).
  * I've made some changes to struct iframe: I've removed the e/r prefixes
    from the member names for both 32/64, so now they're just named ip, ax,
    bp, etc. This makes it easier to write code that works with both 32/64
    without having to deal with different iframe member names.

                                      [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

30 files changed, 958 insertions(+), 727 deletions(-)
headers/private/kernel/arch/x86/32/iframe.h        |   22 +-
headers/private/kernel/arch/x86/64/descriptors.h   |    6 +-
headers/private/kernel/arch/x86/64/iframe.h        |   18 +-
headers/private/kernel/arch/x86/arch_cpu.h         |   23 +-
headers/private/kernel/arch/x86/arch_debug.h       |    2 +-
headers/private/kernel/arch/x86/arch_thread.h      |   25 +-
.../private/kernel/arch/x86/arch_thread_types.h    |   25 +-
headers/private/kernel/arch/x86/smp_priv.h         |    1 -
headers/private/system/elf_common.h                |    2 +-
src/system/kernel/arch/x86/32/arch.S               |    6 +-
src/system/kernel/arch/x86/32/int.cpp              |   66 +--
src/system/kernel/arch/x86/32/interrupts.S         |   14 +-
src/system/kernel/arch/x86/32/thread.cpp           |  396 +++++++++++++
src/system/kernel/arch/x86/64/arch.S               |   56 +-
src/system/kernel/arch/x86/64/int.cpp              |    8 +-
src/system/kernel/arch/x86/64/interrupts.S         |   19 +
src/system/kernel/arch/x86/64/stubs.cpp            |  120 +---
src/system/kernel/arch/x86/64/thread.cpp           |  196 +++++++
src/system/kernel/arch/x86/Jamfile                 |    4 +-
src/system/kernel/arch/x86/arch_cpu.cpp            |   13 +-
src/system/kernel/arch/x86/arch_debug.cpp          |   78 +--
src/system/kernel/arch/x86/arch_int.cpp            |    3 +-
src/system/kernel/arch/x86/arch_smp.cpp            |   12 +-
src/system/kernel/arch/x86/arch_thread.cpp         |  480 ++--------------
src/system/kernel/arch/x86/arch_user_debugger.cpp  |   56 +-
src/system/kernel/arch/x86/asm_offsets.cpp         |   21 +-
src/system/kernel/arch/x86/vm86.cpp                |    2 +-
src/system/kernel/arch/x86/x86_syscalls.h          |    3 +
src/system/kernel/vm/vm.cpp                        |    2 +-
.../libroot/os/arch/x86_64/system_time_asm.S       |    6 +-

############################################################################

Commit:      5e9bb17da7b9cdd76ff9072486fab90688cf8c36

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Mon Jul  9 11:14:18 2012 UTC

Renamed remaining i386_* functions to x86_* for consistency.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/x86/arch_cpu.h 
b/headers/private/kernel/arch/x86/arch_cpu.h
index 204c901..17a3d41 100644
--- a/headers/private/kernel/arch/x86/arch_cpu.h
+++ b/headers/private/kernel/arch/x86/arch_cpu.h
@@ -401,7 +401,7 @@ void x86_page_fault_exception_double_fault(struct iframe* 
frame);
 
 #ifndef __x86_64__
 
-void i386_set_tss_and_kstack(addr_t kstack);
+void x86_set_tss_and_kstack(addr_t kstack);
 void x86_fnsave(void* fpuState);
 void x86_frstor(const void* fpuState);
 void x86_noop_swap(void* oldFpuState, const void* newFpuState);
diff --git a/headers/private/kernel/arch/x86/arch_thread.h 
b/headers/private/kernel/arch/x86/arch_thread.h
index 7efd8b1..4a08809 100644
--- a/headers/private/kernel/arch/x86/arch_thread.h
+++ b/headers/private/kernel/arch/x86/arch_thread.h
@@ -17,9 +17,9 @@ extern "C" {
 #endif
 
 
-struct iframe* i386_get_user_iframe(void);
-struct iframe* i386_get_current_iframe(void);
-struct iframe* i386_get_thread_user_iframe(Thread* thread);
+struct iframe* x86_get_user_iframe(void);
+struct iframe* x86_get_current_iframe(void);
+struct iframe* x86_get_thread_user_iframe(Thread* thread);
 
 uint32 x86_next_page_directory(Thread* from, Thread* to);
 
diff --git a/headers/private/kernel/arch/x86/smp_priv.h 
b/headers/private/kernel/arch/x86/smp_priv.h
index f5e6f45..17b0351 100644
--- a/headers/private/kernel/arch/x86/smp_priv.h
+++ b/headers/private/kernel/arch/x86/smp_priv.h
@@ -7,7 +7,6 @@
 
 #include <SupportDefs.h>
 
-int i386_smp_interrupt(int vector);
 void arch_smp_ack_interrupt(void);
 status_t arch_smp_set_apic_timer(bigtime_t relativeTimeout);
 status_t arch_smp_clear_apic_timer(void);
diff --git a/src/system/kernel/arch/x86/32/interrupts.S 
b/src/system/kernel/arch/x86/32/interrupts.S
index aa4dfe1..014fa33 100644
--- a/src/system/kernel/arch/x86/32/interrupts.S
+++ b/src/system/kernel/arch/x86/32/interrupts.S
@@ -884,7 +884,7 @@ FUNCTION(x86_vm86_enter):
        pushl   THREAD_kernel_stack_top(%edi)
        movl    %esp, THREAD_kernel_stack_top(%edi)
        pushl   %esp
-       call    i386_set_tss_and_kstack
+       call    x86_set_tss_and_kstack
 
        // go to vm86 mode
        cli
@@ -916,7 +916,7 @@ FUNCTION(x86_vm86_return):
        movl    %dr3, %edi
        movl    %eax, THREAD_kernel_stack_top(%edi)
        pushl   %eax
-       call    i386_set_tss_and_kstack
+       call    x86_set_tss_and_kstack
        addl    $4, %esp
 
        // restore registers
diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp 
b/src/system/kernel/arch/x86/arch_cpu.cpp
index 2edd3c3..2c61241 100644
--- a/src/system/kernel/arch/x86/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86/arch_cpu.cpp
@@ -974,7 +974,7 @@ arch_cpu_init_post_modules(kernel_args* args)
 
 #ifndef __x86_64__
 void
-i386_set_tss_and_kstack(addr_t kstack)
+x86_set_tss_and_kstack(addr_t kstack)
 {
        get_cpu_struct()->arch.tss.sp0 = kstack;
 }
diff --git a/src/system/kernel/arch/x86/arch_debug.cpp 
b/src/system/kernel/arch/x86/arch_debug.cpp
index e8b9092..beedfa3 100644
--- a/src/system/kernel/arch/x86/arch_debug.cpp
+++ b/src/system/kernel/arch/x86/arch_debug.cpp
@@ -503,7 +503,7 @@ static struct iframe*
 get_current_iframe(Thread* thread)
 {
        if (thread == thread_get_current_thread())
-               return i386_get_current_iframe();
+               return x86_get_current_iframe();
 
        addr_t ebp = thread->arch_info.current_stack.esp[2];
                // NOTE: This doesn't work, if the thread is running (on 
another CPU).
diff --git a/src/system/kernel/arch/x86/arch_smp.cpp 
b/src/system/kernel/arch/x86/arch_smp.cpp
index 0720ae0..a63051b 100644
--- a/src/system/kernel/arch/x86/arch_smp.cpp
+++ b/src/system/kernel/arch/x86/arch_smp.cpp
@@ -39,7 +39,7 @@ static uint32 sAPICVersions[B_MAX_CPU_COUNT];
 
 
 static int32
-i386_ici_interrupt(void *data)
+x86_ici_interrupt(void *data)
 {
        // genuine inter-cpu interrupt
        int cpu = smp_get_current_cpu();
@@ -49,7 +49,7 @@ i386_ici_interrupt(void *data)
 
 
 static int32
-i386_spurious_interrupt(void *data)
+x86_spurious_interrupt(void *data)
 {
        // spurious interrupt
        TRACE(("spurious interrupt on cpu %ld\n", smp_get_current_cpu()));
@@ -62,7 +62,7 @@ i386_spurious_interrupt(void *data)
 
 
 static int32
-i386_smp_error_interrupt(void *data)
+x86_smp_error_interrupt(void *data)
 {
        // smp error interrupt
        TRACE(("smp error interrupt on cpu %ld\n", smp_get_current_cpu()));
@@ -91,9 +91,9 @@ arch_smp_init(kernel_args *args)
        if (args->num_cpus > 1) {
                // I/O interrupts start at ARCH_INTERRUPT_BASE, so all 
interrupts are shifted
                reserve_io_interrupt_vectors(3, 0xfd - ARCH_INTERRUPT_BASE);
-               install_io_interrupt_handler(0xfd - ARCH_INTERRUPT_BASE, 
&i386_ici_interrupt, NULL, B_NO_LOCK_VECTOR);
-               install_io_interrupt_handler(0xfe - ARCH_INTERRUPT_BASE, 
&i386_smp_error_interrupt, NULL, B_NO_LOCK_VECTOR);
-               install_io_interrupt_handler(0xff - ARCH_INTERRUPT_BASE, 
&i386_spurious_interrupt, NULL, B_NO_LOCK_VECTOR);
+               install_io_interrupt_handler(0xfd - ARCH_INTERRUPT_BASE, 
&x86_ici_interrupt, NULL, B_NO_LOCK_VECTOR);
+               install_io_interrupt_handler(0xfe - ARCH_INTERRUPT_BASE, 
&x86_smp_error_interrupt, NULL, B_NO_LOCK_VECTOR);
+               install_io_interrupt_handler(0xff - ARCH_INTERRUPT_BASE, 
&x86_spurious_interrupt, NULL, B_NO_LOCK_VECTOR);
        }
 
        return B_OK;
diff --git a/src/system/kernel/arch/x86/arch_thread.cpp 
b/src/system/kernel/arch/x86/arch_thread.cpp
index ce482ba..da8e47d 100644
--- a/src/system/kernel/arch/x86/arch_thread.cpp
+++ b/src/system/kernel/arch/x86/arch_thread.cpp
@@ -67,7 +67,6 @@ class RestartSyscall : public AbstractTraceEntry {
 
 
 // from arch_interrupts.S
-extern "C" void i386_stack_init(struct farcall *interrupt_stack_offset);
 extern "C" void x86_return_to_userland(iframe* frame);
 
 // from arch_cpu.c
@@ -160,7 +159,7 @@ initial_return_to_userland(Thread* thread, iframe* frame)
        // disable interrupts and set up CPU specifics for this thread
        disable_interrupts();
 
-       i386_set_tss_and_kstack(thread->kernel_stack_top);
+       x86_set_tss_and_kstack(thread->kernel_stack_top);
        x86_set_tls_context(thread);
        x86_set_syscall_stack(thread->kernel_stack_top);
 
@@ -177,7 +176,7 @@ initial_return_to_userland(Thread* thread, iframe* frame)
                        the thread is a kernel thread).
 */
 struct iframe *
-i386_get_user_iframe(void)
+x86_get_user_iframe(void)
 {
        struct iframe* frame = get_current_iframe();
 
@@ -191,11 +190,11 @@ i386_get_user_iframe(void)
 }
 
 
-/*!    \brief Like i386_get_user_iframe(), just for the given thread.
+/*!    \brief Like x86_get_user_iframe(), just for the given thread.
        The thread must not be running and the threads spinlock must be held.
 */
 struct iframe *
-i386_get_thread_user_iframe(Thread *thread)
+x86_get_thread_user_iframe(Thread *thread)
 {
        if (thread->state == B_THREAD_RUNNING)
                return NULL;
@@ -217,7 +216,7 @@ i386_get_thread_user_iframe(Thread *thread)
 
 
 struct iframe *
-i386_get_current_iframe(void)
+x86_get_current_iframe(void)
 {
        return get_current_iframe();
 }
@@ -367,7 +366,7 @@ arch_thread_init_tls(Thread *thread)
 void
 arch_thread_context_switch(Thread *from, Thread *to)
 {
-       i386_set_tss_and_kstack(to->kernel_stack_top);
+       x86_set_tss_and_kstack(to->kernel_stack_top);
        x86_set_syscall_stack(to->kernel_stack_top);
 
        // set TLS GDT entry to the current thread - since this action is
diff --git a/src/system/kernel/arch/x86/arch_user_debugger.cpp 
b/src/system/kernel/arch/x86/arch_user_debugger.cpp
index 42aaf6f..99e2b83 100644
--- a/src/system/kernel/arch/x86/arch_user_debugger.cpp
+++ b/src/system/kernel/arch/x86/arch_user_debugger.cpp
@@ -516,7 +516,7 @@ debugger_single_step(int argc, char** argv)
        // TODO: Since we need an iframe, this doesn't work when KDL wasn't 
entered
        // via an exception.
 
-       struct iframe* frame = i386_get_current_iframe();
+       struct iframe* frame = x86_get_current_iframe();
        if (frame == NULL) {
                kprintf("Failed to get the current iframe!\n");
                return 0;
@@ -568,7 +568,7 @@ arch_destroy_thread_debug_info(struct 
arch_thread_debug_info *info)
 void
 arch_update_thread_single_step()
 {
-       if (struct iframe* frame = i386_get_user_iframe()) {
+       if (struct iframe* frame = x86_get_user_iframe()) {
                Thread* thread = thread_get_current_thread();
 
                // set/clear TF in EFLAGS depending on whether single stepping 
is
@@ -584,7 +584,7 @@ arch_update_thread_single_step()
 void
 arch_set_debug_cpu_state(const debug_cpu_state *cpuState)
 {
-       if (struct iframe *frame = i386_get_user_iframe()) {
+       if (struct iframe *frame = x86_get_user_iframe()) {
                // For the floating point state to be correct the calling 
function must
                // not use these registers (not even indirectly).
                if (gHasSSE) {
@@ -629,7 +629,7 @@ arch_set_debug_cpu_state(const debug_cpu_state *cpuState)
 void
 arch_get_debug_cpu_state(debug_cpu_state *cpuState)
 {
-       if (struct iframe *frame = i386_get_user_iframe()) {
+       if (struct iframe *frame = x86_get_user_iframe()) {
                // For the floating point state to be correct the calling 
function must
                // not use these registers (not even indirectly).
                if (gHasSSE) {
@@ -852,7 +852,7 @@ x86_handle_debug_exception(struct iframe *frame)
                asm("movl %%dr7, %0" : "=r"(dr7));
        }
 
-       TRACE(("i386_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, 
dr7));
+       TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7));
 
        // check, which exception condition applies
        if (dr6 & X86_DR6_BREAKPOINT_MASK) {
@@ -885,7 +885,7 @@ x86_handle_debug_exception(struct iframe *frame)
                // Occurs only, if GD in DR7 is set (which we don't do) and 
someone
                // tries to write to the debug registers.
                if (IFRAME_IS_USER(frame)) {
-                       dprintf("i386_handle_debug_exception(): ignoring 
spurious general "
+                       dprintf("x86_handle_debug_exception(): ignoring 
spurious general "
                                "detect exception\n");
 
                        enable_interrupts();
@@ -908,7 +908,7 @@ x86_handle_debug_exception(struct iframe *frame)
                        // kernel entry or whether this is genuine kernel 
single-stepping.
                        bool inKernel = true;
                        if (thread->team != team_get_kernel_team()
-                               && i386_get_user_iframe() == NULL) {
+                               && x86_get_user_iframe() == NULL) {
                                // TODO: This is not yet fully correct, since a 
newly created
                                // thread that hasn't entered userland yet also 
has this
                                // property.
@@ -948,7 +948,7 @@ x86_handle_debug_exception(struct iframe *frame)
                // task switch
                // Occurs only, if T in EFLAGS is set (which we don't do).
                if (IFRAME_IS_USER(frame)) {
-                       dprintf("i386_handle_debug_exception(): ignoring 
spurious task switch "
+                       dprintf("x86_handle_debug_exception(): ignoring 
spurious task switch "
                                "exception\n");
 
                        enable_interrupts();
@@ -956,7 +956,7 @@ x86_handle_debug_exception(struct iframe *frame)
                        panic("spurious task switch exception in kernel mode");
        } else {
                if (IFRAME_IS_USER(frame)) {
-                       TRACE(("i386_handle_debug_exception(): ignoring 
spurious debug "
+                       TRACE(("x86_handle_debug_exception(): ignoring spurious 
debug "
                                "exception (no condition recognized)\n"));
 
                        enable_interrupts();
@@ -974,7 +974,7 @@ x86_handle_debug_exception(struct iframe *frame)
 void
 x86_handle_breakpoint_exception(struct iframe *frame)
 {
-       TRACE(("i386_handle_breakpoint_exception()\n"));
+       TRACE(("x86_handle_breakpoint_exception()\n"));
 
        // reset eip to the int3 instruction
        frame->eip--;
diff --git a/src/system/kernel/arch/x86/vm86.cpp 
b/src/system/kernel/arch/x86/vm86.cpp
index ebfce51..948b701 100644
--- a/src/system/kernel/arch/x86/vm86.cpp
+++ b/src/system/kernel/arch/x86/vm86.cpp
@@ -512,7 +512,7 @@ emulate(struct vm86_state *state)
 static bool
 vm86_fault_callback(addr_t address, addr_t faultAddress, bool isWrite)
 {
-       struct iframe *frame = i386_get_user_iframe();
+       struct iframe *frame = x86_get_user_iframe();
 
        TRACE("Unhandled fault at %#" B_PRIxADDR " touching %#" B_PRIxADDR
                "while %s\n", faultAddress, address, isWrite ? "writing" : 
"reading");
diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp
index 21518a2..b4f00fb 100644
--- a/src/system/kernel/vm/vm.cpp
+++ b/src/system/kernel/vm/vm.cpp
@@ -4088,7 +4088,7 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool 
isWrite, bool isUser,
                                        #endif
                                } frame;
 #              ifdef __INTEL__
-                               struct iframe* iframe = i386_get_user_iframe();
+                               struct iframe* iframe = x86_get_user_iframe();
                                if (iframe == NULL)
                                        panic("iframe is NULL!");
 

############################################################################

Commit:      8c5e74719039c7275a5a80b236b830b7b4ba1be7

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Mon Jul  9 11:25:49 2012 UTC

Don't need to shift the factor in system_time(), just store the already shifted 
value.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp 
b/src/system/kernel/arch/x86/arch_cpu.cpp
index 2c61241..41713b3 100644
--- a/src/system/kernel/arch/x86/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86/arch_cpu.cpp
@@ -824,7 +824,8 @@ arch_cpu_init(kernel_args* args)
        // The x86_64 system_time() implementation uses 64-bit multiplication 
and
        // therefore shifting is not necessary for low frequencies (it's also 
not
        // too likely that there'll be any x86_64 CPUs clocked under 1GHz).
-       __x86_setup_system_time(conversionFactor, conversionFactorNsecs);
+       __x86_setup_system_time((uint64)conversionFactor << 32,
+               conversionFactorNsecs);
 #else
        if (conversionFactorNsecs >> 32 != 0) {
                // the TSC frequency is < 1 GHz, which forces us to shift the 
factor
diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S 
b/src/system/libroot/os/arch/x86_64/system_time_asm.S
index 135b54a..641c86d 100644
--- a/src/system/libroot/os/arch/x86_64/system_time_asm.S
+++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S
@@ -29,9 +29,9 @@ FUNCTION_END(__x86_setup_system_time)
 /* int64 system_time(); */
 FUNCTION(system_time):
        // (rdtsc * cv_factor) >> 32.
+       // Factor is pre-shifted left by 32 bits.
 
        movq    cv_factor, %rcx
-       shl             $32, %rcx
 
        // Load 64-bit TSC into %eax (low), %edx (high).
        rdtsc
@@ -43,7 +43,7 @@ FUNCTION(system_time):
        // Multiply by conversion factor, result in %rax (low), %rdx (high).
        mulq    %rcx
 
-       // Conversion factor preshifted by 32, whole result in high.
+       // Due to pre-shifting of the factor the whole result in high.
        movq    %rdx, %rax
        ret
 FUNCTION_END(system_time)
@@ -53,7 +53,7 @@ FUNCTION_END(system_time)
 FUNCTION(system_time_nsecs):
        // Same algorithm as system_time(), but with a different factor.
        // (rdtsc * cv_factor_nsecs) >> 32.
-       // Cannot pre-shift the factor here, otherwise we may lose the upper
+       // Factor has not been pre-shifted here, otherwise we may lose the upper
        // 32 bits.
 
        movq    cv_factor_nsecs, %rcx

############################################################################

Commit:      85d4a8bc4e248b992efcde8af001f156cd2c47a9

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Mon Jul  9 13:35:01 2012 UTC

Fixed compilation of C code using ELF headers.

----------------------------------------------------------------------------

diff --git a/headers/private/system/elf_common.h 
b/headers/private/system/elf_common.h
index edfd744..31eb0c0 100644
--- a/headers/private/system/elf_common.h
+++ b/headers/private/system/elf_common.h
@@ -272,7 +272,7 @@
 #endif
 #define DEFINE_ELF_TYPE(type, name) \
        struct _ELF_TYPE(type); \
-       typedef _ELF_TYPE(type) name
+       typedef struct _ELF_TYPE(type) name
 
 DEFINE_ELF_TYPE(Ehdr, elf_ehdr);
 DEFINE_ELF_TYPE(Phdr, elf_phdr);

############################################################################

Commit:      b5c9d24abcc3599375153ed310b495ea944d46a0

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Mon Jul  9 15:43:01 2012 UTC

Implemented threading for x86_64.

* Thread creation and switching is working fine, however threads do not yet
  get interrupted because I've not implemented hardware interrupt handling
  yet (I'll do that next).
* I've made some changes to struct iframe: I've removed the e/r prefixes
  from the member names for both 32/64, so now they're just named ip, ax,
  bp, etc. This makes it easier to write code that works with both 32/64
  without having to deal with different iframe member names.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/x86/32/iframe.h 
b/headers/private/kernel/arch/x86/32/iframe.h
index 6da6c1f..1aa51ed 100644
--- a/headers/private/kernel/arch/x86/32/iframe.h
+++ b/headers/private/kernel/arch/x86/32/iframe.h
@@ -15,25 +15,25 @@ struct iframe {
        uint32 fs;
        uint32 es;
        uint32 ds;
-       uint32 edi;
-       uint32 esi;
-       uint32 ebp;
-       uint32 esp;
-       uint32 ebx;
-       uint32 edx;
-       uint32 ecx;
-       uint32 eax;
+       uint32 di;
+       uint32 si;
+       uint32 bp;
+       uint32 sp;
+       uint32 bx;
+       uint32 dx;
+       uint32 cx;
+       uint32 ax;
        uint32 orig_eax;
        uint32 orig_edx;
        uint32 vector;
        uint32 error_code;
-       uint32 eip;
+       uint32 ip;
        uint32 cs;
        uint32 flags;
 
-       // user_esp and user_ss are only present when the iframe is a userland
+       // user_sp and user_ss are only present when the iframe is a userland
        // iframe (IFRAME_IS_USER()). A kernel iframe is shorter.
-       uint32 user_esp;
+       uint32 user_sp;
        uint32 user_ss;
 };
 
diff --git a/headers/private/kernel/arch/x86/64/descriptors.h 
b/headers/private/kernel/arch/x86/64/descriptors.h
index 8e70cba..3f05196 100644
--- a/headers/private/kernel/arch/x86/64/descriptors.h
+++ b/headers/private/kernel/arch/x86/64/descriptors.h
@@ -76,9 +76,9 @@ struct gdt_idt_descr {
 
 struct tss {
        uint32 _reserved1;
-       uint64 rsp0;
-       uint64 rsp1;
-       uint64 rsp2;
+       uint64 sp0;
+       uint64 sp1;
+       uint64 sp2;
        uint64 _reserved2;
        uint64 ist1;
        uint64 ist2;
diff --git a/headers/private/kernel/arch/x86/64/iframe.h 
b/headers/private/kernel/arch/x86/64/iframe.h
index a0ca48f..cd257ef 100644
--- a/headers/private/kernel/arch/x86/64/iframe.h
+++ b/headers/private/kernel/arch/x86/64/iframe.h
@@ -16,21 +16,21 @@ struct iframe {
        uint64 r10;
        uint64 r9;
        uint64 r8;
-       uint64 rbp;
-       uint64 rsi;
-       uint64 rdi;
-       uint64 rdx;
-       uint64 rcx;
-       uint64 rbx;
-       uint64 rax;
+       uint64 bp;
+       uint64 si;
+       uint64 di;
+       uint64 dx;
+       uint64 cx;
+       uint64 bx;
+       uint64 ax;
        uint64 vector;
        uint64 error_code;
-       uint64 rip;
+       uint64 ip;
        uint64 cs;
        uint64 flags;
 
        // Only present when the iframe is a userland iframe (IFRAME_IS_USER()).
-       uint64 user_rsp;
+       uint64 user_sp;
        uint64 user_ss;
 } _PACKED;
 
diff --git a/headers/private/kernel/arch/x86/arch_cpu.h 
b/headers/private/kernel/arch/x86/arch_cpu.h
index 17a3d41..32f0129 100644
--- a/headers/private/kernel/arch/x86/arch_cpu.h
+++ b/headers/private/kernel/arch/x86/arch_cpu.h
@@ -24,10 +24,6 @@
 #endif // !_ASSEMBLER
 
 
-#undef PAUSE
-#define PAUSE() asm volatile ("pause;")
-
-
 // MSR registers (possibly Intel specific)
 #define IA32_MSR_TSC                                   0x10
 #define IA32_MSR_APIC_BASE                             0x1b
@@ -40,6 +36,14 @@
 #define IA32_MSR_MTRR_PHYSICAL_BASE_0  0x200
 #define IA32_MSR_MTRR_PHYSICAL_MASK_0  0x201
 
+// x86_64 MSRs.
+#define IA32_MSR_STAR                                  0xc0000081
+#define IA32_MSR_LSTAR                                 0xc0000082
+#define IA32_MSR_FMASK                                 0xc0000084
+#define IA32_MSR_FS_BASE                               0xc0000100
+#define IA32_MSR_GS_BASE                               0xc0000101
+#define IA32_MSR_KERNEL_GS_BASE                        0xc0000102
+
 // K8 MSR registers
 #define K8_MSR_IPM                                             0xc0010055
 
@@ -268,6 +272,9 @@ typedef struct arch_cpu_info {
 } arch_cpu_info;
 
 
+#undef PAUSE
+#define PAUSE() asm volatile ("pause;")
+
 #define nop() __asm__ ("nop"::)
 
 #define x86_read_cr0() ({ \
@@ -379,11 +386,13 @@ void x86_context_switch(struct arch_thread* oldState,
        struct arch_thread* newState);
 void x86_userspace_thread_exit(void);
 void x86_end_userspace_thread_exit(void);
-void x86_swap_pgdir(uint32 newPageDir);
+void x86_swap_pgdir(addr_t newPageDir);
+void x86_set_tss_and_kstack(addr_t kstack);
 void x86_fxsave(void* fpuState);
 void x86_fxrstor(const void* fpuState);
+void x86_noop_swap(void* oldFpuState, const void* newFpuState);
 void x86_fxsave_swap(void* oldFpuState, const void* newFpuState);
-addr_t x86_read_ebp();
+addr_t x86_get_stack_frame();
 uint64 x86_read_msr(uint32 registerNumber);
 void x86_write_msr(uint32 registerNumber, uint64 value);
 void* x86_get_idt(int32 cpu);
@@ -401,10 +410,8 @@ void x86_page_fault_exception_double_fault(struct iframe* 
frame);
 
 #ifndef __x86_64__
 
-void x86_set_tss_and_kstack(addr_t kstack);
 void x86_fnsave(void* fpuState);
 void x86_frstor(const void* fpuState);
-void x86_noop_swap(void* oldFpuState, const void* newFpuState);
 void x86_fnsave_swap(void* oldFpuState, const void* newFpuState);
 void x86_set_task_gate(int32 cpu, int32 n, int32 segment);
 int32 x86_double_fault_get_cpu(void);
diff --git a/headers/private/kernel/arch/x86/arch_debug.h 
b/headers/private/kernel/arch/x86/arch_debug.h
index 789ecc74..eb2028f 100644
--- a/headers/private/kernel/arch/x86/arch_debug.h
+++ b/headers/private/kernel/arch/x86/arch_debug.h
@@ -10,7 +10,7 @@
 
 
 struct arch_debug_registers {
-       uint32  ebp;
+       addr_t  bp;
 };
 
 
diff --git a/headers/private/kernel/arch/x86/arch_thread.h 
b/headers/private/kernel/arch/x86/arch_thread.h
index 4a08809..850cfc9 100644
--- a/headers/private/kernel/arch/x86/arch_thread.h
+++ b/headers/private/kernel/arch/x86/arch_thread.h
@@ -16,35 +16,40 @@
 extern "C" {
 #endif
 
+struct sigaction;
+
 
 struct iframe* x86_get_user_iframe(void);
 struct iframe* x86_get_current_iframe(void);
 struct iframe* x86_get_thread_user_iframe(Thread* thread);
 
-uint32 x86_next_page_directory(Thread* from, Thread* to);
+phys_addr_t x86_next_page_directory(Thread* from, Thread* to);
+void x86_initial_return_to_userland(Thread* thread, struct iframe* iframe);
+uint8* x86_get_signal_stack(Thread* thread, struct iframe* frame,
+       struct sigaction* action);
 
 void x86_restart_syscall(struct iframe* frame);
-
 void x86_set_tls_context(Thread* thread);
 
 
 #ifdef __x86_64__
 
-// TODO
-
-extern Thread* gCurrentThread;
 
 static inline Thread*
 arch_thread_get_current_thread(void)
 {
-       return gCurrentThread;
+       addr_t addr;
+       __asm__("mov %%gs:0, %0" : "=r"(addr));
+       return (Thread*)addr;
 }
 
 
 static inline void
 arch_thread_set_current_thread(Thread* t)
 {
-       gCurrentThread = t;
+       // Point GS segment base at thread architecture data.
+       t->arch_info.thread = t;
+       x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&t->arch_info);
 }
 
 
diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h 
b/headers/private/kernel/arch/x86/arch_thread_types.h
index 900046f..209543e 100644
--- a/headers/private/kernel/arch/x86/arch_thread_types.h
+++ b/headers/private/kernel/arch/x86/arch_thread_types.h
@@ -12,27 +12,42 @@
 #include <arch_cpu.h>
 
 
+namespace BKernel {
+    struct Thread;
+}
+
+
 #define _ALIGNED(bytes) __attribute__((aligned(bytes)))
        // move this to somewhere else, maybe BeBuild.h?
 
 
+#ifndef __x86_64__
 struct farcall {
        uint32* esp;
        uint32* ss;
 };
+#endif
 
 
 // architecture specific thread info
 struct arch_thread {
 #ifdef __x86_64__
-       uint64* rsp;
+       // Back pointer to the containing Thread structure. The GS segment base 
is
+       // pointed here, used to get the current thread.
+       BKernel::Thread* thread;
+
+       // RSP for kernel entry used by SYSCALL, and temporary scratch space.
+       uint64*                 syscall_rsp;
+       uint64*                 user_rsp;
+
+       uint64*                 current_stack;
 #else
-       struct farcall current_stack;
-       struct farcall interrupt_stack;
+       struct farcall  current_stack;
+       struct farcall  interrupt_stack;
 #endif
 
        // 512 byte floating point save point - this must be 16 byte aligned
-       uint8 fpu_state[512] _ALIGNED(16);
+       uint8                   fpu_state[512] _ALIGNED(16);
 } _ALIGNED(16);
 
 
@@ -40,7 +55,7 @@ struct arch_team {
        // gcc treats empty structures as zero-length in C, but as if they 
contain
        // a char in C++. So we have to put a dummy in to be able to use the 
struct
        // from both in a consistent way.
-       char    dummy;
+       char                    dummy;
 };
 
 
diff --git a/src/system/kernel/arch/x86/32/arch.S 
b/src/system/kernel/arch/x86/32/arch.S
index e966580..97eb069 100644
--- a/src/system/kernel/arch/x86/32/arch.S
+++ b/src/system/kernel/arch/x86/32/arch.S
@@ -71,11 +71,11 @@ FUNCTION(x86_fxsave_swap):
        ret
 FUNCTION_END(x86_fxsave_swap)
 
-/* uint32 x86_read_ebp(); */
-FUNCTION(x86_read_ebp):
+/* uint32 x86_get_stack_frame(); */
+FUNCTION(x86_get_stack_frame):
        movl    %ebp, %eax
        ret
-FUNCTION_END(x86_read_ebp)
+FUNCTION_END(x86_get_stack_frame)
 
 /* uint64 x86_read_msr(uint32 register); */
 FUNCTION(x86_read_msr):
diff --git a/src/system/kernel/arch/x86/32/int.cpp 
b/src/system/kernel/arch/x86/32/int.cpp
index d35e3f0..acfc117 100644
--- a/src/system/kernel/arch/x86/32/int.cpp
+++ b/src/system/kernel/arch/x86/32/int.cpp
@@ -161,7 +161,7 @@ invalid_exception(struct iframe* frame)
        char name[32];
        panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n",
                frame->vector, exception_name(frame->vector, name, 
sizeof(name)),
-               frame->eip, thread ? thread->id : -1);
+               frame->ip, thread ? thread->id : -1);
 }
 
 
@@ -194,14 +194,14 @@ unexpected_exception(struct iframe* frame)
                        type = B_DIVIDE_ERROR;
                        signalNumber = SIGFPE;
                        signalCode = FPE_INTDIV;
-                       signalAddress = frame->eip;
+                       signalAddress = frame->ip;
                        break;
 
                case 4:         // Overflow Exception (#OF)
                        type = B_OVERFLOW_EXCEPTION;
                        signalNumber = SIGFPE;
                        signalCode = FPE_INTOVF;
-                       signalAddress = frame->eip;
+                       signalAddress = frame->ip;
                        break;
 
                case 5:         // BOUND Range Exceeded Exception (#BR)
@@ -214,14 +214,14 @@ unexpected_exception(struct iframe* frame)
                        type = B_INVALID_OPCODE_EXCEPTION;
                        signalNumber = SIGILL;
                        signalCode = ILL_ILLOPC;
-                       signalAddress = frame->eip;
+                       signalAddress = frame->ip;
                        break;
 
                case 13:        // General Protection Exception (#GP)
                        type = B_GENERAL_PROTECTION_FAULT;
                        signalNumber = SIGILL;
                        signalCode = ILL_PRVOPC;        // or ILL_PRVREG
-                       signalAddress = frame->eip;
+                       signalAddress = frame->ip;
                        break;
 
                case 16:        // x87 FPU Floating-Point Error (#MF)
@@ -230,7 +230,7 @@ unexpected_exception(struct iframe* frame)
                        signalCode = FPE_FLTDIV;
                                // TODO: Determine the correct cause via the 
FPU status
                                // register!
-                       signalAddress = frame->eip;
+                       signalAddress = frame->ip;
                        break;
 
                case 17:        // Alignment Check Exception (#AC)
@@ -247,7 +247,7 @@ unexpected_exception(struct iframe* frame)
                        signalNumber = SIGFPE;
                        signalCode = FPE_FLTDIV;
                                // TODO: Determine the correct cause via the 
MXCSR register!
-                       signalAddress = frame->eip;
+                       signalAddress = frame->ip;
                        break;
 
                default:
@@ -300,15 +300,15 @@ x86_double_fault_exception(struct iframe* frame)
        frame->ds = tss->ds;
        frame->fs = tss->fs;
        frame->gs = tss->gs;
-       frame->eip = tss->eip;
-       frame->ebp = tss->ebp;
-       frame->esp = tss->esp;
-       frame->eax = tss->eax;
-       frame->ebx = tss->ebx;
-       frame->ecx = tss->ecx;
-       frame->edx = tss->edx;
-       frame->esi = tss->esi;
-       frame->edi = tss->edi;
+       frame->ip = tss->eip;
+       frame->bp = tss->ebp;
+       frame->sp = tss->esp;
+       frame->ax = tss->eax;
+       frame->bx = tss->ebx;
+       frame->cx = tss->ecx;
+       frame->dx = tss->edx;
+       frame->si = tss->esi;
+       frame->di = tss->edi;
        frame->flags = tss->eflags;
 
        // Use a special handler for page faults which avoids the triple fault
@@ -328,10 +328,10 @@ x86_page_fault_exception_double_fault(struct iframe* 
frame)
        cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()];
        addr_t faultHandler = cpu.fault_handler;
        if (faultHandler != 0) {
-               debug_set_page_fault_info(cr2, frame->eip,
+               debug_set_page_fault_info(cr2, frame->ip,
                        (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE 
: 0);
-               frame->eip = faultHandler;
-               frame->ebp = cpu.fault_handler_stack_pointer;
+               frame->ip = faultHandler;
+               frame->bp = cpu.fault_handler_stack_pointer;
                return;
        }
 
@@ -340,7 +340,7 @@ x86_page_fault_exception_double_fault(struct iframe* frame)
        // print the info we've got and enter an infinite loop.
        kprintf("Page fault in double fault debugger without fault handler! "
                "Touching address %p from eip %p. Entering infinite loop...\n",
-               (void*)cr2, (void*)frame->eip);
+               (void*)cr2, (void*)frame->ip);
 
        while (true);
 }
@@ -359,28 +359,28 @@ page_fault_exception(struct iframe* frame)
                if (thread != NULL) {
                        cpu_ent* cpu = &gCPU[smp_get_current_cpu()];
                        if (cpu->fault_handler != 0) {
-                               debug_set_page_fault_info(cr2, frame->eip,
+                               debug_set_page_fault_info(cr2, frame->ip,
                                        (frame->error_code & 0x2) != 0
                                                ? DEBUG_PAGE_FAULT_WRITE : 0);
-                               frame->eip = cpu->fault_handler;
-                               frame->ebp = cpu->fault_handler_stack_pointer;
+                               frame->ip = cpu->fault_handler;
+                               frame->bp = cpu->fault_handler_stack_pointer;
                                return;
                        }
 
                        if (thread->fault_handler != 0) {
                                kprintf("ERROR: thread::fault_handler used in 
kernel "
                                        "debugger!\n");
-                               debug_set_page_fault_info(cr2, frame->eip,
+                               debug_set_page_fault_info(cr2, frame->ip,
                                        (frame->error_code & 0x2) != 0
                                                ? DEBUG_PAGE_FAULT_WRITE : 0);
-                               frame->eip = thread->fault_handler;
+                               frame->ip = thread->fault_handler;
                                return;
                        }
                }
 
                // otherwise, not really
                panic("page fault in debugger without fault handler! Touching "
-                       "address %p from eip %p\n", (void *)cr2, (void 
*)frame->eip);
+                       "address %p from eip %p\n", (void *)cr2, (void 
*)frame->ip);
                return;
        } else if ((frame->flags & 0x200) == 0) {
                // interrupts disabled
@@ -390,8 +390,8 @@ page_fault_exception(struct iframe* frame)
                // disabled, which in most cases is a bug. We should add some 
thread
                // flag allowing to explicitly indicate that this handling is 
desired.
                if (thread && thread->fault_handler != 0) {
-                       if (frame->eip != thread->fault_handler) {
-                               frame->eip = thread->fault_handler;
+                       if (frame->ip != thread->fault_handler) {
+                               frame->ip = thread->fault_handler;
                                return;
                        }
 
@@ -399,30 +399,30 @@ page_fault_exception(struct iframe* frame)
                        // certain infinite loop.
                        panic("page fault, interrupts disabled, fault handler 
loop. "
                                "Touching address %p from eip %p\n", (void*)cr2,
-                               (void*)frame->eip);
+                               (void*)frame->ip);
                }
 
                // If we are not running the kernel startup the page fault was 
not
                // allowed to happen and we must panic.
                panic("page fault, but interrupts were disabled. Touching 
address "
-                       "%p from eip %p\n", (void *)cr2, (void *)frame->eip);
+                       "%p from eip %p\n", (void *)cr2, (void *)frame->ip);
                return;
        } else if (thread != NULL && thread->page_faults_allowed < 1) {
                panic("page fault not allowed at this place. Touching address "
-                       "%p from eip %p\n", (void *)cr2, (void *)frame->eip);
+                       "%p from eip %p\n", (void *)cr2, (void *)frame->ip);
                return;
        }
 
        enable_interrupts();
 
-       vm_page_fault(cr2, frame->eip,
+       vm_page_fault(cr2, frame->ip,
                (frame->error_code & 0x2) != 0, // write access
                (frame->error_code & 0x4) != 0, // userland
                &newip);
        if (newip != 0) {
                // the page fault handler wants us to modify the iframe to set 
the
                // IP the cpu will return to to be this ip
-               frame->eip = newip;
+               frame->ip = newip;
        }
 }
 
diff --git a/src/system/kernel/arch/x86/32/interrupts.S 
b/src/system/kernel/arch/x86/32/interrupts.S
index 014fa33..ea3cd5e 100644
--- a/src/system/kernel/arch/x86/32/interrupts.S
+++ b/src/system/kernel/arch/x86/32/interrupts.S
@@ -138,7 +138,7 @@
        subl    $80, %esp;                                                      
                                                \
                                                                                
                                                                \
        /* get the address of the syscall parameters */                         
                \
-       movl    IFRAME_user_esp(%ebp), %esi;                                    
                        \
+       movl    IFRAME_user_sp(%ebp), %esi;                                     
                                \
        addl    $4, %esi;                                                       
                                                \
        cmp             $KERNEL_BASE, %esi;             /* must not be a kernel 
address */      \
        jae             bad_syscall_params;                                     
                                                \
@@ -673,8 +673,8 @@ STATIC_FUNCTION(handle_syscall):
 
        // overwrite the values of %eax and %edx on the stack (the syscall 
return
        // value)
-       movl    %edx, IFRAME_edx(%ebp)
-       movl    %eax, IFRAME_eax(%ebp)
+       movl    %edx, IFRAME_dx(%ebp)
+       movl    %eax, IFRAME_ax(%ebp)
 
        TRACE_POST_SYSCALL()
 
@@ -725,8 +725,8 @@ FUNCTION_END(handle_syscall)
        jz              1f
        pushl   -8(%ebp)                                // syscall start time
        pushl   -12(%ebp)
-       movl    IFRAME_edx(%ebp), %edx  // syscall return value
-       movl    IFRAME_eax(%ebp), %eax
+       movl    IFRAME_dx(%ebp), %edx   // syscall return value
+       movl    IFRAME_ax(%ebp), %eax
        push    %edx
        push    %eax
        lea             16(%esp), %eax                  // syscall parameters
diff --git a/src/system/kernel/arch/x86/32/thread.cpp 
b/src/system/kernel/arch/x86/32/thread.cpp
new file mode 100644
index 0000000..4df1685
--- /dev/null
+++ b/src/system/kernel/arch/x86/32/thread.cpp
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2002-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ *
+ * Copyright 2001, Travis Geiselbrecht. All rights reserved.
+ * Distributed under the terms of the NewOS License.
+ */
+
+
+#include <arch/thread.h>
+
+#include <string.h>
+
+#include <arch/user_debugger.h>
+#include <arch_cpu.h>
+#include <cpu.h>
+#include <debug.h>
+#include <kernel.h>
+#include <ksignal.h>
+#include <int.h>
+#include <team.h>
+#include <thread.h>
+#include <tls.h>
+#include <tracing.h>
+#include <util/AutoLock.h>
+#include <vm/vm_types.h>
+#include <vm/VMAddressSpace.h>
+
+#include "paging/X86PagingStructures.h"
+#include "paging/X86VMTranslationMap.h"
+#include "x86_signals.h"
+
+
+//#define TRACE_ARCH_THREAD
+#ifdef TRACE_ARCH_THREAD
+#      define TRACE(x) dprintf x
+#else
+#      define TRACE(x) ;
+#endif
+
+
+#ifdef SYSCALL_TRACING
+
+namespace SyscallTracing {
+
+class RestartSyscall : public AbstractTraceEntry {
+       public:
+               RestartSyscall()
+               {
+                       Initialized();
+               }
+
+               virtual void AddDump(TraceOutput& out)
+               {
+                       out.Print("syscall restart");
+               }
+};
+
+}
+
+#      define TSYSCALL(x)      new(std::nothrow) SyscallTracing::x
+
+#else
+#      define TSYSCALL(x)
+#endif // SYSCALL_TRACING
+
+
+// from arch_cpu.cpp
+extern bool gHasSSE;
+
+static struct arch_thread sInitialState _ALIGNED(16);
+       // the fpu_state must be aligned on a 16 byte boundary, so that fxsave 
can use it
+
+
+static inline void
+set_fs_register(uint32 segment)
+{
+       asm("movl %0,%%fs" :: "r" (segment));
+}
+
+
+void
+x86_restart_syscall(struct iframe* frame)
+{
+       Thread* thread = thread_get_current_thread();
+
+       atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
+       atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED);
+
+       frame->ax = frame->orig_eax;
+       frame->dx = frame->orig_edx;
+       frame->ip -= 2;
+               // undoes the "int $99"/"sysenter"/"syscall" instruction
+               // (so that it'll be executed again)
+
+       TSYSCALL(RestartSyscall());
+}
+
+
+void
+x86_set_tls_context(Thread *thread)
+{
+       int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT;
+
+       set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage);
+       set_fs_register((entry << 3) | DPL_USER);
+}
+
+
+//     #pragma mark -
+
+
+status_t
+arch_thread_init(struct kernel_args *args)
+{
+       // save one global valid FPU state; it will be copied in the arch 
dependent
+       // part of each new thread
+
+       asm volatile ("clts; fninit; fnclex;");
+       if (gHasSSE)
+               x86_fxsave(sInitialState.fpu_state);
+       else
+               x86_fnsave(sInitialState.fpu_state);
+
+       return B_OK;
+}
+
+
+status_t
+arch_thread_init_thread_struct(Thread *thread)
+{
+       // set up an initial state (stack & fpu)
+       memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread));
+       return B_OK;
+}
+
+
+/*!    Prepares the given thread's kernel stack for executing its entry 
function.
+
+       \param thread The thread.
+       \param stack The usable bottom of the thread's kernel stack.
+       \param stackTop The usable top of the thread's kernel stack.
+       \param function The entry function the thread shall execute.
+       \param data Pointer to be passed to the entry function.
+*/
+void
+arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
+       void (*function)(void*), const void* data)
+{
+       addr_t* stackTop = (addr_t*)_stackTop;
+
+       TRACE(("arch_thread_init_kthread_stack: stack top %p, function %p, 
data: "
+               "%p\n", stackTop, function, data));
+
+       // push the function argument, a pointer to the data
+       *--stackTop = (addr_t)data;
+
+       // push a dummy return address for the function
+       *--stackTop = 0;
+
+       // push the function address -- that's the return address used after the
+       // context switch
+       *--stackTop = (addr_t)function;
+
+       // simulate pushad as done by x86_context_switch()
+       for (int i = 0; i < 8; i++)
+               *--stackTop = 0;
+
+       // save the stack position
+       thread->arch_info.current_stack.esp = stackTop;
+       thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SEG;
+}
+
+
+/*!    Initializes the user-space TLS local storage pointer in
+       the thread structure, and the reserved TLS slots.
+       
+       Is called from _create_user_thread_kentry().
+*/
+status_t
+arch_thread_init_tls(Thread *thread)
+{
+       uint32 tls[TLS_USER_THREAD_SLOT + 1];
+
+       thread->user_local_storage = thread->user_stack_base
+               + thread->user_stack_size;
+
+       // initialize default TLS fields
+       memset(tls, 0, sizeof(tls));
+       tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
+       tls[TLS_THREAD_ID_SLOT] = thread->id;
+       tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread;
+
+       return user_memcpy((void *)thread->user_local_storage, tls, 
sizeof(tls));
+}
+
+
+void
+arch_thread_dump_info(void *info)
+{
+       struct arch_thread *at = (struct arch_thread *)info;
+
+       kprintf("\tesp: %p\n", at->current_stack.esp);
+       kprintf("\tss: %p\n", at->current_stack.ss);
+       kprintf("\tfpu_state at %p\n", at->fpu_state);
+}
+
+
+/*!    Sets up initial thread context and enters user space
+*/
+status_t
+arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
+       void* args2)
+{
+       addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
+       uint32 codeSize = (addr_t)x86_end_userspace_thread_exit
+               - (addr_t)x86_userspace_thread_exit;
+       uint32 args[3];
+
+       TRACE(("arch_thread_enter_userspace: entry 0x%lx, args %p %p, "
+               "ustack_top 0x%lx\n", entry, args1, args2, stackTop));
+
+       // copy the little stub that calls exit_thread() when the thread entry
+       // function returns, as well as the arguments of the entry function
+       stackTop -= codeSize;
+
+       if (user_memcpy((void *)stackTop, (const void 
*)&x86_userspace_thread_exit, codeSize) < B_OK)
+               return B_BAD_ADDRESS;
+
+       args[0] = stackTop;
+       args[1] = (uint32)args1;
+       args[2] = (uint32)args2;
+       stackTop -= sizeof(args);
+
+       if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK)
+               return B_BAD_ADDRESS;
+
+       // prepare the user iframe
+       iframe frame = {};
+       frame.type = IFRAME_TYPE_SYSCALL;
+       frame.gs = USER_DATA_SEG;
+       // frame.fs not used, we call x86_set_tls_context() on context switch
+       frame.es = USER_DATA_SEG;
+       frame.ds = USER_DATA_SEG;
+       frame.ip = entry;
+       frame.cs = USER_CODE_SEG;
+       frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT
+               | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT);
+       frame.user_sp = stackTop;
+       frame.user_ss = USER_DATA_SEG;
+
+       // return to userland
+       x86_initial_return_to_userland(thread, &frame);
+
+       return B_OK;
+               // never gets here
+}
+
+
+/*!    Sets up the user iframe for invoking a signal handler.
+
+       The function fills in the remaining fields of the given \a 
signalFrameData,
+       copies it to the thread's userland stack (the one on which the signal 
shall
+       be handled), and sets up the user iframe so that when returning to 
userland
+       a wrapper function is executed that calls the user-defined signal 
handler.
+       When the signal handler returns, the wrapper function shall call the
+       "restore signal frame" syscall with the (possibly modified) signal frame
+       data.
+
+       The following fields of the \a signalFrameData structure still need to 
be
+       filled in:
+       - \c context.uc_stack: The stack currently used by the thread.
+       - \c context.uc_mcontext: The current userland state of the registers.
+       - \c syscall_restart_return_value: Architecture specific use. On x86 the
+               value of eax and edx which are overwritten by the syscall 
return value.
+
+       Furthermore the function needs to set \c thread->user_signal_context to 
the
+       userland pointer to the \c ucontext_t on the user stack.
+
+       \param thread The current thread.
+       \param action The signal action specified for the signal to be handled.
+       \param signalFrameData A partially initialized structure of all the data
+               that need to be copied to userland.
+       \return \c B_OK on success, another error code, if something goes wrong.
+*/
+status_t
+arch_setup_signal_frame(Thread* thread, struct sigaction* action,
+       struct signal_frame_data* signalFrameData)
+{
+       struct iframe *frame = x86_get_current_iframe();
+       if (!IFRAME_IS_USER(frame)) {
+               panic("arch_setup_signal_frame(): No user iframe!");
+               return B_BAD_VALUE;
+       }
+
+       // In case of a BeOS compatible handler map SIGBUS to SIGSEGV, since 
they
+       // had the same signal number.
+       if ((action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0
+               && signalFrameData->info.si_signo == SIGBUS) {
+               signalFrameData->info.si_signo = SIGSEGV;
+       }
+
+       // store the register state in signalFrameData->context.uc_mcontext
+       signalFrameData->context.uc_mcontext.eip = frame->ip;
+       signalFrameData->context.uc_mcontext.eflags = frame->flags;
+       signalFrameData->context.uc_mcontext.eax = frame->ax;
+       signalFrameData->context.uc_mcontext.ecx = frame->cx;
+       signalFrameData->context.uc_mcontext.edx = frame->dx;
+       signalFrameData->context.uc_mcontext.ebp = frame->bp;
+       signalFrameData->context.uc_mcontext.esp = frame->user_sp;
+       signalFrameData->context.uc_mcontext.edi = frame->di;
+       signalFrameData->context.uc_mcontext.esi = frame->si;
+       signalFrameData->context.uc_mcontext.ebx = frame->bx;
+       x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs));
+
+       // fill in signalFrameData->context.uc_stack
+       signal_get_user_stack(frame->user_sp, 
&signalFrameData->context.uc_stack);
+
+       // store orig_eax/orig_edx in syscall_restart_return_value
+       signalFrameData->syscall_restart_return_value
+               = (uint64)frame->orig_edx << 32 | frame->orig_eax;
+
+       // get the stack to use -- that's either the current one or a special 
signal
+       // stack
+       uint8* userStack = x86_get_signal_stack(thread, frame, action);
+
+       // copy the signal frame data onto the stack
+       userStack -= sizeof(*signalFrameData);
+       signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack;
+       if (user_memcpy(userSignalFrameData, signalFrameData,
+                       sizeof(*signalFrameData)) != B_OK) {
+               return B_BAD_ADDRESS;
+       }
+
+       // prepare the user stack frame for a function call to the signal 
handler
+       // wrapper function
+       uint32 stackFrame[2] = {
+               frame->ip,              // return address
+               (addr_t)userSignalFrameData, // parameter: pointer to signal 
frame data
+       };
+
+       userStack -= sizeof(stackFrame);
+       if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK)
+               return B_BAD_ADDRESS;
+
+       // Update Thread::user_signal_context, now that everything seems to have
+       // gone fine.
+       thread->user_signal_context = &userSignalFrameData->context;
+
+       // Adjust the iframe's esp and eip, so that the thread will continue 
with
+       // the prepared stack, executing the signal handler wrapper function.
+       frame->user_sp = (addr_t)userStack;
+       frame->ip = x86_get_user_signal_handler_wrapper(
+               (action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0);
+
+       return B_OK;
+}
+
+
+int64
+arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
+{
+       struct iframe* frame = x86_get_current_iframe();
+
+       TRACE(("### arch_restore_signal_frame: entry\n"));
+
+       frame->orig_eax = (uint32)signalFrameData->syscall_restart_return_value;
+       frame->orig_edx
+               = (uint32)(signalFrameData->syscall_restart_return_value >> 32);
+
+       frame->ip = signalFrameData->context.uc_mcontext.eip;
+       frame->flags = (frame->flags & ~(uint32)X86_EFLAGS_USER_FLAGS)
+               | (signalFrameData->context.uc_mcontext.eflags & 
X86_EFLAGS_USER_FLAGS);
+       frame->ax = signalFrameData->context.uc_mcontext.eax;
+       frame->cx = signalFrameData->context.uc_mcontext.ecx;
+       frame->dx = signalFrameData->context.uc_mcontext.edx;
+       frame->bp = signalFrameData->context.uc_mcontext.ebp;
+       frame->user_sp = signalFrameData->context.uc_mcontext.esp;
+       frame->di = signalFrameData->context.uc_mcontext.edi;
+       frame->si = signalFrameData->context.uc_mcontext.esi;
+       frame->bx = signalFrameData->context.uc_mcontext.ebx;
+
+       x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs));
+
+       TRACE(("### arch_restore_signal_frame: exit\n"));
+
+       return (int64)frame->ax | ((int64)frame->dx << 32);
+}
+
+
+void
+arch_syscall_64_bit_return_value(void)
+{
+       Thread* thread = thread_get_current_thread();
+       atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN);
+}
diff --git a/src/system/kernel/arch/x86/64/arch.S 
b/src/system/kernel/arch/x86/64/arch.S
index eb51f75..4fe6573 100644
--- a/src/system/kernel/arch/x86/64/arch.S
+++ b/src/system/kernel/arch/x86/64/arch.S
@@ -6,6 +6,8 @@
 
 #include <asm_defs.h>
 
+#include "asm_offsets.h"
+
 
 .text
 
@@ -24,6 +26,13 @@ FUNCTION(x86_fxrstor):
 FUNCTION_END(x86_fxrstor)
 
 
+/* void x86_noop_swap(void *oldFpuState, const void *newFpuState); */
+FUNCTION(x86_noop_swap):
+       nop
+       ret
+FUNCTION_END(x86_noop_swap)
+
+
 /* void x86_fxsave_swap(void* oldFpuState, const void* newFpuState); */
 FUNCTION(x86_fxsave_swap):
        fxsave  (%rdi)
@@ -32,11 +41,11 @@ FUNCTION(x86_fxsave_swap):
 FUNCTION_END(x86_fxsave_swap)
 
 
-/* addr_t x86_read_ebp(); */
-FUNCTION(x86_read_ebp):
+/* addr_t x86_get_stack_frame(); */
+FUNCTION(x86_get_stack_frame):
        mov             %rbp, %rax
        ret
-FUNCTION_END(x86_read_ebp)
+FUNCTION_END(x86_get_stack_frame)
 
 
 /* uint64 x86_read_msr(uint32 register); */
@@ -61,6 +70,47 @@ FUNCTION(x86_write_msr):
 FUNCTION_END(x86_write_msr)
 
 
+/* void x86_64_thread_entry(); */
+FUNCTION(x86_64_thread_entry):
+       movq    %r15, %rdi
+       jmp             *%r14
+FUNCTION_END(x86_64_thread_entry)
+
+
+/* void x86_context_switch(struct arch_thread* oldState,
+       struct arch_thread* newState); */
+FUNCTION(x86_context_switch):
+       // Just need to save callee-save registers: RBP, RBX, R12-15.
+       push    %r15
+       push    %r14
+       push    %r13
+       push    %r12
+       push    %rbp
+       push    %rbx
+
+       // Swap the stack pointers.
+       movq    %rsp, ARCH_THREAD_current_stack(%rdi)
+       movq    ARCH_THREAD_current_stack(%rsi), %rsp
+
+       // Restore callee-save registers.
+       pop             %rbx
+       pop             %rbp
+       pop             %r12
+       pop             %r13
+       pop             %r14
+       pop             %r15
+
+       ret
+FUNCTION_END(x86_context_switch)
+
+
+/* void x86_swap_pgdir(uint64 newPageDir); */
+FUNCTION(x86_swap_pgdir):
+       movq    %rdi, %cr3
+       ret
+FUNCTION_END(x86_swap_pgdir)
+
+
 null_idt_descr:
        .word   0
        .quad   0
diff --git a/src/system/kernel/arch/x86/64/int.cpp 
b/src/system/kernel/arch/x86/64/int.cpp
index bbc5850..6117171 100644
--- a/src/system/kernel/arch/x86/64/int.cpp
+++ b/src/system/kernel/arch/x86/64/int.cpp
@@ -72,7 +72,7 @@ invalid_exception(iframe* frame)
        char name[32];
        panic("unhandled trap %#lx (%s) at ip %#lx\n",
                frame->vector, exception_name(frame->vector, name, 
sizeof(name)),
-               frame->rip);
+               frame->ip);
 }
 
 
@@ -82,7 +82,7 @@ fatal_exception(iframe* frame)
        char name[32];
        panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n",
                frame->vector, exception_name(frame->vector, name, 
sizeof(name)),
-               frame->rip, frame->error_code);
+               frame->ip, frame->error_code);
 }
 
 
@@ -92,7 +92,7 @@ unexpected_exception(iframe* frame)
        char name[32];
        panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n",
                frame->vector, exception_name(frame->vector, name, 
sizeof(name)),
-               frame->rip, frame->error_code);
+               frame->ip, frame->error_code);
 }
 
 
@@ -102,7 +102,7 @@ page_fault_exception(iframe* frame)
        addr_t cr2 = x86_read_cr2();
 
        panic("page fault exception at ip %#lx on %#lx, error code %#lx\n",
-               frame->rip, cr2, frame->error_code);
+               frame->ip, cr2, frame->error_code);
 }
 
 
diff --git a/src/system/kernel/arch/x86/64/interrupts.S 
b/src/system/kernel/arch/x86/64/interrupts.S
index d5f8fca..7987ed2 100644
--- a/src/system/kernel/arch/x86/64/interrupts.S
+++ b/src/system/kernel/arch/x86/64/interrupts.S
@@ -111,6 +111,7 @@ SYMBOL(isr_array):
                .Lintr = .Lintr+1
        .endr
 
+
 // Common interrupt handling code.
 FUNCTION(int_bottom):
        // If coming from user-mode, need to load the kernel GS segment base.
@@ -141,3 +142,21 @@ FUNCTION(int_bottom):
        jz              2f
        swapgs
 2:     iretq
+FUNCTION_END(int_bottom)
+
+
+/*!    \fn void x86_return_to_userland(iframe* frame)
+       \brief Returns to the userland environment given by \a frame.
+
+       Before returning to userland all potentially necessary kernel exit work 
is
+       done.
+
+       \a frame must point to a location somewhere on the caller's stack (e.g. 
a
+       local variable).
+       The function must be called with interrupts disabled.
+
+       \param frame The iframe defining the userland environment.
+*/
+FUNCTION(x86_return_to_userland):
+       ud2a
+FUNCTION_END(x86_return_to_userland)
diff --git a/src/system/kernel/arch/x86/64/stubs.cpp 
b/src/system/kernel/arch/x86/64/stubs.cpp
index 5f85b9a..2651c32 100644
--- a/src/system/kernel/arch/x86/64/stubs.cpp
+++ b/src/system/kernel/arch/x86/64/stubs.cpp
@@ -37,10 +37,6 @@
 #include <arch/elf.h>
 
 
-// temporary
-Thread* gCurrentThread = NULL;
-
-
 status_t
 arch_commpage_init(void)
 {
@@ -106,23 +102,23 @@ print_iframe(struct iframe* frame)
        bool isUser = IFRAME_IS_USER(frame);
 
        kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", 
frame,
-               isUser ? (uint64*)(frame + 1) : &frame->user_rsp);
+               isUser ? (uint64*)(frame + 1) : &frame->user_sp);
 
-       kprintf(" rax 0x%-16lx    rbx 0x%-16lx    rcx 0x%lx\n", frame->rax,
-               frame->rbx, frame->rcx);
-       kprintf(" rdx 0x%-16lx    rsi 0x%-16lx    rdi 0x%lx\n", frame->rdx,
-               frame->rsi, frame->rdi);
-       kprintf(" rbp 0x%-16lx     r8 0x%-16lx     r9 0x%lx\n", frame->rbp,
+       kprintf(" rax 0x%-16lx    rbx 0x%-16lx    rcx 0x%lx\n", frame->ax,
+               frame->bx, frame->cx);
+       kprintf(" rdx 0x%-16lx    rsi 0x%-16lx    rdi 0x%lx\n", frame->dx,
+               frame->si, frame->di);
+       kprintf(" rbp 0x%-16lx     r8 0x%-16lx     r9 0x%lx\n", frame->bp,
                frame->r8, frame->r9);
        kprintf(" r10 0x%-16lx    r11 0x%-16lx    r12 0x%lx\n", frame->r10,
                frame->r11, frame->r12);
        kprintf(" r13 0x%-16lx    r14 0x%-16lx    r15 0x%lx\n", frame->r13,
                frame->r14, frame->r15);
-       kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->rip, frame->flags);
+       kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->ip, frame->flags);
 
        if (isUser) {
                // from user space
-               kprintf("user rsp 0x%lx", frame->user_rsp);
+               kprintf("user rsp 0x%lx", frame->user_sp);
        }
        kprintf("\n");
        kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector,
@@ -186,7 +182,7 @@ print_stack_frame(addr_t rip, addr_t rbp, addr_t nextRbp, 
int32 callIndex)
 void
 arch_debug_stack_trace(void)
 {
-       addr_t rbp = x86_read_ebp();
+       addr_t rbp = x86_get_stack_frame();
 
        kprintf("frame                       caller             
<image>:function"
                " + offset\n");
@@ -198,9 +194,9 @@ arch_debug_stack_trace(void)
                if (is_iframe(rbp)) {
                        struct iframe* frame = (struct iframe*)rbp;
                        print_iframe(frame);
-                       print_stack_frame(frame->rip, rbp, frame->rbp, 
callIndex);
+                       print_stack_frame(frame->ip, rbp, frame->bp, callIndex);
 
-                       rbp = frame->rbp;
+                       rbp = frame->bp;
                } else {
                        stack_frame* frame = (stack_frame*)rbp;
                        if (frame->return_address == 0)
@@ -374,100 +370,6 @@ arch_system_info_init(struct kernel_args *args)
 }
 
 
-status_t
-arch_thread_init(struct kernel_args *args)
-{
-       return B_ERROR;
-}
-
-
-status_t
-arch_team_init_team_struct(Team *p, bool kernel)
-{
-       return B_OK;
-}
-
-
-status_t
-arch_thread_init_thread_struct(Thread *thread)
-{
-       return B_ERROR;
-}
-
-
-void
-arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
-       void (*function)(void*), const void* data)
-{
-
-}
-
-
-status_t
-arch_thread_init_tls(Thread *thread)
-{
-       return B_ERROR;
-}
-
-
-void
-arch_thread_context_switch(Thread *from, Thread *to)
-{
-
-}
-
-
-void
-arch_thread_dump_info(void *info)
-{
-
-}
-
-
-status_t
-arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
-       void* args2)
-{
-       return B_ERROR;
-}
-
-
-bool
-arch_on_signal_stack(Thread *thread)
-{
-       return false;
-}
-
-
-status_t
-arch_setup_signal_frame(Thread* thread, struct sigaction* action,
-       struct signal_frame_data* signalFrameData)
-{
-       return B_ERROR;
-}
-
-
-int64
-arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
-{
-       return 0;
-}
-
-
-void
-arch_store_fork_frame(struct arch_fork_arg *arg)
-{
-
-}
-
-
-void
-arch_restore_fork_frame(struct arch_fork_arg* arg)
-{
-
-}
-
-
 // The software breakpoint instruction (int3).
 const uint8 kX86SoftwareBreakpoint[1] = { 0xcc };
 
diff --git a/src/system/kernel/arch/x86/64/thread.cpp 
b/src/system/kernel/arch/x86/64/thread.cpp
new file mode 100644
index 0000000..b4e9d8a
--- /dev/null
+++ b/src/system/kernel/arch/x86/64/thread.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
+ * Copyright 2002-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ *
+ * Copyright 2001, Travis Geiselbrecht. All rights reserved.
+ * Distributed under the terms of the NewOS License.
+ */
+
+
+#include <arch/thread.h>
+
+#include <string.h>
+
+#include <arch_cpu.h>
+#include <cpu.h>
+#include <debug.h>
+#include <kernel.h>
+#include <ksignal.h>
+#include <int.h>
+#include <team.h>
+#include <thread.h>
+#include <tls.h>
+#include <vm/vm_types.h>
+#include <vm/VMAddressSpace.h>
+
+#include "paging/X86PagingStructures.h"
+#include "paging/X86VMTranslationMap.h"
+
+
+//#define TRACE_ARCH_THREAD
+#ifdef TRACE_ARCH_THREAD
+#      define TRACE(x...) dprintf(x)
+#else
+#      define TRACE(x...) ;
+#endif
+
+
+extern "C" void x86_64_thread_entry();
+
+// Initial thread saved state.
+static arch_thread sInitialState;
+
+
+void
+x86_set_tls_context(Thread* thread)
+{
+
+}
+
+
+//     #pragma mark -
+
+
+status_t
+arch_thread_init(kernel_args* args)
+{
+       // Save one global valid FPU state; it will be copied in the arch 
dependent
+       // part of each new thread.
+       asm volatile ("clts; fninit; fnclex;");
+       x86_fxsave(sInitialState.fpu_state);
+
+       return B_OK;
+}
+
+
+status_t
+arch_thread_init_thread_struct(Thread* thread)
+{
+       // Copy the initial saved FPU state to the new thread.
+       memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread));
+
+       // Initialise the current thread pointer.
+       thread->arch_info.thread = thread;
+
+       return B_OK;
+}
+
+
+/*!    Prepares the given thread's kernel stack for executing its entry 
function.
+
+       \param thread The thread.
+       \param stack The usable bottom of the thread's kernel stack.
+       \param stackTop The usable top of the thread's kernel stack.
+       \param function The entry function the thread shall execute.
+       \param data Pointer to be passed to the entry function.
+*/
+void
+arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
+       void (*function)(void*), const void* data)
+{
+       addr_t* stackTop = (addr_t*)_stackTop;
+
+       TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: 
"
+               "%p\n", _stackTop, function, data);
+
+       // x86_64 uses registers for argument passing, first argument in RDI,
+       // however we don't save RDI on every context switch (there is no need
+       // for us to: it is not callee-save, and only contains the first 
argument
+       // to x86_context_switch). However, this presents a problem since we
+       // cannot store the argument for the entry function here. Therefore, we
+       // save the function address in R14 and the argument in R15 (which are
+       // restored), and then set up the stack to initially call a wrapper
+       // function which passes the argument correctly.
+
+       *--stackTop = 0;                                                        
// Dummy return address.
+       *--stackTop = (addr_t)x86_64_thread_entry;      // Wrapper function.
+       *--stackTop = (addr_t)data;                                     // R15: 
argument.
+       *--stackTop = (addr_t)function;                         // R14: entry 
function.
+       *--stackTop = 0;                                                        
// R13.
+       *--stackTop = 0;                                                        
// R12.
+       *--stackTop = 0;                                                        
// RBP.
+       *--stackTop = 0;                                                        
// RBX.
+
+       // Save the stack position.
+       thread->arch_info.current_stack = stackTop;
+}
+
+
+/*!    Initializes the user-space TLS local storage pointer in
+       the thread structure, and the reserved TLS slots.
+       
+       Is called from _create_user_thread_kentry().
+*/
+status_t
+arch_thread_init_tls(Thread* thread)
+{
+       dprintf("arch_thread_init_tls: TODO\n");
+       return B_OK;
+}
+
+
+void
+arch_thread_dump_info(void* info)
+{
+       arch_thread* thread = (arch_thread*)info;
+
+       kprintf("\trsp: %p\n", thread->current_stack);
+       kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp);
+       kprintf("\tuser_rsp: %p\n", thread->user_rsp);
+       kprintf("\tfpu_state at %p\n", thread->fpu_state);
+}
+
+
+/*!    Sets up initial thread context and enters user space
+*/
+status_t
+arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
+       void* args2)
+{
+       panic("arch_thread_enter_userspace: TODO\n");
+       return B_ERROR;
+}
+
+
+/*!    Sets up the user iframe for invoking a signal handler.
+
+       The function fills in the remaining fields of the given \a 
signalFrameData,
+       copies it to the thread's userland stack (the one on which the signal 
shall
+       be handled), and sets up the user iframe so that when returning to 
userland
+       a wrapper function is executed that calls the user-defined signal 
handler.
+       When the signal handler returns, the wrapper function shall call the
+       "restore signal frame" syscall with the (possibly modified) signal frame
+       data.
+
+       The following fields of the \a signalFrameData structure still need to 
be
+       filled in:
+       - \c context.uc_stack: The stack currently used by the thread.
+       - \c context.uc_mcontext: The current userland state of the registers.
+       - \c syscall_restart_return_value: Architecture specific use. On x86 the
+               value of eax and edx which are overwritten by the syscall 
return value.
+
+       Furthermore the function needs to set \c thread->user_signal_context to 
the
+       userland pointer to the \c ucontext_t on the user stack.
+
+       \param thread The current thread.
+       \param action The signal action specified for the signal to be handled.
+       \param signalFrameData A partially initialized structure of all the data
+               that need to be copied to userland.
+       \return \c B_OK on success, another error code, if something goes wrong.
+*/
+status_t
+arch_setup_signal_frame(Thread* thread, struct sigaction* action,
+       struct signal_frame_data* signalFrameData)
+{
+       panic("arch_setup_signal_frame: TODO\n");
+       return B_ERROR;
+}
+
+
+int64
+arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
+{
+       panic("arch_restore_signal_frame: TODO\n");
+       return B_ERROR;
+}
diff --git a/src/system/kernel/arch/x86/Jamfile 
b/src/system/kernel/arch/x86/Jamfile
index ad27ff1..0fac1a0 100644
--- a/src/system/kernel/arch/x86/Jamfile
+++ b/src/system/kernel/arch/x86/Jamfile
@@ -24,6 +24,7 @@ if $(TARGET_ARCH) = x86_64 {
                int.cpp
                interrupts.S
                stubs.cpp
+               thread.cpp
 
                # paging
                x86_physical_page_mapper_mapped.cpp
@@ -43,12 +44,12 @@ if $(TARGET_ARCH) = x86_64 {
                cpuid.S
                int.cpp
                interrupts.S
+               thread.cpp
 
                arch_commpage.cpp
                arch_debug.cpp
                arch_real_time_clock.cpp
                arch_smp.cpp
-               arch_thread.cpp
                arch_system_info.cpp
                arch_user_debugger.cpp
                apm.cpp
@@ -83,6 +84,7 @@ local archGenericSources =
        arch_elf.cpp
        arch_int.cpp
        arch_platform.cpp
+       arch_thread.cpp
        arch_timer.cpp
        arch_vm.cpp
        arch_vm_translation_map.cpp
diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp 
b/src/system/kernel/arch/x86/arch_cpu.cpp
index 41713b3..3640773 100644
--- a/src/system/kernel/arch/x86/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86/arch_cpu.cpp
@@ -91,10 +91,8 @@ extern "C" void x86_reboot(void);
        // from arch.S
 
 void (*gCpuIdleFunc)(void);
-#ifndef __x86_64__
 void (*gX86SwapFPUFunc)(void* oldState, const void* newState) = x86_noop_swap;
 bool gHasSSE = false;
-#endif
 
 static uint32 sCpuRendezvous;
 static uint32 sCpuRendezvous2;
@@ -343,10 +341,8 @@ x86_init_fpu(void)
        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));
 
-#ifndef __x86_64__
        gX86SwapFPUFunc = x86_fxsave_swap;
        gHasSSE = true;
-#endif
 }
 
 
@@ -708,7 +704,7 @@ x86_get_double_fault_stack(int32 cpu, size_t* _size)
 int32
 x86_double_fault_get_cpu(void)
 {
-       uint32 stack = x86_read_ebp();
+       uint32 stack = x86_get_stack_frame();
        return (stack - (uint32)sDoubleFaultStacks) / kDoubleFaultStackSize;
 }
 #endif
@@ -973,13 +969,11 @@ arch_cpu_init_post_modules(kernel_args* args)
 }
 
 
-#ifndef __x86_64__
 void
 x86_set_tss_and_kstack(addr_t kstack)
 {
        get_cpu_struct()->arch.tss.sp0 = kstack;
 }
-#endif
 
 
 void
diff --git a/src/system/kernel/arch/x86/arch_debug.cpp 
b/src/system/kernel/arch/x86/arch_debug.cpp
index beedfa3..c8e494c 100644
--- a/src/system/kernel/arch/x86/arch_debug.cpp
+++ b/src/system/kernel/arch/x86/arch_debug.cpp
@@ -363,16 +363,16 @@ print_iframe(struct iframe *frame)
 {
        bool isUser = IFRAME_IS_USER(frame);
        kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", 
frame,
-               isUser ? (uint32*)(frame + 1) : &frame->user_esp);
+               isUser ? (uint32*)(frame + 1) : &frame->user_sp);
 
        kprintf(" eax 0x%-9lx    ebx 0x%-9lx     ecx 0x%-9lx  edx 0x%lx\n",
-               frame->eax, frame->ebx, frame->ecx, frame->edx);
+               frame->ax, frame->bx, frame->cx, frame->dx);
        kprintf(" esi 0x%-9lx    edi 0x%-9lx     ebp 0x%-9lx  esp 0x%lx\n",
-               frame->esi, frame->edi, frame->ebp, frame->esp);
-       kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->eip, frame->flags);
+               frame->si, frame->di, frame->bp, frame->sp);
+       kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->ip, frame->flags);
        if (isUser) {
                // from user space
-               kprintf("user esp 0x%lx", frame->user_esp);
+               kprintf("user esp 0x%lx", frame->user_sp);
        }
        kprintf("\n");
        kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector,
@@ -413,7 +413,7 @@ setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp,
                                        thread->cpu->cpu_num);
                                if (registers == NULL)
                                        return false;
-                               *_ebp = registers->ebp;
+                               *_ebp = registers->bp;
                        } else {
                                // read %ebp from the thread's stack stored by 
a pushad
                                *_ebp = thread->arch_info.current_stack.esp[2];
@@ -495,7 +495,7 @@ get_previous_iframe(Thread* thread, struct iframe* frame)
        if (frame == NULL)
                return NULL;
 
-       return find_previous_iframe(thread, frame->ebp);
+       return find_previous_iframe(thread, frame->bp);
 }
 
 
@@ -532,28 +532,28 @@ find_debug_variable(const char* variableName, bool& 
settable)
                return &frame->cs;
        } else if (strcmp(variableName, "edi") == 0) {
                settable = true;
-               return &frame->edi;
+               return &frame->di;
        } else if (strcmp(variableName, "esi") == 0) {
                settable = true;
-               return &frame->esi;
+               return &frame->si;
        } else if (strcmp(variableName, "ebp") == 0) {
                settable = true;
-               return &frame->ebp;
+               return &frame->bp;
        } else if (strcmp(variableName, "esp") == 0) {
                settable = true;
-               return &frame->esp;
+               return &frame->sp;
        } else if (strcmp(variableName, "ebx") == 0) {
                settable = true;
-               return &frame->ebx;
+               return &frame->bx;
        } else if (strcmp(variableName, "edx") == 0) {
                settable = true;
-               return &frame->edx;
+               return &frame->dx;
        } else if (strcmp(variableName, "ecx") == 0) {
                settable = true;
-               return &frame->ecx;
+               return &frame->cx;
        } else if (strcmp(variableName, "eax") == 0) {
                settable = true;
-               return &frame->eax;
+               return &frame->ax;
        } else if (strcmp(variableName, "orig_eax") == 0) {
                settable = true;
                return &frame->orig_eax;
@@ -562,7 +562,7 @@ find_debug_variable(const char* variableName, bool& 
settable)
                return &frame->orig_edx;
        } else if (strcmp(variableName, "eip") == 0) {
                settable = true;
-               return &frame->eip;
+               return &frame->ip;
        } else if (strcmp(variableName, "eflags") == 0) {
                settable = true;
                return &frame->flags;
@@ -571,7 +571,7 @@ find_debug_variable(const char* variableName, bool& 
settable)
        if (IFRAME_IS_USER(frame)) {
                if (strcmp(variableName, "user_esp") == 0) {
                        settable = true;
-                       return &frame->user_esp;
+                       return &frame->user_sp;
                } else if (strcmp(variableName, "user_ss") == 0) {
                        return &frame->user_ss;
                }
@@ -606,7 +606,7 @@ stack_trace(int argc, char **argv)
        uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
        Thread *thread = NULL;
        uint32 oldPageDirectory = 0;
-       uint32 ebp = x86_read_ebp();
+       uint32 ebp = x86_get_stack_frame();
        int32 num = 0, last = 0;
 
        if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : 
NULL,
@@ -641,10 +641,10 @@ stack_trace(int argc, char **argv)
                        struct iframe *frame = (struct iframe *)ebp;
 
                        print_iframe(frame);
-                       print_stack_frame(thread, frame->eip, ebp, frame->ebp, 
callIndex,
+                       print_stack_frame(thread, frame->ip, ebp, frame->bp, 
callIndex,
                                demangle);
 
-                       ebp = frame->ebp;
+                       ebp = frame->bp;
                } else {
                        addr_t eip, nextEbp;
 
@@ -760,7 +760,7 @@ show_call(int argc, char **argv)
 
        Thread *thread = NULL;
        uint32 oldPageDirectory = 0;
-       addr_t ebp = x86_read_ebp();
+       addr_t ebp = x86_get_stack_frame();
        int32 argCount = 0;
 
        if (argc >= 2 && argv[argc - 1][0] == '-') {
@@ -804,9 +804,9 @@ show_call(int argc, char **argv)
                        struct iframe *frame = (struct iframe *)ebp;
 
                        if (index == callIndex)
-                               print_call(thread, frame->eip, ebp, frame->ebp, 
argCount);
+                               print_call(thread, frame->ip, ebp, frame->bp, 
argCount);
 
-                       ebp = frame->ebp;
+                       ebp = frame->bp;
                } else {
                        addr_t eip, nextEbp;
 
@@ -871,7 +871,7 @@ dump_iframes(int argc, char **argv)
 
        DebuggedThreadSetter threadSetter(thread);
 
-       struct iframe* frame = find_previous_iframe(thread, x86_read_ebp());
+       struct iframe* frame = find_previous_iframe(thread, 
x86_get_stack_frame());
        while (frame != NULL) {
                print_iframe(frame);
                frame = get_previous_iframe(thread, frame);
@@ -965,8 +965,8 @@ void
 arch_debug_save_registers(struct arch_debug_registers* registers)
 {
        // get the caller's frame pointer
-       stack_frame* frame = (stack_frame*)x86_read_ebp();
-       registers->ebp = (addr_t)frame->previous;
+       stack_frame* frame = (stack_frame*)x86_get_stack_frame();
+       registers->bp = (addr_t)frame->previous;
 }
 
 
@@ -985,7 +985,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
 
        addr_t ebp;
        if (thread == thread_get_current_thread())
-               ebp = x86_read_ebp();
+               ebp = x86_get_stack_frame();
        else {
                if (thread->state == B_THREAD_RUNNING) {
                        // The thread is currently running on another CPU.
@@ -995,7 +995,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
                                thread->cpu->cpu_num);
                        if (registers == NULL)
                                return false;
-                       ebp = registers->ebp;
+                       ebp = registers->bp;
                } else {
                        // thread not running
                        ebp = thread->arch_info.current_stack.esp[2];
@@ -1009,10 +1009,10 @@ arch_debug_contains_call(Thread *thread, const char 
*symbol,
                if (is_iframe(thread, ebp)) {
                        struct iframe *frame = (struct iframe *)ebp;
 
-                       if (is_calling(thread, frame->eip, symbol, start, end))
+                       if (is_calling(thread, frame->ip, symbol, start, end))
                                return true;
 
-                       ebp = frame->ebp;
+                       ebp = frame->bp;
                } else {
                        addr_t eip, nextEbp;
 
@@ -1037,7 +1037,7 @@ arch_debug_contains_call(Thread *thread, const char 
*symbol,
 void *
 arch_debug_get_caller(void)
 {
-       struct stack_frame *frame = (struct stack_frame *)x86_read_ebp();
+       struct stack_frame *frame = (struct stack_frame *)x86_get_stack_frame();
        return (void *)frame->previous->return_address;
 }
 
@@ -1064,7 +1064,7 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 
maxCount,
 
        Thread* thread = thread_get_current_thread();
        int32 count = 0;
-       addr_t ebp = x86_read_ebp();
+       addr_t ebp = x86_get_stack_frame();
        bool onKernelStack = true;
 
        while (ebp != 0 && count < maxCount) {
@@ -1078,8 +1078,8 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 
maxCount,
 
                if (onKernelStack && is_iframe(thread, ebp)) {
                        struct iframe *frame = (struct iframe*)ebp;
-                       eip = frame->eip;
-                       nextEbp = frame->ebp;
+                       eip = frame->ip;
+                       nextEbp = frame->bp;
 
                        if (skipIframes > 0) {
                                if (--skipIframes == 0)
@@ -1119,7 +1119,7 @@ arch_debug_get_interrupt_pc(bool* _isSyscall)
        if (_isSyscall != NULL)
                *_isSyscall = frame->vector == 99;
 
-       return (void*)(addr_t)frame->eip;
+       return (void*)(addr_t)frame->ip;
 }
 
 
@@ -1199,9 +1199,9 @@ arch_debug_gdb_get_registers(char* buffer, size_t 
bufferSize)
        // gdb wants the register dump in *big endian* format.
        static const int32 kRegisterCount = 14;
        uint32 registers[kRegisterCount] = {
-               frame->eax, frame->ebx, frame->ecx, frame->edx,
-               frame->esp, frame->ebp, frame->esi, frame->edi,
-               frame->eip, frame->flags,
+               frame->ax, frame->bx, frame->cx, frame->dx,
+               frame->sp, frame->bp, frame->si, frame->di,
+               frame->ip, frame->flags,
                frame->cs, frame->ds, frame->ds, frame->es
                        // assume ss == ds
        };
diff --git a/src/system/kernel/arch/x86/arch_int.cpp 
b/src/system/kernel/arch/x86/arch_int.cpp
index 9bec1d7..3fdee86 100644
--- a/src/system/kernel/arch/x86/arch_int.cpp
+++ b/src/system/kernel/arch/x86/arch_int.cpp
@@ -89,6 +89,7 @@ hardware_interrupt(struct iframe* frame)
                callback(data);
        }
 #else
+       return;
        panic("implement me");
 #endif
 }
@@ -159,7 +160,7 @@ arch_int_init_io(kernel_args* args)
        ioapic_init(args);
        msi_init();
 #else
-       panic("implement me");
+       //panic("implement me");
 #endif
        return B_OK;
 }
diff --git a/src/system/kernel/arch/x86/arch_thread.cpp 
b/src/system/kernel/arch/x86/arch_thread.cpp
index da8e47d..d0a1769 100644
--- a/src/system/kernel/arch/x86/arch_thread.cpp
+++ b/src/system/kernel/arch/x86/arch_thread.cpp
@@ -11,96 +11,36 @@
 
 #include <string.h>
 
-#include <arch/user_debugger.h>
 #include <arch_cpu.h>
 #include <cpu.h>
-#include <debug.h>
 #include <kernel.h>
 #include <ksignal.h>
 #include <int.h>
 #include <team.h>
 #include <thread.h>
-#include <tls.h>
-#include <tracing.h>
-#include <util/AutoLock.h>
 #include <vm/vm_types.h>
 #include <vm/VMAddressSpace.h>
 
 #include "paging/X86PagingStructures.h"
 #include "paging/X86VMTranslationMap.h"
-#include "x86_signals.h"
 #include "x86_syscalls.h"
 
 
-//#define TRACE_ARCH_THREAD
-#ifdef TRACE_ARCH_THREAD
-#      define TRACE(x) dprintf x
-#else
-#      define TRACE(x) ;
-#endif
-
-
-#ifdef SYSCALL_TRACING
-
-namespace SyscallTracing {
-
-class RestartSyscall : public AbstractTraceEntry {
-       public:
-               RestartSyscall()
-               {
-                       Initialized();
-               }
-
-               virtual void AddDump(TraceOutput& out)
-               {
-                       out.Print("syscall restart");
-               }
-};
-
-}
-
-#      define TSYSCALL(x)      new(std::nothrow) SyscallTracing::x
-
-#else
-#      define TSYSCALL(x)
-#endif // SYSCALL_TRACING
-
-
 // from arch_interrupts.S
 extern "C" void x86_return_to_userland(iframe* frame);
 
-// from arch_cpu.c
+// from arch_cpu.cpp
 extern void (*gX86SwapFPUFunc)(void *oldState, const void *newState);
-extern bool gHasSSE;
-
-static struct arch_thread sInitialState _ALIGNED(16);
-       // the fpu_state must be aligned on a 16 byte boundary, so that fxsave 
can use it
-
-
-status_t
-arch_thread_init(struct kernel_args *args)
-{
-       // save one global valid FPU state; it will be copied in the arch 
dependent
-       // part of each new thread
 
-       asm volatile ("clts; fninit; fnclex;");
-       if (gHasSSE)
-               x86_fxsave(sInitialState.fpu_state);
-       else
-               x86_fnsave(sInitialState.fpu_state);
 
-       return B_OK;
-}
-
-
-static struct iframe *
-find_previous_iframe(Thread *thread, addr_t frame)
+static struct iframe*
+find_previous_iframe(Thread* thread, addr_t frame)
 {
        // iterate backwards through the stack frames, until we hit an iframe
        while (frame >= thread->kernel_stack_base
                && frame < thread->kernel_stack_top) {
                addr_t previousFrame = *(addr_t*)frame;
-               if ((previousFrame & ~IFRAME_TYPE_MASK) == 0) {
+               if ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0) {
                        if (previousFrame == 0)
                                return NULL;
                        return (struct iframe*)frame;
@@ -119,7 +59,7 @@ get_previous_iframe(struct iframe* frame)
        if (frame == NULL)
                return NULL;
 
-       return find_previous_iframe(thread_get_current_thread(), frame->ebp);
+       return find_previous_iframe(thread_get_current_thread(), frame->bp);
 }
 
 
@@ -132,39 +72,8 @@ get_previous_iframe(struct iframe* frame)
 static struct iframe*
 get_current_iframe(void)
 {
-       return find_previous_iframe(thread_get_current_thread(), 
x86_read_ebp());
-}
-
-
-static inline void
-set_fs_register(uint32 segment)
-{
-       asm("movl %0,%%fs" :: "r" (segment));
-}
-
-
-/*!    Returns to the userland environment given by \a frame for a thread not
-       having been userland before.
-
-       Before returning to userland all potentially necessary kernel exit work 
is
-       done.
-
-       \param thread The current thread.
-       \param frame The iframe defining the userland environment. Must point 
to a
-               location somewhere on the caller's stack (e.g. a local 
variable).
-*/
-static void
-initial_return_to_userland(Thread* thread, iframe* frame)
-{
-       // disable interrupts and set up CPU specifics for this thread
-       disable_interrupts();
-
-       x86_set_tss_and_kstack(thread->kernel_stack_top);
-       x86_set_tls_context(thread);
-       x86_set_syscall_stack(thread->kernel_stack_top);
-
-       // return to userland
-       x86_return_to_userland(frame);
+       return find_previous_iframe(thread_get_current_thread(),
+               x86_get_stack_frame());
 }
 
 
@@ -175,7 +84,7 @@ initial_return_to_userland(Thread* thread, iframe* frame)
        \return The iframe, or \c NULL, if there is no such iframe (e.g. when
                        the thread is a kernel thread).
 */
-struct iframe *
+struct iframe*
 x86_get_user_iframe(void)
 {
        struct iframe* frame = get_current_iframe();
@@ -193,17 +102,21 @@ x86_get_user_iframe(void)
 /*!    \brief Like x86_get_user_iframe(), just for the given thread.
        The thread must not be running and the threads spinlock must be held.
 */
-struct iframe *
+struct iframe*
 x86_get_thread_user_iframe(Thread *thread)
 {
        if (thread->state == B_THREAD_RUNNING)
                return NULL;
 
-       // read %ebp from the thread's stack stored by a pushad
-       addr_t ebp = thread->arch_info.current_stack.esp[2];
+       // Read frame pointer from the thread's stack.
+#ifdef __x86_64__
+       addr_t bp = thread->arch_info.current_stack[1];
+#else
+       addr_t bp = thread->arch_info.current_stack.esp[2];
+#endif
 
        // find the user iframe
-       struct iframe *frame = find_previous_iframe(thread, ebp);
+       struct iframe* frame = find_previous_iframe(thread, bp);
 
        while (frame != NULL) {
                if (IFRAME_IS_USER(frame))
@@ -215,14 +128,14 @@ x86_get_thread_user_iframe(Thread *thread)
 }
 
 
-struct iframe *
+struct iframe*
 x86_get_current_iframe(void)
 {
        return get_current_iframe();
 }
 
 
-uint32
+phys_addr_t
 x86_next_page_directory(Thread *from, Thread *to)
 {
        VMAddressSpace* toAddressSpace = to->team->address_space;
@@ -239,47 +152,45 @@ x86_next_page_directory(Thread *from, Thread *to)
 }
 
 
-void
-x86_restart_syscall(struct iframe* frame)
-{
-       Thread* thread = thread_get_current_thread();
-
-       atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
-       atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED);
-
-       frame->eax = frame->orig_eax;
-       frame->edx = frame->orig_edx;
-       frame->eip -= 2;
-               // undoes the "int $99"/"sysenter"/"syscall" instruction
-               // (so that it'll be executed again)
-
-       TSYSCALL(RestartSyscall());
-}
+/*!    Returns to the userland environment given by \a frame for a thread not
+       having been userland before.
 
+       Before returning to userland all potentially necessary kernel exit work 
is
+       done.
 
+       \param thread The current thread.
+       \param frame The iframe defining the userland environment. Must point 
to a
+               location somewhere on the caller's stack (e.g. a local 
variable).
+*/
 void
-x86_set_tls_context(Thread *thread)
+x86_initial_return_to_userland(Thread* thread, iframe* frame)
 {
-       int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT;
+       // disable interrupts and set up CPU specifics for this thread
+       disable_interrupts();
+
+       x86_set_tss_and_kstack(thread->kernel_stack_top);
+       x86_set_tls_context(thread);
+       x86_set_syscall_stack(thread->kernel_stack_top);
 
-       set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage);
-       set_fs_register((entry << 3) | DPL_USER);
+       // return to userland
+       x86_return_to_userland(frame);
 }
 
 
-static uint8*
-get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* 
action)
+uint8*
+x86_get_signal_stack(Thread* thread, struct iframe* frame,
+       struct sigaction* action)
 {
        // use the alternate signal stack if we should and can
        if (thread->signal_stack_enabled
                && (action->sa_flags & SA_ONSTACK) != 0
-               && (frame->user_esp < thread->signal_stack_base
-                       || frame->user_esp >= thread->signal_stack_base
+               && (frame->user_sp < thread->signal_stack_base
+                       || frame->user_sp >= thread->signal_stack_base
                                + thread->signal_stack_size)) {
                return (uint8*)(thread->signal_stack_base + 
thread->signal_stack_size);
        }
 
-       return (uint8*)frame->user_esp;
+       return (uint8*)frame->user_sp;
 }
 
 
@@ -287,84 +198,14 @@ get_signal_stack(Thread* thread, struct iframe* frame, 
struct sigaction* action)
 
 
 status_t
-arch_team_init_team_struct(Team *p, bool kernel)
+arch_team_init_team_struct(Team* p, bool kernel)
 {
        return B_OK;
 }
 
 
-status_t
-arch_thread_init_thread_struct(Thread *thread)
-{
-       // set up an initial state (stack & fpu)
-       memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread));
-       return B_OK;
-}
-
-
-/*!    Prepares the given thread's kernel stack for executing its entry 
function.
-
-       \param thread The thread.
-       \param stack The usable bottom of the thread's kernel stack.
-       \param stackTop The usable top of the thread's kernel stack.
-       \param function The entry function the thread shall execute.

[ *** diff truncated: 446 lines dropped *** ]



Other related posts: