source: trunk/source/lisp-kernel/x86-exceptions.h @ 11565

Last change on this file since 11565 was 11565, checked in by gb, 11 years ago

Implement DarwinSigReturn? in terms of the new darwin_sigreturn glue.
We've been trying to do sigreturn via a syscall, but haven't been
doing the syscall correctly. The syscall's been returning with an
error (and without setting the thread's context), and we've been
falling off the end of the functions that use DarwinSigReturn?
(suspend_resume_handler, interrupt_handler) and returning to code in
sigtramp() which does a sigreturn to whatever context is in %esi/%rbx.
We've done So Many Bad Things (copying contexts between stacks,
switching stacks) that what's in that register (a C nvr) is pretty
arbitrary, but it seems to be one of (a) predictably the right thing,
if the interrupt occurred on the foreign stack; (b) accidentally the
right thing, if the nvr contained the "right" context (c) the old
context - received on the lisp stack - if the nvr was not used or
was used to hold the old context before copying.

When -O2 was in effect on Darwin, it seems that we lucked out and
accidentally got (b), which means that a thread's context was restored
to something that may have been updated by the GC. With less aggressive
optimization settings, a thread that was running lisp code when suspended
or interrupted would resume with its registers pointing to where they'd
pointed before the GC ran (as it often would have in the suspend case).

I think that this is likely to be a large part of the 'things are flaky
unless -O2 is in effect' problems that've been around for a while. There
may be other bugs (e.g., bogus TRAs on the lisp stack) that aren't related
to this, but it hasn't been possible to debug them with -O2 in effect and
-O2 seems to have accidentally masked this sigreturn problem.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/*
2   Copyright (C) 2005 Clozure Associates
3   This file is part of OpenMCL. 
4
5   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with OpenMCL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with OpenMCL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   OpenMCL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17#ifndef X86_EXCEPTIONS_H
18#define X86_EXCEPTIONS_H 1
19
20typedef u8_t opcode, *pc;
21
22#ifdef LINUX
23#define xpGPRvector(x) ((natural *)(&((x)->uc_mcontext.gregs)))
24#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
25#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
26#define xpPC(x) (xpGPR(x,Iip))
27#define xpMMXreg(x,n)  *((natural *)(&((x)->uc_mcontext.fpregs->_st[n])))
28#define eflags_register(xp) xpGPR(xp,Iflags)
29#endif
30
31#ifdef DARWIN
32#define DARWIN_USE_PSEUDO_SIGRETURN 1
33#include <sys/syscall.h>
34#define DarwinSigReturn(context) do {\
35    darwin_sigreturn(context);\
36    Bug(context,"sigreturn returned");\
37  } while (0)
38
39#define xpGPRvector(x) ((natural *)(&(UC_MCONTEXT(x)->__ss)))
40#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
41#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
42#define xpPC(x) (xpGPR(x,Iip))
43#define eflags_register(xp) xpGPR(xp,Iflags)
44#define xpFPRvector(x) ((natural *)(&(UC_MCONTEXT(x)->__fs.__fpu_xmm0)))
45#define xpMMXvector(x) (&(UC_MCONTEXT(x)->__fs.__fpu_stmm0))
46/* Note that this yields only the lower half of the MMX reg on x8632 */
47#define xpMMXreg(x,n) *(natural *)&(xpMMXvector(x)[n])
48
49#include <mach/mach.h>
50#include <mach/mach_error.h>
51#include <mach/machine/thread_state.h>
52#include <mach/machine/thread_status.h>
53
54pthread_mutex_t *mach_exception_lock;
55
56#endif
57
58#ifdef FREEBSD
59#ifdef X8664
60#include <machine/fpu.h>
61#else
62#include "freebsdx8632/fpu.h"
63#endif
64#define xpGPRvector(x) ((natural *)(&((x)->uc_mcontext)))
65#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
66#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
67#define eflags_register(xp) xpGPR(xp,Iflags)
68#define xpPC(x) xpGPR(x,Iip)
69#ifdef X8664
70#define xpMMXreg(x,n) *((natural *)(&(((struct savefpu *)(&(x)->uc_mcontext.mc_fpstate))->sv_fp[n])))
71#define xpXMMregs(x)(&(((struct savefpu *)(&(x)->uc_mcontext.mc_fpstate))->sv_xmm[0]))
72#else
73#define xpMMXreg(x,n) *((natural *)(&(((struct ccl_savexmm *)(&(x)->uc_mcontext.mc_fpstate))->sv_fp[n])))
74#define xpXMMregs(x)(&(((struct ccl_savexmm *)(&(x)->uc_mcontext.mc_fpstate))->sv_xmm[0]))
75#endif
76#endif
77
78#ifdef SOLARIS
79#define xpGPRvector(x) ((x)->uc_mcontext.gregs)
80#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
81#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
82#define xpPC(x) xpGPR(x,Iip)
83#define eflags_register(xp) xpGPR(xp,Iflags)
84#define xpXMMregs(x)(&((x)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[0]))
85#ifdef X8632
86#define xpMMXreg(x,n)*(natural *)(&(((struct fnsave_state *)(&(((x)->uc_mcontext.fpregs))))->f_st[n]))
87#endif
88#endif
89
90#ifdef WINDOWS
91#ifdef X8664
92#define xpGPRvector(x) ((DWORD64 *)(&(x)->Rax))
93#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
94#define xpPC(x) xpGPR(x,Iip)
95#define eflags_register(xp) xp->EFlags
96#else
97#define xpGPRvector(x) ((DWORD *)(&(x)->Edi))
98#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
99#define xpPC(x) xpGPR(x,Iip)
100#define eflags_register(xp) xp->EFlags
101#define xpFPRvector(x) ((natural *)(&(x->ExtendedRegisters[10*16])))
102#define xpMMXreg(x,n)  (*((u64_t *)(&(x->FloatSave.RegisterArea[10*(n)]))))
103#endif
104#endif
105
106#ifdef DARWIN
107#define SIGNAL_FOR_PROCESS_INTERRUPT SIGUSR1
108#endif
109#ifdef LINUX
110#define SIGNAL_FOR_PROCESS_INTERRUPT SIGPWR
111#endif
112#ifdef FREEBSD
113#define SIGNAL_FOR_PROCESS_INTERRUPT SIGEMT
114#endif
115#ifdef SOLARIS
116#define SIGNAL_FOR_PROCESS_INTERRUPT SIGUSR1
117#endif
118#ifdef WINDOWS
119#define SIGNAL_FOR_PROCESS_INTERRUPT SIGINT
120#ifndef SIGBUS
121#define SIGBUS 10
122#endif
123#ifndef CONTEXT_ALL
124#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS)
125#endif
126#endif
127
128
129
130void switch_to_foreign_stack(void*, ...);
131
132#define INTN_OPCODE 0xcd
133
134#define UUO_GC_TRAP    0xc4
135#define UUO_ALLOC_TRAP 0xc5
136#define UUO_DEBUG_TRAP 0xca
137#define UUO_DEBUG_TRAP_WITH_STRING 0xcd
138
139#define XUUO_OPCODE_0 0x0f
140#define XUUO_OPCODE_1 0x0b
141
142#define XUUO_TLB_TOO_SMALL 1
143#define XUUO_INTERRUPT_NOW 2
144#define XUUO_SUSPEND_NOW 3
145#define XUUO_INTERRUPT 4
146#define XUUO_SUSPEND 5
147#define XUUO_SUSPEND_ALL 6
148#define XUUO_RESUME 7
149#define XUUO_RESUME_ALL 8
150#define XUUO_KILL 9
151#define XUUO_ALLOCATE_LIST 10
152
153void
154pc_luser_xp(ExceptionInformation*, TCR*, signed_natural*);
155
156
157typedef enum {
158  ID_unrecognized_alloc_instruction,
159  ID_load_allocptr_reg_from_tcr_save_allocptr_instruction,
160  ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction,
161  ID_branch_around_alloc_trap_instruction,
162  ID_alloc_trap_instruction,
163  ID_set_allocptr_header_instruction,
164  ID_clear_tcr_save_allocptr_tag_instruction
165} alloc_instruction_id;
166
167#ifdef LINUX
168#define SIGNUM_FOR_INTN_TRAP SIGSEGV
169#define IS_MAYBE_INT_TRAP(info,xp) (((info->si_code) &0x7f) == 0)
170#define SIGRETURN(context)
171#endif
172
173#ifdef FREEBSD
174extern void freebsd_sigreturn(ExceptionInformation *);
175#define SIGNUM_FOR_INTN_TRAP SIGBUS
176#define IS_MAYBE_INT_TRAP(info,xp) (xp->uc_mcontext.mc_trapno == T_PROTFLT)
177#define SIGRETURN(context) freebsd_sigreturn(context)
178#endif
179
180#ifdef DARWIN
181#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Not really, but our Mach handler fakes that */
182#define IS_MAYBE_INT_TRAP(info,xp) (info->si_code == EXC_I386_GPFLT)
183/* The x86 version of sigreturn just needs the context argument; the
184   hidden, magic "flavor" argument that sigtramp uses is ignored. */
185#define SIGRETURN(context) DarwinSigReturn(context)
186#endif
187
188#ifdef SOLARIS
189#define SIGNUM_FOR_INTN_TRAP SIGSEGV
190#ifdef X8664
191#define IS_MAYBE_INT_TRAP(info,xp) ((xpGPR(xp,REG_TRAPNO)==0xd)&&((xpGPR(xp,REG_ERR)&7)==2))
192#else
193#define IS_MAYBE_INT_TRAP(info,xp) ((xpGPR(xp,TRAPNO)==0xd)&&((xpGPR(xp,ERR)&7)==2))
194#endif
195#define SIGRETURN(context) setcontext(context)
196#endif
197
198#ifdef WINDOWS
199#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Also fake */
200#define IS_MAYBE_INT_TRAP(info,xp) \
201  ((info->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) &&       \
202   (info->ExceptionInformation[0]==0) &&                       \
203   (info->ExceptionInformation[1]==(ULONG_PTR)(-1L)))
204#define SIGRETURN(context)      /* for now */
205#endif
206
207/* Please go away. */
208#ifdef DARWIN_GS_HACK
209extern Boolean ensure_gs_pthread(void);
210extern void set_gs_address(void *);
211#endif
212
213
214/* sigaltstack isn't thread-specific on The World's Most Advanced OS */
215#ifdef DARWIN
216#undef USE_SIGALTSTACK
217#else
218#ifdef WINDOWS
219#undef USE_SIGALTSTACK
220#else
221#define USE_SIGALTSTACK 1
222#endif
223#endif
224
225#ifdef USE_SIGALTSTACK
226void setup_sigaltstack(area *);
227#endif
228
229/* recognizing the function associated with a tagged return address */
230/* now involves recognizinig an "(lea (@ disp (% rip)) (% rn))" */
231/* instruction at the tra */
232
233#define RECOVER_FN_FROM_RIP_LENGTH 7 /* the instruction is 7 bytes long */
234#define RECOVER_FN_FROM_RIP_DISP_OFFSET 3 /* displacement word is 3 bytes in */
235#define RECOVER_FN_FROM_RIP_WORD0 0x8d4c /* 0x4c 0x8d, little-endian */
236#define RECOVER_FN_FROM_RIP_BYTE2 0x2d  /* third byte of opcode */
237
238extern natural get_mxcsr();
239extern void set_mxcsr(natural);
240
241#ifdef WINDOWS
242typedef struct {
243  HANDLE h;
244  OVERLAPPED *o;
245} pending_io;
246#endif
247
248#ifdef X8632
249/* The 32-bit immediate value in the instruction
250 * "(mov ($ 0x12345678) (% fn))" at a tagged return address
251 * refers to the associated function.
252 */
253#define RECOVER_FN_OPCODE 0xbf
254#define RECOVER_FN_LENGTH 5
255#endif
256
257#endif /* X86_EXCEPTIONS_H */
258
Note: See TracBrowser for help on using the repository browser.