Skip to content
Browse files

1.0.0.32: support for FreeBSD/x86-64

  • Loading branch information...
1 parent 4efb45c commit bd455348d39bee562296741689882dcb97c46ba3 sa2c committed Dec 15, 2006
View
1 NEWS
@@ -1,5 +1,6 @@
;;;; -*- coding: utf-8; -*-
changes in sbcl-1.0.1 relative to sbcl-1.0:
+ * new platform: FreeBSD/x86-64, including support for threading.
* new feature: the compiler stores cross-referencing information
abount function calls (who-calls), macroexpansion (who-macroexpands)
and special variables (who-binds, who-sets, who-references) for code
View
1 make-config.sh
@@ -102,6 +102,7 @@ case `uname -m` in
*86) guessed_sbcl_arch=x86 ;;
i86pc) guessed_sbcl_arch=x86 ;;
*x86_64) guessed_sbcl_arch=x86-64 ;;
+ amd64) guessed_sbcl_arch=x86-64 ;;
[Aa]lpha) guessed_sbcl_arch=alpha ;;
sparc*) guessed_sbcl_arch=sparc ;;
sun*) guessed_sbcl_arch=sparc ;;
View
25 src/runtime/Config.x86-64-bsd
@@ -0,0 +1,25 @@
+# -*- makefile -*- for the C-level run-time support for SBCL
+# configuration stuff shared between various *BSD OSes
+
+# This software is part of the SBCL system. See the README file for
+# more information.
+#
+# This software is derived from the CMU CL system, which was
+# written at Carnegie Mellon University and released into the
+# public domain. The software is in the public domain and is
+# provided with absolutely no warranty. See the COPYING and CREDITS
+# files for more information.
+
+ASSEM_SRC = x86-64-assem.S
+ARCH_SRC = x86-64-arch.c
+
+OS_SRC = bsd-os.c x86-64-bsd-os.c
+OS_LIBS = # -ldl
+
+CFLAGS += -fno-omit-frame-pointer
+
+GC_SRC = gencgc.c
+
+# Nothing to do for after-grovel-headers.
+.PHONY: after-grovel-headers
+after-grovel-headers:
View
26 src/runtime/Config.x86-64-freebsd
@@ -0,0 +1,26 @@
+# -*- makefile -*- for the C-level run-time support for SBCL
+
+# This software is part of the SBCL system. See the README file for
+# more information.
+#
+# This software is derived from the CMU CL system, which was
+# written at Carnegie Mellon University and released into the
+# public domain. The software is in the public domain and is
+# provided with absolutely no warranty. See the COPYING and CREDITS
+# files for more information.
+
+include Config.x86-64-bsd
+
+ASSEM_SRC += ldso-stubs.S
+
+# Until sbcl-0.6.7.3, we used "LINKFLAGS+=-static" here, which
+# worked fine for most things, but LOAD-FOREIGN & friends require
+# dlopen() etc., which in turn depend on dynamic linking of the
+# runtime.
+LINKFLAGS += -dynamic -export-dynamic
+
+# use libthr (1:1 threading). libpthread (m:n threading) does not work.
+ifdef LISP_FEATURE_SB_THREAD
+ #OS_LIBS += -lpthread
+ OS_LIBS += -lthr
+endif
View
2 src/runtime/breakpoint.h
@@ -22,6 +22,8 @@ extern void handle_breakpoint(int signal, siginfo_t *info,
os_context_t *context);
extern void *handle_fun_end_breakpoint(int signal, siginfo_t *info,
os_context_t *context);
+extern void handle_single_step_trap (os_context_t *context, int kind,
+ int register_offset);
extern void handle_single_step_trap(os_context_t *context, int kind,
int register_offset);
View
49 src/runtime/bsd-os.c
@@ -41,6 +41,9 @@
#include <signal.h>
/* #include <sys/sysinfo.h> */
#include "validate.h"
+#if defined LISP_FEATURE_GENCGC
+#include "gencgc-internal.h"
+#endif
os_vm_size_t os_vm_page_size;
@@ -55,7 +58,6 @@ static void netbsd_init();
#ifdef __FreeBSD__
#include <sys/sysctl.h>
-#include <osreldate.h>
static void freebsd_init();
#endif /* __FreeBSD__ */
@@ -73,23 +75,6 @@ os_init(char *argv[], char *envp[])
#endif /* __FreeBSD__ */
}
-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 CONTEXT_ADDR_FROM_STEM(eip);
-#elif defined LISP_FEATURE_DARWIN
- return &context->uc_mcontext->ss.srr0;
-#else
-#error unsupported BSD variant
-#endif
-}
-
sigset_t *
os_context_sigmask_addr(os_context_t *context)
{
@@ -172,9 +157,11 @@ is_valid_lisp_addr(os_vm_address_t addr)
in_range_p(addr, DYNAMIC_SPACE_START , dynamic_space_size))
return 1;
for_each_thread(th) {
- if((th->control_stack_start <= addr) && (addr < th->control_stack_end))
+ if(((os_vm_address_t)th->control_stack_start <= addr) &&
+ (addr < (os_vm_address_t)th->control_stack_end))
return 1;
- if(in_range_p(addr, th->binding_stack_start, BINDING_STACK_SIZE))
+ if(in_range_p(addr, (lispobj)th->binding_stack_start,
+ BINDING_STACK_SIZE))
return 1;
}
return 0;
@@ -191,18 +178,28 @@ is_valid_lisp_addr(os_vm_address_t addr)
* page fault on this OS.
*/
static void
-memory_fault_handler(int signal, siginfo_t *siginfo, void *void_context)
+memory_fault_handler(int signal, siginfo_t *siginfo, void *void_context
+#if defined(LISP_FEATURE_FREEBSD) && defined(LISP_FEATURE_X86_64)
+/* FreeBSD/amd64 stores fault address only in undocumented 4th arg. */
+ ,void *fault_addr
+#endif
+ )
{
os_context_t *context = arch_os_get_context(&void_context);
+#if defined(LISP_FEATURE_FREEBSD) && defined(LISP_FEATURE_X86_64)
+ /* KLUDGE: Store fault address into si_addr for compatibilities. */
+ siginfo->si_addr = fault_addr;
+#else
void *fault_addr = arch_get_bad_addr(signal, siginfo, context);
+#endif
#if defined(LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_CONTEXT)
FSHOW_SIGNAL((stderr, "/ TLS: restoring fs: %p in memory_fault_handler\n",
*CONTEXT_ADDR_FROM_STEM(fs)));
os_restore_tls_segment_register(context);
#endif
- FSHOW((stderr, "Memory fault at: %p, PC: %x\n", fault_addr, *os_context_pc_addr(context)));
+ FSHOW((stderr, "Memory fault at: %p, PC: %p\n", fault_addr, *os_context_pc_addr(context)));
if (!gencgc_handle_wp_violation(fault_addr))
if(!handle_guard_page_triggered(context,fault_addr)) {
@@ -225,9 +222,15 @@ os_install_interrupt_handlers(void)
{
SHOW("os_install_interrupt_handlers()/bsd-os/defined(GENCGC)");
undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT,
+#ifdef LISP_FEATURE_FREEBSD
+ (__siginfohandler_t *)
+#endif
memory_fault_handler);
#ifdef SIG_MEMORY_FAULT2
undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT2,
+#ifdef LISP_FEATURE_FREEBSD
+ (__siginfohandler_t *)
+#endif
memory_fault_handler);
#endif
@@ -363,6 +366,8 @@ static void freebsd_init()
#define KERN_PROC_PATHNAME 12
#endif
+extern int getosreldate(void);
+
char *
os_get_runtime_executable_path()
{
View
1 src/runtime/bsd-os.h
@@ -31,7 +31,6 @@ typedef vm_size_t os_vm_size_t;
#endif
typedef off_t os_vm_offset_t;
typedef int os_vm_prot_t;
-typedef int os_context_register_t;
#if defined __OpenBSD__
/* name defined for compatibility between OpenBSD 3.1 sigaltstack(2) and
View
2 src/runtime/coreparse.c
@@ -107,7 +107,7 @@ search_for_embedded_core(char *filename)
}
static void
-process_directory(int fd, u32 *ptr, int count, os_vm_offset_t file_offset)
+process_directory(int fd, lispobj *ptr, int count, os_vm_offset_t file_offset)
{
struct ndir_entry *entry;
View
1 src/runtime/interrupt.c
@@ -584,7 +584,6 @@ run_deferred_handler(struct interrupt_data *data, void *v_context) {
* pending handler before calling it. Trust the handler to finish
* with the siginfo before enabling interrupts. */
void (*pending_handler) (int, siginfo_t*, void*)=data->pending_handler;
- os_context_t *context = arch_os_get_context(&v_context);
data->pending_handler=0;
(*pending_handler)(data->pending_signal,&(data->pending_info), v_context);
View
1 src/runtime/parse.c
@@ -12,6 +12,7 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
View
1 src/runtime/print.c
@@ -19,6 +19,7 @@
*/
#include <stdio.h>
+#include <string.h>
#include "sbcl.h"
#include "print.h"
View
92 src/runtime/x86-64-arch.c
@@ -50,7 +50,7 @@ arch_get_bad_addr(int sig, siginfo_t *code, os_context_t *context)
* want to get to, and on OS, which determines how we get to it.)
*/
-int *
+os_context_register_t *
context_eflags_addr(os_context_t *context)
{
#if defined __linux__
@@ -61,7 +61,7 @@ context_eflags_addr(os_context_t *context)
* instead. */
return &context->uc_mcontext.gregs[17];
#elif defined __FreeBSD__
- return &context->uc_mcontext.mc_eflags;
+ return &context->uc_mcontext.mc_rflags;
#elif defined __OpenBSD__
return &context->sc_eflags;
#else
@@ -106,7 +106,7 @@ void arch_skip_instruction(os_context_t *context)
break;
default:
- fprintf(stderr,"[arch_skip_inst invalid code %d\n]\n",code);
+ fprintf(stderr,"[arch_skip_inst invalid code %ld\n]\n",code);
break;
}
@@ -166,6 +166,11 @@ arch_remove_breakpoint(void *pc, unsigned int orig_inst)
/* When single stepping, single_stepping holds the original instruction
* PC location. */
unsigned int *single_stepping = NULL;
+#ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG
+unsigned int single_step_save1;
+unsigned int single_step_save2;
+unsigned int single_step_save3;
+#endif
void
arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
@@ -176,9 +181,24 @@ arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
*((char *)pc) = orig_inst & 0xff;
*((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
+#ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG
+ /* Install helper instructions for the single step:
+ * pushf; or [esp],0x100; popf. */
+ single_step_save1 = *(pc-3);
+ single_step_save2 = *(pc-2);
+ single_step_save3 = *(pc-1);
+ *(pc-3) = 0x9c909090;
+ *(pc-2) = 0x00240c81;
+ *(pc-1) = 0x9d000001;
+#else
*context_eflags_addr(context) |= 0x100;
+#endif
single_stepping = pc;
+
+#ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG
+ *os_context_pc_addr(context) = (os_context_register_t)((char *)pc - 9);
+#endif
}
@@ -191,10 +211,17 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context)
if (single_stepping && (signal==SIGTRAP))
{
+#ifdef CANNOT_GET_TO_SINGLE_STEP_FLAG
+ /* Un-install single step helper instructions. */
+ *(single_stepping-3) = single_step_save1;
+ *(single_stepping-2) = single_step_save2;
+ *(single_stepping-1) = single_step_save3;
+#else
*context_eflags_addr(context) ^= 0x100;
-
+#endif
/* Re-install the breakpoint if possible. */
- if (*os_context_pc_addr(context) == (int)single_stepping + 1) {
+ if ((char *)*os_context_pc_addr(context) ==
+ (char *)single_stepping + 1) {
fprintf(stderr, "warning: couldn't reinstall breakpoint\n");
} else {
*((char *)single_stepping) = BREAKPOINT_INST; /* x86 INT3 */
@@ -216,7 +243,7 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context)
single-stepping (as far as I can tell) this is somewhat moot,
but it might be worth either moving this code up or deleting
the single-stepping code entirely. -- CSR, 2002-07-15 */
-#ifdef LISP_FEATURE_LINUX
+#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
os_restore_fp_control(context);
#endif
@@ -281,6 +308,56 @@ sigill_handler(int signal, siginfo_t *siginfo, void *void_context) {
lose("fake_foreign_function_call fell through");
}
+#ifdef X86_64_SIGFPE_FIXUP
+#define MXCSR_IE (0x01) /* Invalid Operation */
+#define MXCSR_DE (0x02) /* Denormal */
+#define MXCSR_ZE (0x04) /* Devide-by-Zero */
+#define MXCSR_OE (0x08) /* Overflow */
+#define MXCSR_UE (0x10) /* Underflow */
+#define MXCSR_PE (0x20) /* Precision */
+
+static inline int
+mxcsr_to_code(unsigned int mxcsr)
+{
+ /* Extract unmasked exception bits. */
+ mxcsr &= ~(mxcsr >> 7) & 0x3F;
+
+ /* This order is defined at "Intel 64 and IA-32 Architectures
+ * Software Developerfs Manual" Volume 1: "Basic Architecture",
+ * 4.9.2 "Floating-Point Exception Priority". */
+ if (mxcsr & MXCSR_IE)
+ return FPE_FLTINV;
+ else if (mxcsr & MXCSR_ZE)
+ return FPE_FLTDIV;
+ else if (mxcsr & MXCSR_DE)
+ return FPE_FLTUND;
+ else if (mxcsr & MXCSR_OE)
+ return FPE_FLTOVF;
+ else if (mxcsr & MXCSR_UE)
+ return FPE_FLTUND;
+ else if (mxcsr & MXCSR_PE)
+ return FPE_FLTRES;
+
+ return 0;
+}
+
+static void
+sigfpe_handler(int signal, siginfo_t *siginfo, void *void_context)
+{
+ os_context_t *context = arch_os_get_context(&void_context);
+ unsigned int *mxcsr = arch_os_context_mxcsr_addr(context);
+
+ if (siginfo->si_code == 0) { /* XMM exception */
+ siginfo->si_code = mxcsr_to_code(*mxcsr);
+
+ /* Clear sticky exception flag. */
+ *mxcsr &= ~0x3F;
+ }
+
+ interrupt_handle_now(signal, siginfo, context);
+}
+#endif
+
void
arch_install_interrupt_handlers()
{
@@ -298,6 +375,9 @@ arch_install_interrupt_handlers()
* why.. -- WHN 2001-06-07 */
undoably_install_low_level_interrupt_handler(SIGILL , sigill_handler);
undoably_install_low_level_interrupt_handler(SIGTRAP, sigtrap_handler);
+#ifdef X86_64_SIGFPE_FIXUP
+ undoably_install_low_level_interrupt_handler(SIGFPE, sigfpe_handler);
+#endif
SHOW("returning from arch_install_interrupt_handlers()");
}
View
115 src/runtime/x86-64-bsd-os.c
@@ -0,0 +1,115 @@
+#include <signal.h>
+#include "sbcl.h"
+#include "runtime.h"
+#include "thread.h"
+#include "lispregs.h"
+
+#if defined(LISP_FEATURE_FREEBSD)
+#include <machine/fpu.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
+ * factor out the commonality better; failing that, it might be best
+ * just to split this generic-BSD code into one variant for each BSD.
+ *
+ * KLUDGE II: this split has begun with the addition of the Darwin BSD
+ * flavour, with the cross-architecture complications that this
+ * entails; unfortunately, currently the situation is worse, not
+ * better, than in the above paragraph. */
+
+#if defined(LISP_FEATURE_FREEBSD)
+os_context_register_t *
+os_context_register_addr(os_context_t *context, int offset)
+{
+ switch(offset) {
+ case reg_RAX:
+ return CONTEXT_ADDR_FROM_STEM(rax);
+ case reg_RCX:
+ return CONTEXT_ADDR_FROM_STEM(rcx);
+ case reg_RDX:
+ return CONTEXT_ADDR_FROM_STEM(rdx);
+ case reg_RBX:
+ return CONTEXT_ADDR_FROM_STEM(rbx);
+ case reg_RSP:
+ return CONTEXT_ADDR_FROM_STEM(rsp);
+ case reg_RBP:
+ return CONTEXT_ADDR_FROM_STEM(rbp);
+ case reg_RSI:
+ return CONTEXT_ADDR_FROM_STEM(rsi);
+ case reg_RDI:
+ return CONTEXT_ADDR_FROM_STEM(rdi);
+ case reg_R8:
+ return CONTEXT_ADDR_FROM_STEM(r8);
+ case reg_R9:
+ return CONTEXT_ADDR_FROM_STEM(r9);
+ case reg_R10:
+ return CONTEXT_ADDR_FROM_STEM(r10);
+ case reg_R11:
+ return CONTEXT_ADDR_FROM_STEM(r11);
+ case reg_R12:
+ return CONTEXT_ADDR_FROM_STEM(r12);
+ case reg_R13:
+ return CONTEXT_ADDR_FROM_STEM(r13);
+ case reg_R14:
+ return CONTEXT_ADDR_FROM_STEM(r14);
+ case reg_R15:
+ return CONTEXT_ADDR_FROM_STEM(r15);
+ default:
+ return 0;
+ }
+}
+
+os_context_register_t *
+os_context_sp_addr(os_context_t *context)
+{
+ return CONTEXT_ADDR_FROM_STEM(rsp);
+}
+
+os_context_register_t *
+os_context_pc_addr(os_context_t *context)
+{
+ return CONTEXT_ADDR_FROM_STEM(rip);
+}
+
+#endif
+
+void
+os_flush_icache(os_vm_address_t address, os_vm_size_t length)
+{
+}
+
+int arch_os_thread_init(struct thread *thread) {
+ stack_t sigstack;
+#ifdef LISP_FEATURE_SB_THREAD
+ pthread_setspecific(specials,thread);
+#endif
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
+ /* Signal handlers are run on the control stack, so if it is exhausted
+ * we had better use an alternate stack for whatever signal tells us
+ * we've exhausted it */
+ sigstack.ss_sp=((void *) thread)+dynamic_values_bytes;
+ sigstack.ss_flags=0;
+ sigstack.ss_size = 32*SIGSTKSZ;
+ sigaltstack(&sigstack,0);
+#endif
+ return 1; /* success */
+}
+
+int arch_os_thread_cleanup(struct thread *thread) {
+ return 1; /* success */
+}
+
+#if defined(LISP_FEATURE_FREEBSD)
+void
+os_restore_fp_control(os_context_t *context)
+{
+ struct envxmm *ex = (struct envxmm*)(&context->uc_mcontext.mc_fpstate);
+ /* reset exception flags and restore control flags on SSE2 FPU */
+ unsigned int temp = (ex->en_mxcsr) & ~0x3F;
+ asm ("ldmxcsr %0" : : "m" (temp));
+ /* same for x87 FPU. */
+ asm ("fldcw %0" : : "m" (ex->en_cw));
+}
+#endif
View
43 src/runtime/x86-64-bsd-os.h
@@ -0,0 +1,43 @@
+#ifndef _X86_64_BSD_OS_H
+#define _X86_64_BSD_OS_H
+
+#ifdef LISP_FEATURE_FREEBSD
+#include <machine/fpu.h>
+#endif
+
+typedef register_t os_context_register_t;
+
+static inline os_context_t *arch_os_get_context(void **void_context) {
+ return (os_context_t *) *void_context;
+}
+
+/* The different BSD variants have diverged in exactly where they
+ * store signal context information, but at least they tend to use the
+ * same stems to name the structure fields, so by using this macro we
+ * can share a fair amount of code between different variants. */
+#if defined __FreeBSD__
+#define CONTEXT_ADDR_FROM_STEM(stem) &context->uc_mcontext.mc_ ## stem
+#elif defined(__OpenBSD__)
+#define CONTEXT_ADDR_FROM_STEM(stem) &context->sc_ ## stem
+#elif defined __NetBSD__
+#define CONTEXT_ADDR_FROM_STEM(stem) &((context)->uc_mcontext.__gregs[_REG_ ## stem])
+#else
+#error unsupported BSD variant
+#endif
+
+#if defined LISP_FEATURE_FREEBSD
+#define RESTORE_FP_CONTROL_FROM_CONTEXT
+void os_restore_fp_control(os_context_t *context);
+
+/* FreeBSD does not setup si_code on XMM exception. */
+#define X86_64_SIGFPE_FIXUP
+
+static inline unsigned int *
+arch_os_context_mxcsr_addr(os_context_t *context)
+{
+ struct envxmm *ex = (struct envxmm *)(&context->uc_mcontext.mc_fpstate);
+ return &ex->en_mxcsr;
+}
+#endif
+
+#endif /* _X86_64_BSD_OS_H */
View
16 src/runtime/x86-bsd-os.c
@@ -100,6 +100,22 @@ os_context_sp_addr(os_context_t *context)
#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 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.
View
2 src/runtime/x86-bsd-os.h
@@ -6,6 +6,8 @@
#include <machine/cpufunc.h>
#endif
+typedef int os_context_register_t;
+
static inline os_context_t *arch_os_get_context(void **void_context) {
return (os_context_t *) *void_context;
}
View
4 tests/foreign-stack-alignment.impure.lisp
@@ -43,7 +43,7 @@
;;;; number.
(run "cc"
- #+(and linux (or x86-64 ppc)) "-fPIC"
+ #+(and (or linux freebsd) (or x86-64 ppc)) "-fPIC"
"stack-alignment-offset.c" "-o" "stack-alignment-offset")
(defparameter *good-offset*
@@ -53,7 +53,7 @@
;;;; Build the tool again, this time as a shared object, and load it
(run "cc" "stack-alignment-offset.c"
- #+(and linux (or x86-64 ppc)) "-fPIC"
+ #+(and (or linux freebsd) (or x86-64 ppc)) "-fPIC"
#+darwin "-bundle" #-darwin "-shared"
"-o" "stack-alignment-offset.so")
View
2 version.lisp-expr
@@ -17,4 +17,4 @@
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.0.31"
+"1.0.0.32"

0 comments on commit bd45534

Please sign in to comment.
Something went wrong with that request. Please try again.