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