/[cmucl]/src/lisp/FreeBSD-os.c
ViewVC logotype

Diff of /src/lisp/FreeBSD-os.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10.12.1 by rtoy, Mon Dec 19 01:10:11 2005 UTC revision 1.38 by rtoy, Thu Sep 1 05:18:26 2011 UTC
# Line 16  Line 16 
16   *   *
17   */   */
18    
19  #include <stdio.h>  #include "os.h"
 #include <sys/param.h>  
20  #include <sys/file.h>  #include <sys/file.h>
21    #include <machine/npx.h>
22  #include <errno.h>  #include <errno.h>
 #include "./signal.h"  
 #include "os.h"  
23  #include "arch.h"  #include "arch.h"
24  #include "globals.h"  #include "globals.h"
25  #include "interrupt.h"  #include "interrupt.h"
26  #include "lispregs.h"  #include "lispregs.h"
27  #include "internals.h"  #include "internals.h"
28    
 #include <sys/types.h>  
29  #include <signal.h>  #include <signal.h>
 /* #include <sys/sysinfo.h> */  
 #include <sys/proc.h>  
30  #include <dlfcn.h>  #include <dlfcn.h>
31  #include "validate.h"  #include "validate.h"
32    #include <stdio.h>
33    #include <unistd.h>
34    
35  #if defined GENCGC  #if defined GENCGC
36  #include "gencgc.h"  #include "gencgc.h"
37  #endif  #endif
38    
 #if __FreeBSD_version > 400000  
 /* The lisp runtime is dynamically linked, but we need a definition of  
    errno for genesis. */  
 #undef errno  
 int errno;  
 #endif  
   
39  vm_size_t os_vm_page_size;  vm_size_t os_vm_page_size;
   
40    
41  void  void
42  os_init(void)  os_init0(const char *argv[], const char *envp[])
43    {}
44    
45    void
46    os_init(const char *argv[], const char *envp[])
47  {  {
48      os_vm_page_size = getpagesize();      os_vm_page_size = getpagesize();
49  }  }
50    
51  int  unsigned long *
52  sc_reg(struct sigcontext *c, int offset)  os_sigcontext_reg(ucontext_t *scp, int index)
53  {  {
54      switch (offset) {      __register_t *rv;
55    
56        switch (index) {
57        case 0:        case 0:
58            return c->sc_eax;          rv = &scp->uc_mcontext.mc_eax;
59            break;
60        case 2:        case 2:
61            return c->sc_ecx;          rv = &scp->uc_mcontext.mc_ecx;
62            break;
63        case 4:        case 4:
64            return c->sc_edx;          rv = &scp->uc_mcontext.mc_edx;
65            break;
66        case 6:        case 6:
67            return c->sc_ebx;          rv = &scp->uc_mcontext.mc_ebx;
68            break;
69        case 8:        case 8:
70            return c->sc_esp;          rv = &scp->uc_mcontext.mc_esp;
71            break;
72        case 10:        case 10:
73            return c->sc_ebp;          rv = &scp->uc_mcontext.mc_ebp;
74            break;
75        case 12:        case 12:
76            return c->sc_esi;          rv = &scp->uc_mcontext.mc_esi;
77            break;
78        case 14:        case 14:
79            return c->sc_edi;          rv = &scp->uc_mcontext.mc_edi;
80            break;
81          default:
82            rv = NULL;
83      }      }
84    
85      return 0;      /* Pre-cast to (void *), to avoid the compiler warning:
86         * dereferencing type-punned pointer will break strict-aliasing rules
87         */
88        return (unsigned long *) (void *) rv;
89    }
90    
91    unsigned long *
92    os_sigcontext_pc(ucontext_t *scp)
93    {
94        return (unsigned long *) (void *) &scp->uc_mcontext.mc_eip;
95    }
96    
97    unsigned char *
98    os_sigcontext_fpu_reg(ucontext_t *scp, int index)
99    {
100        union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
101        int fpformat = scp->uc_mcontext.mc_fpformat;
102        unsigned char *reg = NULL;
103    
104        switch (fpformat) {
105          case _MC_FPFMT_XMM:
106              if (index < 8) {
107                  reg = sv->sv_xmm.sv_fp[index].fp_acc.fp_bytes;
108              } else {
109                  reg = sv->sv_xmm.sv_xmm[index - 8].xmm_bytes;
110              }
111              break;
112          case _MC_FPFMT_387:
113              reg = sv->sv_87.sv_ac[index].fp_bytes;
114              break;
115          case _MC_FPFMT_NODEV:
116              reg = NULL;
117              break;
118        }
119        return reg;
120  }  }
121    
122  void  unsigned int
123  os_save_context(void)  os_sigcontext_fpu_modes(ucontext_t *scp)
124  {  {
125      /* Called from interrupt handlers so C stuff knows things set in      unsigned int modes;
        Lisp.  */  
 }  
126    
127  void      union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
128  os_set_context(void)      int fpformat = scp->uc_mcontext.mc_fpformat;
129  {      struct env87 *env_87 = &sv->sv_87.sv_env;
130        struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
131        u_int16_t cw;
132        u_int16_t sw;
133    
134        if (fpformat == _MC_FPFMT_XMM) {
135            cw = env_xmm->en_cw;
136            sw = env_xmm->en_sw;
137        } else if (fpformat == _MC_FPFMT_387) {
138            cw = env_87->en_cw & 0xffff;
139            sw = env_87->en_sw & 0xffff;
140        } else { /* _MC_FPFMT_NODEV */
141            cw = 0;
142            sw = 0x3f;
143        }
144    
145        modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
146    
147    #ifdef FEATURE_SSE2
148        if (fpu_mode == SSE2) {
149            u_int32_t mxcsr = env_xmm->en_mxcsr;
150    
151            DPRINTF(0, (stderr, "SSE2 modes = %08x\n", (int)mxcsr));
152            modes |= mxcsr;
153        }
154    #endif
155        modes ^= (0x3f << 7);
156        return modes;
157  }  }
158    
159  os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)  os_vm_address_t
160    os_validate(os_vm_address_t addr, os_vm_size_t len)
161  {  {
162      int flags = MAP_PRIVATE | MAP_ANONYMOUS;      int flags = MAP_PRIVATE | MAP_ANON;
163    
164      if (addr)      if (addr)
165          flags |= MAP_FIXED;          flags |= MAP_FIXED;
     else  
         flags |= MAP_VARIABLE;  
166    
167      addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);      addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
168    
# Line 154  in_range_p(os_vm_address_t a, lispobj sb Line 217  in_range_p(os_vm_address_t a, lispobj sb
217      return adr >= beg && adr < end;      return adr >= beg && adr < end;
218  }  }
219    
220  boolean valid_addr(os_vm_address_t addr)  boolean
221    valid_addr(os_vm_address_t addr)
222  {  {
     int ret;  
223      os_vm_address_t newaddr;      os_vm_address_t newaddr;
224    
225      newaddr = os_trunc_to_page(addr);      newaddr = os_trunc_to_page(addr);
# Line 175  boolean valid_addr(os_vm_address_t addr) Line 238  boolean valid_addr(os_vm_address_t addr)
238    
239    
240  static void  static void
241  sigbus_handler(int signal, int code, struct sigcontext *context,  protection_violation_handler(HANDLER_ARGS)
                void *fault_addr)  
242  {  {
     int page_index;  
   
243  #ifdef RED_ZONE_HIT  #ifdef RED_ZONE_HIT
244      if (os_control_stack_overflow(fault_addr, context))      if (os_control_stack_overflow(code->si_addr, context))
245          return;          return;
246  #endif  #endif
247    
248  #if defined GENCGC  #if defined GENCGC
249      page_index = find_page_index(fault_addr);      if (code->si_code == PROTECTION_VIOLATION_CODE) {
250            if (gc_write_barrier(code->si_addr)) {
251      /* Check if the fault is within the dynamic space. */              return;
252      if (page_index != -1) {          }
         /* Un-protect the page */  
   
         /* The page should have been marked write protected */  
         if (!PAGE_WRITE_PROTECTED(page_index))  
             fprintf(stderr,  
                     "*** Sigbus in page not marked as write protected\n");  
   
         os_protect(page_address(page_index), 4096, OS_VM_PROT_ALL);  
         page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK;  
         page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK;  
   
         return;  
253      }      }
254  #endif /* GENCGC */  #endif
255    
256      interrupt_handle_now(signal, code, context);      interrupt_handle_now(signal, code, context);
257  }  }
258    
259    /*
260     * Restore the exception flags cleared by the kernel.  These bits must
261     * be set for Lisp to determine which exception caused the signal.  At
262     * present, there is no way to distinguish underflow exceptions from
263     * denormalized operand exceptions.  An underflow exception is assumed
264     * if the subcode is FPE_FLTUND.
265     */
266  static void  static void
267  sigsegv_handler(int signal, int code, struct sigcontext *context)  sigfpe_handler(HANDLER_ARGS)
268  {  {
269        ucontext_t *ucontext = (ucontext_t *) context;
270        union savefpu *sv = (union savefpu *) ucontext->uc_mcontext.mc_fpstate;
271        int fpformat = ucontext->uc_mcontext.mc_fpformat;
272        unsigned char trap = 0;
273    
274        switch (code->si_code) {
275          case FPE_FLTDIV:          /* ZE */
276              trap = 0x04;
277              break;
278          case FPE_FLTOVF:          /* OE */
279              trap = 0x08;
280              break;
281          case FPE_FLTUND:          /* DE or UE */
282              trap = 0x10;
283              break;
284          case FPE_FLTRES:          /* PE */
285              trap = 0x20;
286              break;
287          case FPE_FLTINV:          /* IE */
288              trap = 0x01;
289              break;
290        }
291    
292        switch (fpformat) {
293          case _MC_FPFMT_XMM:
294              sv->sv_xmm.sv_env.en_sw |= trap;
295              break;
296          case _MC_FPFMT_387:
297              sv->sv_87.sv_env.en_sw |= trap;
298              break;
299        }
300      interrupt_handle_now(signal, code, context);      interrupt_handle_now(signal, code, context);
301  }  }
302    
303  void  void
304  os_install_interrupt_handlers(void)  os_install_interrupt_handlers(void)
305  {  {
306      interrupt_install_low_level_handler      interrupt_install_low_level_handler(PROTECTION_VIOLATION_SIGNAL,
307          (SIGSEGV, (void (*)(HANDLER_ARGS)) sigsegv_handler);                                          protection_violation_handler);
308      interrupt_install_low_level_handler      interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
         (SIGBUS, (void (*)(HANDLER_ARGS)) sigbus_handler);  
309  }  }
310    
311  void *  void *
312  os_dlsym(const char *sym_name, lispobj lib_list)  os_dlsym(const char *sym_name, lispobj lib_list)
313  {  {
314        static void *program_handle;
315    
316        if (!program_handle)
317            program_handle = dlopen((void *) 0, RTLD_LAZY | RTLD_GLOBAL);
318    
319      if (lib_list != NIL) {      if (lib_list != NIL) {
320          lispobj lib_list_head;          lispobj lib_list_head;
321    
322          for (lib_list_head = lib_list;          for (lib_list_head = lib_list;
323               lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {               lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {
324              struct cons *lib_cons = CONS(CONS(lib_list_head)->car);              struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
325              struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);              struct sap *dlhandle = (struct sap *)PTR(lib_cons->car);
326              void *sym_addr = dlsym((void *) dlhandle->pointer, sym_name);              void *sym_addr = dlsym((void *)dlhandle->pointer, sym_name);
327    
328              if (sym_addr)              if (sym_addr)
329                  return sym_addr;                  return sym_addr;
330          }          }
331      }      }
332        return dlsym(program_handle, sym_name);
333    }
334    
335    void
336    restore_fpu(ucontext_t *scp)
337    {
338        union savefpu *sv = (union savefpu *) scp->uc_mcontext.mc_fpstate;
339        int fpformat = scp->uc_mcontext.mc_fpformat;
340        struct env87 *env_87 = &sv->sv_87.sv_env;
341        struct envxmm *env_xmm = &sv->sv_xmm.sv_env;
342        u_int16_t cw;
343    
344        if (fpformat == _MC_FPFMT_XMM) {
345            cw = env_xmm->en_cw;
346        } else if (fpformat == _MC_FPFMT_387) {
347            cw = env_87->en_cw & 0xffff;
348        } else { /* _MC_FPFMT_NODEV */
349            return;
350        }
351        DPRINTF(0, (stderr, "restore_fpu:  cw = %08x\n", (int)cw));
352        __asm__ __volatile__ ("fldcw %0"::"m"(*&cw));
353    
354    #ifdef FEATURE_SSE2
355        if (fpu_mode == SSE2) {
356            u_int32_t mxcsr = env_xmm->en_mxcsr;
357    
358            DPRINTF(0, (stderr, "restore_fpu:  mxcsr (raw) = %04x\n", mxcsr));
359            __asm__ __volatile__ ("ldmxcsr %0"::"m"(*&mxcsr));
360        }
361    #endif
362    }
363    
364      return dlsym(RTLD_DEFAULT, sym_name);  #ifdef i386
365    boolean
366    os_support_sse2()
367    {
368        return TRUE;
369  }  }
370    #endif
371    

Legend:
Removed from v.1.10.12.1  
changed lines
  Added in v.1.38

  ViewVC Help
Powered by ViewVC 1.1.5