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