#include "machine/npx.h"
#endif
+#if defined(LISP_FEATURE_OPENBSD)
+#include <machine/frame.h>
+#include <machine/npx.h>
+#include <stddef.h>
+#endif
+
/* KLUDGE: There is strong family resemblance in the signal context
* stuff in FreeBSD and OpenBSD, but in detail they're different in
* almost every line of code. It would be nice to find some way to
{
switch(offset) {
case 0:
- return CONTEXT_ADDR_FROM_STEM(eax);
+ return (int *)CONTEXT_ADDR_FROM_STEM(eax);
case 2:
- return CONTEXT_ADDR_FROM_STEM(ecx);
+ return (int *)CONTEXT_ADDR_FROM_STEM(ecx);
case 4:
- return CONTEXT_ADDR_FROM_STEM(edx);
+ return (int *)CONTEXT_ADDR_FROM_STEM(edx);
case 6:
- return CONTEXT_ADDR_FROM_STEM(ebx);
+ return (int *)CONTEXT_ADDR_FROM_STEM(ebx);
case 8:
- return CONTEXT_ADDR_FROM_STEM(esp);
+ return (int *)CONTEXT_ADDR_FROM_STEM(esp);
case 10:
- return CONTEXT_ADDR_FROM_STEM(ebp);
+ return (int *)CONTEXT_ADDR_FROM_STEM(ebp);
case 12:
- return CONTEXT_ADDR_FROM_STEM(esi);
+ return (int *)CONTEXT_ADDR_FROM_STEM(esi);
case 14:
- return CONTEXT_ADDR_FROM_STEM(edi);
+ return (int *)CONTEXT_ADDR_FROM_STEM(edi);
default:
return 0;
}
int *
os_context_sp_addr(os_context_t *context)
{
- return CONTEXT_ADDR_FROM_STEM(esp);
+ return (int *)CONTEXT_ADDR_FROM_STEM(esp);
}
#endif /* __FreeBSD__ || __OpenBSD__ */
#endif /* __NetBSD__ */
+int *os_context_pc_addr(os_context_t *context)
+{
+#if defined __FreeBSD__
+ return CONTEXT_ADDR_FROM_STEM(eip);
+#elif defined __OpenBSD__
+ return CONTEXT_ADDR_FROM_STEM(pc);
+#elif defined __NetBSD__
+ return CONTEXT_ADDR_FROM_STEM(EIP);
+#elif defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ return (int *)CONTEXT_ADDR_FROM_STEM(eip);
+#elif defined LISP_FEATURE_DARWIN
+ return &context->uc_mcontext->ss.srr0;
+#else
+#error unsupported BSD variant
+#endif
+}
/* FIXME: If this can be a no-op on BSD/x86, then it
* deserves a more precise name.
struct segment_descriptor ldt_entry = { 0, 0, SDT_MEMRW, SEL_UPL, 1,
0, 0, 1, 0, 0 };
- set_data_desc_addr(&ldt_entry, (unsigned long) thread);
+ set_data_desc_addr(&ldt_entry, thread);
set_data_desc_size(&ldt_entry, dynamic_values_bytes);
n = i386_set_ldt(LDT_AUTO_ALLOC, (union descriptor*) &ldt_entry, 1);
}
FSHOW_SIGNAL((stderr, "/ TLS: Allocated LDT %x\n", n));
sel = LSEL(n, SEL_UPL);
- __asm__ __volatile__ ("mov %0, %%fs" : : "r"(sel));
+ load_fs(sel);
thread->tls_cookie=n;
+#ifdef LISP_FEATURE_GCC_TLS
+ current_thread = thread;
+#else
pthread_setspecific(specials,thread);
#endif
+#endif
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
stack_t sigstack;
#if defined(LISP_FEATURE_SB_THREAD)
int n = thread->tls_cookie;
- /* Set the %%fs register back to 0 and free the the ldt
- * by setting it to NULL.
+ /* Set the %%fs register back to 0 and free the ldt by setting it
+ * to NULL.
*/
FSHOW_SIGNAL((stderr, "/ TLS: Freeing LDT %x\n", n));
#endif /* !LISP_FEATURE_DARWIN */
#if defined(LISP_FEATURE_FREEBSD)
+#if defined(LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_CONTEXT)
+void
+os_restore_tls_segment_register(os_context_t *context)
+{
+ load_fs(context->uc_mcontext.mc_fs);
+}
+#endif
+
+void
+os_restore_fp_control(os_context_t *context)
+{
+ /* FPU state is saved per context on post-KSE systems.
+ * On earlier systems, it is shared in a whole process.
+ */
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 500040
+ struct envxmm *ex = (struct envxmm *)(context->uc_mcontext.mc_fpstate);
+ __asm__ __volatile__ ("fldcw %0" : : "m" (ex->en_cw));
+#endif
+#if defined(LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_CONTEXT)
+ /* Calling this function here may not be good idea. Or rename
+ * function name os_restore_fp_control to os_restore_context or
+ * so, to match the behavior? */
+ os_restore_tls_segment_register(context);
+#endif
+}
+#endif
+
+#if defined(LISP_FEATURE_OPENBSD)
void
os_restore_fp_control(os_context_t *context)
{
- struct envxmm *ex = (struct envxmm*)(&context->uc_mcontext.mc_fpstate);
- asm ("fldcw %0" : : "m" (ex->en_cw));
+ struct sigframe *frame;
+ union savefpu *fpu;
+
+ frame = (struct sigframe *)((char*)context - offsetof(struct sigframe, sf_sc));
+ fpu = frame->sf_fpstate;
+ if (openbsd_use_fxsave)
+ __asm__ __volatile__ ("fldcw %0" : : "m" (fpu->sv_xmm.sv_env.en_cw));
+ else
+ __asm__ __volatile__ ("fldcw %0" : : "m" (fpu->sv_87.sv_env.en_cw));
}
#endif