/[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 - (hide 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 pmai 1.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 rtoy 1.35 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/Darwin-os.c,v 1.35 2011/09/03 04:46:34 rtoy Exp $
18 pmai 1.1 *
19     */
20    
21     #include <stdio.h>
22     #include <sys/param.h>
23     #include <sys/file.h>
24     #include <errno.h>
25 cshapiro 1.9 #include <dlfcn.h>
26 cshapiro 1.14 #include <string.h>
27 pmai 1.1 #include "os.h"
28     #include "arch.h"
29     #include "globals.h"
30     #include "interrupt.h"
31     #include "lispregs.h"
32     #include "internals.h"
33 rtoy 1.6 #ifdef GENCGC
34     #include "gencgc.h"
35     #endif
36 pmai 1.1
37     #include <sys/types.h>
38     #include <signal.h>
39     /* #include <sys/sysinfo.h> */
40     /* #include <sys/proc.h> */
41 rtoy 1.4 /* For timebase info */
42     #include <sys/sysctl.h>
43    
44 rtoy 1.3
45     /* Need this to define ppc_saved_state_t (for 10.4) */
46     #include <mach/thread_status.h>
47    
48 pmai 1.1 #include "validate.h"
49     vm_size_t os_vm_page_size;
50    
51 rtoy 1.5
52 pmai 1.1
53 rtoy 1.4 /*
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 cshapiro 1.9 #ifdef __ppc__
65 rtoy 1.5 void
66 cshapiro 1.16 timebase_init(void)
67 rtoy 1.4 {
68 rtoy 1.5 int mib[2];
69     int tbfrequency;
70     int cpufrequency;
71     unsigned int miblen;
72     size_t len;
73 rtoy 1.4
74 rtoy 1.5 mib[0] = CTL_HW;
75 rtoy 1.4 #ifndef HW_TB_FREQ
76 rtoy 1.5 /*
77     * Mac OS X 10.2.8 doesn't have this, so we take it from 10.3.8,
78     * which does.
79     */
80 rtoy 1.4 #define HW_TB_FREQ 23
81 rtoy 1.5 #endif
82     mib[1] = HW_TB_FREQ;
83     miblen = 2;
84     len = sizeof(tbfrequency);
85 rtoy 1.4
86 rtoy 1.5 if (sysctl(mib, miblen, &tbfrequency, &len, NULL, 0) == -1) {
87     perror("Error getting HW_TB_FREQ from sysctl: ");
88     }
89 rtoy 1.4
90 rtoy 1.5 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 pmai 1.1
98 rtoy 1.5 cycles_per_tick = cpufrequency / tbfrequency;
99 pmai 1.1 }
100 cshapiro 1.9 #endif
101 rtoy 1.5
102 rtoy 1.33 void
103     os_init0(const char *argv[], const char *envp[])
104     {}
105 pmai 1.1
106 rtoy 1.5 void
107 rtoy 1.27 os_init(const char *argv[], const char *envp[])
108 pmai 1.1 {
109 rtoy 1.5 os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
110 cshapiro 1.9 #ifdef __ppc__
111 rtoy 1.5 timebase_init();
112 cshapiro 1.9 #endif
113 pmai 1.1 }
114    
115 cshapiro 1.9 #if defined(__ppc__)
116 rtoy 1.5 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 rtoy 1.7 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 rtoy 1.5 case 41:
195     return &context->uc_mcontext->es.dar;
196     case 42:
197     return &context->uc_mcontext->es.dsisr;
198     }
199 pmai 1.1
200 rtoy 1.5 return (int *) 0;
201 pmai 1.1 }
202 cshapiro 1.9 #elif defined(__i386__)
203 rtoy 1.24 #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 rtoy 1.28 #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 rtoy 1.24 #endif
240 rtoy 1.25
241     unsigned long *
242     os_sigcontext_reg(ucontext_t *scp, int index)
243     {
244 cshapiro 1.14 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 cshapiro 1.9 {
268 cshapiro 1.14 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 rtoy 1.30 #ifdef FEATURE_SSE2
292 rtoy 1.29 case 8:
293 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0;
294 rtoy 1.29 case 9:
295 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1;
296 rtoy 1.29 case 10:
297 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2;
298 rtoy 1.29 case 11:
299 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3;
300 rtoy 1.29 case 12:
301 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4;
302 rtoy 1.29 case 13:
303 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5;
304 rtoy 1.29 case 14:
305 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6;
306 rtoy 1.29 case 15:
307 rtoy 1.28 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
308 rtoy 1.30 #endif
309 rtoy 1.28 }
310     return NULL;
311     }
312    
313 rtoy 1.23 unsigned int
314 cshapiro 1.14 os_sigcontext_fpu_modes(ucontext_t *scp)
315     {
316 rtoy 1.23 unsigned int modes;
317     unsigned int mxcsr;
318 cshapiro 1.14 unsigned short cw, sw;
319 rtoy 1.21
320     /*
321     * Get the status word and the control word.
322     */
323 cshapiro 1.14 memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
324     memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw));
325 rtoy 1.21
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 rtoy 1.25 if (fpu_mode == SSE2) {
337     mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
338     DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr));
339 rtoy 1.21
340 rtoy 1.25 modes |= mxcsr;
341     }
342    
343 rtoy 1.21 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 cshapiro 1.14 return modes;
349     }
350    
351     void
352     restore_fpu(ucontext_t *scp)
353     {
354     unsigned short cw;
355 rtoy 1.21 unsigned int mxcsr;
356    
357 cshapiro 1.14 memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
358 rtoy 1.21 DPRINTF(0, (stderr, "restore_fpu: FPU cw = 0x%x\n", cw));
359 rtoy 1.15 __asm__ __volatile__ ("fclex");
360 cshapiro 1.14 __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
361 rtoy 1.21
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 cshapiro 1.9 }
366     #endif
367 pmai 1.1
368 rtoy 1.5 os_vm_address_t
369     os_validate(os_vm_address_t addr, os_vm_size_t len)
370 pmai 1.1 {
371 cshapiro 1.8 int flags = MAP_PRIVATE | MAP_ANON;
372 pmai 1.1
373 rtoy 1.5 if (addr)
374     flags |= MAP_FIXED;
375 pmai 1.1
376 cshapiro 1.9 DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len));
377 pmai 1.1
378 rtoy 1.5 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
379 pmai 1.1
380 rtoy 1.5 if (addr == (os_vm_address_t) - 1) {
381     perror("mmap");
382     return NULL;
383 pmai 1.1 }
384    
385 cshapiro 1.9 DPRINTF(0, (stderr, "%p\n", addr));
386 pmai 1.1
387 rtoy 1.5 return addr;
388 pmai 1.1 }
389    
390 rtoy 1.5 void
391     os_invalidate(os_vm_address_t addr, os_vm_size_t len)
392 pmai 1.1 {
393 cshapiro 1.9 DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len));
394 pmai 1.1
395 rtoy 1.5 if (munmap(addr, len) == -1)
396     perror("munmap");
397 pmai 1.1 }
398    
399 rtoy 1.5 os_vm_address_t
400     os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
401 pmai 1.1 {
402 rtoy 1.5 addr = mmap(addr, len,
403     OS_VM_PROT_ALL,
404     MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
405 pmai 1.1
406 rtoy 1.5 if (addr == (os_vm_address_t) - 1)
407     perror("mmap");
408 pmai 1.1
409 rtoy 1.5 return addr;
410 pmai 1.1 }
411    
412 rtoy 1.5 void
413     os_flush_icache(os_vm_address_t address, os_vm_size_t length)
414 pmai 1.1 {
415 cshapiro 1.9 #ifdef __ppc__
416 pmai 1.1 /* see ppc-arch.c */
417 rtoy 1.5 ppc_flush_icache(address, length);
418 cshapiro 1.9 #endif
419 pmai 1.1 }
420    
421 rtoy 1.5 void
422     os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
423 pmai 1.1 {
424 rtoy 1.5 if (mprotect(address, length, prot) == -1)
425     perror("mprotect");
426 pmai 1.1 }
427 rtoy 1.5
428 pmai 1.1
429    
430 rtoy 1.5 static boolean
431     in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
432 pmai 1.1 {
433 rtoy 1.5 char *beg = (char *) sbeg;
434     char *end = (char *) sbeg + slen;
435     char *adr = (char *) a;
436    
437     return (adr >= beg && adr < end);
438 pmai 1.1 }
439    
440 rtoy 1.5 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 rtoy 1.6 #ifndef GENCGC
451 rtoy 1.5 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
452 rtoy 1.6 #endif
453 rtoy 1.5 || 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 pmai 1.1
459 rtoy 1.32 static void
460     sigbus_handle_now(HANDLER_ARGS)
461     {
462     interrupt_handle_now(signal, code, context);
463     }
464    
465 rtoy 1.5 static void
466 rtoy 1.6 sigbus_handler(HANDLER_ARGS)
467 pmai 1.1 {
468 rtoy 1.6 #if defined(GENCGC)
469 rtoy 1.5 caddr_t fault_addr = code->si_addr;
470 rtoy 1.6 #endif
471    
472 rtoy 1.32 #ifdef RED_ZONE_HIT
473     if (os_control_stack_overflow((void *) fault_addr, context))
474     return;
475     #endif
476    
477 rtoy 1.18 #ifdef __ppc__
478 rtoy 1.6 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 rtoy 1.18 #endif
487 rtoy 1.6
488 rtoy 1.34 #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 rtoy 1.32
500 rtoy 1.20 /* a *real* protection fault */
501 rtoy 1.35 fprintf(stderr, "sigbus_handler: Real protection violation at %p, PC = %p\n",
502     fault_addr, SC_PC(context));
503 rtoy 1.32 sigbus_handle_now(signal, code, context);
504 rtoy 1.18 #ifdef __ppc__
505 rtoy 1.5 /* Work around G5 bug; fix courtesy gbyers via chandler */
506     sigreturn(context);
507 rtoy 1.18 #endif
508 pmai 1.1 }
509    
510 rtoy 1.5 void
511     os_install_interrupt_handlers(void)
512 pmai 1.1 {
513 rtoy 1.5 interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
514 pmai 1.1 }
515    
516 rtoy 1.5 void *
517     os_dlsym(const char *sym_name, lispobj lib_list)
518 rtoy 1.2 {
519     static void *program_handle;
520     void *sym_addr = 0;
521    
522     if (!program_handle)
523 rtoy 1.5 program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
524 rtoy 1.2 if (lib_list != NIL) {
525     lispobj lib_list_head;
526    
527     for (lib_list_head = lib_list;
528 rtoy 1.5 lib_list_head != NIL; lib_list_head = (CONS(lib_list_head))->cdr) {
529 rtoy 1.2 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
530 rtoy 1.5 struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
531 rtoy 1.2
532 rtoy 1.5 sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
533 rtoy 1.2 if (sym_addr)
534     return sym_addr;
535     }
536     }
537     sym_addr = dlsym(program_handle, sym_name);
538    
539     return sym_addr;
540 pmai 1.1 }
541 rswindells 1.31
542     #ifdef i386
543     boolean
544     os_support_sse2()
545     {
546     return TRUE;
547     }
548     #endif

  ViewVC Help
Powered by ViewVC 1.1.5