8c545036f3211f2b977fa932a4812f1e0db200f1
[sbcl.git] / src / runtime / x86-64-bsd-os.c
1 #include <signal.h>
2 #include "sbcl.h"
3 #include "runtime.h"
4 #include "thread.h"
5 #include "lispregs.h"
6
7 #if defined(LISP_FEATURE_FREEBSD)
8 #include <machine/fpu.h>
9 #endif
10
11 #if defined(LISP_FEATURE_OPENBSD)
12 #include <machine/fpu.h>
13 #endif
14
15 #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER
16 #include <mach/mach.h>
17
18 kern_return_t mach_thread_init(mach_port_t thread_exception_port);
19 #endif
20
21 /* KLUDGE: There is strong family resemblance in the signal context
22  * stuff in FreeBSD and OpenBSD, but in detail they're different in
23  * almost every line of code. It would be nice to find some way to
24  * factor out the commonality better; failing that, it might be best
25  * just to split this generic-BSD code into one variant for each BSD.
26  *
27  * KLUDGE II: this split has begun with the addition of the Darwin BSD
28  * flavour, with the cross-architecture complications that this
29  * entails; unfortunately, currently the situation is worse, not
30  * better, than in the above paragraph. */
31
32 #if defined(LISP_FEATURE_FREEBSD) || defined(LISP_FEATURE_DARWIN) || defined(LISP_FEATURE_OPENBSD)
33 os_context_register_t *
34 os_context_register_addr(os_context_t *context, int offset)
35 {
36     switch(offset) {
37     case reg_RAX:
38         return CONTEXT_ADDR_FROM_STEM(rax);
39     case reg_RCX:
40         return CONTEXT_ADDR_FROM_STEM(rcx);
41     case reg_RDX:
42         return CONTEXT_ADDR_FROM_STEM(rdx);
43     case reg_RBX:
44         return CONTEXT_ADDR_FROM_STEM(rbx);
45     case reg_RSP:
46         return CONTEXT_ADDR_FROM_STEM(rsp);
47     case reg_RBP:
48         return CONTEXT_ADDR_FROM_STEM(rbp);
49     case reg_RSI:
50         return CONTEXT_ADDR_FROM_STEM(rsi);
51     case reg_RDI:
52         return CONTEXT_ADDR_FROM_STEM(rdi);
53     case reg_R8:
54         return CONTEXT_ADDR_FROM_STEM(r8);
55     case reg_R9:
56         return CONTEXT_ADDR_FROM_STEM(r9);
57     case reg_R10:
58         return CONTEXT_ADDR_FROM_STEM(r10);
59     case reg_R11:
60         return CONTEXT_ADDR_FROM_STEM(r11);
61     case reg_R12:
62         return CONTEXT_ADDR_FROM_STEM(r12);
63     case reg_R13:
64         return CONTEXT_ADDR_FROM_STEM(r13);
65     case reg_R14:
66         return CONTEXT_ADDR_FROM_STEM(r14);
67     case reg_R15:
68         return CONTEXT_ADDR_FROM_STEM(r15);
69     default:
70         return 0;
71     }
72 }
73
74 os_context_register_t *
75 os_context_sp_addr(os_context_t *context)
76 {
77     return CONTEXT_ADDR_FROM_STEM(rsp);
78 }
79
80 os_context_register_t *
81 os_context_pc_addr(os_context_t *context)
82 {
83     return CONTEXT_ADDR_FROM_STEM(rip);
84 }
85
86 #elif defined(LISP_FEATURE_NETBSD)
87 os_context_register_t *
88 os_context_register_addr(os_context_t *context, int offset)
89 {
90     switch(offset) {
91     case reg_RAX:
92         return CONTEXT_ADDR_FROM_STEM(RAX);
93     case reg_RCX:
94         return CONTEXT_ADDR_FROM_STEM(RCX);
95     case reg_RDX:
96         return CONTEXT_ADDR_FROM_STEM(RDX);
97     case reg_RBX:
98         return CONTEXT_ADDR_FROM_STEM(RBX);
99     case reg_RSP:
100         return CONTEXT_ADDR_FROM_STEM(RSP);
101     case reg_RBP:
102         return CONTEXT_ADDR_FROM_STEM(RBP);
103     case reg_RSI:
104         return CONTEXT_ADDR_FROM_STEM(RSI);
105     case reg_RDI:
106         return CONTEXT_ADDR_FROM_STEM(RDI);
107     case reg_R8:
108         return CONTEXT_ADDR_FROM_STEM(R8);
109     case reg_R9:
110         return CONTEXT_ADDR_FROM_STEM(R9);
111     case reg_R10:
112         return CONTEXT_ADDR_FROM_STEM(R10);
113     case reg_R11:
114         return CONTEXT_ADDR_FROM_STEM(R11);
115     case reg_R12:
116         return CONTEXT_ADDR_FROM_STEM(R12);
117     case reg_R13:
118         return CONTEXT_ADDR_FROM_STEM(R13);
119     case reg_R14:
120         return CONTEXT_ADDR_FROM_STEM(R14);
121     case reg_R15:
122         return CONTEXT_ADDR_FROM_STEM(R15);
123     default:
124         return 0;
125     }
126 }
127
128 os_context_register_t *
129 os_context_sp_addr(os_context_t *context)
130 {
131     return CONTEXT_ADDR_FROM_STEM(RSP);
132 }
133
134 os_context_register_t *
135 os_context_pc_addr(os_context_t *context)
136 {
137     return CONTEXT_ADDR_FROM_STEM(RIP);
138 }
139
140 #endif
141
142 void
143 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
144 {
145 }
146
147 int arch_os_thread_init(struct thread *thread) {
148     stack_t sigstack;
149 #ifdef LISP_FEATURE_SB_THREAD
150 #ifdef LISP_FEATURE_GCC_TLS
151     current_thread = thread;
152 #else
153     pthread_setspecific(specials,thread);
154 #endif
155 #endif
156
157 #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER
158     mach_thread_init(THREAD_STRUCT_TO_EXCEPTION_PORT(thread));
159 #endif
160
161 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
162     /* Signal handlers are run on the control stack, so if it is exhausted
163      * we had better use an alternate stack for whatever signal tells us
164      * we've exhausted it */
165     sigstack.ss_sp=((void *) thread)+dynamic_values_bytes;
166     sigstack.ss_flags=0;
167     sigstack.ss_size = 32*SIGSTKSZ;
168     sigaltstack(&sigstack,0);
169 #endif
170     return 1;                  /* success */
171 }
172
173 int arch_os_thread_cleanup(struct thread *thread) {
174     return 1;                  /* success */
175 }
176
177 #if defined(LISP_FEATURE_FREEBSD)
178 void
179 os_restore_fp_control(os_context_t *context)
180 {
181     struct envxmm *ex = (struct envxmm*)(&context->uc_mcontext.mc_fpstate);
182     /* reset exception flags and restore control flags on SSE2 FPU */
183     unsigned int temp = (ex->en_mxcsr) & ~0x3F;
184     asm ("ldmxcsr %0" : : "m" (temp));
185     /* same for x87 FPU. */
186     asm ("fldcw %0" : : "m" (ex->en_cw));
187 }
188 #endif
189
190 #if defined(LISP_FEATURE_OPENBSD)
191 void
192 os_restore_fp_control(os_context_t *context)
193 {
194     if (context->sc_fpstate != NULL) {
195         u_int32_t mxcsr = context->sc_fpstate->fx_mxcsr & ~0x3F;
196         u_int16_t cw = context->sc_fpstate->fx_fcw;
197         asm ("ldmxcsr %0" : : "m" (mxcsr));
198         asm ("fldcw %0" : : "m" (cw));
199     }
200 }
201 #endif