#include <signal.h>
+#include <stdio.h>
#include "sbcl.h"
#include "runtime.h"
#include "thread.h"
#include "machine/npx.h"
#endif
+#if defined(LISP_FEATURE_OPENBSD)
+#include <machine/npx.h>
+#include <stddef.h>
+#include "openbsd-sigcontext.h"
+#ifdef OS_OPENBSD_FPSTATE_IN_SIGFRAME
+# include <machine/frame.h>
+#endif
+#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__ */
#elif defined __NetBSD__
return CONTEXT_ADDR_FROM_STEM(EIP);
#elif defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
- return CONTEXT_ADDR_FROM_STEM(eip);
+ return (int *)CONTEXT_ADDR_FROM_STEM(eip);
#elif defined LISP_FEATURE_DARWIN
return &context->uc_mcontext->ss.srr0;
#else
#endif
+#ifdef LISP_FEATURE_SB_THREAD
+void
+arch_os_load_ldt(struct thread *thread)
+{
+ int sel = LSEL(thread->tls_cookie, SEL_UPL);
+ unsigned int fs = rfs();
+
+ /* Load FS only if it's necessary. Modifying a selector
+ * causes privilege checking and it takes long time. */
+ if (fs != sel)
+ load_fs(sel);
+}
+#endif
+
int arch_os_thread_init(struct thread *thread) {
#ifdef LISP_FEATURE_SB_THREAD
int n;
- int sel;
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);
lose("unexpected i386_set_ldt(..) failure\n");
}
FSHOW_SIGNAL((stderr, "/ TLS: Allocated LDT %x\n", n));
- sel = LSEL(n, SEL_UPL);
- load_fs(sel);
-
thread->tls_cookie=n;
+ arch_os_load_ldt(thread);
+
+#ifdef LISP_FEATURE_GCC_TLS
+ current_thread = thread;
+#else
pthread_setspecific(specials,thread);
#endif
+#endif
+
+#ifdef LISP_FEATURE_SB_SAFEPOINT
+ thread->selfptr = thread;
+#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)
{
* 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 ("fldcw %0" : : "m" (ex->en_cw));
+ 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)
+{
+#ifdef OS_OPENBSD_FPSTATE_IN_SIGFRAME
+ struct sigframe *frame = (struct sigframe *)((char*)context -
+ offsetof(struct sigframe, sf_sc));
+ union savefpu *fpu = frame->sf_fpstate;
+#elif defined(OS_OPENBSD_FPSTATE_IN_SIGCONTEXT)
+ union savefpu *fpu = context->sc_fpstate;
+#endif
+
+ 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