3 * From FreeBSD-os.c 1.6 2000/10/24 13:32:30 dtc Exp
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.
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.
17 * $Header: /project/cmucl/cvsroot/src/lisp/Darwin-os.c,v 1.16.4.3 2009-03-18 15:37:29 rtoy Exp $
22 #include <sys/param.h>
30 #include "interrupt.h"
32 #include "internals.h"
37 #include <sys/types.h>
39 /* #include <sys/sysinfo.h> */
40 /* #include <sys/proc.h> */
41 /* For timebase info */
42 #include <sys/sysctl.h>
45 /* Need this to define ppc_saved_state_t (for 10.4) */
46 #include <mach/thread_status.h>
49 vm_size_t os_vm_page_size;
54 * This is accessed by Lisp! Make this a static symbol?
56 int cycles_per_tick = 1;
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.
77 * Mac OS X 10.2.8 doesn't have this, so we take it from 10.3.8,
84 len = sizeof(tbfrequency);
86 if (sysctl(mib, miblen, &tbfrequency, &len, NULL, 0) == -1) {
87 perror("Error getting HW_TB_FREQ from sysctl: ");
93 len = sizeof(cpufrequency);
94 if (sysctl(mib, miblen, &cpufrequency, &len, NULL, 0) == -1) {
95 perror("Error getting HW_CPU_FREQ from sysctl: ");
98 cycles_per_tick = cpufrequency / tbfrequency;
104 os_init0(const char *argv[], const char *envp[])
108 os_init(const char *argv[], const char *envp[])
110 os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
119 /* Nothing needed for 10.5 */
159 #define __dsisr dsisr
163 sc_reg(os_context_t * context, int offset)
165 _STRUCT_PPC_THREAD_STATE *state = &context->uc_mcontext->__ss;
189 return &state->__r10;
191 return &state->__r11;
193 return &state->__r12;
195 return &state->__r13;
197 return &state->__r14;
199 return &state->__r15;
201 return &state->__r16;
203 return &state->__r17;
205 return &state->__r18;
207 return &state->__r19;
209 return &state->__r20;
211 return &state->__r21;
213 return &state->__r22;
215 return &state->__r23;
217 return &state->__r24;
219 return &state->__r25;
221 return &state->__r26;
223 return &state->__r27;
225 return &state->__r28;
227 return &state->__r29;
229 return &state->__r30;
231 return &state->__r31;
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.
239 return &state->__ctr;
241 return &context->uc_mcontext->__es.__dar;
243 return &context->uc_mcontext->__es.__dsisr;
246 return (unsigned int *) 0;
248 #elif defined(__i386__)
250 /* Nothing needed for 10.5 */
252 /* This is for 10.4 */
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
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
288 os_sigcontext_reg(ucontext_t *scp, int index)
292 return (unsigned long *) &scp->uc_mcontext->__ss.__eax;
294 return (unsigned long *) &scp->uc_mcontext->__ss.__ecx;
296 return (unsigned long *) &scp->uc_mcontext->__ss.__edx;
298 return (unsigned long *) &scp->uc_mcontext->__ss.__ebx;
300 return (unsigned long *) &scp->uc_mcontext->__ss.__esp;
302 return (unsigned long *) &scp->uc_mcontext->__ss.__ebp;
304 return (unsigned long *) &scp->uc_mcontext->__ss.__esi;
306 return (unsigned long *) &scp->uc_mcontext->__ss.__edi;
312 os_sigcontext_pc(ucontext_t *scp)
314 return (unsigned long *) &scp->uc_mcontext->__ss.__eip;
318 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
322 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm0;
324 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm1;
326 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm2;
328 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm3;
330 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm4;
332 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm5;
334 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm6;
336 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
339 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0;
341 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1;
343 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2;
345 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3;
347 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4;
349 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5;
351 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6;
353 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
360 os_sigcontext_fpu_modes(ucontext_t *scp)
364 unsigned short cw, sw;
367 * Get the status word and the control word.
369 memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
370 memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw));
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
377 modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
379 DPRINTF(0, (stderr, "FPU modes = %08x (sw = %4x, cw = %4x)\n",
380 modes, (unsigned int) sw, (unsigned int) cw));
382 if (fpu_mode == SSE2) {
383 mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
384 DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr));
389 DPRINTF(0, (stderr, "modes pre mask = %08x\n", modes));
391 /* Convert exception mask to exception enable */
392 modes ^= (0x3f << 7);
393 DPRINTF(0, (stderr, "Finale = %08x\n", modes));
398 restore_fpu(ucontext_t *scp)
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));
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));
415 os_validate(os_vm_address_t addr, os_vm_size_t len)
417 int flags = MAP_PRIVATE | MAP_ANON;
422 DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len));
424 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
426 if (addr == (os_vm_address_t) - 1) {
431 DPRINTF(0, (stderr, "%p\n", addr));
437 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
439 DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len));
441 if (munmap(addr, len) == -1)
446 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
448 addr = mmap(addr, len,
450 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
452 if (addr == (os_vm_address_t) - 1)
459 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
463 ppc_flush_icache(address, length);
468 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
470 if (mprotect(address, length, prot) == -1)
477 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
479 char *beg = (char *) sbeg;
480 char *end = (char *) sbeg + slen;
481 char *adr = (char *) a;
483 return (adr >= beg && adr < end);
487 valid_addr(os_vm_address_t addr)
489 os_vm_address_t newaddr;
491 newaddr = os_trunc_to_page(addr);
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)
497 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
499 || in_range_p(addr, CONTROL_STACK_START, control_stack_size)
500 || in_range_p(addr, BINDING_STACK_START, binding_stack_size))
506 sigbus_handle_now(HANDLER_ARGS)
508 interrupt_handle_now(signal, code, context);
512 sigbus_handler(HANDLER_ARGS)
514 os_context_t *os_context = (os_context_t *) context;
516 caddr_t fault_addr = code->si_addr;
520 if (os_control_stack_overflow((void *) fault_addr, os_context))
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));
536 #if defined(SIGSEGV_VERBOSE)
537 fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n",
538 signal, fault_addr, page_index);
540 if (gc_write_barrier(code->si_addr))
543 if (interrupt_maybe_gc(signal, code, os_context))
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);
551 /* Work around G5 bug; fix courtesy gbyers via chandler */
552 sigreturn(os_context);
557 os_install_interrupt_handlers(void)
559 interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
563 os_dlsym(const char *sym_name, lispobj lib_list)
565 static void *program_handle;
569 program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
570 if (lib_list != NIL) {
571 lispobj lib_list_head;
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);
578 sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
583 sym_addr = dlsym(program_handle, sym_name);