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