diff options
Diffstat (limited to 'lib/libpthread/arch')
-rw-r--r-- | lib/libpthread/arch/amd64/_atomic_lock.c | 16 | ||||
-rw-r--r-- | lib/libpthread/arch/amd64/uthread_machdep.c | 72 | ||||
-rw-r--r-- | lib/libpthread/arch/amd64/uthread_machdep.h | 9 | ||||
-rw-r--r-- | lib/libpthread/arch/amd64/uthread_machdep_asm.S | 62 | ||||
-rw-r--r-- | lib/libpthread/arch/x86_64/_atomic_lock.c | 16 | ||||
-rw-r--r-- | lib/libpthread/arch/x86_64/uthread_machdep.c | 72 | ||||
-rw-r--r-- | lib/libpthread/arch/x86_64/uthread_machdep.h | 9 | ||||
-rw-r--r-- | lib/libpthread/arch/x86_64/uthread_machdep_asm.S | 62 |
8 files changed, 298 insertions, 20 deletions
diff --git a/lib/libpthread/arch/amd64/_atomic_lock.c b/lib/libpthread/arch/amd64/_atomic_lock.c index 087186e2858..70bdb487381 100644 --- a/lib/libpthread/arch/amd64/_atomic_lock.c +++ b/lib/libpthread/arch/amd64/_atomic_lock.c @@ -1,5 +1,6 @@ +/* $OpenBSD: _atomic_lock.c,v 1.2 2004/02/25 03:48:36 deraadt Exp $ */ /* - * Atomic lock for amd64 + * Atomic lock for amd64 -- taken from i386 code. */ #include "spinlock.h" @@ -7,5 +8,16 @@ int _atomic_lock(volatile _spinlock_lock_t *lock) { - /* dummy for now */ + _spinlock_lock_t old; + + /* + * Use the eXCHanGe instruction to swap the lock value with + * a local variable containing the locked state. + */ + old = _SPINLOCK_LOCKED; + __asm__("xchg %0,%1" + : "=r" (old), "=m" (*lock) + : "0" (old), "1" (*lock)); + + return (old != _SPINLOCK_UNLOCKED); } diff --git a/lib/libpthread/arch/amd64/uthread_machdep.c b/lib/libpthread/arch/amd64/uthread_machdep.c index d66bfbaa853..e01da1b6c58 100644 --- a/lib/libpthread/arch/amd64/uthread_machdep.c +++ b/lib/libpthread/arch/amd64/uthread_machdep.c @@ -2,26 +2,88 @@ #include <pthread.h> #include "pthread_private.h" +struct frame { + long fr_gs; + long fr_fs; + long fr_es; + long fr_ds; + + long flag; + long fr_r15; + long fr_r14; + long fr_r13; + long fr_r12; + + long fr_r11; + long fr_r10; + long fr_r9; + long fr_r8; + + long fr_rdi; + long fr_rsi; + long fr_rbp; + + long fr_rbx; + long fr_rdx; + long fr_rcx; + long fr_rax; + + long fr_rip; + int fr_cs; /* XXX unreachable? */ + int pad; +}; + +#define copyreg(reg, lval) \ + __asm__("mov %%" #reg ", %0" : "=g"(lval)) + /* * Given a stack and an entry function, initialise a state * structure that can be later switched to. */ void _thread_machdep_init(struct _machdep_state* statep, void *base, int len, - void (*entry)(void)) + void (*entry)(void)) { - /* dummy */ + struct frame *f; + int foo; + + /* Locate the initial frame, aligned at the top of the stack */ + f = (struct frame *)(((long)base + len - sizeof *f) & ~ALIGNBYTES); + + copyreg(cs, foo); + f->fr_cs = foo; + copyreg(ds, foo); + f->fr_ds = foo; + copyreg(es, foo); + f->fr_es = foo; + copyreg(fs, foo); + f->fr_fs = foo; + copyreg(gs, foo); + f->fr_gs = foo; + + f->fr_rbp = (long)-1; + f->fr_rip = (long)entry; + + statep->rsp = (long)f; + + _thread_machdep_save_float_state(statep); } +#define fxsave(addr) __asm("fxsave %0" : "=m" (*addr)) +#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*addr)) +#define fwait() __asm("fwait") +#define fninit() __asm("fninit") + void _thread_machdep_save_float_state(struct _machdep_state *ms) { - /* dummy */ + fxsave(&ms->fpreg); + fninit(); + fwait(); } void _thread_machdep_restore_float_state(struct _machdep_state *ms) { - /* dummy */ + fxrstor(&ms->fpreg); } - diff --git a/lib/libpthread/arch/amd64/uthread_machdep.h b/lib/libpthread/arch/amd64/uthread_machdep.h index 46f5e9e87d1..43187585d17 100644 --- a/lib/libpthread/arch/amd64/uthread_machdep.h +++ b/lib/libpthread/arch/amd64/uthread_machdep.h @@ -1,5 +1,10 @@ -/* dummy */ +/* $OpenBSD: uthread_machdep.h,v 1.2 2004/02/25 03:48:36 deraadt Exp $ */ + +#include <sys/types.h> +#include <machine/fpu.h> struct _machdep_state { + long rsp; + /* must be 128-bit aligned */ + struct savefpu fpreg __attribute__ ((aligned (16))); }; - diff --git a/lib/libpthread/arch/amd64/uthread_machdep_asm.S b/lib/libpthread/arch/amd64/uthread_machdep_asm.S index 3a5f255f285..51294f9ae5c 100644 --- a/lib/libpthread/arch/amd64/uthread_machdep_asm.S +++ b/lib/libpthread/arch/amd64/uthread_machdep_asm.S @@ -6,5 +6,65 @@ /* void _thread_machdep_switch(new, oldsave); */ ENTRY(_thread_machdep_switch) - /* dummy */ + pushq %rax + pushq %rcx + pushq %rdx + pushq %rbx + + pushq %rbp + pushq %rsi + pushq %rdi + + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq $0xdeaf12345678beaf, %r15 + pushq %r15 + + movl %ds,%eax + pushq %rax + movl %es,%eax + pushq %rax + movl %fs,%eax + pushq %rax + movl %gs,%eax + pushq %rax + + movq %rsp, 0(%rsi) /* *arg2 = %rsp */ + movq 0(%rdi), %rsp /* %rsp = *arg1 */ + + popq %rax + movl %eax,%gs + popq %rax + movl %eax,%fs + popq %rax + movl %eax,%es + popq %rax + movl %eax,%ds + + popq %r15 # flag word. + popq %r15 + popq %r14 + popq %r13 + popq %r12 + + popq %r11 + popq %r10 + popq %r9 + popq %r8 + + popq %rdi + popq %rsi + popq %rbp + + popq %rbx + popq %rdx + popq %rcx + popq %rax ret diff --git a/lib/libpthread/arch/x86_64/_atomic_lock.c b/lib/libpthread/arch/x86_64/_atomic_lock.c index 087186e2858..70bdb487381 100644 --- a/lib/libpthread/arch/x86_64/_atomic_lock.c +++ b/lib/libpthread/arch/x86_64/_atomic_lock.c @@ -1,5 +1,6 @@ +/* $OpenBSD: _atomic_lock.c,v 1.2 2004/02/25 03:48:36 deraadt Exp $ */ /* - * Atomic lock for amd64 + * Atomic lock for amd64 -- taken from i386 code. */ #include "spinlock.h" @@ -7,5 +8,16 @@ int _atomic_lock(volatile _spinlock_lock_t *lock) { - /* dummy for now */ + _spinlock_lock_t old; + + /* + * Use the eXCHanGe instruction to swap the lock value with + * a local variable containing the locked state. + */ + old = _SPINLOCK_LOCKED; + __asm__("xchg %0,%1" + : "=r" (old), "=m" (*lock) + : "0" (old), "1" (*lock)); + + return (old != _SPINLOCK_UNLOCKED); } diff --git a/lib/libpthread/arch/x86_64/uthread_machdep.c b/lib/libpthread/arch/x86_64/uthread_machdep.c index d66bfbaa853..e01da1b6c58 100644 --- a/lib/libpthread/arch/x86_64/uthread_machdep.c +++ b/lib/libpthread/arch/x86_64/uthread_machdep.c @@ -2,26 +2,88 @@ #include <pthread.h> #include "pthread_private.h" +struct frame { + long fr_gs; + long fr_fs; + long fr_es; + long fr_ds; + + long flag; + long fr_r15; + long fr_r14; + long fr_r13; + long fr_r12; + + long fr_r11; + long fr_r10; + long fr_r9; + long fr_r8; + + long fr_rdi; + long fr_rsi; + long fr_rbp; + + long fr_rbx; + long fr_rdx; + long fr_rcx; + long fr_rax; + + long fr_rip; + int fr_cs; /* XXX unreachable? */ + int pad; +}; + +#define copyreg(reg, lval) \ + __asm__("mov %%" #reg ", %0" : "=g"(lval)) + /* * Given a stack and an entry function, initialise a state * structure that can be later switched to. */ void _thread_machdep_init(struct _machdep_state* statep, void *base, int len, - void (*entry)(void)) + void (*entry)(void)) { - /* dummy */ + struct frame *f; + int foo; + + /* Locate the initial frame, aligned at the top of the stack */ + f = (struct frame *)(((long)base + len - sizeof *f) & ~ALIGNBYTES); + + copyreg(cs, foo); + f->fr_cs = foo; + copyreg(ds, foo); + f->fr_ds = foo; + copyreg(es, foo); + f->fr_es = foo; + copyreg(fs, foo); + f->fr_fs = foo; + copyreg(gs, foo); + f->fr_gs = foo; + + f->fr_rbp = (long)-1; + f->fr_rip = (long)entry; + + statep->rsp = (long)f; + + _thread_machdep_save_float_state(statep); } +#define fxsave(addr) __asm("fxsave %0" : "=m" (*addr)) +#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*addr)) +#define fwait() __asm("fwait") +#define fninit() __asm("fninit") + void _thread_machdep_save_float_state(struct _machdep_state *ms) { - /* dummy */ + fxsave(&ms->fpreg); + fninit(); + fwait(); } void _thread_machdep_restore_float_state(struct _machdep_state *ms) { - /* dummy */ + fxrstor(&ms->fpreg); } - diff --git a/lib/libpthread/arch/x86_64/uthread_machdep.h b/lib/libpthread/arch/x86_64/uthread_machdep.h index 46f5e9e87d1..43187585d17 100644 --- a/lib/libpthread/arch/x86_64/uthread_machdep.h +++ b/lib/libpthread/arch/x86_64/uthread_machdep.h @@ -1,5 +1,10 @@ -/* dummy */ +/* $OpenBSD: uthread_machdep.h,v 1.2 2004/02/25 03:48:36 deraadt Exp $ */ + +#include <sys/types.h> +#include <machine/fpu.h> struct _machdep_state { + long rsp; + /* must be 128-bit aligned */ + struct savefpu fpreg __attribute__ ((aligned (16))); }; - diff --git a/lib/libpthread/arch/x86_64/uthread_machdep_asm.S b/lib/libpthread/arch/x86_64/uthread_machdep_asm.S index 3a5f255f285..51294f9ae5c 100644 --- a/lib/libpthread/arch/x86_64/uthread_machdep_asm.S +++ b/lib/libpthread/arch/x86_64/uthread_machdep_asm.S @@ -6,5 +6,65 @@ /* void _thread_machdep_switch(new, oldsave); */ ENTRY(_thread_machdep_switch) - /* dummy */ + pushq %rax + pushq %rcx + pushq %rdx + pushq %rbx + + pushq %rbp + pushq %rsi + pushq %rdi + + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq $0xdeaf12345678beaf, %r15 + pushq %r15 + + movl %ds,%eax + pushq %rax + movl %es,%eax + pushq %rax + movl %fs,%eax + pushq %rax + movl %gs,%eax + pushq %rax + + movq %rsp, 0(%rsi) /* *arg2 = %rsp */ + movq 0(%rdi), %rsp /* %rsp = *arg1 */ + + popq %rax + movl %eax,%gs + popq %rax + movl %eax,%fs + popq %rax + movl %eax,%es + popq %rax + movl %eax,%ds + + popq %r15 # flag word. + popq %r15 + popq %r14 + popq %r13 + popq %r12 + + popq %r11 + popq %r10 + popq %r9 + popq %r8 + + popq %rdi + popq %rsi + popq %rbp + + popq %rbx + popq %rdx + popq %rcx + popq %rax ret |