/[cmucl]/src/lisp/FreeBSD-os.c
ViewVC logotype

Contents of /src/lisp/FreeBSD-os.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.38 - (show annotations)
Thu Sep 1 05:18:26 2011 UTC (2 years, 7 months ago) by rtoy
Branch: MAIN
CVS Tags: GIT-CONVERSION, snapshot-2011-09, HEAD
Changes since 1.37: +5 -1 lines
File MIME type: text/plain
Add os_init0 to allow for some really early OS inits.

On Linux, os_init can re-exec lisp to set up the correct personality.
Not normally a problem, but if any output happens before os_init is
called, the output appears to happen twice.  So add os_init0 to do
this early on, before any output.  This is a bit of a kludge.

lisp/lisp.c:
o Call os_init0 early in main.

lisp/Linux-os.c:
o Move the personality stuff from os_init to os_init0.

lisp/Darwin-os.c:
lisp/FreeBSD-os.c:
lisp/NetBSD-os.c:
lisp/OpenBSD-os.c:
lisp/hpux-os.c:
lisp/irix-os.c:
lisp/mach-os.c:
lisp/osf1-os.c:
lisp/solaris-os.c:
lisp/sunos-os.c:
o Add dummy implementation of os_init0.  These OSes don't (currently)
  need anything special.

lisp/os.h:
o Declare os_init0.
1 /*
2 * FreeBSD-os.c. Maybe could be just BSD-os.c
3 * From osf1-os.c,v 1.1 94/03/27 15:30:51 hallgren Exp $
4 *
5 * OS-dependent routines. This file (along with os.h) exports an
6 * OS-independent interface to the operating system VM facilities.
7 * Suprisingly, this interface looks a lot like the Mach interface
8 * (but simpler in some places). For some operating systems, a subset
9 * of these functions will have to be emulated.
10 *
11 * This is the OSF1 version. By Sean Hallgren.
12 * Much hacked by Paul Werkowski
13 * GENCGC support by Douglas Crosher, 1996, 1997.
14 *
15 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/FreeBSD-os.c,v 1.38 2011/09/01 05:18:26 rtoy Exp $
16 *
17 */
18
19 #include "os.h"
20 #include <sys/file.h>
21 #include <machine/npx.h>
22 #include <errno.h>
23 #include "arch.h"
24 #include "globals.h"
25 #include "interrupt.h"
26 #include "lispregs.h"
27 #include "internals.h"
28
29 #include <signal.h>
30 #include <dlfcn.h>
31 #include "validate.h"
32 #include <stdio.h>
33 #include <unistd.h>
34
35 #if defined GENCGC
36 #include "gencgc.h"
37 #endif
38
39 vm_size_t os_vm_page_size;
40
41 void
42 os_init0(const char *argv[], const char *envp[])
43 {}
44
45 void
46 os_init(const char *argv[], const char *envp[])
47 {
48 os_vm_page_size = getpagesize();
49 }
50
51 unsigned long *
52 os_sigcontext_reg(ucontext_t *scp, int index)
53 {
54 __register_t *rv;
55
56 switch (index) {
57 case 0:
58 rv = &scp->uc_mcontext.mc_eax;
59 break;
60 case 2:
61 rv = &scp->uc_mcontext.mc_ecx;
62 break;
63 case 4:
64 rv = &scp->uc_mcontext.mc_edx;
65 break;
66 case 6:
67 rv = &scp->uc_mcontext.mc_ebx;
68 break;
69 case 8:
70 rv = &scp->uc_mcontext.mc_esp;
71 break;
72 case 10:
73 rv = &scp->uc_mcontext.mc_ebp;
74 break;
75 case 12:
76 rv = &scp->uc_mcontext.mc_esi;
77 break;
78 case 14:
79 rv = &scp->uc_mcontext.mc_edi;
80 break;
81 default:
82 rv = NULL;
83 }
84
85 /* Pre-cast to (void *), to avoid the compiler warning:
86 * dereferencing type-punned pointer will break strict-aliasing rules
87 */
88 return (unsigned long *) (void *) rv;
89 }
90
91 unsigned long *
92 os_sigcontext_pc(ucontext_t *scp)
93 {
94 return (unsigned long *) (void *) &scp->uc_mcontext.mc_eip;
95 }
96
97 unsigned char *
98 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
99 {
100 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
101 int fpformat = scp->uc_mcontext.mc_fpformat;
102 unsigned char *reg = NULL;
103
104 switch (fpformat) {
105 case _MC_FPFMT_XMM:
106 if (index < 8) {
107 reg = sv->sv_xmm.sv_fp[index].fp_acc.fp_bytes;
108 } else {
109 reg = sv->sv_xmm.sv_xmm[index - 8].xmm_bytes;
110 }
111 break;
112 case _MC_FPFMT_387:
113 reg = sv->sv_87.sv_ac[index].fp_bytes;
114 break;
115 case _MC_FPFMT_NODEV:
116 reg = NULL;
117 break;
118 }
119 return reg;
120 }
121
122 unsigned int
123 os_sigcontext_fpu_modes(ucontext_t *scp)
124 {
125 unsigned int modes;
126
127 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
128 int fpformat = scp->uc_mcontext.mc_fpformat;
129 struct env87 *env_87 = &sv->sv_87.sv_env;
130 struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
131 u_int16_t cw;
132 u_int16_t sw;
133
134 if (fpformat == _MC_FPFMT_XMM) {
135 cw = env_xmm->en_cw;
136 sw = env_xmm->en_sw;
137 } else if (fpformat == _MC_FPFMT_387) {
138 cw = env_87->en_cw & 0xffff;
139 sw = env_87->en_sw & 0xffff;
140 } else { /* _MC_FPFMT_NODEV */
141 cw = 0;
142 sw = 0x3f;
143 }
144
145 modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
146
147 #ifdef FEATURE_SSE2
148 if (fpu_mode == SSE2) {
149 u_int32_t mxcsr = env_xmm->en_mxcsr;
150
151 DPRINTF(0, (stderr, "SSE2 modes = %08x\n", (int)mxcsr));
152 modes |= mxcsr;
153 }
154 #endif
155 modes ^= (0x3f << 7);
156 return modes;
157 }
158
159 os_vm_address_t
160 os_validate(os_vm_address_t addr, os_vm_size_t len)
161 {
162 int flags = MAP_PRIVATE | MAP_ANON;
163
164 if (addr)
165 flags |= MAP_FIXED;
166
167 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
168
169 if (addr == (os_vm_address_t) - 1) {
170 perror("mmap");
171 return NULL;
172 }
173
174 return addr;
175 }
176
177 void
178 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
179 {
180 if (munmap(addr, len) == -1)
181 perror("munmap");
182 }
183
184 os_vm_address_t
185 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
186 {
187 addr = mmap(addr, len, OS_VM_PROT_ALL,
188 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
189
190 if (addr == (os_vm_address_t) - 1)
191 perror("mmap");
192
193 return addr;
194 }
195
196 void
197 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
198 {
199 }
200
201 void
202 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
203 {
204 if (mprotect(address, length, prot) == -1)
205 perror("mprotect");
206 }
207
208
209
210 static boolean
211 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
212 {
213 char *beg = (char *) sbeg;
214 char *end = (char *) sbeg + slen;
215 char *adr = (char *) a;
216
217 return adr >= beg && adr < end;
218 }
219
220 boolean
221 valid_addr(os_vm_address_t addr)
222 {
223 os_vm_address_t newaddr;
224
225 newaddr = os_trunc_to_page(addr);
226
227 if (in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE)
228 || in_range_p(addr, STATIC_SPACE_START, STATIC_SPACE_SIZE)
229 || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
230 #ifndef GENCGC
231 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
232 #endif
233 || in_range_p(addr, CONTROL_STACK_START, CONTROL_STACK_SIZE)
234 || in_range_p(addr, BINDING_STACK_START, BINDING_STACK_SIZE))
235 return TRUE;
236 return FALSE;
237 }
238
239
240 static void
241 protection_violation_handler(HANDLER_ARGS)
242 {
243 #ifdef RED_ZONE_HIT
244 if (os_control_stack_overflow(code->si_addr, context))
245 return;
246 #endif
247
248 #if defined GENCGC
249 if (code->si_code == PROTECTION_VIOLATION_CODE) {
250 if (gc_write_barrier(code->si_addr)) {
251 return;
252 }
253 }
254 #endif
255
256 interrupt_handle_now(signal, code, context);
257 }
258
259 /*
260 * Restore the exception flags cleared by the kernel. These bits must
261 * be set for Lisp to determine which exception caused the signal. At
262 * present, there is no way to distinguish underflow exceptions from
263 * denormalized operand exceptions. An underflow exception is assumed
264 * if the subcode is FPE_FLTUND.
265 */
266 static void
267 sigfpe_handler(HANDLER_ARGS)
268 {
269 ucontext_t *ucontext = (ucontext_t *) context;
270 union savefpu *sv = (union savefpu *) ucontext->uc_mcontext.mc_fpstate;
271 int fpformat = ucontext->uc_mcontext.mc_fpformat;
272 unsigned char trap = 0;
273
274 switch (code->si_code) {
275 case FPE_FLTDIV: /* ZE */
276 trap = 0x04;
277 break;
278 case FPE_FLTOVF: /* OE */
279 trap = 0x08;
280 break;
281 case FPE_FLTUND: /* DE or UE */
282 trap = 0x10;
283 break;
284 case FPE_FLTRES: /* PE */
285 trap = 0x20;
286 break;
287 case FPE_FLTINV: /* IE */
288 trap = 0x01;
289 break;
290 }
291
292 switch (fpformat) {
293 case _MC_FPFMT_XMM:
294 sv->sv_xmm.sv_env.en_sw |= trap;
295 break;
296 case _MC_FPFMT_387:
297 sv->sv_87.sv_env.en_sw |= trap;
298 break;
299 }
300 interrupt_handle_now(signal, code, context);
301 }
302
303 void
304 os_install_interrupt_handlers(void)
305 {
306 interrupt_install_low_level_handler(PROTECTION_VIOLATION_SIGNAL,
307 protection_violation_handler);
308 interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
309 }
310
311 void *
312 os_dlsym(const char *sym_name, lispobj lib_list)
313 {
314 static void *program_handle;
315
316 if (!program_handle)
317 program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
318
319 if (lib_list != NIL) {
320 lispobj lib_list_head;
321
322 for (lib_list_head = lib_list;
323 lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {
324 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
325 struct sap *dlhandle = (struct sap *)PTR(lib_cons->car);
326 void *sym_addr = dlsym((void *)dlhandle->pointer, sym_name);
327
328 if (sym_addr)
329 return sym_addr;
330 }
331 }
332 return dlsym(program_handle, sym_name);
333 }
334
335 void
336 restore_fpu(ucontext_t *scp)
337 {
338 union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
339 int fpformat = scp->uc_mcontext.mc_fpformat;
340 struct env87 *env_87 = &sv->sv_87.sv_env;
341 struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
342 u_int16_t cw;
343
344 if (fpformat == _MC_FPFMT_XMM) {
345 cw = env_xmm->en_cw;
346 } else if (fpformat == _MC_FPFMT_387) {
347 cw = env_87->en_cw & 0xffff;
348 } else { /* _MC_FPFMT_NODEV */
349 return;
350 }
351 DPRINTF(0, (stderr, "restore_fpu: cw = %08x\n", (int)cw));
352 __asm__ __volatile__ ("fldcw %0"::"m"(*&cw));
353
354 #ifdef FEATURE_SSE2
355 if (fpu_mode == SSE2) {
356 u_int32_t mxcsr = env_xmm->en_mxcsr;
357
358 DPRINTF(0, (stderr, "restore_fpu: mxcsr (raw) = %04x\n", mxcsr));
359 __asm__ __volatile__ ("ldmxcsr %0"::"m"(*&mxcsr));
360 }
361 #endif
362 }
363
364 #ifdef i386
365 boolean
366 os_support_sse2()
367 {
368 return TRUE;
369 }
370 #endif
371

  ViewVC Help
Powered by ViewVC 1.1.5