/* $OpenBSD: uthread_machdep.c,v 1.3 2004/02/25 04:10:53 deraadt Exp $ */ /* * Copyright (c) 2004 Theo de Raadt * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #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)) { 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) { fxsave(&ms->fpreg); fninit(); fwait(); } void _thread_machdep_restore_float_state(struct _machdep_state *ms) { fxrstor(&ms->fpreg); }