thread stage 3: create independant thread structure, unembed from proc.
[dragonfly.git] / sys / platform / pc32 / i386 / support.s
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: src/sys/i386/i386/support.s,v 1.67.2.5 2001/08/15 01:23:50 peter Exp $
af0bff84 34 * $DragonFly: src/sys/platform/pc32/i386/support.s,v 1.4 2003/06/18 07:04:25 dillon Exp $
984263bc
MD
35 */
36
37#include "npx.h"
38
39#include <machine/asmacros.h>
40#include <machine/cputypes.h>
41#include <machine/pmap.h>
42#include <machine/specialreg.h>
43
44#include "assym.s"
45
46#define IDXSHIFT 10
47
48 .data
49 .globl _bcopy_vector
50_bcopy_vector:
51 .long _generic_bcopy
52 .globl _bzero
53_bzero:
54 .long _generic_bzero
55 .globl _copyin_vector
56_copyin_vector:
57 .long _generic_copyin
58 .globl _copyout_vector
59_copyout_vector:
60 .long _generic_copyout
61 .globl _ovbcopy_vector
62_ovbcopy_vector:
63 .long _generic_bcopy
64#if defined(I586_CPU) && NNPX > 0
65kernel_fpu_lock:
66 .byte 0xfe
67 .space 3
68#endif
69
70 .text
71
72/*
73 * bcopy family
74 * void bzero(void *buf, u_int len)
75 */
76
77ENTRY(generic_bzero)
78 pushl %edi
79 movl 8(%esp),%edi
80 movl 12(%esp),%ecx
81 xorl %eax,%eax
82 shrl $2,%ecx
83 cld
84 rep
85 stosl
86 movl 12(%esp),%ecx
87 andl $3,%ecx
88 rep
89 stosb
90 popl %edi
91 ret
92
93#if defined(I486_CPU)
94ENTRY(i486_bzero)
95 movl 4(%esp),%edx
96 movl 8(%esp),%ecx
97 xorl %eax,%eax
98/*
99 * do 64 byte chunks first
100 *
101 * XXX this is probably over-unrolled at least for DX2's
102 */
1032:
104 cmpl $64,%ecx
105 jb 3f
106 movl %eax,(%edx)
107 movl %eax,4(%edx)
108 movl %eax,8(%edx)
109 movl %eax,12(%edx)
110 movl %eax,16(%edx)
111 movl %eax,20(%edx)
112 movl %eax,24(%edx)
113 movl %eax,28(%edx)
114 movl %eax,32(%edx)
115 movl %eax,36(%edx)
116 movl %eax,40(%edx)
117 movl %eax,44(%edx)
118 movl %eax,48(%edx)
119 movl %eax,52(%edx)
120 movl %eax,56(%edx)
121 movl %eax,60(%edx)
122 addl $64,%edx
123 subl $64,%ecx
124 jnz 2b
125 ret
126
127/*
128 * do 16 byte chunks
129 */
130 SUPERALIGN_TEXT
1313:
132 cmpl $16,%ecx
133 jb 4f
134 movl %eax,(%edx)
135 movl %eax,4(%edx)
136 movl %eax,8(%edx)
137 movl %eax,12(%edx)
138 addl $16,%edx
139 subl $16,%ecx
140 jnz 3b
141 ret
142
143/*
144 * do 4 byte chunks
145 */
146 SUPERALIGN_TEXT
1474:
148 cmpl $4,%ecx
149 jb 5f
150 movl %eax,(%edx)
151 addl $4,%edx
152 subl $4,%ecx
153 jnz 4b
154 ret
155
156/*
157 * do 1 byte chunks
158 * a jump table seems to be faster than a loop or more range reductions
159 *
160 * XXX need a const section for non-text
161 */
162 .data
163jtab:
164 .long do0
165 .long do1
166 .long do2
167 .long do3
168
169 .text
170 SUPERALIGN_TEXT
1715:
172 jmp *jtab(,%ecx,4)
173
174 SUPERALIGN_TEXT
175do3:
176 movw %ax,(%edx)
177 movb %al,2(%edx)
178 ret
179
180 SUPERALIGN_TEXT
181do2:
182 movw %ax,(%edx)
183 ret
184
185 SUPERALIGN_TEXT
186do1:
187 movb %al,(%edx)
188 ret
189
190 SUPERALIGN_TEXT
191do0:
192 ret
193#endif
194
195#if defined(I586_CPU) && NNPX > 0
196ENTRY(i586_bzero)
197 movl 4(%esp),%edx
198 movl 8(%esp),%ecx
199
200 /*
201 * The FPU register method is twice as fast as the integer register
202 * method unless the target is in the L1 cache and we pre-allocate a
203 * cache line for it (then the integer register method is 4-5 times
204 * faster). However, we never pre-allocate cache lines, since that
205 * would make the integer method 25% or more slower for the common
206 * case when the target isn't in either the L1 cache or the L2 cache.
207 * Thus we normally use the FPU register method unless the overhead
208 * would be too large.
209 */
210 cmpl $256,%ecx /* empirical; clts, fninit, smsw cost a lot */
211 jb intreg_i586_bzero
212
213 /*
214 * The FPU registers may belong to an application or to fastmove()
215 * or to another invocation of bcopy() or ourself in a higher level
216 * interrupt or trap handler. Preserving the registers is
217 * complicated since we avoid it if possible at all levels. We
218 * want to localize the complications even when that increases them.
219 * Here the extra work involves preserving CR0_TS in TS.
af0bff84
MD
220 * `npxthread != NULL' is supposed to be the condition that all the
221 * FPU resources belong to an application, but npxthread and CR0_TS
984263bc
MD
222 * aren't set atomically enough for this condition to work in
223 * interrupt handlers.
224 *
225 * Case 1: FPU registers belong to the application: we must preserve
226 * the registers if we use them, so we only use the FPU register
227 * method if the target size is large enough to amortize the extra
228 * overhead for preserving them. CR0_TS must be preserved although
229 * it is very likely to end up as set.
230 *
231 * Case 2: FPU registers belong to fastmove(): fastmove() currently
232 * makes the registers look like they belong to an application so
233 * that cpu_switch() and savectx() don't have to know about it, so
234 * this case reduces to case 1.
235 *
236 * Case 3: FPU registers belong to the kernel: don't use the FPU
237 * register method. This case is unlikely, and supporting it would
238 * be more complicated and might take too much stack.
239 *
240 * Case 4: FPU registers don't belong to anyone: the FPU registers
241 * don't need to be preserved, so we always use the FPU register
242 * method. CR0_TS must be preserved although it is very likely to
243 * always end up as clear.
244 */
af0bff84 245 cmpl $0,_npxthread
984263bc
MD
246 je i586_bz1
247 cmpl $256+184,%ecx /* empirical; not quite 2*108 more */
248 jb intreg_i586_bzero
249 sarb $1,kernel_fpu_lock
250 jc intreg_i586_bzero
251 smsw %ax
252 clts
253 subl $108,%esp
254 fnsave 0(%esp)
255 jmp i586_bz2
256
257i586_bz1:
258 sarb $1,kernel_fpu_lock
259 jc intreg_i586_bzero
260 smsw %ax
261 clts
262 fninit /* XXX should avoid needing this */
263i586_bz2:
264 fldz
265
266 /*
267 * Align to an 8 byte boundary (misalignment in the main loop would
268 * cost a factor of >= 2). Avoid jumps (at little cost if it is
269 * already aligned) by always zeroing 8 bytes and using the part up
270 * to the _next_ alignment position.
271 */
272 fstl 0(%edx)
273 addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */
274 addl $8,%edx
275 andl $~7,%edx
276 subl %edx,%ecx
277
278 /*
279 * Similarly align `len' to a multiple of 8.
280 */
281 fstl -8(%edx,%ecx)
282 decl %ecx
283 andl $~7,%ecx
284
285 /*
286 * This wouldn't be any faster if it were unrolled, since the loop
287 * control instructions are much faster than the fstl and/or done
288 * in parallel with it so their overhead is insignificant.
289 */
290fpureg_i586_bzero_loop:
291 fstl 0(%edx)
292 addl $8,%edx
293 subl $8,%ecx
294 cmpl $8,%ecx
295 jae fpureg_i586_bzero_loop
296
af0bff84 297 cmpl $0,_npxthread
984263bc
MD
298 je i586_bz3
299 frstor 0(%esp)
300 addl $108,%esp
301 lmsw %ax
302 movb $0xfe,kernel_fpu_lock
303 ret
304
305i586_bz3:
306 fstp %st(0)
307 lmsw %ax
308 movb $0xfe,kernel_fpu_lock
309 ret
310
311intreg_i586_bzero:
312 /*
313 * `rep stos' seems to be the best method in practice for small
314 * counts. Fancy methods usually take too long to start up due
315 * to cache and BTB misses.
316 */
317 pushl %edi
318 movl %edx,%edi
319 xorl %eax,%eax
320 shrl $2,%ecx
321 cld
322 rep
323 stosl
324 movl 12(%esp),%ecx
325 andl $3,%ecx
326 jne 1f
327 popl %edi
328 ret
329
3301:
331 rep
332 stosb
333 popl %edi
334 ret
335#endif /* I586_CPU && NNPX > 0 */
336
337ENTRY(i686_pagezero)
338 pushl %edi
339 pushl %ebx
340
341 movl 12(%esp), %edi
342 movl $1024, %ecx
343 cld
344
345 ALIGN_TEXT
3461:
347 xorl %eax, %eax
348 repe
349 scasl
350 jnz 2f
351
352 popl %ebx
353 popl %edi
354 ret
355
356 ALIGN_TEXT
357
3582:
359 incl %ecx
360 subl $4, %edi
361
362 movl %ecx, %edx
363 cmpl $16, %ecx
364
365 jge 3f
366
367 movl %edi, %ebx
368 andl $0x3f, %ebx
369 shrl %ebx
370 shrl %ebx
371 movl $16, %ecx
372 subl %ebx, %ecx
373
3743:
375 subl %ecx, %edx
376 rep
377 stosl
378
379 movl %edx, %ecx
380 testl %edx, %edx
381 jnz 1b
382
383 popl %ebx
384 popl %edi
385 ret
386
387/* fillw(pat, base, cnt) */
388ENTRY(fillw)
389 pushl %edi
390 movl 8(%esp),%eax
391 movl 12(%esp),%edi
392 movl 16(%esp),%ecx
393 cld
394 rep
395 stosw
396 popl %edi
397 ret
398
399ENTRY(bcopyb)
400 pushl %esi
401 pushl %edi
402 movl 12(%esp),%esi
403 movl 16(%esp),%edi
404 movl 20(%esp),%ecx
405 movl %edi,%eax
406 subl %esi,%eax
407 cmpl %ecx,%eax /* overlapping && src < dst? */
408 jb 1f
409 cld /* nope, copy forwards */
410 rep
411 movsb
412 popl %edi
413 popl %esi
414 ret
415
416 ALIGN_TEXT
4171:
418 addl %ecx,%edi /* copy backwards. */
419 addl %ecx,%esi
420 decl %edi
421 decl %esi
422 std
423 rep
424 movsb
425 popl %edi
426 popl %esi
427 cld
428 ret
429
430ENTRY(bcopy)
431 MEXITCOUNT
432 jmp *_bcopy_vector
433
434ENTRY(ovbcopy)
435 MEXITCOUNT
436 jmp *_ovbcopy_vector
437
438/*
439 * generic_bcopy(src, dst, cnt)
440 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
441 */
442ENTRY(generic_bcopy)
443 pushl %esi
444 pushl %edi
445 movl 12(%esp),%esi
446 movl 16(%esp),%edi
447 movl 20(%esp),%ecx
448
449 movl %edi,%eax
450 subl %esi,%eax
451 cmpl %ecx,%eax /* overlapping && src < dst? */
452 jb 1f
453
454 shrl $2,%ecx /* copy by 32-bit words */
455 cld /* nope, copy forwards */
456 rep
457 movsl
458 movl 20(%esp),%ecx
459 andl $3,%ecx /* any bytes left? */
460 rep
461 movsb
462 popl %edi
463 popl %esi
464 ret
465
466 ALIGN_TEXT
4671:
468 addl %ecx,%edi /* copy backwards */
469 addl %ecx,%esi
470 decl %edi
471 decl %esi
472 andl $3,%ecx /* any fractional bytes? */
473 std
474 rep
475 movsb
476 movl 20(%esp),%ecx /* copy remainder by 32-bit words */
477 shrl $2,%ecx
478 subl $3,%esi
479 subl $3,%edi
480 rep
481 movsl
482 popl %edi
483 popl %esi
484 cld
485 ret
486
487#if defined(I586_CPU) && NNPX > 0
488ENTRY(i586_bcopy)
489 pushl %esi
490 pushl %edi
491 movl 12(%esp),%esi
492 movl 16(%esp),%edi
493 movl 20(%esp),%ecx
494
495 movl %edi,%eax
496 subl %esi,%eax
497 cmpl %ecx,%eax /* overlapping && src < dst? */
498 jb 1f
499
500 cmpl $1024,%ecx
501 jb small_i586_bcopy
502
503 sarb $1,kernel_fpu_lock
504 jc small_i586_bcopy
af0bff84 505 cmpl $0,_npxthread
984263bc
MD
506 je i586_bc1
507 smsw %dx
508 clts
509 subl $108,%esp
510 fnsave 0(%esp)
511 jmp 4f
512
513i586_bc1:
514 smsw %dx
515 clts
516 fninit /* XXX should avoid needing this */
517
518 ALIGN_TEXT
5194:
520 pushl %ecx
521#define DCACHE_SIZE 8192
522 cmpl $(DCACHE_SIZE-512)/2,%ecx
523 jbe 2f
524 movl $(DCACHE_SIZE-512)/2,%ecx
5252:
526 subl %ecx,0(%esp)
527 cmpl $256,%ecx
528 jb 5f /* XXX should prefetch if %ecx >= 32 */
529 pushl %esi
530 pushl %ecx
531 ALIGN_TEXT
5323:
533 movl 0(%esi),%eax
534 movl 32(%esi),%eax
535 movl 64(%esi),%eax
536 movl 96(%esi),%eax
537 movl 128(%esi),%eax
538 movl 160(%esi),%eax
539 movl 192(%esi),%eax
540 movl 224(%esi),%eax
541 addl $256,%esi
542 subl $256,%ecx
543 cmpl $256,%ecx
544 jae 3b
545 popl %ecx
546 popl %esi
5475:
548 ALIGN_TEXT
549large_i586_bcopy_loop:
550 fildq 0(%esi)
551 fildq 8(%esi)
552 fildq 16(%esi)
553 fildq 24(%esi)
554 fildq 32(%esi)
555 fildq 40(%esi)
556 fildq 48(%esi)
557 fildq 56(%esi)
558 fistpq 56(%edi)
559 fistpq 48(%edi)
560 fistpq 40(%edi)
561 fistpq 32(%edi)
562 fistpq 24(%edi)
563 fistpq 16(%edi)
564 fistpq 8(%edi)
565 fistpq 0(%edi)
566 addl $64,%esi
567 addl $64,%edi
568 subl $64,%ecx
569 cmpl $64,%ecx
570 jae large_i586_bcopy_loop
571 popl %eax
572 addl %eax,%ecx
573 cmpl $64,%ecx
574 jae 4b
575
af0bff84 576 cmpl $0,_npxthread
984263bc
MD
577 je i586_bc2
578 frstor 0(%esp)
579 addl $108,%esp
580i586_bc2:
581 lmsw %dx
582 movb $0xfe,kernel_fpu_lock
583
584/*
585 * This is a duplicate of the main part of generic_bcopy. See the comments
586 * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and
587 * would mess up high resolution profiling.
588 */
589 ALIGN_TEXT
590small_i586_bcopy:
591 shrl $2,%ecx
592 cld
593 rep
594 movsl
595 movl 20(%esp),%ecx
596 andl $3,%ecx
597 rep
598 movsb
599 popl %edi
600 popl %esi
601 ret
602
603 ALIGN_TEXT
6041:
605 addl %ecx,%edi
606 addl %ecx,%esi
607 decl %edi
608 decl %esi
609 andl $3,%ecx
610 std
611 rep
612 movsb
613 movl 20(%esp),%ecx
614 shrl $2,%ecx
615 subl $3,%esi
616 subl $3,%edi
617 rep
618 movsl
619 popl %edi
620 popl %esi
621 cld
622 ret
623#endif /* I586_CPU && NNPX > 0 */
624
625/*
626 * Note: memcpy does not support overlapping copies
627 */
628ENTRY(memcpy)
629 pushl %edi
630 pushl %esi
631 movl 12(%esp),%edi
632 movl 16(%esp),%esi
633 movl 20(%esp),%ecx
634 movl %edi,%eax
635 shrl $2,%ecx /* copy by 32-bit words */
636 cld /* nope, copy forwards */
637 rep
638 movsl
639 movl 20(%esp),%ecx
640 andl $3,%ecx /* any bytes left? */
641 rep
642 movsb
643 popl %esi
644 popl %edi
645 ret
646
647
648/*****************************************************************************/
649/* copyout and fubyte family */
650/*****************************************************************************/
651/*
652 * Access user memory from inside the kernel. These routines and possibly
653 * the math- and DOS emulators should be the only places that do this.
654 *
655 * We have to access the memory with user's permissions, so use a segment
656 * selector with RPL 3. For writes to user space we have to additionally
657 * check the PTE for write permission, because the 386 does not check
658 * write permissions when we are executing with EPL 0. The 486 does check
659 * this if the WP bit is set in CR0, so we can use a simpler version here.
660 *
661 * These routines set curpcb->onfault for the time they execute. When a
662 * protection violation occurs inside the functions, the trap handler
663 * returns to *curpcb->onfault instead of the function.
664 */
665
666/*
667 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
668 */
669ENTRY(copyout)
670 MEXITCOUNT
671 jmp *_copyout_vector
672
673ENTRY(generic_copyout)
674 movl _curpcb,%eax
675 movl $copyout_fault,PCB_ONFAULT(%eax)
676 pushl %esi
677 pushl %edi
678 pushl %ebx
679 movl 16(%esp),%esi
680 movl 20(%esp),%edi
681 movl 24(%esp),%ebx
682 testl %ebx,%ebx /* anything to do? */
683 jz done_copyout
684
685 /*
686 * Check explicitly for non-user addresses. If 486 write protection
687 * is being used, this check is essential because we are in kernel
688 * mode so the h/w does not provide any protection against writing
689 * kernel addresses.
690 */
691
692 /*
693 * First, prevent address wrapping.
694 */
695 movl %edi,%eax
696 addl %ebx,%eax
697 jc copyout_fault
698/*
699 * XXX STOP USING VM_MAXUSER_ADDRESS.
700 * It is an end address, not a max, so every time it is used correctly it
701 * looks like there is an off by one error, and of course it caused an off
702 * by one error in several places.
703 */
704 cmpl $VM_MAXUSER_ADDRESS,%eax
705 ja copyout_fault
706
707#if defined(I386_CPU)
708
709#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
710 cmpl $CPUCLASS_386,_cpu_class
711 jne 3f
712#endif
713/*
714 * We have to check each PTE for user write permission.
715 * The checking may cause a page fault, so it is important to set
716 * up everything for return via copyout_fault before here.
717 */
718 /* compute number of pages */
719 movl %edi,%ecx
720 andl $PAGE_MASK,%ecx
721 addl %ebx,%ecx
722 decl %ecx
723 shrl $IDXSHIFT+2,%ecx
724 incl %ecx
725
726 /* compute PTE offset for start address */
727 movl %edi,%edx
728 shrl $IDXSHIFT,%edx
729 andb $0xfc,%dl
730
7311:
732 /* check PTE for each page */
733 leal _PTmap(%edx),%eax
734 shrl $IDXSHIFT,%eax
735 andb $0xfc,%al
736 testb $PG_V,_PTmap(%eax) /* PTE page must be valid */
737 je 4f
738 movb _PTmap(%edx),%al
739 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
740 cmpb $PG_V|PG_RW|PG_U,%al
741 je 2f
742
7434:
744 /* simulate a trap */
745 pushl %edx
746 pushl %ecx
747 shll $IDXSHIFT,%edx
748 pushl %edx
749 call _trapwrite /* trapwrite(addr) */
750 popl %edx
751 popl %ecx
752 popl %edx
753
754 testl %eax,%eax /* if not ok, return EFAULT */
755 jnz copyout_fault
756
7572:
758 addl $4,%edx
759 decl %ecx
760 jnz 1b /* check next page */
761#endif /* I386_CPU */
762
763 /* bcopy(%esi, %edi, %ebx) */
7643:
765 movl %ebx,%ecx
766
767#if defined(I586_CPU) && NNPX > 0
768 ALIGN_TEXT
769slow_copyout:
770#endif
771 shrl $2,%ecx
772 cld
773 rep
774 movsl
775 movb %bl,%cl
776 andb $3,%cl
777 rep
778 movsb
779
780done_copyout:
781 popl %ebx
782 popl %edi
783 popl %esi
784 xorl %eax,%eax
785 movl _curpcb,%edx
786 movl %eax,PCB_ONFAULT(%edx)
787 ret
788
789 ALIGN_TEXT
790copyout_fault:
791 popl %ebx
792 popl %edi
793 popl %esi
794 movl _curpcb,%edx
795 movl $0,PCB_ONFAULT(%edx)
796 movl $EFAULT,%eax
797 ret
798
799#if defined(I586_CPU) && NNPX > 0
800ENTRY(i586_copyout)
801 /*
802 * Duplicated from generic_copyout. Could be done a bit better.
803 */
804 movl _curpcb,%eax
805 movl $copyout_fault,PCB_ONFAULT(%eax)
806 pushl %esi
807 pushl %edi
808 pushl %ebx
809 movl 16(%esp),%esi
810 movl 20(%esp),%edi
811 movl 24(%esp),%ebx
812 testl %ebx,%ebx /* anything to do? */
813 jz done_copyout
814
815 /*
816 * Check explicitly for non-user addresses. If 486 write protection
817 * is being used, this check is essential because we are in kernel
818 * mode so the h/w does not provide any protection against writing
819 * kernel addresses.
820 */
821
822 /*
823 * First, prevent address wrapping.
824 */
825 movl %edi,%eax
826 addl %ebx,%eax
827 jc copyout_fault
828/*
829 * XXX STOP USING VM_MAXUSER_ADDRESS.
830 * It is an end address, not a max, so every time it is used correctly it
831 * looks like there is an off by one error, and of course it caused an off
832 * by one error in several places.
833 */
834 cmpl $VM_MAXUSER_ADDRESS,%eax
835 ja copyout_fault
836
837 /* bcopy(%esi, %edi, %ebx) */
8383:
839 movl %ebx,%ecx
840 /*
841 * End of duplicated code.
842 */
843
844 cmpl $1024,%ecx
845 jb slow_copyout
846
847 pushl %ecx
848 call _fastmove
849 addl $4,%esp
850 jmp done_copyout
851#endif /* I586_CPU && NNPX > 0 */
852
853/*
854 * copyin(from_user, to_kernel, len) - MP SAFE
855 */
856ENTRY(copyin)
857 MEXITCOUNT
858 jmp *_copyin_vector
859
860ENTRY(generic_copyin)
861 movl _curpcb,%eax
862 movl $copyin_fault,PCB_ONFAULT(%eax)
863 pushl %esi
864 pushl %edi
865 movl 12(%esp),%esi /* caddr_t from */
866 movl 16(%esp),%edi /* caddr_t to */
867 movl 20(%esp),%ecx /* size_t len */
868
869 /*
870 * make sure address is valid
871 */
872 movl %esi,%edx
873 addl %ecx,%edx
874 jc copyin_fault
875 cmpl $VM_MAXUSER_ADDRESS,%edx
876 ja copyin_fault
877
878#if defined(I586_CPU) && NNPX > 0
879 ALIGN_TEXT
880slow_copyin:
881#endif
882 movb %cl,%al
883 shrl $2,%ecx /* copy longword-wise */
884 cld
885 rep
886 movsl
887 movb %al,%cl
888 andb $3,%cl /* copy remaining bytes */
889 rep
890 movsb
891
892#if defined(I586_CPU) && NNPX > 0
893 ALIGN_TEXT
894done_copyin:
895#endif
896 popl %edi
897 popl %esi
898 xorl %eax,%eax
899 movl _curpcb,%edx
900 movl %eax,PCB_ONFAULT(%edx)
901 ret
902
903 ALIGN_TEXT
904copyin_fault:
905 popl %edi
906 popl %esi
907 movl _curpcb,%edx
908 movl $0,PCB_ONFAULT(%edx)
909 movl $EFAULT,%eax
910 ret
911
912#if defined(I586_CPU) && NNPX > 0
913ENTRY(i586_copyin)
914 /*
915 * Duplicated from generic_copyin. Could be done a bit better.
916 */
917 movl _curpcb,%eax
918 movl $copyin_fault,PCB_ONFAULT(%eax)
919 pushl %esi
920 pushl %edi
921 movl 12(%esp),%esi /* caddr_t from */
922 movl 16(%esp),%edi /* caddr_t to */
923 movl 20(%esp),%ecx /* size_t len */
924
925 /*
926 * make sure address is valid
927 */
928 movl %esi,%edx
929 addl %ecx,%edx
930 jc copyin_fault
931 cmpl $VM_MAXUSER_ADDRESS,%edx
932 ja copyin_fault
933 /*
934 * End of duplicated code.
935 */
936
937 cmpl $1024,%ecx
938 jb slow_copyin
939
940 pushl %ebx /* XXX prepare for fastmove_fault */
941 pushl %ecx
942 call _fastmove
943 addl $8,%esp
944 jmp done_copyin
945#endif /* I586_CPU && NNPX > 0 */
946
947#if defined(I586_CPU) && NNPX > 0
948/* fastmove(src, dst, len)
949 src in %esi
950 dst in %edi
951 len in %ecx XXX changed to on stack for profiling
952 uses %eax and %edx for tmp. storage
953 */
954/* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */
955ENTRY(fastmove)
956 pushl %ebp
957 movl %esp,%ebp
958 subl $PCB_SAVE87_SIZE+3*4,%esp
959
960 movl 8(%ebp),%ecx
961 cmpl $63,%ecx
962 jbe fastmove_tail
963
964 testl $7,%esi /* check if src addr is multiple of 8 */
965 jnz fastmove_tail
966
967 testl $7,%edi /* check if dst addr is multiple of 8 */
968 jnz fastmove_tail
969
af0bff84
MD
970/* if (npxthread != NULL) { */
971 cmpl $0,_npxthread
984263bc
MD
972 je 6f
973/* fnsave(&curpcb->pcb_savefpu); */
974 movl _curpcb,%eax
975 fnsave PCB_SAVEFPU(%eax)
af0bff84
MD
976/* npxthread = NULL; */
977 movl $0,_npxthread
984263bc
MD
978/* } */
9796:
980/* now we own the FPU. */
981
982/*
983 * The process' FP state is saved in the pcb, but if we get
984 * switched, the cpu_switch() will store our FP state in the
985 * pcb. It should be possible to avoid all the copying for
986 * this, e.g., by setting a flag to tell cpu_switch() to
987 * save the state somewhere else.
988 */
989/* tmp = curpcb->pcb_savefpu; */
990 movl %ecx,-12(%ebp)
991 movl %esi,-8(%ebp)
992 movl %edi,-4(%ebp)
993 movl %esp,%edi
994 movl _curpcb,%esi
995 addl $PCB_SAVEFPU,%esi
996 cld
997 movl $PCB_SAVE87_SIZE>>2,%ecx
998 rep
999 movsl
1000 movl -12(%ebp),%ecx
1001 movl -8(%ebp),%esi
1002 movl -4(%ebp),%edi
1003/* stop_emulating(); */
1004 clts
af0bff84 1005/* npxthread = curthread; */
84b592ba 1006 movl _curthread,%eax
af0bff84 1007 movl %eax,_npxthread
984263bc
MD
1008 movl _curpcb,%eax
1009 movl $fastmove_fault,PCB_ONFAULT(%eax)
10104:
1011 movl %ecx,-12(%ebp)
1012 cmpl $1792,%ecx
1013 jbe 2f
1014 movl $1792,%ecx
10152:
1016 subl %ecx,-12(%ebp)
1017 cmpl $256,%ecx
1018 jb 5f
1019 movl %ecx,-8(%ebp)
1020 movl %esi,-4(%ebp)
1021 ALIGN_TEXT
10223:
1023 movl 0(%esi),%eax
1024 movl 32(%esi),%eax
1025 movl 64(%esi),%eax
1026 movl 96(%esi),%eax
1027 movl 128(%esi),%eax
1028 movl 160(%esi),%eax
1029 movl 192(%esi),%eax
1030 movl 224(%esi),%eax
1031 addl $256,%esi
1032 subl $256,%ecx
1033 cmpl $256,%ecx
1034 jae 3b
1035 movl -8(%ebp),%ecx
1036 movl -4(%ebp),%esi
10375:
1038 ALIGN_TEXT
1039fastmove_loop:
1040 fildq 0(%esi)
1041 fildq 8(%esi)
1042 fildq 16(%esi)
1043 fildq 24(%esi)
1044 fildq 32(%esi)
1045 fildq 40(%esi)
1046 fildq 48(%esi)
1047 fildq 56(%esi)
1048 fistpq 56(%edi)
1049 fistpq 48(%edi)
1050 fistpq 40(%edi)
1051 fistpq 32(%edi)
1052 fistpq 24(%edi)
1053 fistpq 16(%edi)
1054 fistpq 8(%edi)
1055 fistpq 0(%edi)
1056 addl $-64,%ecx
1057 addl $64,%esi
1058 addl $64,%edi
1059 cmpl $63,%ecx
1060 ja fastmove_loop
1061 movl -12(%ebp),%eax
1062 addl %eax,%ecx
1063 cmpl $64,%ecx
1064 jae 4b
1065
1066/* curpcb->pcb_savefpu = tmp; */
1067 movl %ecx,-12(%ebp)
1068 movl %esi,-8(%ebp)
1069 movl %edi,-4(%ebp)
1070 movl _curpcb,%edi
1071 addl $PCB_SAVEFPU,%edi
1072 movl %esp,%esi
1073 cld
1074 movl $PCB_SAVE87_SIZE>>2,%ecx
1075 rep
1076 movsl
1077 movl -12(%ebp),%ecx
1078 movl -8(%ebp),%esi
1079 movl -4(%ebp),%edi
1080
1081/* start_emulating(); */
1082 smsw %ax
1083 orb $CR0_TS,%al
1084 lmsw %ax
af0bff84
MD
1085/* npxthread = NULL; */
1086 movl $0,_npxthread
984263bc
MD
1087
1088 ALIGN_TEXT
1089fastmove_tail:
1090 movl _curpcb,%eax
1091 movl $fastmove_tail_fault,PCB_ONFAULT(%eax)
1092
1093 movb %cl,%al
1094 shrl $2,%ecx /* copy longword-wise */
1095 cld
1096 rep
1097 movsl
1098 movb %al,%cl
1099 andb $3,%cl /* copy remaining bytes */
1100 rep
1101 movsb
1102
1103 movl %ebp,%esp
1104 popl %ebp
1105 ret
1106
1107 ALIGN_TEXT
1108fastmove_fault:
1109 movl _curpcb,%edi
1110 addl $PCB_SAVEFPU,%edi
1111 movl %esp,%esi
1112 cld
1113 movl $PCB_SAVE87_SIZE>>2,%ecx
1114 rep
1115 movsl
1116
1117 smsw %ax
1118 orb $CR0_TS,%al
1119 lmsw %ax
af0bff84 1120 movl $0,_npxthread
984263bc
MD
1121
1122fastmove_tail_fault:
1123 movl %ebp,%esp
1124 popl %ebp
1125 addl $8,%esp
1126 popl %ebx
1127 popl %edi
1128 popl %esi
1129 movl _curpcb,%edx
1130 movl $0,PCB_ONFAULT(%edx)
1131 movl $EFAULT,%eax
1132 ret
1133#endif /* I586_CPU && NNPX > 0 */
1134
1135/*
1136 * fu{byte,sword,word} - MP SAFE
1137 *
1138 * Fetch a byte (sword, word) from user memory
1139 */
1140ENTRY(fuword)
1141 movl _curpcb,%ecx
1142 movl $fusufault,PCB_ONFAULT(%ecx)
1143 movl 4(%esp),%edx /* from */
1144
1145 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
1146 ja fusufault
1147
1148 movl (%edx),%eax
1149 movl $0,PCB_ONFAULT(%ecx)
1150 ret
1151
1152/*
1153 * These two routines are called from the profiling code, potentially
1154 * at interrupt time. If they fail, that's okay, good things will
1155 * happen later. Fail all the time for now - until the trap code is
1156 * able to deal with this.
1157 */
1158ALTENTRY(suswintr)
1159ENTRY(fuswintr)
1160 movl $-1,%eax
1161 ret
1162
1163/*
1164 * fusword - MP SAFE
1165 */
1166ENTRY(fusword)
1167 movl _curpcb,%ecx
1168 movl $fusufault,PCB_ONFAULT(%ecx)
1169 movl 4(%esp),%edx
1170
1171 cmpl $VM_MAXUSER_ADDRESS-2,%edx
1172 ja fusufault
1173
1174 movzwl (%edx),%eax
1175 movl $0,PCB_ONFAULT(%ecx)
1176 ret
1177
1178/*
1179 * fubyte - MP SAFE
1180 */
1181ENTRY(fubyte)
1182 movl _curpcb,%ecx
1183 movl $fusufault,PCB_ONFAULT(%ecx)
1184 movl 4(%esp),%edx
1185
1186 cmpl $VM_MAXUSER_ADDRESS-1,%edx
1187 ja fusufault
1188
1189 movzbl (%edx),%eax
1190 movl $0,PCB_ONFAULT(%ecx)
1191 ret
1192
1193 ALIGN_TEXT
1194fusufault:
1195 movl _curpcb,%ecx
1196 xorl %eax,%eax
1197 movl %eax,PCB_ONFAULT(%ecx)
1198 decl %eax
1199 ret
1200
1201/*
1202 * su{byte,sword,word} - MP SAFE (if not I386_CPU)
1203 *
1204 * Write a byte (word, longword) to user memory
1205 */
1206ENTRY(suword)
1207 movl _curpcb,%ecx
1208 movl $fusufault,PCB_ONFAULT(%ecx)
1209 movl 4(%esp),%edx
1210
1211#if defined(I386_CPU)
1212
1213#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1214 cmpl $CPUCLASS_386,_cpu_class
1215 jne 2f /* we only have to set the right segment selector */
1216#endif /* I486_CPU || I586_CPU || I686_CPU */
1217
1218 /* XXX - page boundary crossing is still not handled */
1219 movl %edx,%eax
1220 shrl $IDXSHIFT,%edx
1221 andb $0xfc,%dl
1222
1223 leal _PTmap(%edx),%ecx
1224 shrl $IDXSHIFT,%ecx
1225 andb $0xfc,%cl
1226 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1227 je 4f
1228 movb _PTmap(%edx),%dl
1229 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1230 cmpb $PG_V|PG_RW|PG_U,%dl
1231 je 1f
1232
12334:
1234 /* simulate a trap */
1235 pushl %eax
1236 call _trapwrite
1237 popl %edx /* remove junk parameter from stack */
1238 testl %eax,%eax
1239 jnz fusufault
12401:
1241 movl 4(%esp),%edx
1242#endif
1243
12442:
1245 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
1246 ja fusufault
1247
1248 movl 8(%esp),%eax
1249 movl %eax,(%edx)
1250 xorl %eax,%eax
1251 movl _curpcb,%ecx
1252 movl %eax,PCB_ONFAULT(%ecx)
1253 ret
1254
1255/*
1256 * susword - MP SAFE (if not I386_CPU)
1257 */
1258ENTRY(susword)
1259 movl _curpcb,%ecx
1260 movl $fusufault,PCB_ONFAULT(%ecx)
1261 movl 4(%esp),%edx
1262
1263#if defined(I386_CPU)
1264
1265#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1266 cmpl $CPUCLASS_386,_cpu_class
1267 jne 2f
1268#endif /* I486_CPU || I586_CPU || I686_CPU */
1269
1270 /* XXX - page boundary crossing is still not handled */
1271 movl %edx,%eax
1272 shrl $IDXSHIFT,%edx
1273 andb $0xfc,%dl
1274
1275 leal _PTmap(%edx),%ecx
1276 shrl $IDXSHIFT,%ecx
1277 andb $0xfc,%cl
1278 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1279 je 4f
1280 movb _PTmap(%edx),%dl
1281 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1282 cmpb $PG_V|PG_RW|PG_U,%dl
1283 je 1f
1284
12854:
1286 /* simulate a trap */
1287 pushl %eax
1288 call _trapwrite
1289 popl %edx /* remove junk parameter from stack */
1290 testl %eax,%eax
1291 jnz fusufault
12921:
1293 movl 4(%esp),%edx
1294#endif
1295
12962:
1297 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
1298 ja fusufault
1299
1300 movw 8(%esp),%ax
1301 movw %ax,(%edx)
1302 xorl %eax,%eax
1303 movl _curpcb,%ecx /* restore trashed register */
1304 movl %eax,PCB_ONFAULT(%ecx)
1305 ret
1306
1307/*
1308 * su[i]byte - MP SAFE (if not I386_CPU)
1309 */
1310ALTENTRY(suibyte)
1311ENTRY(subyte)
1312 movl _curpcb,%ecx
1313 movl $fusufault,PCB_ONFAULT(%ecx)
1314 movl 4(%esp),%edx
1315
1316#if defined(I386_CPU)
1317
1318#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1319 cmpl $CPUCLASS_386,_cpu_class
1320 jne 2f
1321#endif /* I486_CPU || I586_CPU || I686_CPU */
1322
1323 movl %edx,%eax
1324 shrl $IDXSHIFT,%edx
1325 andb $0xfc,%dl
1326
1327 leal _PTmap(%edx),%ecx
1328 shrl $IDXSHIFT,%ecx
1329 andb $0xfc,%cl
1330 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1331 je 4f
1332 movb _PTmap(%edx),%dl
1333 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1334 cmpb $PG_V|PG_RW|PG_U,%dl
1335 je 1f
1336
13374:
1338 /* simulate a trap */
1339 pushl %eax
1340 call _trapwrite
1341 popl %edx /* remove junk parameter from stack */
1342 testl %eax,%eax
1343 jnz fusufault
13441:
1345 movl 4(%esp),%edx
1346#endif
1347
13482:
1349 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
1350 ja fusufault
1351
1352 movb 8(%esp),%al
1353 movb %al,(%edx)
1354 xorl %eax,%eax
1355 movl _curpcb,%ecx /* restore trashed register */
1356 movl %eax,PCB_ONFAULT(%ecx)
1357 ret
1358
1359/*
1360 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
1361 *
1362 * copy a string from from to to, stop when a 0 character is reached.
1363 * return ENAMETOOLONG if string is longer than maxlen, and
1364 * EFAULT on protection violations. If lencopied is non-zero,
1365 * return the actual length in *lencopied.
1366 */
1367ENTRY(copyinstr)
1368 pushl %esi
1369 pushl %edi
1370 movl _curpcb,%ecx
1371 movl $cpystrflt,PCB_ONFAULT(%ecx)
1372
1373 movl 12(%esp),%esi /* %esi = from */
1374 movl 16(%esp),%edi /* %edi = to */
1375 movl 20(%esp),%edx /* %edx = maxlen */
1376
1377 movl $VM_MAXUSER_ADDRESS,%eax
1378
1379 /* make sure 'from' is within bounds */
1380 subl %esi,%eax
1381 jbe cpystrflt
1382
1383 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1384 cmpl %edx,%eax
1385 jae 1f
1386 movl %eax,%edx
1387 movl %eax,20(%esp)
13881:
1389 incl %edx
1390 cld
1391
13922:
1393 decl %edx
1394 jz 3f
1395
1396 lodsb
1397 stosb
1398 orb %al,%al
1399 jnz 2b
1400
1401 /* Success -- 0 byte reached */
1402 decl %edx
1403 xorl %eax,%eax
1404 jmp cpystrflt_x
14053:
1406 /* edx is zero - return ENAMETOOLONG or EFAULT */
1407 cmpl $VM_MAXUSER_ADDRESS,%esi
1408 jae cpystrflt
14094:
1410 movl $ENAMETOOLONG,%eax
1411 jmp cpystrflt_x
1412
1413cpystrflt:
1414 movl $EFAULT,%eax
1415
1416cpystrflt_x:
1417 /* set *lencopied and return %eax */
1418 movl _curpcb,%ecx
1419 movl $0,PCB_ONFAULT(%ecx)
1420 movl 20(%esp),%ecx
1421 subl %edx,%ecx
1422 movl 24(%esp),%edx
1423 testl %edx,%edx
1424 jz 1f
1425 movl %ecx,(%edx)
14261:
1427 popl %edi
1428 popl %esi
1429 ret
1430
1431
1432/*
1433 * copystr(from, to, maxlen, int *lencopied) - MP SAFE
1434 */
1435ENTRY(copystr)
1436 pushl %esi
1437 pushl %edi
1438
1439 movl 12(%esp),%esi /* %esi = from */
1440 movl 16(%esp),%edi /* %edi = to */
1441 movl 20(%esp),%edx /* %edx = maxlen */
1442 incl %edx
1443 cld
14441:
1445 decl %edx
1446 jz 4f
1447 lodsb
1448 stosb
1449 orb %al,%al
1450 jnz 1b
1451
1452 /* Success -- 0 byte reached */
1453 decl %edx
1454 xorl %eax,%eax
1455 jmp 6f
14564:
1457 /* edx is zero -- return ENAMETOOLONG */
1458 movl $ENAMETOOLONG,%eax
1459
14606:
1461 /* set *lencopied and return %eax */
1462 movl 20(%esp),%ecx
1463 subl %edx,%ecx
1464 movl 24(%esp),%edx
1465 testl %edx,%edx
1466 jz 7f
1467 movl %ecx,(%edx)
14687:
1469 popl %edi
1470 popl %esi
1471 ret
1472
1473ENTRY(bcmp)
1474 pushl %edi
1475 pushl %esi
1476 movl 12(%esp),%edi
1477 movl 16(%esp),%esi
1478 movl 20(%esp),%edx
1479 xorl %eax,%eax
1480
1481 movl %edx,%ecx
1482 shrl $2,%ecx
1483 cld /* compare forwards */
1484 repe
1485 cmpsl
1486 jne 1f
1487
1488 movl %edx,%ecx
1489 andl $3,%ecx
1490 repe
1491 cmpsb
1492 je 2f
14931:
1494 incl %eax
14952:
1496 popl %esi
1497 popl %edi
1498 ret
1499
1500
1501/*
1502 * Handling of special 386 registers and descriptor tables etc
1503 */
1504/* void lgdt(struct region_descriptor *rdp); */
1505ENTRY(lgdt)
1506 /* reload the descriptor table */
1507 movl 4(%esp),%eax
1508 lgdt (%eax)
1509
1510 /* flush the prefetch q */
1511 jmp 1f
1512 nop
15131:
1514 /* reload "stale" selectors */
1515 movl $KDSEL,%eax
1516 mov %ax,%ds
1517 mov %ax,%es
1518 mov %ax,%gs
1519 mov %ax,%ss
1520#ifdef SMP
1521 movl $KPSEL,%eax
1522#endif
1523 mov %ax,%fs
1524
1525 /* reload code selector by turning return into intersegmental return */
1526 movl (%esp),%eax
1527 pushl %eax
1528 movl $KCSEL,4(%esp)
1529 lret
1530
1531/*
1532 * void lidt(struct region_descriptor *rdp);
1533 */
1534ENTRY(lidt)
1535 movl 4(%esp),%eax
1536 lidt (%eax)
1537 ret
1538
1539/*
1540 * void lldt(u_short sel)
1541 */
1542ENTRY(lldt)
1543 lldt 4(%esp)
1544 ret
1545
1546/*
1547 * void ltr(u_short sel)
1548 */
1549ENTRY(ltr)
1550 ltr 4(%esp)
1551 ret
1552
1553/* ssdtosd(*ssdp,*sdp) */
1554ENTRY(ssdtosd)
1555 pushl %ebx
1556 movl 8(%esp),%ecx
1557 movl 8(%ecx),%ebx
1558 shll $16,%ebx
1559 movl (%ecx),%edx
1560 roll $16,%edx
1561 movb %dh,%bl
1562 movb %dl,%bh
1563 rorl $8,%ebx
1564 movl 4(%ecx),%eax
1565 movw %ax,%dx
1566 andl $0xf0000,%eax
1567 orl %eax,%ebx
1568 movl 12(%esp),%ecx
1569 movl %edx,(%ecx)
1570 movl %ebx,4(%ecx)
1571 popl %ebx
1572 ret
1573
1574/* load_cr0(cr0) */
1575ENTRY(load_cr0)
1576 movl 4(%esp),%eax
1577 movl %eax,%cr0
1578 ret
1579
1580/* rcr0() */
1581ENTRY(rcr0)
1582 movl %cr0,%eax
1583 ret
1584
1585/* rcr3() */
1586ENTRY(rcr3)
1587 movl %cr3,%eax
1588 ret
1589
1590/* void load_cr3(caddr_t cr3) */
1591ENTRY(load_cr3)
1592#if defined(SWTCH_OPTIM_STATS)
1593 incl _tlb_flush_count
1594#endif
1595 movl 4(%esp),%eax
1596 movl %eax,%cr3
1597 ret
1598
1599/* rcr4() */
1600ENTRY(rcr4)
1601 movl %cr4,%eax
1602 ret
1603
1604/* void load_cr4(caddr_t cr4) */
1605ENTRY(load_cr4)
1606 movl 4(%esp),%eax
1607 movl %eax,%cr4
1608 ret
1609
1610/* void reset_dbregs() */
1611ENTRY(reset_dbregs)
1612 movl $0,%eax
1613 movl %eax,%dr7 /* disable all breapoints first */
1614 movl %eax,%dr0
1615 movl %eax,%dr1
1616 movl %eax,%dr2
1617 movl %eax,%dr3
1618 movl %eax,%dr6
1619 ret
1620
1621/*****************************************************************************/
1622/* setjump, longjump */
1623/*****************************************************************************/
1624
1625ENTRY(setjmp)
1626 movl 4(%esp),%eax
1627 movl %ebx,(%eax) /* save ebx */
1628 movl %esp,4(%eax) /* save esp */
1629 movl %ebp,8(%eax) /* save ebp */
1630 movl %esi,12(%eax) /* save esi */
1631 movl %edi,16(%eax) /* save edi */
1632 movl (%esp),%edx /* get rta */
1633 movl %edx,20(%eax) /* save eip */
1634 xorl %eax,%eax /* return(0); */
1635 ret
1636
1637ENTRY(longjmp)
1638 movl 4(%esp),%eax
1639 movl (%eax),%ebx /* restore ebx */
1640 movl 4(%eax),%esp /* restore esp */
1641 movl 8(%eax),%ebp /* restore ebp */
1642 movl 12(%eax),%esi /* restore esi */
1643 movl 16(%eax),%edi /* restore edi */
1644 movl 20(%eax),%edx /* get rta */
1645 movl %edx,(%esp) /* put in return frame */
1646 xorl %eax,%eax /* return(1); */
1647 incl %eax
1648 ret
1649
1650/*
1651 * Support for BB-profiling (gcc -a). The kernbb program will extract
1652 * the data from the kernel.
1653 */
1654
1655 .data
1656 ALIGN_DATA
1657 .globl bbhead
1658bbhead:
1659 .long 0
1660
1661 .text
1662NON_GPROF_ENTRY(__bb_init_func)
1663 movl 4(%esp),%eax
1664 movl $1,(%eax)
1665 movl bbhead,%edx
1666 movl %edx,16(%eax)
1667 movl %eax,bbhead
1668 .byte 0xc3 /* avoid macro for `ret' */