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