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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.35 - (show annotations)
Sat Sep 3 04:46:34 2011 UTC (2 years, 7 months ago) by rtoy
Branch: MAIN
CVS Tags: GIT-CONVERSION, snapshot-2011-09, HEAD
Changes since 1.34: +3 -29 lines
File MIME type: text/plain
Cleanup sigbus handler for stack overflow.

We don't need sigbus_handler_tramp; sigbus_handle_now is good enough.
Print out the PC too when we get a real sigbus.
1 /*
2 * Darwin-os.c.
3 * From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc 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 * Frobbed for OpenBSD by Pierre R. Mai, 2001.
15 * Frobbed for Darwin by Pierre R. Mai, 2003.
16 *
17 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/Darwin-os.c,v 1.35 2011/09/03 04:46:34 rtoy Exp $
18 *
19 */
20
21 #include <stdio.h>
22 #include <sys/param.h>
23 #include <sys/file.h>
24 #include <errno.h>
25 #include <dlfcn.h>
26 #include <string.h>
27 #include "os.h"
28 #include "arch.h"
29 #include "globals.h"
30 #include "interrupt.h"
31 #include "lispregs.h"
32 #include "internals.h"
33 #ifdef GENCGC
34 #include "gencgc.h"
35 #endif
36
37 #include <sys/types.h>
38 #include <signal.h>
39 /* #include <sys/sysinfo.h> */
40 /* #include <sys/proc.h> */
41 /* For timebase info */
42 #include <sys/sysctl.h>
43
44
45 /* Need this to define ppc_saved_state_t (for 10.4) */
46 #include <mach/thread_status.h>
47
48 #include "validate.h"
49 vm_size_t os_vm_page_size;
50
51
52
53 /*
54 * This is accessed by Lisp! Make this a static symbol?
55 */
56 int cycles_per_tick = 1;
57
58 /*
59 * Compute the conversion factor from the numbef of time base ticks to
60 * clock frequency. The timebase counter on PPC is not a cycle
61 * counter; we have to derive the relationship ourselves.
62 */
63
64 #ifdef __ppc__
65 void
66 timebase_init(void)
67 {
68 int mib[2];
69 int tbfrequency;
70 int cpufrequency;
71 unsigned int miblen;
72 size_t len;
73
74 mib[0] = CTL_HW;
75 #ifndef HW_TB_FREQ
76 /*
77 * Mac OS X 10.2.8 doesn't have this, so we take it from 10.3.8,
78 * which does.
79 */
80 #define HW_TB_FREQ 23
81 #endif
82 mib[1] = HW_TB_FREQ;
83 miblen = 2;
84 len = sizeof(tbfrequency);
85
86 if (sysctl(mib, miblen, &tbfrequency, &len, NULL, 0) == -1) {
87 perror("Error getting HW_TB_FREQ from sysctl: ");
88 }
89
90 mib[0] = CTL_HW;
91 mib[1] = HW_CPU_FREQ;
92 miblen = 2;
93 len = sizeof(cpufrequency);
94 if (sysctl(mib, miblen, &cpufrequency, &len, NULL, 0) == -1) {
95 perror("Error getting HW_CPU_FREQ from sysctl: ");
96 }
97
98 cycles_per_tick = cpufrequency / tbfrequency;
99 }
100 #endif
101
102 void
103 os_init0(const char *argv[], const char *envp[])
104 {}
105
106 void
107 os_init(const char *argv[], const char *envp[])
108 {
109 os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
110 #ifdef __ppc__
111 timebase_init();
112 #endif
113 }
114
115 #if defined(__ppc__)
116 int *
117 sc_reg(os_context_t * context, int offset)
118 {
119 ppc_saved_state_t *state = &context->uc_mcontext->ss;
120
121 switch (offset) {
122 case 0:
123 return &state->r0;
124 case 1:
125 return &state->r1;
126 case 2:
127 return &state->r2;
128 case 3:
129 return &state->r3;
130 case 4:
131 return &state->r4;
132 case 5:
133 return &state->r5;
134 case 6:
135 return &state->r6;
136 case 7:
137 return &state->r7;
138 case 8:
139 return &state->r8;
140 case 9:
141 return &state->r9;
142 case 10:
143 return &state->r10;
144 case 11:
145 return &state->r11;
146 case 12:
147 return &state->r12;
148 case 13:
149 return &state->r13;
150 case 14:
151 return &state->r14;
152 case 15:
153 return &state->r15;
154 case 16:
155 return &state->r16;
156 case 17:
157 return &state->r17;
158 case 18:
159 return &state->r18;
160 case 19:
161 return &state->r19;
162 case 20:
163 return &state->r20;
164 case 21:
165 return &state->r21;
166 case 22:
167 return &state->r22;
168 case 23:
169 return &state->r23;
170 case 24:
171 return &state->r24;
172 case 25:
173 return &state->r25;
174 case 26:
175 return &state->r26;
176 case 27:
177 return &state->r27;
178 case 28:
179 return &state->r28;
180 case 29:
181 return &state->r29;
182 case 30:
183 return &state->r30;
184 case 31:
185 return &state->r31;
186 case 34:
187 /*
188 * Not sure if this is really defined anywhere, but after
189 * r31 is cr, xer, lr, and ctr. So we let 34 be lr.
190 */
191 return &state->lr;
192 case 35:
193 return &state->ctr;
194 case 41:
195 return &context->uc_mcontext->es.dar;
196 case 42:
197 return &context->uc_mcontext->es.dsisr;
198 }
199
200 return (int *) 0;
201 }
202 #elif defined(__i386__)
203 #if __DARWIN_UNIX03
204 /* Nothing needed for 10.5 */
205 #else
206 /* This is for 10.4 */
207 #define __ss ss
208 #define __eax eax
209 #define __ecx ecx
210 #define __edx edx
211 #define __ebx ebx
212 #define __esp esp
213 #define __ebp ebp
214 #define __esi esi
215 #define __edi edi
216 #define __eip eip
217 #define __fs fs
218 #define __fpu_stmm0 fpu_stmm0
219 #define __fpu_stmm1 fpu_stmm1
220 #define __fpu_stmm2 fpu_stmm2
221 #define __fpu_stmm3 fpu_stmm3
222 #define __fpu_stmm4 fpu_stmm4
223 #define __fpu_stmm5 fpu_stmm5
224 #define __fpu_stmm6 fpu_stmm6
225 #define __fpu_stmm7 fpu_stmm7
226 #define __fpu_fcw fpu_fcw
227 #define __fpu_fsw fpu_fsw
228 #define __fpu_mxcsr fpu_mxcsr
229 #ifdef FEATURE_SSE2
230 #define __fpu_xmm0 fpu_xmm0
231 #define __fpu_xmm1 fpu_xmm1
232 #define __fpu_xmm2 fpu_xmm2
233 #define __fpu_xmm3 fpu_xmm3
234 #define __fpu_xmm4 fpu_xmm4
235 #define __fpu_xmm5 fpu_xmm5
236 #define __fpu_xmm6 fpu_xmm6
237 #define __fpu_xmm7 fpu_xmm7
238 #endif
239 #endif
240
241 unsigned long *
242 os_sigcontext_reg(ucontext_t *scp, int index)
243 {
244 switch (index) {
245 case 0:
246 return (unsigned long *) &scp->uc_mcontext->__ss.__eax;
247 case 2:
248 return (unsigned long *) &scp->uc_mcontext->__ss.__ecx;
249 case 4:
250 return (unsigned long *) &scp->uc_mcontext->__ss.__edx;
251 case 6:
252 return (unsigned long *) &scp->uc_mcontext->__ss.__ebx;
253 case 8:
254 return (unsigned long *) &scp->uc_mcontext->__ss.__esp;
255 case 10:
256 return (unsigned long *) &scp->uc_mcontext->__ss.__ebp;
257 case 12:
258 return (unsigned long *) &scp->uc_mcontext->__ss.__esi;
259 case 14:
260 return (unsigned long *) &scp->uc_mcontext->__ss.__edi;
261 }
262 return NULL;
263 }
264
265 unsigned long *
266 os_sigcontext_pc(ucontext_t *scp)
267 {
268 return (unsigned long *) &scp->uc_mcontext->__ss.__eip;
269 }
270
271 unsigned char *
272 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
273 {
274 switch (index) {
275 case 0:
276 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm0;
277 case 1:
278 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm1;
279 case 2:
280 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm2;
281 case 3:
282 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm3;
283 case 4:
284 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm4;
285 case 5:
286 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm5;
287 case 6:
288 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm6;
289 case 7:
290 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
291 #ifdef FEATURE_SSE2
292 case 8:
293 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0;
294 case 9:
295 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1;
296 case 10:
297 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2;
298 case 11:
299 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3;
300 case 12:
301 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4;
302 case 13:
303 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5;
304 case 14:
305 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6;
306 case 15:
307 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
308 #endif
309 }
310 return NULL;
311 }
312
313 unsigned int
314 os_sigcontext_fpu_modes(ucontext_t *scp)
315 {
316 unsigned int modes;
317 unsigned int mxcsr;
318 unsigned short cw, sw;
319
320 /*
321 * Get the status word and the control word.
322 */
323 memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
324 memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw));
325
326 /*
327 * Put the cw in the upper bits and the status word in the lower 6
328 * bits, ignoring everything except the exception masks and the
329 * exception flags.
330 */
331 modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
332
333 DPRINTF(0, (stderr, "FPU modes = %08x (sw = %4x, cw = %4x)\n",
334 modes, (unsigned int) sw, (unsigned int) cw));
335
336 if (fpu_mode == SSE2) {
337 mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
338 DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr));
339
340 modes |= mxcsr;
341 }
342
343 DPRINTF(0, (stderr, "modes pre mask = %08x\n", modes));
344
345 /* Convert exception mask to exception enable */
346 modes ^= (0x3f << 7);
347 DPRINTF(0, (stderr, "Finale = %08x\n", modes));
348 return modes;
349 }
350
351 void
352 restore_fpu(ucontext_t *scp)
353 {
354 unsigned short cw;
355 unsigned int mxcsr;
356
357 memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
358 DPRINTF(0, (stderr, "restore_fpu: FPU cw = 0x%x\n", cw));
359 __asm__ __volatile__ ("fclex");
360 __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
361
362 mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
363 DPRINTF(0, (stderr, "restore_fpu: mxcsr (raw) = %04x\n", mxcsr));
364 __asm__ __volatile__ ("ldmxcsr %0" :: "m" (*&mxcsr));
365 }
366 #endif
367
368 os_vm_address_t
369 os_validate(os_vm_address_t addr, os_vm_size_t len)
370 {
371 int flags = MAP_PRIVATE | MAP_ANON;
372
373 if (addr)
374 flags |= MAP_FIXED;
375
376 DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len));
377
378 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
379
380 if (addr == (os_vm_address_t) - 1) {
381 perror("mmap");
382 return NULL;
383 }
384
385 DPRINTF(0, (stderr, "%p\n", addr));
386
387 return addr;
388 }
389
390 void
391 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
392 {
393 DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len));
394
395 if (munmap(addr, len) == -1)
396 perror("munmap");
397 }
398
399 os_vm_address_t
400 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
401 {
402 addr = mmap(addr, len,
403 OS_VM_PROT_ALL,
404 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
405
406 if (addr == (os_vm_address_t) - 1)
407 perror("mmap");
408
409 return addr;
410 }
411
412 void
413 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
414 {
415 #ifdef __ppc__
416 /* see ppc-arch.c */
417 ppc_flush_icache(address, length);
418 #endif
419 }
420
421 void
422 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
423 {
424 if (mprotect(address, length, prot) == -1)
425 perror("mprotect");
426 }
427
428
429
430 static boolean
431 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
432 {
433 char *beg = (char *) sbeg;
434 char *end = (char *) sbeg + slen;
435 char *adr = (char *) a;
436
437 return (adr >= beg && adr < end);
438 }
439
440 boolean
441 valid_addr(os_vm_address_t addr)
442 {
443 os_vm_address_t newaddr;
444
445 newaddr = os_trunc_to_page(addr);
446
447 if (in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE)
448 || in_range_p(addr, STATIC_SPACE_START, STATIC_SPACE_SIZE)
449 || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
450 #ifndef GENCGC
451 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
452 #endif
453 || in_range_p(addr, CONTROL_STACK_START, CONTROL_STACK_SIZE)
454 || in_range_p(addr, BINDING_STACK_START, BINDING_STACK_SIZE))
455 return TRUE;
456 return FALSE;
457 }
458
459 static void
460 sigbus_handle_now(HANDLER_ARGS)
461 {
462 interrupt_handle_now(signal, code, context);
463 }
464
465 static void
466 sigbus_handler(HANDLER_ARGS)
467 {
468 #if defined(GENCGC)
469 caddr_t fault_addr = code->si_addr;
470 #endif
471
472 #ifdef RED_ZONE_HIT
473 if (os_control_stack_overflow((void *) fault_addr, context))
474 return;
475 #endif
476
477 #ifdef __ppc__
478 DPRINTF(0, (stderr, "sigbus:\n"));
479 DPRINTF(0, (stderr, " PC = %p\n", SC_PC(context)));
480 DPRINTF(0, (stderr, " ALLOC-TN = %p\n", SC_REG(context, reg_ALLOC)));
481 DPRINTF(0, (stderr, " CODE-TN = %p\n", SC_REG(context, reg_CODE)));
482 DPRINTF(0, (stderr, " LRA-TN = %p\n", SC_REG(context, reg_LRA)));
483 DPRINTF(0, (stderr, " CFP-TN = %p\n", SC_REG(context, reg_CFP)));
484 DPRINTF(0, (stderr, " FDEFN-TN = %p\n", SC_REG(context, reg_FDEFN)));
485 DPRINTF(0, (stderr, " foreign_function_call = %d\n", foreign_function_call_active));
486 #endif
487
488 #if defined(GENCGC)
489 #if defined(SIGSEGV_VERBOSE)
490 fprintf(stderr, "Signal %d, fault_addr=%x\n",
491 signal, fault_addr);
492 #endif
493 if (gc_write_barrier(code->si_addr))
494 return;
495 #else
496 if (interrupt_maybe_gc(signal, code, context))
497 return;
498 #endif
499
500 /* a *real* protection fault */
501 fprintf(stderr, "sigbus_handler: Real protection violation at %p, PC = %p\n",
502 fault_addr, SC_PC(context));
503 sigbus_handle_now(signal, code, context);
504 #ifdef __ppc__
505 /* Work around G5 bug; fix courtesy gbyers via chandler */
506 sigreturn(context);
507 #endif
508 }
509
510 void
511 os_install_interrupt_handlers(void)
512 {
513 interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
514 }
515
516 void *
517 os_dlsym(const char *sym_name, lispobj lib_list)
518 {
519 static void *program_handle;
520 void *sym_addr = 0;
521
522 if (!program_handle)
523 program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
524 if (lib_list != NIL) {
525 lispobj lib_list_head;
526
527 for (lib_list_head = lib_list;
528 lib_list_head != NIL; lib_list_head = (CONS(lib_list_head))->cdr) {
529 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
530 struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
531
532 sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
533 if (sym_addr)
534 return sym_addr;
535 }
536 }
537 sym_addr = dlsym(program_handle, sym_name);
538
539 return sym_addr;
540 }
541
542 #ifdef i386
543 boolean
544 os_support_sse2()
545 {
546 return TRUE;
547 }
548 #endif

  ViewVC Help
Powered by ViewVC 1.1.5