Get rid of the indirect function pointer for bzero(). We haven't used it
[dragonfly.git] / sys / platform / pc32 / i386 / support.s
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.15 2006/10/23 15:42:45 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
51 memcpy_vector:
52         .long   asm_generic_memcpy
53
54         .globl  bcopy_vector
55 bcopy_vector:
56         .long   asm_generic_bcopy
57
58         .globl  ovbcopy_vector
59 ovbcopy_vector:
60         .long   asm_generic_bcopy
61
62         .text
63
64 /* fillw(pat, base, cnt) */
65 ENTRY(fillw)
66         pushl   %edi
67         movl    8(%esp),%eax
68         movl    12(%esp),%edi
69         movl    16(%esp),%ecx
70         cld
71         rep
72         stosw
73         popl    %edi
74         ret
75
76 /*
77  * void bcopy(const void *s, void *d, size_t count)
78  *
79  * Normal bcopy() vector, an optimized bcopy may be installed in
80  * bcopy_vector.
81  */
82 ENTRY(bcopy)
83         pushl   %esi
84         pushl   %edi
85         movl    4+8(%esp),%esi                  /* caddr_t from */
86         movl    8+8(%esp),%edi                  /* caddr_t to */
87         movl    12+8(%esp),%ecx                 /* size_t  len */
88         call    *bcopy_vector
89         popl    %edi
90         popl    %esi
91         ret
92
93 /*
94  * Generic (integer-only) bcopy() vector.
95  */
96 ENTRY(generic_bcopy)
97         pushl   %esi
98         pushl   %edi
99         movl    4+8(%esp),%esi                  /* caddr_t from */
100         movl    8+8(%esp),%edi                  /* caddr_t to */
101         movl    12+8(%esp),%ecx                 /* size_t  len */
102         call    asm_generic_bcopy
103         popl    %edi
104         popl    %esi
105         ret
106
107 ENTRY(ovbcopy)
108         pushl   %esi
109         pushl   %edi
110         movl    4+8(%esp),%esi                  /* caddr_t from */
111         movl    8+8(%esp),%edi                  /* caddr_t to */
112         movl    12+8(%esp),%ecx                 /* size_t  len */
113         call    *ovbcopy_vector
114         popl    %edi
115         popl    %esi
116         ret
117
118 /*
119  * void *memcpy(void *d, const void *s, size_t count)
120  *
121  * Note: memcpy does not have to support overlapping copies.
122  *
123  * Note: (d, s) arguments reversed from bcopy, and memcpy() returns d
124  * while bcopy() returns void.
125  */
126 ENTRY(memcpy)
127         pushl   %esi
128         pushl   %edi
129         movl    4+8(%esp),%edi
130         movl    8+8(%esp),%esi
131         movl    12+8(%esp),%ecx
132         call    *memcpy_vector
133         movl    4+8(%esp),%eax
134         popl    %edi
135         popl    %esi
136         ret
137
138 /*
139  * A stack-based on-fault routine is used for more complex PCB_ONFAULT
140  * situations (such as memcpy/bcopy/bzero).  In this case the on-fault
141  * routine must be pushed on the stack.
142  */
143 stack_onfault:
144         ret
145
146 /*****************************************************************************/
147 /* copyout and fubyte family                                                 */
148 /*****************************************************************************/
149 /*
150  * Access user memory from inside the kernel. These routines and possibly
151  * the math- and DOS emulators should be the only places that do this.
152  *
153  * We have to access the memory with user's permissions, so use a segment
154  * selector with RPL 3. For writes to user space we have to additionally
155  * check the PTE for write permission, because the 386 does not check
156  * write permissions when we are executing with EPL 0. The 486 does check
157  * this if the WP bit is set in CR0, so we can use a simpler version here.
158  *
159  * These routines set curpcb->onfault for the time they execute. When a
160  * protection violation occurs inside the functions, the trap handler
161  * returns to *curpcb->onfault instead of the function.
162  */
163
164 /*
165  * copyout(from_kernel, to_user, len)  - MP SAFE (if not I386_CPU)
166  */
167 ENTRY(copyout)
168         movl    PCPU(curthread),%eax
169         movl    TD_PCB(%eax),%eax
170         pushl   %esi
171         pushl   %edi
172         pushl   %ebx
173         pushl   $copyout_fault2
174         movl    $stack_onfault,PCB_ONFAULT(%eax)
175         movl    4+16(%esp),%esi
176         movl    8+16(%esp),%edi
177         movl    12+16(%esp),%ebx
178         testl   %ebx,%ebx                       /* anything to do? */
179         jz      done_copyout
180
181         /*
182          * Check explicitly for non-user addresses.  If 486 write protection
183          * is being used, this check is essential because we are in kernel
184          * mode so the h/w does not provide any protection against writing
185          * kernel addresses.
186          */
187
188         /*
189          * First, prevent address wrapping.
190          */
191         movl    %edi,%eax
192         addl    %ebx,%eax
193         jc      copyout_fault1
194 /*
195  * XXX STOP USING VM_MAXUSER_ADDRESS.
196  * It is an end address, not a max, so every time it is used correctly it
197  * looks like there is an off by one error, and of course it caused an off
198  * by one error in several places.
199  */
200         cmpl    $VM_MAXUSER_ADDRESS,%eax
201         ja      copyout_fault1
202
203 #if defined(I386_CPU)
204
205 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
206         cmpl    $CPUCLASS_386,cpu_class
207         jne     3f
208 #endif
209 /*
210  * We have to check each PTE for user write permission.
211  * The checking may cause a page fault, so it is important to set
212  * up everything for return via copyout_fault before here.
213  */
214         /* compute number of pages */
215         movl    %edi,%ecx
216         andl    $PAGE_MASK,%ecx
217         addl    %ebx,%ecx
218         decl    %ecx
219         shrl    $IDXSHIFT+2,%ecx
220         incl    %ecx
221
222         /* compute PTE offset for start address */
223         movl    %edi,%edx
224         shrl    $IDXSHIFT,%edx
225         andb    $0xfc,%dl
226
227 1:
228         /* check PTE for each page */
229         leal    PTmap(%edx),%eax
230         shrl    $IDXSHIFT,%eax
231         andb    $0xfc,%al
232         testb   $PG_V,PTmap(%eax)               /* PTE page must be valid */
233         je      4f
234         movb    PTmap(%edx),%al
235         andb    $PG_V|PG_RW|PG_U,%al            /* page must be valid and user writable */
236         cmpb    $PG_V|PG_RW|PG_U,%al
237         je      2f
238
239 4:
240         /* simulate a trap */
241         pushl   %edx
242         pushl   %ecx
243         shll    $IDXSHIFT,%edx
244         pushl   %edx
245         call    trapwrite                       /* trapwrite(addr) */
246         popl    %edx
247         popl    %ecx
248         popl    %edx
249
250         testl   %eax,%eax                       /* if not ok, return EFAULT */
251         jnz     copyout_fault1
252
253 2:
254         addl    $4,%edx
255         decl    %ecx
256         jnz     1b                              /* check next page */
257 #endif /* I386_CPU */
258
259         /*
260          * Convert copyout to memcpy_vector(dest:%edi, src:%esi, conut:%ecx)
261          */
262 3:
263         movl    %ebx,%ecx
264         call    *memcpy_vector
265
266 done_copyout:
267         /*
268          * non-error return
269          */
270         addl    $4,%esp
271         movl    PCPU(curthread),%edx
272         xorl    %eax,%eax
273         movl    TD_PCB(%edx),%edx
274         popl    %ebx
275         popl    %edi
276         popl    %esi
277         movl    %eax,PCB_ONFAULT(%edx)
278         ret
279
280         ALIGN_TEXT
281 copyout_fault1:
282         addl    $4,%esp         /* skip pushed copyout_fault vector */
283 copyout_fault2:
284         popl    %ebx
285         popl    %edi
286         popl    %esi
287         movl    PCPU(curthread),%edx
288         movl    TD_PCB(%edx),%edx
289         movl    $0,PCB_ONFAULT(%edx)
290         movl    $EFAULT,%eax
291         ret
292
293 /*
294  * copyin(from_user, to_kernel, len) - MP SAFE
295  */
296
297 ENTRY(copyin)
298         movl    PCPU(curthread),%eax
299         movl    TD_PCB(%eax),%eax
300         pushl   %esi
301         pushl   %edi
302         pushl   $copyin_fault2
303         movl    $stack_onfault,PCB_ONFAULT(%eax)
304         movl    4+12(%esp),%esi                 /* caddr_t from */
305         movl    8+12(%esp),%edi                 /* caddr_t to */
306         movl    12+12(%esp),%ecx                /* size_t  len */
307
308         /*
309          * make sure address is valid
310          */
311         movl    %esi,%edx
312         addl    %ecx,%edx
313         jc      copyin_fault1
314         cmpl    $VM_MAXUSER_ADDRESS,%edx
315         ja      copyin_fault1
316
317         /*
318          * Call memcpy(destination:%edi, source:%esi, bytes:%ecx)
319          */
320         call    *memcpy_vector
321
322         /*
323          * return 0 (no error)
324          */
325         addl    $4,%esp
326         movl    PCPU(curthread),%edx
327         xorl    %eax,%eax
328         movl    TD_PCB(%edx),%edx
329         popl    %edi
330         popl    %esi
331         movl    %eax,PCB_ONFAULT(%edx)
332         ret
333
334         /*
335          * return EFAULT
336          */
337         ALIGN_TEXT
338 copyin_fault1:
339         addl    $4,%esp         /* skip pushed copyin_fault vector */
340 copyin_fault2:
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  */
354 ENTRY(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  */
373 ALTENTRY(suswintr)
374 ENTRY(fuswintr)
375         movl    $-1,%eax
376         ret
377
378 /*
379  * fusword - MP SAFE
380  */
381 ENTRY(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  */
397 ENTRY(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
411 fusufault:
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  */
424 ENTRY(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
452 4:
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
459 1:
460         movl    4(%esp),%edx
461 #endif
462
463 2:
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  */
478 ENTRY(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
506 4:
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
513 1:
514         movl    4(%esp),%edx
515 #endif
516
517 2:
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  */
532 ALTENTRY(suibyte)
533 ENTRY(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
560 4:
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
567 1:
568         movl    4(%esp),%edx
569 #endif
570
571 2:
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  */
591 ENTRY(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)
613 1:
614         incl    %edx
615         cld
616
617 2:
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
630 3:
631         /* edx is zero - return ENAMETOOLONG or EFAULT */
632         cmpl    $VM_MAXUSER_ADDRESS,%esi
633         jae     cpystrflt
634 4:
635         movl    $ENAMETOOLONG,%eax
636         jmp     cpystrflt_x
637
638 cpystrflt:
639         movl    $EFAULT,%eax
640
641 cpystrflt_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)
652 1:
653         popl    %edi
654         popl    %esi
655         ret
656
657
658 /*
659  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
660  */
661 ENTRY(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
670 1:
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
682 4:
683         /* edx is zero -- return ENAMETOOLONG */
684         movl    $ENAMETOOLONG,%eax
685
686 6:
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)
694 7:
695         popl    %edi
696         popl    %esi
697         ret
698
699 ENTRY(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
719 1:
720         incl    %eax
721 2:
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); */
731 ENTRY(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
739 1:
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  */
758 ENTRY(lidt)
759         movl    4(%esp),%eax
760         lidt    (%eax)
761         ret
762
763 /*
764  * void lldt(u_short sel)
765  */
766 ENTRY(lldt)
767         lldt    4(%esp)
768         ret
769
770 /*
771  * void ltr(u_short sel)
772  */
773 ENTRY(ltr)
774         ltr     4(%esp)
775         ret
776
777 /* ssdtosd(*ssdp,*sdp) */
778 ENTRY(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) */
799 ENTRY(load_cr0)
800         movl    4(%esp),%eax
801         movl    %eax,%cr0
802         ret
803
804 /* rcr0() */
805 ENTRY(rcr0)
806         movl    %cr0,%eax
807         ret
808
809 /* rcr3() */
810 ENTRY(rcr3)
811         movl    %cr3,%eax
812         ret
813
814 /* void load_cr3(caddr_t cr3) */
815 ENTRY(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() */
824 ENTRY(rcr4)
825         movl    %cr4,%eax
826         ret
827
828 /* void load_cr4(caddr_t cr4) */
829 ENTRY(load_cr4)
830         movl    4(%esp),%eax
831         movl    %eax,%cr4
832         ret
833
834 /* void reset_dbregs() */
835 ENTRY(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
849 ENTRY(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
861 ENTRY(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
882 bbhead:
883         .long 0
884
885         .text
886 NON_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' */