Fix a race in the FP copy code. If we setup our temporary FP save area
[dragonfly.git] / sys / platform / pc32 / i386 / support.s
... / ...
CommitLineData
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 $
34 * $DragonFly: src/sys/platform/pc32/i386/support.s,v 1.11 2004/04/29 17:24:58 dillon Exp $
35 */
36
37#include "use_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
50 .globl memcpy_vector
51memcpy_vector:
52 .long asm_generic_memcpy
53
54 .globl bcopy_vector
55bcopy_vector:
56 .long asm_generic_bcopy
57
58 .globl bzero
59bzero:
60 .long generic_bzero
61
62 .globl ovbcopy_vector
63ovbcopy_vector:
64 .long asm_generic_bcopy
65
66 .text
67
68/* fillw(pat, base, cnt) */
69ENTRY(fillw)
70 pushl %edi
71 movl 8(%esp),%eax
72 movl 12(%esp),%edi
73 movl 16(%esp),%ecx
74 cld
75 rep
76 stosw
77 popl %edi
78 ret
79
80/*
81 * void bcopy(const void *s, void *d, size_t count)
82 *
83 * Normal bcopy() vector, an optimized bcopy may be installed in
84 * bcopy_vector.
85 */
86ENTRY(bcopy)
87 pushl %esi
88 pushl %edi
89 movl 4+8(%esp),%esi /* caddr_t from */
90 movl 8+8(%esp),%edi /* caddr_t to */
91 movl 12+8(%esp),%ecx /* size_t len */
92 call *bcopy_vector
93 popl %edi
94 popl %esi
95 ret
96
97/*
98 * Generic (integer-only) bcopy() vector.
99 */
100ENTRY(generic_bcopy)
101 pushl %esi
102 pushl %edi
103 movl 4+8(%esp),%esi /* caddr_t from */
104 movl 8+8(%esp),%edi /* caddr_t to */
105 movl 12+8(%esp),%ecx /* size_t len */
106 call asm_generic_bcopy
107 popl %edi
108 popl %esi
109 ret
110
111ENTRY(ovbcopy)
112 pushl %esi
113 pushl %edi
114 movl 4+8(%esp),%esi /* caddr_t from */
115 movl 8+8(%esp),%edi /* caddr_t to */
116 movl 12+8(%esp),%ecx /* size_t len */
117 call *ovbcopy_vector
118 popl %edi
119 popl %esi
120 ret
121
122/*
123 * void *memcpy(void *d, const void *s, size_t count)
124 *
125 * Note: memcpy does not have to support overlapping copies.
126 *
127 * Note: (d, s) arguments reversed from bcopy, and memcpy() returns d
128 * while bcopy() returns void.
129 */
130ENTRY(memcpy)
131 pushl %esi
132 pushl %edi
133 movl 4+8(%esp),%edi
134 movl 8+8(%esp),%esi
135 movl 12+8(%esp),%ecx
136 call *memcpy_vector
137 movl 4+8(%esp),%eax
138 popl %edi
139 popl %esi
140 ret
141
142/*
143 * A stack-based on-fault routine is used for more complex PCB_ONFAULT
144 * situations (such as memcpy/bcopy/bzero). In this case the on-fault
145 * routine must be pushed on the stack.
146 */
147stack_onfault:
148 ret
149
150/*****************************************************************************/
151/* copyout and fubyte family */
152/*****************************************************************************/
153/*
154 * Access user memory from inside the kernel. These routines and possibly
155 * the math- and DOS emulators should be the only places that do this.
156 *
157 * We have to access the memory with user's permissions, so use a segment
158 * selector with RPL 3. For writes to user space we have to additionally
159 * check the PTE for write permission, because the 386 does not check
160 * write permissions when we are executing with EPL 0. The 486 does check
161 * this if the WP bit is set in CR0, so we can use a simpler version here.
162 *
163 * These routines set curpcb->onfault for the time they execute. When a
164 * protection violation occurs inside the functions, the trap handler
165 * returns to *curpcb->onfault instead of the function.
166 */
167
168/*
169 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
170 */
171ENTRY(copyout)
172 movl PCPU(curthread),%eax
173 movl TD_PCB(%eax),%eax
174 pushl %esi
175 pushl %edi
176 pushl %ebx
177 pushl $copyout_fault
178 movl $stack_onfault,PCB_ONFAULT(%eax)
179 movl 4+16(%esp),%esi
180 movl 8+16(%esp),%edi
181 movl 12+16(%esp),%ebx
182 testl %ebx,%ebx /* anything to do? */
183 jz done_copyout
184
185 /*
186 * Check explicitly for non-user addresses. If 486 write protection
187 * is being used, this check is essential because we are in kernel
188 * mode so the h/w does not provide any protection against writing
189 * kernel addresses.
190 */
191
192 /*
193 * First, prevent address wrapping.
194 */
195 movl %edi,%eax
196 addl %ebx,%eax
197 jc copyout_fault
198/*
199 * XXX STOP USING VM_MAXUSER_ADDRESS.
200 * It is an end address, not a max, so every time it is used correctly it
201 * looks like there is an off by one error, and of course it caused an off
202 * by one error in several places.
203 */
204 cmpl $VM_MAXUSER_ADDRESS,%eax
205 ja copyout_fault
206
207#if defined(I386_CPU)
208
209#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
210 cmpl $CPUCLASS_386,cpu_class
211 jne 3f
212#endif
213/*
214 * We have to check each PTE for user write permission.
215 * The checking may cause a page fault, so it is important to set
216 * up everything for return via copyout_fault before here.
217 */
218 /* compute number of pages */
219 movl %edi,%ecx
220 andl $PAGE_MASK,%ecx
221 addl %ebx,%ecx
222 decl %ecx
223 shrl $IDXSHIFT+2,%ecx
224 incl %ecx
225
226 /* compute PTE offset for start address */
227 movl %edi,%edx
228 shrl $IDXSHIFT,%edx
229 andb $0xfc,%dl
230
2311:
232 /* check PTE for each page */
233 leal PTmap(%edx),%eax
234 shrl $IDXSHIFT,%eax
235 andb $0xfc,%al
236 testb $PG_V,PTmap(%eax) /* PTE page must be valid */
237 je 4f
238 movb PTmap(%edx),%al
239 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
240 cmpb $PG_V|PG_RW|PG_U,%al
241 je 2f
242
2434:
244 /* simulate a trap */
245 pushl %edx
246 pushl %ecx
247 shll $IDXSHIFT,%edx
248 pushl %edx
249 call trapwrite /* trapwrite(addr) */
250 popl %edx
251 popl %ecx
252 popl %edx
253
254 testl %eax,%eax /* if not ok, return EFAULT */
255 jnz copyout_fault
256
2572:
258 addl $4,%edx
259 decl %ecx
260 jnz 1b /* check next page */
261#endif /* I386_CPU */
262
263 /*
264 * Convert copyout to memcpy_vector(dest:%edi, src:%esi, conut:%ecx)
265 */
2663:
267 movl %ebx,%ecx
268 call *memcpy_vector
269
270done_copyout:
271 /*
272 * non-error return
273 */
274 addl $4,%esp
275 movl PCPU(curthread),%edx
276 xorl %eax,%eax
277 movl TD_PCB(%edx),%edx
278 popl %ebx
279 popl %edi
280 popl %esi
281 movl %eax,PCB_ONFAULT(%edx)
282 ret
283
284 ALIGN_TEXT
285copyout_fault:
286 popl %ebx
287 popl %edi
288 popl %esi
289 movl PCPU(curthread),%edx
290 movl TD_PCB(%edx),%edx
291 movl $0,PCB_ONFAULT(%edx)
292 movl $EFAULT,%eax
293 ret
294
295/*
296 * copyin(from_user, to_kernel, len) - MP SAFE
297 */
298
299ENTRY(copyin)
300 movl PCPU(curthread),%eax
301 movl TD_PCB(%eax),%eax
302 pushl %esi
303 pushl %edi
304 pushl $copyin_fault
305 movl $stack_onfault,PCB_ONFAULT(%eax)
306 movl 4+12(%esp),%esi /* caddr_t from */
307 movl 8+12(%esp),%edi /* caddr_t to */
308 movl 12+12(%esp),%ecx /* size_t len */
309
310 /*
311 * make sure address is valid
312 */
313 movl %esi,%edx
314 addl %ecx,%edx
315 jc copyin_fault
316 cmpl $VM_MAXUSER_ADDRESS,%edx
317 ja copyin_fault
318
319 /*
320 * Call memcpy(destination:%edi, source:%esi, bytes:%ecx)
321 */
322 call *memcpy_vector
323
324 /*
325 * return 0 (no error)
326 */
327 addl $4,%esp
328 movl PCPU(curthread),%edx
329 xorl %eax,%eax
330 movl TD_PCB(%edx),%edx
331 popl %edi
332 popl %esi
333 movl %eax,PCB_ONFAULT(%edx)
334 ret
335
336 /*
337 * return EFAULT
338 */
339 ALIGN_TEXT
340copyin_fault:
341 popl %edi
342 popl %esi
343 movl PCPU(curthread),%edx
344 movl TD_PCB(%edx),%edx
345 movl $0,PCB_ONFAULT(%edx)
346 movl $EFAULT,%eax
347 ret
348
349/*
350 * fu{byte,sword,word} - MP SAFE
351 *
352 * Fetch a byte (sword, word) from user memory
353 */
354ENTRY(fuword)
355 movl PCPU(curthread),%ecx
356 movl TD_PCB(%ecx),%ecx
357 movl $fusufault,PCB_ONFAULT(%ecx)
358 movl 4(%esp),%edx /* from */
359
360 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
361 ja fusufault
362
363 movl (%edx),%eax
364 movl $0,PCB_ONFAULT(%ecx)
365 ret
366
367/*
368 * These two routines are called from the profiling code, potentially
369 * at interrupt time. If they fail, that's okay, good things will
370 * happen later. Fail all the time for now - until the trap code is
371 * able to deal with this.
372 */
373ALTENTRY(suswintr)
374ENTRY(fuswintr)
375 movl $-1,%eax
376 ret
377
378/*
379 * fusword - MP SAFE
380 */
381ENTRY(fusword)
382 movl PCPU(curthread),%ecx
383 movl TD_PCB(%ecx),%ecx
384 movl $fusufault,PCB_ONFAULT(%ecx)
385 movl 4(%esp),%edx
386
387 cmpl $VM_MAXUSER_ADDRESS-2,%edx
388 ja fusufault
389
390 movzwl (%edx),%eax
391 movl $0,PCB_ONFAULT(%ecx)
392 ret
393
394/*
395 * fubyte - MP SAFE
396 */
397ENTRY(fubyte)
398 movl PCPU(curthread),%ecx
399 movl TD_PCB(%ecx),%ecx
400 movl $fusufault,PCB_ONFAULT(%ecx)
401 movl 4(%esp),%edx
402
403 cmpl $VM_MAXUSER_ADDRESS-1,%edx
404 ja fusufault
405
406 movzbl (%edx),%eax
407 movl $0,PCB_ONFAULT(%ecx)
408 ret
409
410 ALIGN_TEXT
411fusufault:
412 movl PCPU(curthread),%ecx
413 movl TD_PCB(%ecx),%ecx
414 xorl %eax,%eax
415 movl %eax,PCB_ONFAULT(%ecx)
416 decl %eax
417 ret
418
419/*
420 * su{byte,sword,word} - MP SAFE (if not I386_CPU)
421 *
422 * Write a byte (word, longword) to user memory
423 */
424ENTRY(suword)
425 movl PCPU(curthread),%ecx
426 movl TD_PCB(%ecx),%ecx
427 movl $fusufault,PCB_ONFAULT(%ecx)
428 movl 4(%esp),%edx
429
430#if defined(I386_CPU)
431
432#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
433 cmpl $CPUCLASS_386,cpu_class
434 jne 2f /* we only have to set the right segment selector */
435#endif /* I486_CPU || I586_CPU || I686_CPU */
436
437 /* XXX - page boundary crossing is still not handled */
438 movl %edx,%eax
439 shrl $IDXSHIFT,%edx
440 andb $0xfc,%dl
441
442 leal PTmap(%edx),%ecx
443 shrl $IDXSHIFT,%ecx
444 andb $0xfc,%cl
445 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
446 je 4f
447 movb PTmap(%edx),%dl
448 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
449 cmpb $PG_V|PG_RW|PG_U,%dl
450 je 1f
451
4524:
453 /* simulate a trap */
454 pushl %eax
455 call trapwrite
456 popl %edx /* remove junk parameter from stack */
457 testl %eax,%eax
458 jnz fusufault
4591:
460 movl 4(%esp),%edx
461#endif
462
4632:
464 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
465 ja fusufault
466
467 movl 8(%esp),%eax
468 movl %eax,(%edx)
469 xorl %eax,%eax
470 movl PCPU(curthread),%ecx
471 movl TD_PCB(%ecx),%ecx
472 movl %eax,PCB_ONFAULT(%ecx)
473 ret
474
475/*
476 * susword - MP SAFE (if not I386_CPU)
477 */
478ENTRY(susword)
479 movl PCPU(curthread),%ecx
480 movl TD_PCB(%ecx),%ecx
481 movl $fusufault,PCB_ONFAULT(%ecx)
482 movl 4(%esp),%edx
483
484#if defined(I386_CPU)
485
486#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
487 cmpl $CPUCLASS_386,cpu_class
488 jne 2f
489#endif /* I486_CPU || I586_CPU || I686_CPU */
490
491 /* XXX - page boundary crossing is still not handled */
492 movl %edx,%eax
493 shrl $IDXSHIFT,%edx
494 andb $0xfc,%dl
495
496 leal PTmap(%edx),%ecx
497 shrl $IDXSHIFT,%ecx
498 andb $0xfc,%cl
499 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
500 je 4f
501 movb PTmap(%edx),%dl
502 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
503 cmpb $PG_V|PG_RW|PG_U,%dl
504 je 1f
505
5064:
507 /* simulate a trap */
508 pushl %eax
509 call trapwrite
510 popl %edx /* remove junk parameter from stack */
511 testl %eax,%eax
512 jnz fusufault
5131:
514 movl 4(%esp),%edx
515#endif
516
5172:
518 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
519 ja fusufault
520
521 movw 8(%esp),%ax
522 movw %ax,(%edx)
523 xorl %eax,%eax
524 movl PCPU(curthread),%ecx /* restore trashed register */
525 movl TD_PCB(%ecx),%ecx
526 movl %eax,PCB_ONFAULT(%ecx)
527 ret
528
529/*
530 * su[i]byte - MP SAFE (if not I386_CPU)
531 */
532ALTENTRY(suibyte)
533ENTRY(subyte)
534 movl PCPU(curthread),%ecx
535 movl TD_PCB(%ecx),%ecx
536 movl $fusufault,PCB_ONFAULT(%ecx)
537 movl 4(%esp),%edx
538
539#if defined(I386_CPU)
540
541#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
542 cmpl $CPUCLASS_386,cpu_class
543 jne 2f
544#endif /* I486_CPU || I586_CPU || I686_CPU */
545
546 movl %edx,%eax
547 shrl $IDXSHIFT,%edx
548 andb $0xfc,%dl
549
550 leal PTmap(%edx),%ecx
551 shrl $IDXSHIFT,%ecx
552 andb $0xfc,%cl
553 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
554 je 4f
555 movb PTmap(%edx),%dl
556 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
557 cmpb $PG_V|PG_RW|PG_U,%dl
558 je 1f
559
5604:
561 /* simulate a trap */
562 pushl %eax
563 call trapwrite
564 popl %edx /* remove junk parameter from stack */
565 testl %eax,%eax
566 jnz fusufault
5671:
568 movl 4(%esp),%edx
569#endif
570
5712:
572 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
573 ja fusufault
574
575 movb 8(%esp),%al
576 movb %al,(%edx)
577 xorl %eax,%eax
578 movl PCPU(curthread),%ecx /* restore trashed register */
579 movl TD_PCB(%ecx),%ecx
580 movl %eax,PCB_ONFAULT(%ecx)
581 ret
582
583/*
584 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
585 *
586 * copy a string from from to to, stop when a 0 character is reached.
587 * return ENAMETOOLONG if string is longer than maxlen, and
588 * EFAULT on protection violations. If lencopied is non-zero,
589 * return the actual length in *lencopied.
590 */
591ENTRY(copyinstr)
592 pushl %esi
593 pushl %edi
594 movl PCPU(curthread),%ecx
595 movl TD_PCB(%ecx),%ecx
596 movl $cpystrflt,PCB_ONFAULT(%ecx)
597
598 movl 12(%esp),%esi /* %esi = from */
599 movl 16(%esp),%edi /* %edi = to */
600 movl 20(%esp),%edx /* %edx = maxlen */
601
602 movl $VM_MAXUSER_ADDRESS,%eax
603
604 /* make sure 'from' is within bounds */
605 subl %esi,%eax
606 jbe cpystrflt
607
608 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
609 cmpl %edx,%eax
610 jae 1f
611 movl %eax,%edx
612 movl %eax,20(%esp)
6131:
614 incl %edx
615 cld
616
6172:
618 decl %edx
619 jz 3f
620
621 lodsb
622 stosb
623 orb %al,%al
624 jnz 2b
625
626 /* Success -- 0 byte reached */
627 decl %edx
628 xorl %eax,%eax
629 jmp cpystrflt_x
6303:
631 /* edx is zero - return ENAMETOOLONG or EFAULT */
632 cmpl $VM_MAXUSER_ADDRESS,%esi
633 jae cpystrflt
6344:
635 movl $ENAMETOOLONG,%eax
636 jmp cpystrflt_x
637
638cpystrflt:
639 movl $EFAULT,%eax
640
641cpystrflt_x:
642 /* set *lencopied and return %eax */
643 movl PCPU(curthread),%ecx
644 movl TD_PCB(%ecx),%ecx
645 movl $0,PCB_ONFAULT(%ecx)
646 movl 20(%esp),%ecx
647 subl %edx,%ecx
648 movl 24(%esp),%edx
649 testl %edx,%edx
650 jz 1f
651 movl %ecx,(%edx)
6521:
653 popl %edi
654 popl %esi
655 ret
656
657
658/*
659 * copystr(from, to, maxlen, int *lencopied) - MP SAFE
660 */
661ENTRY(copystr)
662 pushl %esi
663 pushl %edi
664
665 movl 12(%esp),%esi /* %esi = from */
666 movl 16(%esp),%edi /* %edi = to */
667 movl 20(%esp),%edx /* %edx = maxlen */
668 incl %edx
669 cld
6701:
671 decl %edx
672 jz 4f
673 lodsb
674 stosb
675 orb %al,%al
676 jnz 1b
677
678 /* Success -- 0 byte reached */
679 decl %edx
680 xorl %eax,%eax
681 jmp 6f
6824:
683 /* edx is zero -- return ENAMETOOLONG */
684 movl $ENAMETOOLONG,%eax
685
6866:
687 /* set *lencopied and return %eax */
688 movl 20(%esp),%ecx
689 subl %edx,%ecx
690 movl 24(%esp),%edx
691 testl %edx,%edx
692 jz 7f
693 movl %ecx,(%edx)
6947:
695 popl %edi
696 popl %esi
697 ret
698
699ENTRY(bcmp)
700 pushl %edi
701 pushl %esi
702 movl 12(%esp),%edi
703 movl 16(%esp),%esi
704 movl 20(%esp),%edx
705 xorl %eax,%eax
706
707 movl %edx,%ecx
708 shrl $2,%ecx
709 cld /* compare forwards */
710 repe
711 cmpsl
712 jne 1f
713
714 movl %edx,%ecx
715 andl $3,%ecx
716 repe
717 cmpsb
718 je 2f
7191:
720 incl %eax
7212:
722 popl %esi
723 popl %edi
724 ret
725
726
727/*
728 * Handling of special 386 registers and descriptor tables etc
729 */
730/* void lgdt(struct region_descriptor *rdp); */
731ENTRY(lgdt)
732 /* reload the descriptor table */
733 movl 4(%esp),%eax
734 lgdt (%eax)
735
736 /* flush the prefetch q */
737 jmp 1f
738 nop
7391:
740 /* reload "stale" selectors */
741 movl $KDSEL,%eax
742 mov %ax,%ds
743 mov %ax,%es
744 mov %ax,%gs
745 mov %ax,%ss
746 movl $KPSEL,%eax
747 mov %ax,%fs
748
749 /* reload code selector by turning return into intersegmental return */
750 movl (%esp),%eax
751 pushl %eax
752 movl $KCSEL,4(%esp)
753 lret
754
755/*
756 * void lidt(struct region_descriptor *rdp);
757 */
758ENTRY(lidt)
759 movl 4(%esp),%eax
760 lidt (%eax)
761 ret
762
763/*
764 * void lldt(u_short sel)
765 */
766ENTRY(lldt)
767 lldt 4(%esp)
768 ret
769
770/*
771 * void ltr(u_short sel)
772 */
773ENTRY(ltr)
774 ltr 4(%esp)
775 ret
776
777/* ssdtosd(*ssdp,*sdp) */
778ENTRY(ssdtosd)
779 pushl %ebx
780 movl 8(%esp),%ecx
781 movl 8(%ecx),%ebx
782 shll $16,%ebx
783 movl (%ecx),%edx
784 roll $16,%edx
785 movb %dh,%bl
786 movb %dl,%bh
787 rorl $8,%ebx
788 movl 4(%ecx),%eax
789 movw %ax,%dx
790 andl $0xf0000,%eax
791 orl %eax,%ebx
792 movl 12(%esp),%ecx
793 movl %edx,(%ecx)
794 movl %ebx,4(%ecx)
795 popl %ebx
796 ret
797
798/* load_cr0(cr0) */
799ENTRY(load_cr0)
800 movl 4(%esp),%eax
801 movl %eax,%cr0
802 ret
803
804/* rcr0() */
805ENTRY(rcr0)
806 movl %cr0,%eax
807 ret
808
809/* rcr3() */
810ENTRY(rcr3)
811 movl %cr3,%eax
812 ret
813
814/* void load_cr3(caddr_t cr3) */
815ENTRY(load_cr3)
816#if defined(SWTCH_OPTIM_STATS)
817 incl _tlb_flush_count
818#endif
819 movl 4(%esp),%eax
820 movl %eax,%cr3
821 ret
822
823/* rcr4() */
824ENTRY(rcr4)
825 movl %cr4,%eax
826 ret
827
828/* void load_cr4(caddr_t cr4) */
829ENTRY(load_cr4)
830 movl 4(%esp),%eax
831 movl %eax,%cr4
832 ret
833
834/* void reset_dbregs() */
835ENTRY(reset_dbregs)
836 movl $0,%eax
837 movl %eax,%dr7 /* disable all breapoints first */
838 movl %eax,%dr0
839 movl %eax,%dr1
840 movl %eax,%dr2
841 movl %eax,%dr3
842 movl %eax,%dr6
843 ret
844
845/*****************************************************************************/
846/* setjump, longjump */
847/*****************************************************************************/
848
849ENTRY(setjmp)
850 movl 4(%esp),%eax
851 movl %ebx,(%eax) /* save ebx */
852 movl %esp,4(%eax) /* save esp */
853 movl %ebp,8(%eax) /* save ebp */
854 movl %esi,12(%eax) /* save esi */
855 movl %edi,16(%eax) /* save edi */
856 movl (%esp),%edx /* get rta */
857 movl %edx,20(%eax) /* save eip */
858 xorl %eax,%eax /* return(0); */
859 ret
860
861ENTRY(longjmp)
862 movl 4(%esp),%eax
863 movl (%eax),%ebx /* restore ebx */
864 movl 4(%eax),%esp /* restore esp */
865 movl 8(%eax),%ebp /* restore ebp */
866 movl 12(%eax),%esi /* restore esi */
867 movl 16(%eax),%edi /* restore edi */
868 movl 20(%eax),%edx /* get rta */
869 movl %edx,(%esp) /* put in return frame */
870 xorl %eax,%eax /* return(1); */
871 incl %eax
872 ret
873
874/*
875 * Support for BB-profiling (gcc -a). The kernbb program will extract
876 * the data from the kernel.
877 */
878
879 .data
880 ALIGN_DATA
881 .globl bbhead
882bbhead:
883 .long 0
884
885 .text
886NON_GPROF_ENTRY(__bb_init_func)
887 movl 4(%esp),%eax
888 movl $1,(%eax)
889 movl bbhead,%edx
890 movl %edx,16(%eax)
891 movl %eax,bbhead
892 .byte 0xc3 /* avoid macro for `ret' */