Darwin-os.c 13.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Darwin-os.c.
 * From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc Exp
 *
 * OS-dependent routines.  This file (along with os.h) exports an
 * OS-independent interface to the operating system VM facilities.
 * Suprisingly, this interface looks a lot like the Mach interface
 * (but simpler in some places).  For some operating systems, a subset
 * of these functions will have to be emulated.
 *
 * This is the OSF1 version.  By Sean Hallgren.
 * Much hacked by Paul Werkowski
 * GENCGC support by Douglas Crosher, 1996, 1997.
 * Frobbed for OpenBSD by Pierre R. Mai, 2001.
 * Frobbed for Darwin by Pierre R. Mai, 2003.
 *
 */

#include <stdio.h>
#include <sys/param.h>
#include <sys/file.h>
#include <errno.h>
cshapiro's avatar
cshapiro committed
23
#include <dlfcn.h>
24
#include <string.h>
25
26
27
28
29
30
#include "os.h"
#include "arch.h"
#include "globals.h"
#include "interrupt.h"
#include "lispregs.h"
#include "internals.h"
rtoy's avatar
rtoy committed
31
32
33
#ifdef GENCGC
#include "gencgc.h"
#endif
34
35
36
37
38

#include <sys/types.h>
#include <signal.h>
/* #include <sys/sysinfo.h> */
/* #include <sys/proc.h> */
39
40
41
/* For timebase info */
#include <sys/sysctl.h>

42
43
44
45

/* Need this to define ppc_saved_state_t (for 10.4) */
#include <mach/thread_status.h>

46
47
48
#include "validate.h"
vm_size_t os_vm_page_size;

49

50

51
52
53
54
55
56
57
58
59
60
61
/*
 * This is accessed by Lisp!  Make this a static symbol?
 */
int cycles_per_tick = 1;

/*
 * Compute the conversion factor from the numbef of time base ticks to
 * clock frequency.  The timebase counter on PPC is not a cycle
 * counter; we have to derive the relationship ourselves.
 */

cshapiro's avatar
cshapiro committed
62
#ifdef __ppc__
63
void
64
timebase_init(void)
65
{
66
67
68
69
70
    int mib[2];
    int tbfrequency;
    int cpufrequency;
    unsigned int miblen;
    size_t len;
71

72
    mib[0] = CTL_HW;
73
#ifndef HW_TB_FREQ
74
75
76
77
    /*
     * Mac OS X 10.2.8 doesn't have this, so we take it from 10.3.8,
     * which does.
     */
78
#define HW_TB_FREQ	23
79
80
81
82
83
84
85
86
#endif
    mib[1] = HW_TB_FREQ;
    miblen = 2;
    len = sizeof(tbfrequency);

    if (sysctl(mib, miblen, &tbfrequency, &len, NULL, 0) == -1) {
	perror("Error getting HW_TB_FREQ from sysctl: ");
    }
87

88
89
90
91
92
93
94
95
96
97
    mib[0] = CTL_HW;
    mib[1] = HW_CPU_FREQ;
    miblen = 2;
    len = sizeof(cpufrequency);
    if (sysctl(mib, miblen, &cpufrequency, &len, NULL, 0) == -1) {
	perror("Error getting HW_CPU_FREQ from sysctl: ");
    }

    cycles_per_tick = cpufrequency / tbfrequency;
}
cshapiro's avatar
cshapiro committed
98
#endif
99

100

101
102
103
104
void
os_init0(const char *argv[], const char *envp[])
{}

105
void
rtoy's avatar
rtoy committed
106
os_init(const char *argv[], const char *envp[])
107
{
108
    os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
cshapiro's avatar
cshapiro committed
109
#ifdef __ppc__
110
    timebase_init();
cshapiro's avatar
cshapiro committed
111
#endif
112
113
}

114

cshapiro's avatar
cshapiro committed
115
#if defined(__ppc__)
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#if __DARWIN_UNIX03
  /* Nothing needed for 10.5 */
#else
/* For 10.4 */
#define __ss ss
#define __r0 r0
#define __r1 r1
#define __r2 r2
#define __r3 r3
#define __r4 r4
#define __r5 r5
#define __r6 r6
#define __r7 r7
#define __r8 r8
#define __r9 r9
#define __r10 r10
#define __r11 r11
#define __r12 r12
#define __r13 r13
#define __r14 r14
#define __r15 r15
#define __r16 r16
#define __r17 r17
#define __r18 r18
#define __r19 r19
#define __r20 r20
#define __r21 r21
#define __r22 r22
#define __r23 r23
#define __r24 r24
#define __r25 r25
#define __r26 r26
#define __r27 r27
#define __r28 r28
#define __r29 r29
#define __r30 r30
#define __r31 r31
#define __lr lr
#define __ctr ctr
#define __es es
#define __dar dar
#define __dsisr dsisr
#endif

160
unsigned int *
161
sc_reg(os_context_t * context, int offset)
162
{
163
    _STRUCT_PPC_THREAD_STATE *state = &context->uc_mcontext->__ss;
164
165
166

    switch (offset) {
      case 0:
167
	  return &state->__r0;
168
      case 1:
169
	  return &state->__r1;
170
      case 2:
171
	  return &state->__r2;
172
      case 3:
173
	  return &state->__r3;
174
      case 4:
175
	  return &state->__r4;
176
      case 5:
177
	  return &state->__r5;
178
      case 6:
179
	  return &state->__r6;
180
      case 7:
181
	  return &state->__r7;
182
      case 8:
183
	  return &state->__r8;
184
      case 9:
185
	  return &state->__r9;
186
      case 10:
187
	  return &state->__r10;
188
      case 11:
189
	  return &state->__r11;
190
      case 12:
191
	  return &state->__r12;
192
      case 13:
193
	  return &state->__r13;
194
      case 14:
195
	  return &state->__r14;
196
      case 15:
197
	  return &state->__r15;
198
      case 16:
199
	  return &state->__r16;
200
      case 17:
201
	  return &state->__r17;
202
      case 18:
203
	  return &state->__r18;
204
      case 19:
205
	  return &state->__r19;
206
      case 20:
207
	  return &state->__r20;
208
      case 21:
209
	  return &state->__r21;
210
      case 22:
211
	  return &state->__r22;
212
      case 23:
213
	  return &state->__r23;
214
      case 24:
215
	  return &state->__r24;
216
      case 25:
217
	  return &state->__r25;
218
      case 26:
219
	  return &state->__r26;
220
      case 27:
221
	  return &state->__r27;
222
      case 28:
223
	  return &state->__r28;
224
      case 29:
225
	  return &state->__r29;
226
      case 30:
227
	  return &state->__r30;
228
      case 31:
229
	  return &state->__r31;
230
231
232
233
234
      case 34:
	  /*
	   * Not sure if this is really defined anywhere, but after
	   * r31 is cr, xer, lr, and ctr.  So we let 34 be lr.
	   */
235
	  return &state->__lr;
236
      case 35:
237
	  return &state->__ctr;
238
      case 41:
239
	  return &context->uc_mcontext->__es.__dar;
240
      case 42:
241
	  return &context->uc_mcontext->__es.__dsisr;
242
243
    }

244
    return (unsigned int *) 0;
245
}
cshapiro's avatar
cshapiro committed
246
#elif defined(__i386__)
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#if __DARWIN_UNIX03
  /* Nothing needed for 10.5 */
#else
  /* This is for 10.4 */
#define __ss ss
#define __eax eax
#define __ecx ecx
#define __edx edx
#define __ebx ebx
#define __esp esp
#define __ebp ebp
#define __esi esi
#define __edi edi
#define __eip eip  
#define __fs fs
#define __fpu_stmm0 fpu_stmm0
#define __fpu_stmm1 fpu_stmm1
#define __fpu_stmm2 fpu_stmm2
#define __fpu_stmm3 fpu_stmm3
#define __fpu_stmm4 fpu_stmm4
#define __fpu_stmm5 fpu_stmm5
#define __fpu_stmm6 fpu_stmm6
#define __fpu_stmm7 fpu_stmm7
#define __fpu_fcw   fpu_fcw
#define __fpu_fsw   fpu_fsw
#define __fpu_mxcsr fpu_mxcsr
273
274
275
276
277
278
279
280
281
282
#ifdef FEATURE_SSE2
#define __fpu_xmm0 fpu_xmm0
#define __fpu_xmm1 fpu_xmm1
#define __fpu_xmm2 fpu_xmm2
#define __fpu_xmm3 fpu_xmm3
#define __fpu_xmm4 fpu_xmm4
#define __fpu_xmm5 fpu_xmm5
#define __fpu_xmm6 fpu_xmm6
#define __fpu_xmm7 fpu_xmm7
#endif
283
#endif
284
285
286
287

unsigned long *
os_sigcontext_reg(ucontext_t *scp, int index)
{
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    switch (index) {
    case 0:
	return (unsigned long *) &scp->uc_mcontext->__ss.__eax;
    case 2:
	return (unsigned long *) &scp->uc_mcontext->__ss.__ecx;
    case 4:
	return (unsigned long *) &scp->uc_mcontext->__ss.__edx;
    case 6:
	return (unsigned long *) &scp->uc_mcontext->__ss.__ebx;
    case 8:
	return (unsigned long *) &scp->uc_mcontext->__ss.__esp;
    case 10:
	return (unsigned long *) &scp->uc_mcontext->__ss.__ebp;
    case 12:
	return (unsigned long *) &scp->uc_mcontext->__ss.__esi;
    case 14:
	return (unsigned long *) &scp->uc_mcontext->__ss.__edi;
cshapiro's avatar
cshapiro committed
305
    }
306
307
    return NULL;
}
cshapiro's avatar
cshapiro committed
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
unsigned long *
os_sigcontext_pc(ucontext_t *scp)
{
    return (unsigned long *) &scp->uc_mcontext->__ss.__eip;
}

unsigned char *
os_sigcontext_fpu_reg(ucontext_t *scp, int index)
{
    switch (index) {
    case 0:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm0;
    case 1:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm1;
    case 2:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm2;
    case 3:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm3;
    case 4:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm4;
    case 5:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm5;
    case 6:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm6;
    case 7:
	return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
#ifdef FEATURE_SSE2
    case 8:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0;
    case 9:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1;
    case 10:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2;
    case 11:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3;
    case 12:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4;
    case 13:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5;
    case 14:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6;
    case 15:
       return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
#endif
353
354
355
356
    }
    return NULL;
}

357
unsigned int
358
359
os_sigcontext_fpu_modes(ucontext_t *scp)
{
360
361
    unsigned int modes;
    unsigned int mxcsr;
362
    unsigned short cw, sw;
363
364
365
366

    /*
     * Get the status word and the control word.  
     */
367
368
    memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
    memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw));
369
370
371
372
373
374
375
376
377
378
379

    /*
     * Put the cw in the upper bits and the status word in the lower 6
     * bits, ignoring everything except the exception masks and the
     * exception flags.
     */
    modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
    
    DPRINTF(0, (stderr, "FPU modes = %08x (sw =  %4x, cw = %4x)\n",
		modes, (unsigned int) sw, (unsigned int) cw));

380
381
382
    if (fpu_mode == SSE2) {
      mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
      DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr));
383

384
385
386
      modes |= mxcsr;
    }
    
387
388
389
390
391
    DPRINTF(0, (stderr, "modes pre mask = %08x\n", modes));

    /* Convert exception mask to exception enable */
    modes ^= (0x3f << 7);
    DPRINTF(0, (stderr, "Finale = %08x\n", modes));
392
393
394
395
396
397
398
    return modes;
}

void
restore_fpu(ucontext_t *scp)
{
    unsigned short cw;
399
400
    unsigned int mxcsr;

401
    memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
402
    DPRINTF(0, (stderr, "restore_fpu: FPU cw = 0x%x\n", cw));
403
    __asm__ __volatile__ ("fclex");
404
    __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
405
406
407
408
            
    mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
    DPRINTF(0, (stderr, "restore_fpu:  mxcsr (raw) = %04x\n", mxcsr));
    __asm__ __volatile__ ("ldmxcsr %0" :: "m" (*&mxcsr));
cshapiro's avatar
cshapiro committed
409
410
}
#endif
411

412
413
os_vm_address_t
os_validate(os_vm_address_t addr, os_vm_size_t len)
414
{
cshapiro's avatar
cshapiro committed
415
    int flags = MAP_PRIVATE | MAP_ANON;
416

417
418
    if (addr)
	flags |= MAP_FIXED;
419

cshapiro's avatar
cshapiro committed
420
    DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len));
421

422
    addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
423

424
425
426
    if (addr == (os_vm_address_t) - 1) {
	perror("mmap");
	return NULL;
427
428
    }

cshapiro's avatar
cshapiro committed
429
    DPRINTF(0, (stderr, "%p\n", addr));
430

431
    return addr;
432
433
}

434
435
void
os_invalidate(os_vm_address_t addr, os_vm_size_t len)
436
{
cshapiro's avatar
cshapiro committed
437
    DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len));
438

439
440
    if (munmap(addr, len) == -1)
	perror("munmap");
441
442
}

443
444
os_vm_address_t
os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
445
{
446
447
448
    addr = mmap(addr, len,
		OS_VM_PROT_ALL,
		MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
449

450
451
    if (addr == (os_vm_address_t) - 1)
	perror("mmap");
452

453
    return addr;
454
455
}

456
457
void
os_flush_icache(os_vm_address_t address, os_vm_size_t length)
458
{
cshapiro's avatar
cshapiro committed
459
#ifdef __ppc__    
460
    /* see ppc-arch.c */
461
    ppc_flush_icache(address, length);
cshapiro's avatar
cshapiro committed
462
#endif
463
464
}

465
466
void
os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
467
{
468
469
    if (mprotect(address, length, prot) == -1)
	perror("mprotect");
470
471
472
}


473
474
475

static boolean
in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
476
{
477
478
479
480
481
    char *beg = (char *) sbeg;
    char *end = (char *) sbeg + slen;
    char *adr = (char *) a;

    return (adr >= beg && adr < end);
482
483
}

484
485
boolean
valid_addr(os_vm_address_t addr)
486
{
487
488
    if (in_range_p(addr, READ_ONLY_SPACE_START, read_only_space_size)
	|| in_range_p(addr, STATIC_SPACE_START, static_space_size)
489
	|| in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
rtoy's avatar
rtoy committed
490
#ifndef GENCGC
491
	|| in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
rtoy's avatar
rtoy committed
492
#endif
493
494
	|| in_range_p(addr, CONTROL_STACK_START, control_stack_size)
	|| in_range_p(addr, BINDING_STACK_START, binding_stack_size))
495
496
	return TRUE;
    return FALSE;
497
498
}

499
500
501
502
503
static void
sigbus_handle_now(HANDLER_ARGS)
{
    interrupt_handle_now(signal, code, context);
}
504

505
static void
rtoy's avatar
rtoy committed
506
sigbus_handler(HANDLER_ARGS)
507
{
508
    os_context_t *os_context = (os_context_t *) context;
rtoy's avatar
rtoy committed
509
#if defined(GENCGC)
510
    caddr_t fault_addr = code->si_addr;
rtoy's avatar
rtoy committed
511
512
#endif
    
513
#ifdef RED_ZONE_HIT
514
    if (os_control_stack_overflow((void *) fault_addr, os_context))
515
516
517
       return;
#endif

518
#ifdef __ppc__
rtoy's avatar
rtoy committed
519
    DPRINTF(0, (stderr, "sigbus:\n"));
520
521
522
523
524
525
    DPRINTF(0, (stderr, " PC       = %p\n", SC_PC(os_context)));
    DPRINTF(0, (stderr, " ALLOC-TN = %p\n", SC_REG(os_context, reg_ALLOC)));
    DPRINTF(0, (stderr, " CODE-TN  = %p\n", SC_REG(os_context, reg_CODE)));
    DPRINTF(0, (stderr, " LRA-TN   = %p\n", SC_REG(os_context, reg_LRA)));
    DPRINTF(0, (stderr, " CFP-TN   = %p\n", SC_REG(os_context, reg_CFP)));
    DPRINTF(0, (stderr, " FDEFN-TN = %p\n", SC_REG(os_context, reg_FDEFN)));
rtoy's avatar
rtoy committed
526
    DPRINTF(0, (stderr, " foreign_function_call = %d\n", foreign_function_call_active));
527
#endif
rtoy's avatar
rtoy committed
528
    
529
530
#if defined(GENCGC)
#if defined(SIGSEGV_VERBOSE)
531
532
    fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n",
	    signal, fault_addr, page_index);
533
534
535
536
#endif
    if (gc_write_barrier(code->si_addr))
	 return;
#else
537
    if (interrupt_maybe_gc(signal, code, os_context))
538
539
	return;
#endif
540
    /* a *real* protection fault */
541
    fprintf(stderr, "sigbus_handler: Real protection violation at %p, PC = %p\n",
542
543
            fault_addr, (void *) SC_PC(os_context));
    sigbus_handle_now(signal, code, os_context);
544
#ifdef __ppc__
545
    /* Work around G5 bug; fix courtesy gbyers via chandler */
546
    sigreturn(os_context);
cshapiro's avatar
cshapiro committed
547
#endif
548
}
549

550
551
void
os_install_interrupt_handlers(void)
552
{
553
    interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
554
555
}

556
557
void *
os_dlsym(const char *sym_name, lispobj lib_list)
558
559
560
561
562
{
    static void *program_handle;
    void *sym_addr = 0;

    if (!program_handle)
563
	program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
564
565
566
567
    if (lib_list != NIL) {
	lispobj lib_list_head;

	for (lib_list_head = lib_list;
568
	     lib_list_head != NIL; lib_list_head = (CONS(lib_list_head))->cdr) {
569
	    struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
570
	    struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
571

572
	    sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
573
574
575
576
577
578
579
580
	    if (sym_addr)
		return sym_addr;
	}
    }
    sym_addr = dlsym(program_handle, sym_name);

    return sym_addr;
}
581
582
583
584
585
586
587
588

#ifdef i386
boolean
os_support_sse2()
{
    return TRUE;
}
#endif