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.
20 #include <sys/param.h>
28 #include "interrupt.h"
30 #include "internals.h"
35 #include <sys/types.h>
37 /* #include <sys/sysinfo.h> */
38 /* #include <sys/proc.h> */
39 /* For timebase info */
40 #include <sys/sysctl.h>
43 /* Need this to define ppc_saved_state_t (for 10.4) */
44 #include <mach/thread_status.h>
47 vm_size_t os_vm_page_size;
52 * This is accessed by Lisp! Make this a static symbol?
54 int cycles_per_tick = 1;
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.
75 * Mac OS X 10.2.8 doesn't have this, so we take it from 10.3.8,
82 len = sizeof(tbfrequency);
84 if (sysctl(mib, miblen, &tbfrequency, &len, NULL, 0) == -1) {
85 perror("Error getting HW_TB_FREQ from sysctl: ");
91 len = sizeof(cpufrequency);
92 if (sysctl(mib, miblen, &cpufrequency, &len, NULL, 0) == -1) {
93 perror("Error getting HW_CPU_FREQ from sysctl: ");
96 cycles_per_tick = cpufrequency / tbfrequency;
102 os_init0(const char *argv[], const char *envp[])
106 os_init(const char *argv[], const char *envp[])
108 os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
117 /* Nothing needed for 10.5 */
157 #define __dsisr dsisr
161 sc_reg(os_context_t * context, int offset)
163 _STRUCT_PPC_THREAD_STATE *state = &context->uc_mcontext->__ss;
187 return &state->__r10;
189 return &state->__r11;
191 return &state->__r12;
193 return &state->__r13;
195 return &state->__r14;
197 return &state->__r15;
199 return &state->__r16;
201 return &state->__r17;
203 return &state->__r18;
205 return &state->__r19;
207 return &state->__r20;
209 return &state->__r21;
211 return &state->__r22;
213 return &state->__r23;
215 return &state->__r24;
217 return &state->__r25;
219 return &state->__r26;
221 return &state->__r27;
223 return &state->__r28;
225 return &state->__r29;
227 return &state->__r30;
229 return &state->__r31;
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.
237 return &state->__ctr;
239 return &context->uc_mcontext->__es.__dar;
241 return &context->uc_mcontext->__es.__dsisr;
244 return (unsigned int *) 0;
246 #elif defined(__i386__)
248 /* Nothing needed for 10.5 */
250 /* This is for 10.4 */
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
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
286 os_sigcontext_reg(ucontext_t *scp, int index)
290 return (unsigned long *) &scp->uc_mcontext->__ss.__eax;
292 return (unsigned long *) &scp->uc_mcontext->__ss.__ecx;
294 return (unsigned long *) &scp->uc_mcontext->__ss.__edx;
296 return (unsigned long *) &scp->uc_mcontext->__ss.__ebx;
298 return (unsigned long *) &scp->uc_mcontext->__ss.__esp;
300 return (unsigned long *) &scp->uc_mcontext->__ss.__ebp;
302 return (unsigned long *) &scp->uc_mcontext->__ss.__esi;
304 return (unsigned long *) &scp->uc_mcontext->__ss.__edi;
310 os_sigcontext_pc(ucontext_t *scp)
312 return (unsigned long *) &scp->uc_mcontext->__ss.__eip;
316 os_sigcontext_fpu_reg(ucontext_t *scp, int index)
320 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm0;
322 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm1;
324 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm2;
326 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm3;
328 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm4;
330 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm5;
332 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm6;
334 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
337 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm0;
339 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm1;
341 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm2;
343 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm3;
345 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm4;
347 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm5;
349 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_xmm6;
351 return (unsigned char *) &scp->uc_mcontext->__fs.__fpu_stmm7;
358 os_sigcontext_fpu_modes(ucontext_t *scp)
362 unsigned short cw, sw;
365 * Get the status word and the control word.
367 memcpy(&cw, &scp->uc_mcontext->__fs.__fpu_fcw, sizeof(cw));
368 memcpy(&sw, &scp->uc_mcontext->__fs.__fpu_fsw, sizeof(sw));
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
375 modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
377 DPRINTF(0, (stderr, "FPU modes = %08x (sw = %4x, cw = %4x)\n",
378 modes, (unsigned int) sw, (unsigned int) cw));
380 if (fpu_mode == SSE2) {
381 mxcsr = scp->uc_mcontext->__fs.__fpu_mxcsr;
382 DPRINTF(0, (stderr, "SSE2 modes = %08x\n", mxcsr));
387 DPRINTF(0, (stderr, "modes pre mask = %08x\n", modes));
389 /* Convert exception mask to exception enable */
390 modes ^= (0x3f << 7);
391 DPRINTF(0, (stderr, "Finale = %08x\n", modes));
396 restore_fpu(ucontext_t *scp)
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));
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));
413 os_validate(os_vm_address_t addr, os_vm_size_t len)
415 int flags = MAP_PRIVATE | MAP_ANON;
420 DPRINTF(0, (stderr, "os_validate %p %d => ", addr, len));
422 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
424 if (addr == (os_vm_address_t) - 1) {
429 DPRINTF(0, (stderr, "%p\n", addr));
435 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
437 DPRINTF(0, (stderr, "os_invalidate %p %d\n", addr, len));
439 if (munmap(addr, len) == -1)
444 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
446 addr = mmap(addr, len,
448 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
450 if (addr == (os_vm_address_t) - 1)
457 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
461 ppc_flush_icache(address, length);
466 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
468 if (mprotect(address, length, prot) == -1)
475 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
477 char *beg = (char *) sbeg;
478 char *end = (char *) sbeg + slen;
479 char *adr = (char *) a;
481 return (adr >= beg && adr < end);
485 valid_addr(os_vm_address_t addr)
487 os_vm_address_t newaddr;
489 newaddr = os_trunc_to_page(addr);
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)
493 || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
495 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
497 || in_range_p(addr, CONTROL_STACK_START, control_stack_size)
498 || in_range_p(addr, BINDING_STACK_START, binding_stack_size))
504 sigbus_handle_now(HANDLER_ARGS)
506 interrupt_handle_now(signal, code, context);
510 sigbus_handler(HANDLER_ARGS)
512 os_context_t *os_context = (os_context_t *) context;
514 caddr_t fault_addr = code->si_addr;
518 if (os_control_stack_overflow((void *) fault_addr, os_context))
523 DPRINTF(0, (stderr, "sigbus:\n"));
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)));
530 DPRINTF(0, (stderr, " foreign_function_call = %d\n", foreign_function_call_active));
534 #if defined(SIGSEGV_VERBOSE)
535 fprintf(stderr, "Signal %d, fault_addr=%x, page_index=%d:\n",
536 signal, fault_addr, page_index);
538 if (gc_write_barrier(code->si_addr))
541 if (interrupt_maybe_gc(signal, code, os_context))
544 /* a *real* protection fault */
545 fprintf(stderr, "sigbus_handler: Real protection violation at %p, PC = %p\n",
546 fault_addr, (void *) SC_PC(os_context));
547 sigbus_handle_now(signal, code, os_context);
549 /* Work around G5 bug; fix courtesy gbyers via chandler */
550 sigreturn(os_context);
555 os_install_interrupt_handlers(void)
557 interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
561 os_dlsym(const char *sym_name, lispobj lib_list)
563 static void *program_handle;
567 program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
568 if (lib_list != NIL) {
569 lispobj lib_list_head;
571 for (lib_list_head = lib_list;
572 lib_list_head != NIL; lib_list_head = (CONS(lib_list_head))->cdr) {
573 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
574 struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
576 sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
581 sym_addr = dlsym(program_handle, sym_name);