Deleted Added
full compact
cpu_switch.S (72276) cpu_switch.S (72358)
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/sys/amd64/amd64/cpu_switch.S 72276 2001-02-10 02:20:34Z jhb $
36 * $FreeBSD: head/sys/amd64/amd64/cpu_switch.S 72358 2001-02-11 10:44:09Z markm $
37 */
38
39#include "opt_npx.h"
40#include "opt_user_ldt.h"
41
42#include <sys/rtprio.h>
43
44#include <machine/asmacros.h>
45#include <machine/ipl.h>
46
47#ifdef SMP
48#include <machine/pmap.h>
49#include <machine/apic.h>
50#include <machine/smptests.h> /** GRAB_LOPRIO */
37 */
38
39#include "opt_npx.h"
40#include "opt_user_ldt.h"
41
42#include <sys/rtprio.h>
43
44#include <machine/asmacros.h>
45#include <machine/ipl.h>
46
47#ifdef SMP
48#include <machine/pmap.h>
49#include <machine/apic.h>
50#include <machine/smptests.h> /** GRAB_LOPRIO */
51#include <machine/lock.h>
52#endif /* SMP */
53
54#include "assym.s"
55
56
57/*****************************************************************************/
58/* Scheduling */
59/*****************************************************************************/
60
61 .data
62
63 .globl _panic
64
65#if defined(SWTCH_OPTIM_STATS)
66 .globl _swtch_optim_stats, _tlb_flush_count
67_swtch_optim_stats: .long 0 /* number of _swtch_optims */
68_tlb_flush_count: .long 0
69#endif
70
71 .text
72
73/*
74 * cpu_throw()
75 */
76ENTRY(cpu_throw)
77 jmp sw1
78
79/*
80 * cpu_switch()
81 */
82ENTRY(cpu_switch)
83
84 /* switch to new process. first, save context as needed */
85 movl PCPU(CURPROC),%ecx
86
87 /* if no process to save, don't bother */
88 testl %ecx,%ecx
89 jz sw1
90
91#ifdef SMP
92 movb P_ONCPU(%ecx), %al /* save "last" cpu */
93 movb %al, P_LASTCPU(%ecx)
94 movb $0xff, P_ONCPU(%ecx) /* "leave" the cpu */
95#endif /* SMP */
96 movl P_VMSPACE(%ecx), %edx
97#ifdef SMP
98 movl PCPU(CPUID), %eax
99#else
100 xorl %eax, %eax
101#endif /* SMP */
102 btrl %eax, VM_PMAP+PM_ACTIVE(%edx)
103
104 movl P_ADDR(%ecx),%edx
105
106 movl (%esp),%eax /* Hardware registers */
107 movl %eax,PCB_EIP(%edx)
108 movl %ebx,PCB_EBX(%edx)
109 movl %esp,PCB_ESP(%edx)
110 movl %ebp,PCB_EBP(%edx)
111 movl %esi,PCB_ESI(%edx)
112 movl %edi,PCB_EDI(%edx)
113 movl %gs,PCB_GS(%edx)
114
115 /* test if debug registers should be saved */
116 movb PCB_FLAGS(%edx),%al
117 andb $PCB_DBREGS,%al
118 jz 1f /* no, skip over */
119 movl %dr7,%eax /* yes, do the save */
120 movl %eax,PCB_DR7(%edx)
121 andl $0x0000ff00, %eax /* disable all watchpoints */
122 movl %eax,%dr7
123 movl %dr6,%eax
124 movl %eax,PCB_DR6(%edx)
125 movl %dr3,%eax
126 movl %eax,PCB_DR3(%edx)
127 movl %dr2,%eax
128 movl %eax,PCB_DR2(%edx)
129 movl %dr1,%eax
130 movl %eax,PCB_DR1(%edx)
131 movl %dr0,%eax
132 movl %eax,PCB_DR0(%edx)
1331:
134
135 /* save sched_lock recursion count */
136 movl _sched_lock+MTX_RECURSECNT,%eax
137 movl %eax,PCB_SCHEDNEST(%edx)
138
139#ifdef SMP
140 /* XXX FIXME: we should be saving the local APIC TPR */
141#endif /* SMP */
142
143#ifdef DEV_NPX
144 /* have we used fp, and need a save? */
145 cmpl %ecx,PCPU(NPXPROC)
146 jne 1f
147 addl $PCB_SAVEFPU,%edx /* h/w bugs make saving complicated */
148 pushl %edx
149 call _npxsave /* do it in a big C function */
150 popl %eax
1511:
152#endif /* DEV_NPX */
153
154 /* save is done, now choose a new process */
155sw1:
156
157#ifdef SMP
158 /* Stop scheduling if smp_active goes zero and we are not BSP */
159 cmpl $0,_smp_active
160 jne 1f
161 cmpl $0,PCPU(CPUID)
162 je 1f
163
164 movl PCPU(IDLEPROC), %eax
165 jmp sw1b
1661:
167#endif
168
169 /*
170 * Choose a new process to schedule. chooseproc() returns idleproc
171 * if it cannot find another process to run.
172 */
173sw1a:
174 call _chooseproc /* trash ecx, edx, ret eax*/
175
176#ifdef INVARIANTS
177 testl %eax,%eax /* no process? */
178 jz badsw3 /* no, panic */
179#endif
180sw1b:
181 movl %eax,%ecx
182
183#ifdef INVARIANTS
184 cmpb $SRUN,P_STAT(%ecx)
185 jne badsw2
186#endif
187
188 movl P_ADDR(%ecx),%edx
189
190#if defined(SWTCH_OPTIM_STATS)
191 incl _swtch_optim_stats
192#endif
193 /* switch address space */
194 movl %cr3,%ebx
195 cmpl PCB_CR3(%edx),%ebx
196 je 4f
197#if defined(SWTCH_OPTIM_STATS)
198 decl _swtch_optim_stats
199 incl _tlb_flush_count
200#endif
201 movl PCB_CR3(%edx),%ebx
202 movl %ebx,%cr3
2034:
204
205#ifdef SMP
206 movl PCPU(CPUID), %esi
207#else
208 xorl %esi, %esi
209#endif
210 cmpl $0, PCB_EXT(%edx) /* has pcb extension? */
211 je 1f
212 btsl %esi, _private_tss /* mark use of private tss */
213 movl PCB_EXT(%edx), %edi /* new tss descriptor */
214 jmp 2f
2151:
216
217 /* update common_tss.tss_esp0 pointer */
218 movl %edx, %ebx /* pcb */
219 addl $(UPAGES * PAGE_SIZE - 16), %ebx
220 movl %ebx, PCPU(COMMON_TSS) + TSS_ESP0
221
222 btrl %esi, _private_tss
223 jae 3f
224 PCPU_ADDR(COMMON_TSSD, %edi)
2252:
226 /* move correct tss descriptor into GDT slot, then reload tr */
227 movl PCPU(TSS_GDT), %ebx /* entry in GDT */
228 movl 0(%edi), %eax
229 movl %eax, 0(%ebx)
230 movl 4(%edi), %eax
231 movl %eax, 4(%ebx)
232 movl $GPROC0_SEL*8, %esi /* GSEL(entry, SEL_KPL) */
233 ltr %si
2343:
235 movl P_VMSPACE(%ecx), %ebx
236#ifdef SMP
237 movl PCPU(CPUID), %eax
238#else
239 xorl %eax, %eax
240#endif
241 btsl %eax, VM_PMAP+PM_ACTIVE(%ebx)
242
243 /* restore context */
244 movl PCB_EBX(%edx),%ebx
245 movl PCB_ESP(%edx),%esp
246 movl PCB_EBP(%edx),%ebp
247 movl PCB_ESI(%edx),%esi
248 movl PCB_EDI(%edx),%edi
249 movl PCB_EIP(%edx),%eax
250 movl %eax,(%esp)
251
252#ifdef SMP
253#ifdef GRAB_LOPRIO /* hold LOPRIO for INTs */
254#ifdef CHEAP_TPR
255 movl $0, _lapic+LA_TPR
256#else
257 andl $~APIC_TPR_PRIO, _lapic+LA_TPR
258#endif /** CHEAP_TPR */
259#endif /** GRAB_LOPRIO */
260 movl PCPU(CPUID),%eax
261 movb %al, P_ONCPU(%ecx)
262#endif /* SMP */
263 movl %edx, PCPU(CURPCB)
264 movl %ecx, PCPU(CURPROC) /* into next process */
265
266#ifdef SMP
267 /* XXX FIXME: we should be restoring the local APIC TPR */
268#endif /* SMP */
269
270#ifdef USER_LDT
271 cmpl $0, PCB_USERLDT(%edx)
272 jnz 1f
273 movl __default_ldt,%eax
274 cmpl PCPU(CURRENTLDT),%eax
275 je 2f
276 lldt __default_ldt
277 movl %eax,PCPU(CURRENTLDT)
278 jmp 2f
2791: pushl %edx
280 call _set_user_ldt
281 popl %edx
2822:
283#endif
284
285 /* This must be done after loading the user LDT. */
286 .globl cpu_switch_load_gs
287cpu_switch_load_gs:
288 movl PCB_GS(%edx),%gs
289
290 /* test if debug regisers should be restored */
291 movb PCB_FLAGS(%edx),%al
292 andb $PCB_DBREGS,%al
293 jz 1f /* no, skip over */
294 movl PCB_DR6(%edx),%eax /* yes, do the restore */
295 movl %eax,%dr6
296 movl PCB_DR3(%edx),%eax
297 movl %eax,%dr3
298 movl PCB_DR2(%edx),%eax
299 movl %eax,%dr2
300 movl PCB_DR1(%edx),%eax
301 movl %eax,%dr1
302 movl PCB_DR0(%edx),%eax
303 movl %eax,%dr0
304 movl PCB_DR7(%edx),%eax
305 movl %eax,%dr7
3061:
307
308 /*
309 * restore sched_lock recursion count and transfer ownership to
310 * new process
311 */
312 movl PCB_SCHEDNEST(%edx),%eax
313 movl %eax,_sched_lock+MTX_RECURSECNT
314
315 movl PCPU(CURPROC),%eax
316 movl %eax,_sched_lock+MTX_LOCK
317
318 ret
319
320CROSSJUMPTARGET(sw1a)
321
322#ifdef INVARIANTS
323badsw2:
324 pushl $sw0_2
325 call _panic
326
327sw0_2: .asciz "cpu_switch: not SRUN"
328
329badsw3:
330 pushl $sw0_3
331 call _panic
332
333sw0_3: .asciz "cpu_switch: chooseproc returned NULL"
334#endif
335
336/*
337 * savectx(pcb)
338 * Update pcb, saving current processor state.
339 */
340ENTRY(savectx)
341 /* fetch PCB */
342 movl 4(%esp),%ecx
343
344 /* caller's return address - child won't execute this routine */
345 movl (%esp),%eax
346 movl %eax,PCB_EIP(%ecx)
347
348 movl %cr3,%eax
349 movl %eax,PCB_CR3(%ecx)
350
351 movl %ebx,PCB_EBX(%ecx)
352 movl %esp,PCB_ESP(%ecx)
353 movl %ebp,PCB_EBP(%ecx)
354 movl %esi,PCB_ESI(%ecx)
355 movl %edi,PCB_EDI(%ecx)
356 movl %gs,PCB_GS(%ecx)
357
358#ifdef DEV_NPX
359 /*
360 * If npxproc == NULL, then the npx h/w state is irrelevant and the
361 * state had better already be in the pcb. This is true for forks
362 * but not for dumps (the old book-keeping with FP flags in the pcb
363 * always lost for dumps because the dump pcb has 0 flags).
364 *
365 * If npxproc != NULL, then we have to save the npx h/w state to
366 * npxproc's pcb and copy it to the requested pcb, or save to the
367 * requested pcb and reload. Copying is easier because we would
368 * have to handle h/w bugs for reloading. We used to lose the
369 * parent's npx state for forks by forgetting to reload.
370 */
371 movl PCPU(NPXPROC),%eax
372 testl %eax,%eax
373 je 1f
374
375 pushl %ecx
376 movl P_ADDR(%eax),%eax
377 leal PCB_SAVEFPU(%eax),%eax
378 pushl %eax
379 pushl %eax
380 call _npxsave
381 addl $4,%esp
382 popl %eax
383 popl %ecx
384
385 pushl $PCB_SAVEFPU_SIZE
386 leal PCB_SAVEFPU(%ecx),%ecx
387 pushl %ecx
388 pushl %eax
389 call _bcopy
390 addl $12,%esp
391#endif /* DEV_NPX */
392
3931:
394 ret
51#endif /* SMP */
52
53#include "assym.s"
54
55
56/*****************************************************************************/
57/* Scheduling */
58/*****************************************************************************/
59
60 .data
61
62 .globl _panic
63
64#if defined(SWTCH_OPTIM_STATS)
65 .globl _swtch_optim_stats, _tlb_flush_count
66_swtch_optim_stats: .long 0 /* number of _swtch_optims */
67_tlb_flush_count: .long 0
68#endif
69
70 .text
71
72/*
73 * cpu_throw()
74 */
75ENTRY(cpu_throw)
76 jmp sw1
77
78/*
79 * cpu_switch()
80 */
81ENTRY(cpu_switch)
82
83 /* switch to new process. first, save context as needed */
84 movl PCPU(CURPROC),%ecx
85
86 /* if no process to save, don't bother */
87 testl %ecx,%ecx
88 jz sw1
89
90#ifdef SMP
91 movb P_ONCPU(%ecx), %al /* save "last" cpu */
92 movb %al, P_LASTCPU(%ecx)
93 movb $0xff, P_ONCPU(%ecx) /* "leave" the cpu */
94#endif /* SMP */
95 movl P_VMSPACE(%ecx), %edx
96#ifdef SMP
97 movl PCPU(CPUID), %eax
98#else
99 xorl %eax, %eax
100#endif /* SMP */
101 btrl %eax, VM_PMAP+PM_ACTIVE(%edx)
102
103 movl P_ADDR(%ecx),%edx
104
105 movl (%esp),%eax /* Hardware registers */
106 movl %eax,PCB_EIP(%edx)
107 movl %ebx,PCB_EBX(%edx)
108 movl %esp,PCB_ESP(%edx)
109 movl %ebp,PCB_EBP(%edx)
110 movl %esi,PCB_ESI(%edx)
111 movl %edi,PCB_EDI(%edx)
112 movl %gs,PCB_GS(%edx)
113
114 /* test if debug registers should be saved */
115 movb PCB_FLAGS(%edx),%al
116 andb $PCB_DBREGS,%al
117 jz 1f /* no, skip over */
118 movl %dr7,%eax /* yes, do the save */
119 movl %eax,PCB_DR7(%edx)
120 andl $0x0000ff00, %eax /* disable all watchpoints */
121 movl %eax,%dr7
122 movl %dr6,%eax
123 movl %eax,PCB_DR6(%edx)
124 movl %dr3,%eax
125 movl %eax,PCB_DR3(%edx)
126 movl %dr2,%eax
127 movl %eax,PCB_DR2(%edx)
128 movl %dr1,%eax
129 movl %eax,PCB_DR1(%edx)
130 movl %dr0,%eax
131 movl %eax,PCB_DR0(%edx)
1321:
133
134 /* save sched_lock recursion count */
135 movl _sched_lock+MTX_RECURSECNT,%eax
136 movl %eax,PCB_SCHEDNEST(%edx)
137
138#ifdef SMP
139 /* XXX FIXME: we should be saving the local APIC TPR */
140#endif /* SMP */
141
142#ifdef DEV_NPX
143 /* have we used fp, and need a save? */
144 cmpl %ecx,PCPU(NPXPROC)
145 jne 1f
146 addl $PCB_SAVEFPU,%edx /* h/w bugs make saving complicated */
147 pushl %edx
148 call _npxsave /* do it in a big C function */
149 popl %eax
1501:
151#endif /* DEV_NPX */
152
153 /* save is done, now choose a new process */
154sw1:
155
156#ifdef SMP
157 /* Stop scheduling if smp_active goes zero and we are not BSP */
158 cmpl $0,_smp_active
159 jne 1f
160 cmpl $0,PCPU(CPUID)
161 je 1f
162
163 movl PCPU(IDLEPROC), %eax
164 jmp sw1b
1651:
166#endif
167
168 /*
169 * Choose a new process to schedule. chooseproc() returns idleproc
170 * if it cannot find another process to run.
171 */
172sw1a:
173 call _chooseproc /* trash ecx, edx, ret eax*/
174
175#ifdef INVARIANTS
176 testl %eax,%eax /* no process? */
177 jz badsw3 /* no, panic */
178#endif
179sw1b:
180 movl %eax,%ecx
181
182#ifdef INVARIANTS
183 cmpb $SRUN,P_STAT(%ecx)
184 jne badsw2
185#endif
186
187 movl P_ADDR(%ecx),%edx
188
189#if defined(SWTCH_OPTIM_STATS)
190 incl _swtch_optim_stats
191#endif
192 /* switch address space */
193 movl %cr3,%ebx
194 cmpl PCB_CR3(%edx),%ebx
195 je 4f
196#if defined(SWTCH_OPTIM_STATS)
197 decl _swtch_optim_stats
198 incl _tlb_flush_count
199#endif
200 movl PCB_CR3(%edx),%ebx
201 movl %ebx,%cr3
2024:
203
204#ifdef SMP
205 movl PCPU(CPUID), %esi
206#else
207 xorl %esi, %esi
208#endif
209 cmpl $0, PCB_EXT(%edx) /* has pcb extension? */
210 je 1f
211 btsl %esi, _private_tss /* mark use of private tss */
212 movl PCB_EXT(%edx), %edi /* new tss descriptor */
213 jmp 2f
2141:
215
216 /* update common_tss.tss_esp0 pointer */
217 movl %edx, %ebx /* pcb */
218 addl $(UPAGES * PAGE_SIZE - 16), %ebx
219 movl %ebx, PCPU(COMMON_TSS) + TSS_ESP0
220
221 btrl %esi, _private_tss
222 jae 3f
223 PCPU_ADDR(COMMON_TSSD, %edi)
2242:
225 /* move correct tss descriptor into GDT slot, then reload tr */
226 movl PCPU(TSS_GDT), %ebx /* entry in GDT */
227 movl 0(%edi), %eax
228 movl %eax, 0(%ebx)
229 movl 4(%edi), %eax
230 movl %eax, 4(%ebx)
231 movl $GPROC0_SEL*8, %esi /* GSEL(entry, SEL_KPL) */
232 ltr %si
2333:
234 movl P_VMSPACE(%ecx), %ebx
235#ifdef SMP
236 movl PCPU(CPUID), %eax
237#else
238 xorl %eax, %eax
239#endif
240 btsl %eax, VM_PMAP+PM_ACTIVE(%ebx)
241
242 /* restore context */
243 movl PCB_EBX(%edx),%ebx
244 movl PCB_ESP(%edx),%esp
245 movl PCB_EBP(%edx),%ebp
246 movl PCB_ESI(%edx),%esi
247 movl PCB_EDI(%edx),%edi
248 movl PCB_EIP(%edx),%eax
249 movl %eax,(%esp)
250
251#ifdef SMP
252#ifdef GRAB_LOPRIO /* hold LOPRIO for INTs */
253#ifdef CHEAP_TPR
254 movl $0, _lapic+LA_TPR
255#else
256 andl $~APIC_TPR_PRIO, _lapic+LA_TPR
257#endif /** CHEAP_TPR */
258#endif /** GRAB_LOPRIO */
259 movl PCPU(CPUID),%eax
260 movb %al, P_ONCPU(%ecx)
261#endif /* SMP */
262 movl %edx, PCPU(CURPCB)
263 movl %ecx, PCPU(CURPROC) /* into next process */
264
265#ifdef SMP
266 /* XXX FIXME: we should be restoring the local APIC TPR */
267#endif /* SMP */
268
269#ifdef USER_LDT
270 cmpl $0, PCB_USERLDT(%edx)
271 jnz 1f
272 movl __default_ldt,%eax
273 cmpl PCPU(CURRENTLDT),%eax
274 je 2f
275 lldt __default_ldt
276 movl %eax,PCPU(CURRENTLDT)
277 jmp 2f
2781: pushl %edx
279 call _set_user_ldt
280 popl %edx
2812:
282#endif
283
284 /* This must be done after loading the user LDT. */
285 .globl cpu_switch_load_gs
286cpu_switch_load_gs:
287 movl PCB_GS(%edx),%gs
288
289 /* test if debug regisers should be restored */
290 movb PCB_FLAGS(%edx),%al
291 andb $PCB_DBREGS,%al
292 jz 1f /* no, skip over */
293 movl PCB_DR6(%edx),%eax /* yes, do the restore */
294 movl %eax,%dr6
295 movl PCB_DR3(%edx),%eax
296 movl %eax,%dr3
297 movl PCB_DR2(%edx),%eax
298 movl %eax,%dr2
299 movl PCB_DR1(%edx),%eax
300 movl %eax,%dr1
301 movl PCB_DR0(%edx),%eax
302 movl %eax,%dr0
303 movl PCB_DR7(%edx),%eax
304 movl %eax,%dr7
3051:
306
307 /*
308 * restore sched_lock recursion count and transfer ownership to
309 * new process
310 */
311 movl PCB_SCHEDNEST(%edx),%eax
312 movl %eax,_sched_lock+MTX_RECURSECNT
313
314 movl PCPU(CURPROC),%eax
315 movl %eax,_sched_lock+MTX_LOCK
316
317 ret
318
319CROSSJUMPTARGET(sw1a)
320
321#ifdef INVARIANTS
322badsw2:
323 pushl $sw0_2
324 call _panic
325
326sw0_2: .asciz "cpu_switch: not SRUN"
327
328badsw3:
329 pushl $sw0_3
330 call _panic
331
332sw0_3: .asciz "cpu_switch: chooseproc returned NULL"
333#endif
334
335/*
336 * savectx(pcb)
337 * Update pcb, saving current processor state.
338 */
339ENTRY(savectx)
340 /* fetch PCB */
341 movl 4(%esp),%ecx
342
343 /* caller's return address - child won't execute this routine */
344 movl (%esp),%eax
345 movl %eax,PCB_EIP(%ecx)
346
347 movl %cr3,%eax
348 movl %eax,PCB_CR3(%ecx)
349
350 movl %ebx,PCB_EBX(%ecx)
351 movl %esp,PCB_ESP(%ecx)
352 movl %ebp,PCB_EBP(%ecx)
353 movl %esi,PCB_ESI(%ecx)
354 movl %edi,PCB_EDI(%ecx)
355 movl %gs,PCB_GS(%ecx)
356
357#ifdef DEV_NPX
358 /*
359 * If npxproc == NULL, then the npx h/w state is irrelevant and the
360 * state had better already be in the pcb. This is true for forks
361 * but not for dumps (the old book-keeping with FP flags in the pcb
362 * always lost for dumps because the dump pcb has 0 flags).
363 *
364 * If npxproc != NULL, then we have to save the npx h/w state to
365 * npxproc's pcb and copy it to the requested pcb, or save to the
366 * requested pcb and reload. Copying is easier because we would
367 * have to handle h/w bugs for reloading. We used to lose the
368 * parent's npx state for forks by forgetting to reload.
369 */
370 movl PCPU(NPXPROC),%eax
371 testl %eax,%eax
372 je 1f
373
374 pushl %ecx
375 movl P_ADDR(%eax),%eax
376 leal PCB_SAVEFPU(%eax),%eax
377 pushl %eax
378 pushl %eax
379 call _npxsave
380 addl $4,%esp
381 popl %eax
382 popl %ecx
383
384 pushl $PCB_SAVEFPU_SIZE
385 leal PCB_SAVEFPU(%ecx),%ecx
386 pushl %ecx
387 pushl %eax
388 call _bcopy
389 addl $12,%esp
390#endif /* DEV_NPX */
391
3921:
393 ret