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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5