source: trunk/source/lisp-kernel/x86-asmutils64.s @ 11710

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

Try to handle the case of suspending a Windows thread that's in the
middle of restore_windows_context() more sanely/completely, especially
on win32.

Move the code that's concerned with this into a separate function
(pc_luser_restore_windows_context), which always overwrites some or
all of the context as of thread suspend with the context that the
suspended thread is trying to restore (e.g., whatever pc-lusering
we do always has the effect of causing the thread to resume at the
point where restore_windows_context() would have completed.

Since restore_windows_context() is only used to return from an
exception, clear tcr->pending_exception_context when we've got
things to a known point.

Define ia32_iret_frame in x86-constants32.h.

Use iret to restore flags/cs:eip on ia32.

Ensure that the last thing that win32_restore_context() does before
the iret is to reload %rcx/%ecx from the context (kept in %rcx/%ecx),
so suspending in the middle of restore_lisp_context() - before the iret -
just has to find the context being restored in %rcx/%ecx (it doesn't
matter where we are in the process of restoring it.)

If we're at the iret, just emulate the (machine-specific) effects of
the iret.

Need to make sure that this isn't grossly broken on win64, and need
to look at interrupt (vice suspend) code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/*   Copyright (C) 2005 Clozure Associates */
2/*   This file is part of OpenMCL.   */
3 
4/*   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public */
5/*   License , known as the LLGPL and distributed with OpenMCL as the */
6/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
7/*   which is distributed with OpenMCL as the file "LGPL".  Where these */
8/*   conflict, the preamble takes precedence.   */
9 
10/*   OpenMCL is referenced in the preamble as the "LIBRARY." */
11 
12/*   The LLGPL is also available online at */
13/*   http://opensource.franz.com/preamble.html */
14
15
16       
17
18        include(lisp.s)
19
20        _beginfile
21
22/* Flush %carg1 cache lines, starting at address in %carg0.  Each line is */
23/*   assumed to be %carg2 bytes wide. */
24_exportfn(C(flush_cache_lines))
25        __(cmpq $0,%carg1)
26        __(jmp 2f)
271:      __(clflush (%carg0))
28        __(addq %carg2,%carg0)
29        __(subq $1,%carg1)
302:      __(jg 1b)       
31        __(repret)
32_endfn
33
34_exportfn(C(current_stack_pointer))
35        __(movq %rsp,%cret)
36        __(ret)
37_endfn
38
39_exportfn(C(touch_page))
40        __(movq %carg0,(%carg0))
41        __(movq $0,(%carg0))
42        __(movl $1,%cret_l)
43        .globl C(touch_page_end)
44C(touch_page_end):     
45        __(ret)
46                       
47_exportfn(C(count_leading_zeros))
48        __(bsrq %carg0,%cret)
49        __(xorq $63,%cret)
50        __(ret)
51_endfn
52
53_exportfn(C(noop))
54        __(retq)
55_endfn
56
57_exportfn(C(set_mxcsr))
58        __(pushq %carg0)
59        __(ldmxcsr (%rsp))
60        __(addq $8,%rsp)
61        __(ret)
62_endfn
63       
64_exportfn(C(get_mxcsr))
65        __(pushq $0)
66        __(stmxcsr (%rsp))
67        __(popq %cret)
68        __(ret)
69_endfn
70
71_exportfn(C(save_fp_context))
72_endfn
73       
74_exportfn(C(restore_fp_context))
75_endfn                       
76
77/*  Atomically store new value (%carg2) in *%carg0, if old value == %carg1. */
78/*  Return actual old value. */
79_exportfn(C(store_conditional))
80        __(mov %carg1,%cret)
81        __(lock)
82        __(cmpxchgq %carg2,(%carg0))
83        __(cmovne %carg2,%cret)
84        __(ret)
85_endfn
86
87/*      Atomically store new_value(%carg1) in *%carg0 ;  return previous contents */
88/*      of *%carg0. */
89
90_exportfn(C(atomic_swap))
91        __(lock) 
92        __(xchg %carg1,(%carg0))
93        __(mov %carg1,%cret)
94        __(ret)
95_endfn
96
97/*        Logior the value in *%carg0 with the value in %carg1 (presumably a */
98/*      bitmask with exactly 1 bit set.)  Return non-zero if any of */
99/*      the bits in that bitmask were already set. */
100_exportfn(C(atomic_ior))
1010:      __(movq (%carg0),%cret)
102        __(movq %cret,%carg2)
103        __(orq %carg1,%carg2)
104        __(lock)
105        __(cmpxchg %carg2,(%carg0))
106        __(jnz 0b)
107        __(andq %carg1,%cret)
108        __(ret)
109_endfn
110       
111       
112/* Logand the value in *carg0 with the value in carg1 (presumably a bitmask with exactly 1 */
113/* bit set.)  Return the value now in *carg0 (for some value of "now" */
114
115_exportfn(C(atomic_and))
1160:      __(movq (%carg0),%cret)
117        __(movq %cret,%carg2)
118        __(and %carg1,%carg2)
119        __(lock)
120        __(cmpxchg %carg2,(%carg0))
121        __(jnz 0b)
122        __(movq %carg2,%cret)
123        __(ret)
124_endfn
125
126
127        __ifdef([DARWIN])
128_exportfn(C(pseudo_sigreturn))
129        __(hlt)
130        __(jmp C(pseudo_sigreturn))
131_endfn
132        __endif                       
133
134/* int cpuid (natural code, natural *pebx, natural *pecx, natural *pedx)  */
135_exportfn(C(cpuid))
136        __(pushq %carg2)
137        __(pushq %carg3)
138        __(movq %carg1, %ctemp0)
139        __(pushq %rbx)          /* non-volatile reg, clobbered by CPUID */
140        __(movq %carg0, %rax)
141        __(xorq %rcx,%rcx)
142        __(cpuid)
143        __(movq %rbx,(%ctemp0))
144        __(popq %rbx)
145        __(popq %ctemp0)           /* recover pedx */
146        __(movq %rdx,(%ctemp0))
147        __(popq %ctemp0)                /* recover pecx */
148        __(movq %rcx,(%ctemp0))
149        __(ret)
150_endfn
151
152/* switch_to_foreign_stack(new_sp, func, arg_0, arg_1, arg_2, arg_3)  */
153/*   Not fully general, but should get us off of the signal stack */
154        __ifndef([WINDOWS])
155_exportfn(C(switch_to_foreign_stack))
156        __(movq %rdi,%rsp)
157        __(movq %rsi,%rax)
158        __(movq %rdx,%rdi)
159        __(movq %rcx,%rsi)
160        __(movq %r8,%rdx)
161        __(movq %r9,%rcx)
162        __(jmp *%rax)
163_endfn
164        __endif
165       
166_exportfn(C(freebsd_sigreturn))
167        __(movl $417,%eax)      /* SYS_sigreturn */
168        __(syscall)                             
169_exportfn(C(get_vector_registers))
170_endfn
171
172        __ifdef([DARWIN])
173_exportfn(C(darwin_sigreturn))
174        .globl C(sigreturn)
175/* Need to set the sigreturn 'infostyle' argument, which is mostly
176   undocumented.  On x8664 Darwin, sigtramp() sets it to 0x1e, and
177   since we're trying to do what sigtramp() would do if we'd returned
178   to it ... */
179        __(movl $0x1e,%esi)
180        __(jmp C(sigreturn))
181_endfn
182        __endif
183
184_exportfn(C(put_vector_registers))
185_endfn                         
186       
187       
188        __ifdef([DARWIN_GS_HACK])
189/* Check (in an ugly, non-portable way) to see if %gs is addressing
190   pthreads data.  If it was, return 0; otherwise, assume that it's
191   addressing a lisp tcr and set %gs to point to the tcr's tcr.osid,
192   then return 1. */
193       
194thread_signature = 0x54485244 /* 'THRD' */
195       
196_exportfn(C(ensure_gs_pthread))
197        __(cmpl $thread_signature,%gs:0)
198        __(movl $0,%eax)
199        __(je 9f)
200        __(movq %gs:tcr.osid,%rdi)
201        __(movl $0x3000003,%eax)
202        __(syscall)
203        __(movl $1,%eax)
2049:      __(repret)
205_endfn
206
207        /* Ensure that %gs addresses the linear address in %rdi */
208        /* This incidentally returns the segment selector .*/
209_exportfn(C(set_gs_address))
210        __(movl $0x3000003,%eax)
211        __(syscall)
212        __(ret)
213_endfn
214        __endif
215
216        __ifdef([WIN_64])
217/* %rcx = CONTEXT, %rdx = tcr, %r8 = old_valence.  This pretty
218   much has to be uninterruptible */       
219_exportfn(C(restore_windows_context))
220Xrestore_windows_context_start:         
221        __(subq $0x38,%rsp)
222        __(xorl %eax,%eax)
223        __(movq %r8,tcr.valence(%rdx))
224        __(movq %rax,tcr.pending_exception_context(%rdx))
225        __(fxrstor win64_context.fpstate(%rcx))
226        __(movapd win64_context.Xmm0(%rcx),%xmm0)
227        __(movapd win64_context.Xmm1(%rcx),%xmm1)
228        __(movapd win64_context.Xmm2(%rcx),%xmm2)
229        __(movapd win64_context.Xmm3(%rcx),%xmm3)
230        __(movapd win64_context.Xmm4(%rcx),%xmm4)
231        __(movapd win64_context.Xmm5(%rcx),%xmm5)
232        __(movapd win64_context.Xmm6(%rcx),%xmm6)
233        __(movapd win64_context.Xmm7(%rcx),%xmm7)
234        __(movapd win64_context.Xmm8(%rcx),%xmm8)
235        __(movapd win64_context.Xmm9(%rcx),%xmm9)
236        __(movapd win64_context.Xmm10(%rcx),%xmm10)
237        __(movapd win64_context.Xmm11(%rcx),%xmm11)
238        __(movapd win64_context.Xmm12(%rcx),%xmm12)
239        __(movapd win64_context.Xmm13(%rcx),%xmm13)
240        __(movapd win64_context.Xmm14(%rcx),%xmm14)
241        __(movapd win64_context.Xmm15(%rcx),%xmm15)
242        __(ldmxcsr win64_context.MxCsr(%rcx))
243        __(movw win64_context.SegSs(%rcx),%ax)
244        __(movw %ax,0x20(%rsp))
245        __(movq win64_context.Rsp(%rcx),%rax)
246        __(movq %rax,0x18(%rsp))
247        __(movl win64_context.EFlags(%rcx),%eax)
248        __(movl %eax,0x10(%rsp))
249        __(movw win64_context.SegCs(%rcx),%ax)
250        __(movw %ax,8(%rsp))
251        __(movq win64_context.Rip(%rcx),%rax)
252        __(movq %rax,(%rsp))
253        __(movq win64_context.Rax(%rcx),%rax)
254        __(movq win64_context.Rbx(%rcx),%rbx)
255        __(movq win64_context.Rdx(%rcx),%rdx)
256        __(movq win64_context.Rdi(%rcx),%rdi)
257        __(movq win64_context.Rsi(%rcx),%rsi)
258        __(movq win64_context.Rbp(%rcx),%rbp)
259        __(movq win64_context.R8(%rcx),%r8)
260        __(movq win64_context.R9(%rcx),%r9)
261        __(movq win64_context.R10(%rcx),%r10)
262        __(movq win64_context.R11(%rcx),%r11)
263        __(movq win64_context.R12(%rcx),%r12)
264        __(movq win64_context.R13(%rcx),%r13)
265        __(movq win64_context.R14(%rcx),%r14)
266        __(movq win64_context.R15(%rcx),%r15)
267        /* This must be the last thing before the iret, e.g., if we're
268        interrupted before the iret, the context we're returning to here
269        is still in %rcx.  If we're interrupted -at- the iret, then
270        everything but that which the iret will restore has been restored. */
271        __(movq win64_context.Rcx(%rcx),%rcx)
272Xrestore_windows_context_iret:           
273        __(iretq)
274Xrestore_windows_context_end:             
275        __(nop)
276_endfn
277       
278_exportfn(C(windows_switch_to_foreign_stack))
279        __(pop %rax)
280        __(lea -0x20(%rcx),%rsp)
281        __(push %rax)
282        __(movq %r8,%rcx)
283        __(jmp *%rdx)
284_endfn       
285
286        .data
287        .globl C(restore_windows_context_start)
288        .globl C(restore_windows_context_end)
289        .globl C(restore_windows_context_iret)
290C(restore_windows_context_start):  .quad Xrestore_windows_context_start
291C(restore_windows_context_end): .quad Xrestore_windows_context_end
292C(restore_windows_context_iret): .quad Xrestore_windows_context_iret
293        .text
294
295/* Something that we shouldn't return to */
296_exportfn(C(windows_halt))
297        __(hlt)
298_endfn         
299_exportfn(C(ensure_safe_for_string_operations))
300        __(cld)
301        __(ret)
302_endfn                                       
303        __endif
304        _endfile
Note: See TracBrowser for help on using the repository browser.