/[cmucl]/src/lisp/amd64-arch.c
ViewVC logotype

Diff of /src/lisp/amd64-arch.c

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

revision 1.3 by cwang, Tue Jun 22 22:38:27 2004 UTC revision 1.3.2.1 by rtoy, Mon Dec 19 01:10:12 2005 UTC
# Line 23  Line 23 
23    
24  #define BREAKPOINT_INST 0xcc    /* INT3 */  #define BREAKPOINT_INST 0xcc    /* INT3 */
25    
26  unsigned long  fast_random_state = 1;  unsigned long fast_random_state = 1;
27    
28  char * arch_init(void)  char *
29    arch_init(void)
30  {  {
31    return "lisp.core";      return "lisp.core";
32  }  }
   
33    
34    
35    
36  /*  /*
37   * Assuming we get here via an INT3 xxx instruction, the PC now   * Assuming we get here via an INT3 xxx instruction, the PC now
38   * points to the interrupt code (lisp value) so we just move past   * points to the interrupt code (lisp value) so we just move past
# Line 39  char * arch_init(void) Line 40  char * arch_init(void)
40   * Cerror-trap then skip the data bytes that follow.   * Cerror-trap then skip the data bytes that follow.
41   */   */
42    
43  void arch_skip_instruction(struct sigcontext *context)  void
44    arch_skip_instruction(struct sigcontext *context)
45  {  {
46    int vlen,code;      int vlen, code;
47    
48    DPRINTF(0,(stderr,"[arch_skip_inst at %x>]\n", context->sc_pc));      DPRINTF(0, (stderr, "[arch_skip_inst at %x>]\n", context->sc_pc));
49    
50    /* Get and skip the lisp error code. */      /* Get and skip the lisp error code. */
51    code = *(char*) context->sc_pc++;      code = *(char *) context->sc_pc++;
52    switch (code)      switch (code) {
53      {        case trap_Error:
54      case trap_Error:        case trap_Cerror:
55      case trap_Cerror:            /* Lisp error arg vector length */
56        /* Lisp error arg vector length */            vlen = *(char *) context->sc_pc++;
57        vlen = *(char*) context->sc_pc++;            /* Skip lisp error arg data bytes */
58        /* Skip lisp error arg data bytes */            while (vlen-- > 0)
59        while(vlen-- > 0)                ((char *) context->sc_pc)++;
60          ((char*) context->sc_pc)++;            break;
61        break;  
62          case trap_Breakpoint:
63      case trap_Breakpoint:        case trap_FunctionEndBreakpoint:
64      case trap_FunctionEndBreakpoint:            break;
65        break;  
66          case trap_PendingInterrupt:
67      case trap_PendingInterrupt:        case trap_Halt:
68      case trap_Halt:            /* Only needed to skip the Code. */
69        /* Only needed to skip the Code. */            break;
70        break;  
71          default:
72      default:            fprintf(stderr, "[arch_skip_inst invalid code %d\n]\n", code);
73        fprintf(stderr, "[arch_skip_inst invalid code %d\n]\n", code);            break;
       break;  
74      }      }
75    
76    DPRINTF(0,(stderr,"[arch_skip_inst resuming at %x>]\n", context->sc_pc));      DPRINTF(0, (stderr, "[arch_skip_inst resuming at %x>]\n", context->sc_pc));
77  }  }
78    
79  unsigned char * arch_internal_error_arguments(struct sigcontext *context)  unsigned char *
80    arch_internal_error_arguments(struct sigcontext *context)
81  {  {
82    return (unsigned char *) (context->sc_pc + 1);      return (unsigned char *) (context->sc_pc + 1);
83  }  }
84    
85  boolean arch_pseudo_atomic_atomic(struct sigcontext *context)  boolean
86    arch_pseudo_atomic_atomic(struct sigcontext *context)
87  {  {
88    return SymbolValue(PSEUDO_ATOMIC_ATOMIC);      return SymbolValue(PSEUDO_ATOMIC_ATOMIC);
89  }  }
90    
91  void arch_set_pseudo_atomic_interrupted(struct sigcontext *context)  void
92    arch_set_pseudo_atomic_interrupted(struct sigcontext *context)
93  {  {
94    SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1));      SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1));
95  }  }
   
96    
97    
98  unsigned long  arch_install_breakpoint(void *pc)  
99    unsigned long
100    arch_install_breakpoint(void *pc)
101  {  {
102    unsigned long result = *(unsigned long*)pc;      unsigned long result = *(unsigned long *) pc;
103    
104    *(char*)pc = BREAKPOINT_INST;         /* x86 INT3       */      *(char *) pc = BREAKPOINT_INST;     /* x86 INT3       */
105    *((char*)pc+1) = trap_Breakpoint;     /* Lisp trap code */      *((char *) pc + 1) = trap_Breakpoint;       /* Lisp trap code */
106    
107    return result;      return result;
108  }  }
109    
110  void  arch_remove_breakpoint(void *pc, unsigned long orig_inst)  void
111    arch_remove_breakpoint(void *pc, unsigned long orig_inst)
112  {  {
113    *((char *) pc) = orig_inst & 0xff;      *((char *) pc) = orig_inst & 0xff;
114    *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;      *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;
115  }  }
   
116    
117    
118    
119  /*  /*
120   * When single stepping single_stepping holds the original instruction   * When single stepping single_stepping holds the original instruction
121   * pc location.   * pc location.
122   */   */
123    
124  unsigned int *single_stepping = NULL;  unsigned int *single_stepping = NULL;
125    
126  #ifndef __linux__  #ifndef __linux__
127  unsigned int  single_step_save1;  unsigned int single_step_save1;
128  unsigned int  single_step_save2;  unsigned int single_step_save2;
129  unsigned int  single_step_save3;  unsigned int single_step_save3;
130  #endif  #endif
131    
132  void  arch_do_displaced_inst(struct sigcontext *context,  void
133                               unsigned long orig_inst)  arch_do_displaced_inst(struct sigcontext *context, unsigned long orig_inst)
134  {  {
135    unsigned int *pc = (unsigned int*) context->sc_pc;      unsigned int *pc = (unsigned int *) context->sc_pc;
136    
137    /*      /*
138     * Put the original instruction back.       * Put the original instruction back.
139     */       */
140    
141    *((char *) pc) = orig_inst & 0xff;      *((char *) pc) = orig_inst & 0xff;
142    *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;      *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;
143    
144  #ifdef __linux__  #ifdef __linux__
145    context->eflags |= 0x100;      context->eflags |= 0x100;
146  #else  #else
147    
148    /*      /*
149     * Install helper instructions for the single step:       * Install helper instructions for the single step:
150     *    pushf; or [esp],0x100; popf.       *    pushf; or [esp],0x100; popf.
151     */       */
152    
153    single_step_save1 = *(pc - 3);      single_step_save1 = *(pc - 3);
154    single_step_save2 = *(pc - 2);      single_step_save2 = *(pc - 2);
155    single_step_save3 = *(pc - 1);      single_step_save3 = *(pc - 1);
156    *(pc - 3) = 0x9c909090;      *(pc - 3) = 0x9c909090;
157    *(pc - 2) = 0x00240c81;      *(pc - 2) = 0x00240c81;
158    *(pc - 1) = 0x9d000001;      *(pc - 1) = 0x9d000001;
159  #endif  #endif
160    
161    single_stepping = (unsigned int*) pc;      single_stepping = (unsigned int *) pc;
162    
163  #ifndef __linux__  #ifndef __linux__
164    (unsigned int*) context->sc_pc = (char *) pc - 9;      (unsigned int *) context->sc_pc = (char *) pc - 9;
165  #endif  #endif
166  }  }
167    
168    
169  void  sigtrap_handler(HANDLER_ARGS)  void
170    sigtrap_handler(HANDLER_ARGS)
171  {  {
172    unsigned int  trap;      unsigned int trap;
173    
174  #ifdef __linux__  #ifdef __linux__
175    GET_CONTEXT      GET_CONTEXT
176  #endif  #endif
   
177  #if 0  #if 0
178    fprintf(stderr,"x86sigtrap: %8x %x\n",          fprintf(stderr, "x86sigtrap: %8x %x\n",
179            context->sc_pc, *(unsigned char *)(context->sc_pc-1));                  context->sc_pc, *(unsigned char *) (context->sc_pc - 1));
180    fprintf(stderr,"sigtrap(%d %d %x)\n",signal,code,context);      fprintf(stderr, "sigtrap(%d %d %x)\n", signal, code, context);
181  #endif  #endif
182    
183    if (single_stepping && (signal == SIGTRAP))      if (single_stepping && (signal == SIGTRAP)) {
     {  
184  #if 0  #if 0
185        fprintf(stderr,"* Single step trap %x\n", single_stepping);          fprintf(stderr, "* Single step trap %x\n", single_stepping);
186  #endif  #endif
187    
188  #ifndef __linux__  #ifndef __linux__
189        /* Un-install single step helper instructions. */          /* Un-install single step helper instructions. */
190        *(single_stepping-3) = single_step_save1;          *(single_stepping - 3) = single_step_save1;
191        *(single_stepping-2) = single_step_save2;          *(single_stepping - 2) = single_step_save2;
192        *(single_stepping-1) = single_step_save3;          *(single_stepping - 1) = single_step_save3;
193  #else  #else
194         context->eflags ^= 0x100;          context->eflags ^= 0x100;
195  #endif  #endif
196    
197        /*          /*
198         * Re-install the breakpoint if possible.           * Re-install the breakpoint if possible.
199         */           */
200    
201        if ((int) context->sc_pc == (int) single_stepping + 1)          if ((int) context->sc_pc == (int) single_stepping + 1)
202          fprintf(stderr, "* Breakpoint not re-install\n");              fprintf(stderr, "* Breakpoint not re-install\n");
203        else          else {
204          {              char *ptr = (char *) single_stepping;
205            char *ptr = (char *) single_stepping;  
206            ptr[0] = BREAKPOINT_INST;     /* x86 INT3 */              ptr[0] = BREAKPOINT_INST;   /* x86 INT3 */
207            ptr[1] = trap_Breakpoint;              ptr[1] = trap_Breakpoint;
208          }          }
209    
210        single_stepping = NULL;          single_stepping = NULL;
211        return;          return;
212      }      }
213    
214    SAVE_CONTEXT();      SAVE_CONTEXT();
215    
216    /* This is just for info in case monitor wants to print an approx */      /* This is just for info in case monitor wants to print an approx */
217    current_control_stack_pointer = (unsigned long*) context->sc_sp;      current_control_stack_pointer = (unsigned long *) context->sc_sp;
218    
219  #if defined(__linux__) && (defined(i386) || defined(__x86_64))  #if defined(__linux__) && (defined(i386) || defined(__x86_64))
220    /*      /*
221     * Restore the FPU control word, setting the rounding mode to nearest.       * Restore the FPU control word, setting the rounding mode to nearest.
222     */       */
223    
224    if (contextstruct.fpstate)      if (contextstruct.fpstate)
225  #if defined(__x86_64)  #if defined(__x86_64)
226      setfpucw(contextstruct.fpstate->cwd & ~0xc00);          setfpucw(contextstruct.fpstate->cwd & ~0xc00);
227  #else  #else
228      setfpucw(contextstruct.fpstate->cw & ~0xc00);          setfpucw(contextstruct.fpstate->cw & ~0xc00);
229  #endif  #endif
230  #endif  #endif
231    
232   /*      /*
233    * On entry %eip points just after the INT3 byte and aims at the       * On entry %eip points just after the INT3 byte and aims at the
234    * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a       * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
235    * number of bytes will follow, the first is the length of the byte       * number of bytes will follow, the first is the length of the byte
236    * arguments to follow.       * arguments to follow.
237    */       */
238    
239    trap = *(unsigned char *) (context->sc_pc);      trap = *(unsigned char *) (context->sc_pc);
240    
241    switch (trap)      switch (trap) {
242      {        case trap_PendingInterrupt:
243      case trap_PendingInterrupt:            DPRINTF(0, (stderr, "<trap Pending Interrupt.>\n"));
244        DPRINTF(0,(stderr,"<trap Pending Interrupt.>\n"));            arch_skip_instruction(context);
245        arch_skip_instruction(context);            interrupt_handle_pending(context);
246        interrupt_handle_pending(context);            break;
247        break;  
248          case trap_Halt:
249      case trap_Halt:            {
       {  
250  #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)  #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
251          int fpu_state[27];                int fpu_state[27];
252          fpu_save(fpu_state);  
253                  fpu_save(fpu_state);
254  #endif  #endif
255          fake_foreign_function_call(context);                fake_foreign_function_call(context);
256          lose("%%primitive halt called; the party is over.\n");                lose("%%primitive halt called; the party is over.\n");
257          undo_fake_foreign_function_call(context);                undo_fake_foreign_function_call(context);
258  #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)  #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
259          fpu_restore(fpu_state);                fpu_restore(fpu_state);
260  #endif  #endif
261          arch_skip_instruction(context);                arch_skip_instruction(context);
262          break;                break;
263        }            }
264    
265      case trap_Error:        case trap_Error:
266      case trap_Cerror:        case trap_Cerror:
267        DPRINTF(0, (stderr, "<trap Error %d>\n",code));            DPRINTF(0, (stderr, "<trap Error %d>\n", code));
268  #ifdef __linux__  #ifdef __linux__
269        interrupt_internal_error(signal, contextstruct, code == trap_Cerror);            interrupt_internal_error(signal, contextstruct, code == trap_Cerror);
270  #else  #else
271        interrupt_internal_error(signal, code, context, code == trap_Cerror);            interrupt_internal_error(signal, code, context, code == trap_Cerror);
272  #endif  #endif
273        break;            break;
274    
275      case trap_Breakpoint:        case trap_Breakpoint:
276  #if 0  #if 0
277        fprintf(stderr,"*C break\n");            fprintf(stderr, "*C break\n");
278  #endif  #endif
279        (char*) context->sc_pc -= 1;            (char *) context->sc_pc -= 1;
280        handle_breakpoint(signal, code, context);            handle_breakpoint(signal, code, context);
281  #if 0  #if 0
282        fprintf(stderr,"*C break return\n");            fprintf(stderr, "*C break return\n");
283  #endif  #endif
284        break;            break;
285    
286      case trap_FunctionEndBreakpoint:        case trap_FunctionEndBreakpoint:
287        (char*) context->sc_pc -= 1;            (char *) context->sc_pc -= 1;
288        context->sc_pc = (int) handle_function_end_breakpoint(signal, code, context);            context->sc_pc =
289        break;                (int) handle_function_end_breakpoint(signal, code, context);
290              break;
291    
292  #ifdef DYNAMIC_SPACE_OVERFLOW_WARNING_HIT  #ifdef DYNAMIC_SPACE_OVERFLOW_WARNING_HIT
293      case trap_DynamicSpaceOverflowWarning:        case trap_DynamicSpaceOverflowWarning:
294          interrupt_handle_space_overflow(SymbolFunction(DYNAMIC_SPACE_OVERFLOW_WARNING_HIT),            interrupt_handle_space_overflow(SymbolFunction
295                                          context);                                            (DYNAMIC_SPACE_OVERFLOW_WARNING_HIT),
296          break;                                            context);
297              break;
298  #endif  #endif
299  #ifdef DYNAMIC_SPACE_OVERFLOW_ERROR_HIT  #ifdef DYNAMIC_SPACE_OVERFLOW_ERROR_HIT
300      case trap_DynamicSpaceOverflowError:        case trap_DynamicSpaceOverflowError:
301          interrupt_handle_space_overflow(SymbolFunction(DYNAMIC_SPACE_OVERFLOW_ERROR_HIT),            interrupt_handle_space_overflow(SymbolFunction
302                                          context);                                            (DYNAMIC_SPACE_OVERFLOW_ERROR_HIT),
303              break;                                            context);
304  #endif            break;
305      default:  #endif
306        DPRINTF(0,(stderr,"[C--trap default %d %d %x]\n", signal, code,context));        default:
307              DPRINTF(0,
308                      (stderr, "[C--trap default %d %d %x]\n", signal, code,
309                       context));
310  #ifdef __linux__  #ifdef __linux__
311        interrupt_handle_now(signal, contextstruct);            interrupt_handle_now(signal, contextstruct);
312  #else  #else
313        interrupt_handle_now(signal, code, context);            interrupt_handle_now(signal, code, context);
314  #endif  #endif
315        break;            break;
316      }      }
317  }  }
318    
319  #define FIXNUM_VALUE(lispobj) (((int) lispobj) >> 2)  #define FIXNUM_VALUE(lispobj) (((int) lispobj) >> 2)
320    
321  void arch_install_interrupt_handlers()  void
322    arch_install_interrupt_handlers()
323  {  {
324      interrupt_install_low_level_handler(SIGILL, sigtrap_handler);      interrupt_install_low_level_handler(SIGILL, sigtrap_handler);
325      interrupt_install_low_level_handler(SIGTRAP, sigtrap_handler);      interrupt_install_low_level_handler(SIGTRAP, sigtrap_handler);
326  }  }
327    
328    
329  extern lispobj call_into_lisp(lispobj fun, lispobj *args, int nargs);  extern lispobj call_into_lisp(lispobj fun, lispobj * args, int nargs);
330    
331  /* These next four functions are an interface to the  /* These next four functions are an interface to the
332   * Lisp call-in facility. Since this is C we can know   * Lisp call-in facility. Since this is C we can know
# Line 328  extern lispobj call_into_lisp(lispobj fu Line 340  extern lispobj call_into_lisp(lispobj fu
340   * call-in function figure it out.   * call-in function figure it out.
341   */   */
342    
343  lispobj  funcall0(lispobj function)  lispobj
344    funcall0(lispobj function)
345  {  {
346      lispobj *args = NULL;      lispobj *args = NULL;
347    
348      return call_into_lisp(function, args, 0);      return call_into_lisp(function, args, 0);
349  }  }
350    
351  lispobj  funcall1(lispobj function, lispobj arg0)  lispobj
352    funcall1(lispobj function, lispobj arg0)
353  {  {
354      lispobj args[1];      lispobj args[1];
355    
356      args[0] = arg0;      args[0] = arg0;
357      return call_into_lisp(function, args, 1);      return call_into_lisp(function, args, 1);
358  }  }
359    
360  lispobj  funcall2(lispobj function, lispobj arg0, lispobj arg1)  lispobj
361    funcall2(lispobj function, lispobj arg0, lispobj arg1)
362  {  {
363      lispobj args[2];      lispobj args[2];
364    
365      args[0] = arg0;      args[0] = arg0;
366      args[1] = arg1;      args[1] = arg1;
367      return call_into_lisp(function, args, 2);      return call_into_lisp(function, args, 2);
368  }  }
369    
370  lispobj  funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)  lispobj
371    funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
372  {  {
373      lispobj args[3];      lispobj args[3];
374    
375      args[0] = arg0;      args[0] = arg0;
376      args[1] = arg1;      args[1] = arg1;
377      args[2] = arg2;      args[2] = arg2;
# Line 365  lispobj  funcall3(lispobj function, lisp Line 384  lispobj  funcall3(lispobj function, lisp
384  #define LinkageEntrySize 16  #define LinkageEntrySize 16
385  #endif  #endif
386    
387  void arch_make_linkage_entry(long linkage_entry, void *target_addr, long type)  void
388    arch_make_linkage_entry(long linkage_entry, void *target_addr, long type)
389  {  {
390      char *reloc_addr = (char *)(FOREIGN_LINKAGE_SPACE_START      char *reloc_addr = (char *) (FOREIGN_LINKAGE_SPACE_START
                                 + linkage_entry * LinkageEntrySize);  
391    
392      if (type == 1) {                    /* code reference */                                   + linkage_entry * LinkageEntrySize);
393          /* Make JMP to function entry. */  
394          long offset = (char *)target_addr;      if (type == 1) {            /* code reference */
395            /* Make JMP to function entry. */
396            long offset = (char *) target_addr;
397          int i;          int i;
398    
399          /* %r11 is a temp register */          /* %r11 is a temp register */
400          *reloc_addr++ = 0x49;           /* opcode for MOV */          *reloc_addr++ = 0x49;   /* opcode for MOV */
401          *reloc_addr++ = 0xbb; /* %r11 */          *reloc_addr++ = 0xbb;   /* %r11 */
402          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
403              *reloc_addr++ = offset & 0xff;              *reloc_addr++ = offset & 0xff;
404              offset >>= 8;              offset >>= 8;
405          }          }
406          *reloc_addr++ = 0x41; /* jmpq */          *reloc_addr++ = 0x41;   /* jmpq */
407          *reloc_addr++ = 0xff;          *reloc_addr++ = 0xff;
408          *reloc_addr++ = 0xe3; /* %r11 */          *reloc_addr++ = 0xe3;   /* %r11 */
409          /* write a nop for good measure. */          /* write a nop for good measure. */
410          *reloc_addr = 0x90;          *reloc_addr = 0x90;
411      } else if (type == 2) {      } else if (type == 2) {
412          *(unsigned long *)reloc_addr = (unsigned long)target_addr;          *(unsigned long *) reloc_addr = (unsigned long) target_addr;
413      }      }
414  }  }
415    
416  /* Make a call to the first function in the linkage table, which is  /* Make a call to the first function in the linkage table, which is
417     resolve_linkage_tramp. */     resolve_linkage_tramp. */
418  void arch_make_lazy_linkage(long linkage_entry)  void
419    arch_make_lazy_linkage(long linkage_entry)
420  {  {
421      char *reloc_addr = (char *)(FOREIGN_LINKAGE_SPACE_START      char *reloc_addr = (char *) (FOREIGN_LINKAGE_SPACE_START
422                                  + linkage_entry * LinkageEntrySize);  
423      long offset = (char *)(FOREIGN_LINKAGE_SPACE_START) - (reloc_addr + 5);                                   + linkage_entry * LinkageEntrySize);
424        long offset = (char *) (FOREIGN_LINKAGE_SPACE_START) - (reloc_addr + 5);
425      int i;      int i;
426    
427      *reloc_addr++ = 0xe8;               /* opcode for CALL rel32 */      *reloc_addr++ = 0xe8;       /* opcode for CALL rel32 */
428      for (i = 0; i < 4; i++) {      for (i = 0; i < 4; i++) {
429          *reloc_addr++ = offset & 0xff;          *reloc_addr++ = offset & 0xff;
430          offset >>= 8;          offset >>= 8;
# Line 414  void arch_make_lazy_linkage(long linkage Line 437  void arch_make_lazy_linkage(long linkage
437     entry is a CALL; the return address we're passed points to the next     entry is a CALL; the return address we're passed points to the next
438     instruction. */     instruction. */
439    
440  long arch_linkage_entry(unsigned long retaddr)  long
441    arch_linkage_entry(unsigned long retaddr)
442  {  {
443      return ((retaddr - 5) - FOREIGN_LINKAGE_SPACE_START) / LinkageEntrySize;      return ((retaddr - 5) - FOREIGN_LINKAGE_SPACE_START) / LinkageEntrySize;
444  }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.3.2.1

  ViewVC Help
Powered by ViewVC 1.1.5