f878a8487360b1634dca116161c950e96d188463
[projects/cmucl/cmucl.git] / src / lisp / Darwin-os.c
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: /project/cmucl/cvsroot/src/lisp/Darwin-os.c,v 1.16.4.3 2009-03-18 15:37:29 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 \f
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 \f
102
103 void
104 os_init0(const char *argv[], const char *envp[])
105 {}
106
107 void
108 os_init(const char *argv[], const char *envp[])
109 {
110     os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
111 #ifdef __ppc__
112     timebase_init();
113 #endif
114 }
115
116
117 #if defined(__ppc__)
118 #if __DARWIN_UNIX03
119   /* Nothing needed for 10.5 */
120 #else
121 /* For 10.4 */
122 #define __ss ss
123 #define __r0 r0
124 #define __r1 r1
125 #define __r2 r2
126 #define __r3 r3
127 #define __r4 r4
128 #define __r5 r5
129 #define __r6 r6
130 #define __r7 r7
131 #define __r8 r8
132 #define __r9 r9
133 #define __r10 r10
134 #define __r11 r11
135 #define __r12 r12
136 #define __r13 r13
137 #define __r14 r14
138 #define __r15 r15
139 #define __r16 r16
140 #define __r17 r17
141 #define __r18 r18
142 #define __r19 r19
143 #define __r20 r20
144 #define __r21 r21
145 #define __r22 r22
146 #define __r23 r23
147 #define __r24 r24
148 #define __r25 r25
149 #define __r26 r26
150 #define __r27 r27
151 #define __r28 r28
152 #define __r29 r29
153 #define __r30 r30
154 #define __r31 r31
155 #define __lr lr
156 #define __ctr ctr
157 #define __es es
158 #define __dar dar
159 #define __dsisr dsisr
160 #endif
161
162 unsigned int *
163 sc_reg(os_context_t * context, int offset)
164 {
165     _STRUCT_PPC_THREAD_STATE *state = &context->uc_mcontext->__ss;
166
167     switch (offset) {
168       case 0:
169           return &state->__r0;
170       case 1:
171           return &state->__r1;
172       case 2:
173           return &state->__r2;
174       case 3:
175           return &state->__r3;
176       case 4:
177           return &state->__r4;
178       case 5:
179           return &state->__r5;
180       case 6:
181           return &state->__r6;
182       case 7:
183           return &state->__r7;
184       case 8:
185           return &state->__r8;
186       case 9:
187           return &state->__r9;
188       case 10:
189           return &state->__r10;
190       case 11:
191           return &state->__r11;
192       case 12:
193           return &state->__r12;
194       case 13:
195           return &state->__r13;
196       case 14:
197           return &state->__r14;
198       case 15:
199           return &state->__r15;
200       case 16:
201           return &state->__r16;
202       case 17:
203           return &state->__r17;
204       case 18:
205           return &state->__r18;
206       case 19:
207           return &state->__r19;
208       case 20:
209           return &state->__r20;
210       case 21:
211           return &state->__r21;
212       case 22:
213           return &state->__r22;
214       case 23:
215           return &state->__r23;
216       case 24:
217           return &state->__r24;
218       case 25:
219           return &state->__r25;
220       case 26:
221           return &state->__r26;
222       case 27:
223           return &state->__r27;
224       case 28:
225           return &state->__r28;
226       case 29:
227           return &state->__r29;
228       case 30:
229           return &state->__r30;
230       case 31:
231           return &state->__r31;
232       case 34:
233           /*
234            * Not sure if this is really defined anywhere, but after
235            * r31 is cr, xer, lr, and ctr.  So we let 34 be lr.
236            */
237           return &state->__lr;
238       case 35:
239           return &state->__ctr;
240       case 41:
241           return &context->uc_mcontext->__es.__dar;
242       case 42:
243           return &context->uc_mcontext->__es.__dsisr;
244     }
245
246     return (unsigned int *) 0;
247 }
248 #elif defined(__i386__)
249 #if __DARWIN_UNIX03
250   /* Nothing needed for 10.5 */
251 #else
252   /* This is for 10.4 */
253 #define __ss ss
254 #define __eax eax
255 #define __ecx ecx
256 #define __edx edx
257 #define __ebx ebx
258 #define __esp esp
259 #define __ebp ebp
260 #define __esi esi
261 #define __edi edi
262 #define __eip eip  
263 #define __fs fs
264 #define __fpu_stmm0 fpu_stmm0
265 #define __fpu_stmm1 fpu_stmm1
266 #define __fpu_stmm2 fpu_stmm2
267 #define __fpu_stmm3 fpu_stmm3
268 #define __fpu_stmm4 fpu_stmm4
269 #define __fpu_stmm5 fpu_stmm5
270 #define __fpu_stmm6 fpu_stmm6
271 #define __fpu_stmm7 fpu_stmm7
272 #define __fpu_fcw   fpu_fcw
273 #define __fpu_fsw   fpu_fsw
274 #define __fpu_mxcsr fpu_mxcsr
275 #ifdef FEATURE_SSE2
276 #define __fpu_xmm0 fpu_xmm0
277 #define __fpu_xmm1 fpu_xmm1
278 #define __fpu_xmm2 fpu_xmm2
279 #define __fpu_xmm3 fpu_xmm3
280 #define __fpu_xmm4 fpu_xmm4
281 #define __fpu_xmm5 fpu_xmm5
282 #define __fpu_xmm6 fpu_xmm6
283 #define __fpu_xmm7 fpu_xmm7
284 #endif
285 #endif
286
287 unsigned long *
288 os_sigcontext_reg(ucontext_t *scp, int index)
289 {
290     switch (index) {
291     case 0:
292         return (unsigned long *) &scp->uc_mcontext->__ss.__eax;
293     case 2:
294         return (unsigned long *) &scp->uc_mcontext->__ss.__ecx;
295     case 4:
296         return (unsigned long *) &scp->uc_mcontext->__ss.__edx;
297     case 6:
298         return (unsigned long *) &scp->uc_mcontext->__ss.__ebx;
299     case 8:
300         return (unsigned long *) &scp->uc_mcontext->__ss.__esp;
301     case 10:
302         return (unsigned long *) &scp->uc_mcontext->__ss.__ebp;
303     case 12:
304         return (unsigned long *) &scp->uc_mcontext->__ss.__esi;
305     case 14:
306         return (unsigned long *) &scp->uc_mcontext->__ss.__edi;
307     }
308     return NULL;
309 }
310
311 unsigned long *
312 os_sigcontext_pc(ucontext_t *scp)
313 {
314     return (unsigned long *) &scp->uc_mcontext->__ss.__eip;
315 }
316
317 unsigned char *
318 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
319 {
320     switch (index) {
321     case 0:
322         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm0;
323     case 1:
324         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm1;
325     case 2:
326         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm2;
327     case 3:
328         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm3;
329     case 4:
330         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm4;
331     case 5:
332         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm5;
333     case 6:
334         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm6;
335     case 7:
336         return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
337 #ifdef FEATURE_SSE2
338     case 8:
339        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0;
340     case 9:
341        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1;
342     case 10:
343        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2;
344     case 11:
345        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3;
346     case 12:
347        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4;
348     case 13:
349        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5;
350     case 14:
351        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6;
352     case 15:
353        return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
354 #endif
355     }
356     return NULL;
357 }
358
359 unsigned int
360 os_sigcontext_fpu_modes(ucontext_t *scp)
361 {
362     unsigned int modes;
363     unsigned int mxcsr;
364     unsigned short cw, sw;
365
366     /*
367      * Get the status word and the control word.  
368      */
369     memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
370     memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw));
371
372     /*
373      * Put the cw in the upper bits and the status word in the lower 6
374      * bits, ignoring everything except the exception masks and the
375      * exception flags.
376      */
377     modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
378     
379     DPRINTF(0, (stderr, "FPU modes = %08x (sw =  %4x, cw = %4x)\n",
380                 modes, (unsigned int) sw, (unsigned int) cw));
381
382     if (fpu_mode == SSE2) {
383       mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
384       DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr));
385
386       modes |= mxcsr;
387     }
388     
389     DPRINTF(0, (stderr, "modes pre mask = %08x\n", modes));
390
391     /* Convert exception mask to exception enable */
392     modes ^= (0x3f << 7);
393     DPRINTF(0, (stderr, "Finale = %08x\n", modes));
394     return modes;
395 }
396
397 void
398 restore_fpu(ucontext_t *scp)
399 {
400     unsigned short cw;
401     unsigned int mxcsr;
402
403     memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
404     DPRINTF(0, (stderr, "restore_fpu: FPU cw = 0x%x\n", cw));
405     __asm__ __volatile__ ("fclex");
406     __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
407             
408     mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
409     DPRINTF(0, (stderr, "restore_fpu:  mxcsr (raw) = %04x\n", mxcsr));
410     __asm__ __volatile__ ("ldmxcsr %0" :: "m" (*&mxcsr));
411 }
412 #endif
413
414 os_vm_address_t
415 os_validate(os_vm_address_t addr, os_vm_size_t len)
416 {
417     int flags = MAP_PRIVATE | MAP_ANON;
418
419     if (addr)
420         flags |= MAP_FIXED;
421
422     DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len));
423
424     addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
425
426     if (addr == (os_vm_address_t) - 1) {
427         perror("mmap");
428         return NULL;
429     }
430
431     DPRINTF(0, (stderr, "%p\n", addr));
432
433     return addr;
434 }
435
436 void
437 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
438 {
439     DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len));
440
441     if (munmap(addr, len) == -1)
442         perror("munmap");
443 }
444
445 os_vm_address_t
446 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
447 {
448     addr = mmap(addr, len,
449                 OS_VM_PROT_ALL,
450                 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
451
452     if (addr == (os_vm_address_t) - 1)
453         perror("mmap");
454
455     return addr;
456 }
457
458 void
459 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
460 {
461 #ifdef __ppc__    
462     /* see ppc-arch.c */
463     ppc_flush_icache(address, length);
464 #endif
465 }
466
467 void
468 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
469 {
470     if (mprotect(address, length, prot) == -1)
471         perror("mprotect");
472 }
473 \f
474
475
476 static boolean
477 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
478 {
479     char *beg = (char *) sbeg;
480     char *end = (char *) sbeg + slen;
481     char *adr = (char *) a;
482
483     return (adr >= beg && adr < end);
484 }
485
486 boolean
487 valid_addr(os_vm_address_t addr)
488 {
489     os_vm_address_t newaddr;
490
491     newaddr = os_trunc_to_page(addr);
492
493     if (in_range_p(addr, READ_ONLY_SPACE_START, read_only_space_size)
494         || in_range_p(addr, STATIC_SPACE_START, static_space_size)
495         || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
496 #ifndef GENCGC
497         || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
498 #endif
499         || in_range_p(addr, CONTROL_STACK_START, control_stack_size)
500         || in_range_p(addr, BINDING_STACK_START, binding_stack_size))
501         return TRUE;
502     return FALSE;
503 }
504 \f
505 static void
506 sigbus_handle_now(HANDLER_ARGS)
507 {
508     interrupt_handle_now(signal, code, context);
509 }
510
511 static void
512 sigbus_handler(HANDLER_ARGS)
513 {
514     os_context_t *os_context = (os_context_t *) context;
515 #if defined(GENCGC)
516     caddr_t fault_addr = code->si_addr;
517 #endif
518     
519 #ifdef RED_ZONE_HIT
520     if (os_control_stack_overflow((void *) fault_addr, os_context))
521        return;
522 #endif
523
524 #ifdef __ppc__
525     DPRINTF(0, (stderr, "sigbus:\n"));
526     DPRINTF(0, (stderr, " PC       = %p\n", SC_PC(os_context)));
527     DPRINTF(0, (stderr, " ALLOC-TN = %p\n", SC_REG(os_context, reg_ALLOC)));
528     DPRINTF(0, (stderr, " CODE-TN  = %p\n", SC_REG(os_context, reg_CODE)));
529     DPRINTF(0, (stderr, " LRA-TN   = %p\n", SC_REG(os_context, reg_LRA)));
530     DPRINTF(0, (stderr, " CFP-TN   = %p\n", SC_REG(os_context, reg_CFP)));
531     DPRINTF(0, (stderr, " FDEFN-TN = %p\n", SC_REG(os_context, reg_FDEFN)));
532     DPRINTF(0, (stderr, " foreign_function_call = %d\n", foreign_function_call_active));
533 #endif
534     
535 #if defined(GENCGC)
536 #if defined(SIGSEGV_VERBOSE)
537     fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n",
538             signal, fault_addr, page_index);
539 #endif
540     if (gc_write_barrier(code->si_addr))
541          return;
542 #else
543     if (interrupt_maybe_gc(signal, code, os_context))
544         return;
545 #endif
546     /* a *real* protection fault */
547     fprintf(stderr, "sigbus_handler: Real protection violation at %p, PC = %p\n",
548             fault_addr, (void *) SC_PC(os_context));
549     sigbus_handle_now(signal, code, os_context);
550 #ifdef __ppc__
551     /* Work around G5 bug; fix courtesy gbyers via chandler */
552     sigreturn(os_context);
553 #endif
554 }
555
556 void
557 os_install_interrupt_handlers(void)
558 {
559     interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
560 }
561
562 void *
563 os_dlsym(const char *sym_name, lispobj lib_list)
564 {
565     static void *program_handle;
566     void *sym_addr = 0;
567
568     if (!program_handle)
569         program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
570     if (lib_list != NIL) {
571         lispobj lib_list_head;
572
573         for (lib_list_head = lib_list;
574              lib_list_head != NIL; lib_list_head = (CONS(lib_list_head))->cdr) {
575             struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
576             struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
577
578             sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
579             if (sym_addr)
580                 return sym_addr;
581         }
582     }
583     sym_addr = dlsym(program_handle, sym_name);
584
585     return sym_addr;
586 }
587
588 #ifdef i386
589 boolean
590 os_support_sse2()
591 {
592     return TRUE;
593 }
594 #endif