4d1e4366584092fe6f8b4e02a2b8f7db7265cadd
[dragonfly.git] / lib / libcaps / i386 / td_switch_asm.S
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  * LWKT threads Copyright (c) 2003 Matthew Dillon
5  *
6  * This code is derived from software contributed to Berkeley by
7  * William Jolitz.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * $FreeBSD: src/sys/i386/i386/swtch.s,v 1.89.2.10 2003/01/23 03:36:24 ps Exp $
38  * $DragonFly: src/lib/libcaps/i386/td_switch_asm.S,v 1.2 2003/12/07 04:21:54 dillon Exp $
39  */
40
41 #include "asmacros.h"
42 #include "asdefs.h"
43
44         .text
45
46 /*
47  *  cpu_exit_switch()
48  *
49  *      The switch function is changed to this when a thread is going away
50  *      for good.  We have to ensure that the MMU state is not cached, and
51  *      we don't bother saving the existing thread state before switching.
52  *
53  *      At this point we are in a critical section and this cpu owns the
54  *      thread's token, which serves as an interlock until the switchout is
55  *      complete.
56  */
57 NON_GPROF_ENTRY(cpu_exit_switch)
58         /*
59          * Get us out of the vmspace
60          */
61         movl    PCPU(curthread),%ebx
62         /*
63          * Switch to the next thread.  RET into the restore function, which
64          * expects the new thread in EAX and the old in EBX.
65          *
66          * There is a one-instruction window where curthread is the new
67          * thread but %esp still points to the old thread's stack, but
68          * we are protected by a critical section so it is ok.
69          */
70         movl    4(%esp),%eax
71         movl    %eax,PCPU(curthread)
72         movl    TD_SP(%eax),%esp
73         ret
74
75 /*
76  * cpu_kthread_start() (current thread is %eax on entry) (one-time execution)
77  *
78  *      Run only on first function
79  */
80 NON_GPROF_ENTRY(cpu_kthread_start)
81         andl    $~TDF_RUNNING,TD_FLAGS(%ebx)
82         orl     $TDF_RUNNING,TD_FLAGS(%eax)
83         subl    $TDPRI_CRIT,TD_PRI(%eax)
84         /* call splz here? */
85         movl    $0,%eax
86         movl    %eax,%ebx
87         movl    %eax,%ecx
88         movl    %eax,%edx
89         movl    %eax,%esi
90         movl    %eax,%edi
91         movl    %eax,%ebp
92         ret
93
94 /*
95  * cpu_rfork_start().  The current thread is the idlethread.  We restore the
96  * idle thread which generally causes us to jump to cpu_kthraed_start.
97  */
98 NON_GPROF_ENTRY(cpu_rfork_start)
99         movl    PCPU(curthread),%eax
100         movl    %eax,%ebx
101         movl    TD_SP(%eax),%esp
102         ret
103
104 /*
105  * cpu_lwkt_switch()
106  *
107  *      Standard LWKT switching function.  Only non-scratch registers are
108  *      saved and we don't bother with the MMU state or anything else.
109  *
110  *      This function is always called while in a critical section.
111  *
112  *      There is a one-instruction window where curthread is the new
113  *      thread but %esp still points to the old thread's stack, but
114  *      we are protected by a critical section so it is ok.
115  *
116  *      YYY BGL, SPL
117  */
118 NON_GPROF_ENTRY(cpu_lwkt_switch)
119         movl    4(%esp),%eax
120         pushl   %ebp
121         pushl   %ebx
122         pushl   %esi
123         pushl   %edi
124         pushfl
125         movl    PCPU(curthread),%ebx
126         pushl   $cpu_lwkt_restore
127         movl    %esp,TD_SP(%ebx)
128         movl    %eax,PCPU(curthread)
129         movl    TD_SP(%eax),%esp
130
131         /*
132          * eax contains new thread, ebx contains old thread.
133          */
134         ret
135
136 /*
137  * cpu_lwkt_restore()   (current thread in %eax on entry)
138  *                      (old thread %ebx on entry)
139  *
140  *      Standard LWKT restore function.  This function is always called
141  *      while in a critical section.
142  *      
143  *      Warning: due to preemption the restore function can be used to 
144  *      'return' to the original thread.  Interrupt disablement must be
145  *      protected through the switch so we cannot run splz here.
146  *
147  *      YYY we theoretically do not need to load IdlePTD into cr3, but if
148  *      so we need a way to detect when the PTD we are using is being 
149  *      deleted due to a process exiting.
150  */
151 NON_GPROF_ENTRY(cpu_lwkt_restore)
152         andl    $~TDF_RUNNING,TD_FLAGS(%ebx)
153         orl     $TDF_RUNNING,TD_FLAGS(%eax)
154         popfl
155         popl    %edi
156         popl    %esi
157         popl    %ebx
158         popl    %ebp
159         ret
160
161 /*
162  * cpu_user_switch()
163  *
164  *      Standard USER switching function.  FP and non-scratch registers
165  *      are saved.
166  *
167  *      This function is always called while in a critical section.
168  *
169  *      There is a one-instruction window where curthread is the new
170  *      thread but %esp still points to the old thread's stack, but
171  *      we are protected by a critical section so it is ok.
172  *
173  *      YYY BGL, SPL
174  */
175 NON_GPROF_ENTRY(cpu_user_switch)
176         movl    4(%esp),%eax
177         pushl   %ebp
178         pushl   %ebx
179         pushl   %esi
180         pushl   %edi
181         pushfl
182         subl    $108,%esp
183         fnsave  0(%esp)
184         movl    PCPU(curthread),%ebx
185         pushl   $cpu_user_restore
186         movl    %esp,TD_SP(%ebx)
187         movl    %eax,PCPU(curthread)
188         movl    TD_SP(%eax),%esp
189
190         /*
191          * eax contains new thread, ebx contains old thread.
192          */
193         ret
194
195 /*
196  * cpu_user_restore()   (current thread in %eax on entry)
197  *
198  *      Standard LWKT restore function.  This function is always called
199  *      while in a critical section.
200  *      
201  *      Warning: due to preemption the restore function can be used to 
202  *      'return' to the original thread.  Interrupt disablement must be
203  *      protected through the switch so we cannot run splz here.
204  *
205  *      YYY we theoretically do not need to load IdlePTD into cr3, but if
206  *      so we need a way to detect when the PTD we are using is being 
207  *      deleted due to a process exiting.
208  */
209 NON_GPROF_ENTRY(cpu_user_restore)
210         andl    $~TDF_RUNNING,TD_FLAGS(%ebx)
211         orl     $TDF_RUNNING,TD_FLAGS(%eax)
212         frstor  0(%esp)
213         addl    $108,%esp
214         popfl
215         popl    %edi
216         popl    %esi
217         popl    %ebx
218         popl    %ebp
219         ret
220
221         .end