FreeBSD/Linux Kernel Cross Reference
sys/i386/cswitch.s
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: cswitch.s,v $
29 * Revision 2.13 93/02/04 07:55:51 danner
30 * Convert asm comment "/" over to "/ *" "* /"
31 * [93/01/27 rvb]
32 *
33 * Revision 2.12 92/01/03 20:04:43 dbg
34 * Floating-point state is now saved by caller.
35 * [91/10/20 dbg]
36 *
37 * Revision 2.11 91/07/31 17:34:56 dbg
38 * Push user state directly in PCB and switch to kernel stack on
39 * trap entry.
40 * [91/07/30 16:48:18 dbg]
41 *
42 * Revision 2.10 91/06/19 11:54:57 rvb
43 * cputypes.h->platforms.h
44 * [91/06/12 13:44:37 rvb]
45 *
46 * Revision 2.9 91/05/14 16:04:42 mrt
47 * Correcting copyright
48 *
49 * Revision 2.8 91/05/08 12:31:19 dbg
50 * Put parentheses around substituted immediate expressions, so
51 * that they will pass through the GNU preprocessor.
52 *
53 * Handle multiple CPUs. Save floating-point state when saving
54 * context or switching stacks. Add switch_to_shutdown_context to
55 * handle CPU shutdown.
56 * [91/03/21 dbg]
57 *
58 * Revision 2.7 91/03/16 14:43:51 rpd
59 * Renamed Switch_task_context to Switch_context.
60 * [91/02/17 rpd]
61 * Added active_stacks.
62 * [91/01/29 rpd]
63 *
64 * Revision 2.6 91/02/05 17:10:57 mrt
65 * Changed to new Mach copyright
66 * [91/02/01 17:30:50 mrt]
67 *
68 * Revision 2.5 91/01/09 22:41:09 rpd
69 * Renamed to Load_context and Switch_task_context.
70 * Removed ktss munging.
71 * [91/01/09 rpd]
72 *
73 * Revision 2.4 91/01/08 15:10:09 rpd
74 * Minor cleanup.
75 * [90/12/31 rpd]
76 * Added switch_task_context, switch_thread_context.
77 * [90/12/12 rpd]
78 *
79 * Reorganized the pcb.
80 * [90/12/11 rpd]
81 *
82 * Revision 2.3 90/12/20 16:35:48 jeffreyh
83 * Changes for __STDC__
84 *
85 * Changes for __STDC__
86 * [90/12/07 15:45:37 jeffreyh]
87 *
88 *
89 * Revision 2.2 90/05/03 15:25:00 dbg
90 * Created.
91 * [90/02/08 dbg]
92 *
93 */
94
95 #include <cpus.h>
96 #include <platforms.h>
97
98 #include <i386/asm.h>
99 #include <i386/proc_reg.h>
100 #include <assym.s>
101
102 #if NCPUS > 1
103
104 #ifdef SYMMETRY
105 #include <sqt/asm_macros.h>
106 #endif
107
108 #define CX(addr, reg) addr(,reg,4)
109
110 #else /* NCPUS == 1 */
111
112 #define CPU_NUMBER(reg)
113 #define CX(addr,reg) addr
114
115 #endif /* NCPUS == 1 */
116
117 /*
118 * Context switch routines for i386.
119 */
120
121 ENTRY(Load_context)
122 movl S_ARG0,%ecx /* get thread */
123 movl TH_KERNEL_STACK(%ecx),%ecx /* get kernel stack */
124 lea KERNEL_STACK_SIZE-IKS_SIZE-IEL_SIZE(%ecx),%edx
125 /* point to stack top */
126 CPU_NUMBER(%eax)
127 movl %ecx,CX(_active_stacks,%eax) /* store stack address */
128 movl %edx,CX(_kernel_stack,%eax) /* store stack top */
129
130 movl KSS_ESP(%ecx),%esp /* switch stacks */
131 movl KSS_ESI(%ecx),%esi /* restore registers */
132 movl KSS_EDI(%ecx),%edi
133 movl KSS_EBP(%ecx),%ebp
134 movl KSS_EBX(%ecx),%ebx
135 xorl %eax,%eax /* return zero (no old thread) */
136 jmp *KSS_EIP(%ecx) /* resume thread */
137
138 /*
139 * This really only has to save registers
140 * when there is no explicit continuation.
141 */
142
143 ENTRY(Switch_context)
144 CPU_NUMBER(%edx)
145 movl CX(_active_stacks,%edx),%ecx /* get old kernel stack */
146
147 movl %ebx,KSS_EBX(%ecx) /* save registers */
148 movl %ebp,KSS_EBP(%ecx)
149 movl %edi,KSS_EDI(%ecx)
150 movl %esi,KSS_ESI(%ecx)
151 popl KSS_EIP(%ecx) /* save return PC */
152 movl %esp,KSS_ESP(%ecx) /* save SP */
153
154 movl 0(%esp),%eax /* get old thread */
155 movl %ecx,TH_KERNEL_STACK(%eax) /* save old stack */
156 movl 4(%esp),%ebx /* get continuation */
157 movl %ebx,TH_SWAP_FUNC(%eax) /* save continuation */
158
159 movl 8(%esp),%esi /* get new thread */
160
161 movl TH_KERNEL_STACK(%esi),%ecx /* get its kernel stack */
162 lea KERNEL_STACK_SIZE-IKS_SIZE-IEL_SIZE(%ecx),%ebx
163 /* point to stack top */
164
165 movl %esi,CX(_active_threads,%edx) /* new thread is active */
166 movl %ecx,CX(_active_stacks,%edx) /* set current stack */
167 movl %ebx,CX(_kernel_stack,%edx) /* set stack top */
168
169 movl KSS_ESP(%ecx),%esp /* switch stacks */
170 movl KSS_ESI(%ecx),%esi /* restore registers */
171 movl KSS_EDI(%ecx),%edi
172 movl KSS_EBP(%ecx),%ebp
173 movl KSS_EBX(%ecx),%ebx
174 jmp *KSS_EIP(%ecx) /* return old thread */
175
176 ENTRY(Thread_continue)
177 pushl %eax /* push the thread argument */
178 xorl %ebp,%ebp /* zero frame pointer */
179 call *%ebx /* call real continuation */
180
181 #if NCPUS > 1
182 /*
183 * void switch_to_shutdown_context(thread_t thread,
184 * void (*routine)(processor_t),
185 * processor_t processor)
186 *
187 * saves the kernel context of the thread,
188 * switches to the interrupt stack,
189 * continues the thread (with thread_continue),
190 * then runs routine on the interrupt stack.
191 *
192 * Assumes that the thread is a kernel thread (thus
193 * has no FPU state)
194 */
195 ENTRY(switch_to_shutdown_context)
196 CPU_NUMBER(%edx)
197 movl _active_stacks(,%edx,4),%ecx /* get old kernel stack */
198 movl %ebx,KSS_EBX(%ecx) /* save registers */
199 movl %ebp,KSS_EBP(%ecx)
200 movl %edi,KSS_EDI(%ecx)
201 movl %esi,KSS_ESI(%ecx)
202 popl KSS_EIP(%ecx) /* save return PC */
203 movl %esp,KSS_ESP(%ecx) /* save SP */
204
205 movl 0(%esp),%eax /* get old thread */
206 movl %ecx,TH_KERNEL_STACK(%eax) /* save old stack */
207 movl $0,TH_SWAP_FUNC(%eax) /* clear continuation */
208 movl 4(%esp),%ebx /* get routine to run next */
209 movl 8(%esp),%esi /* get its argument */
210
211 movl _interrupt_stack(,%edx,4),%ecx /* point to its interrupt stack */
212 lea INTSTACK_SIZE(%ecx),%esp /* switch to it (top) */
213
214 pushl %eax /* push thread */
215 call EXT(thread_dispatch) /* reschedule thread */
216 addl $4,%esp /* clean stack */
217
218 pushl %esi /* push argument */
219 call *%ebx /* call routine to run */
220 hlt /* (should never return) */
221
222 #endif NCPUS > 1
223
Cache object: 50a8201c7728c0bf58753f445062706b
|