Merge from vendor branch LIBPCAP:
[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.19 2007/01/08 03:33:42 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_MAX_USER_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_MAX_USER_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_MAX_USER_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_MAX_USER_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  * fusword - MP SAFE
369  */
370 ENTRY(fusword)
371         movl    PCPU(curthread),%ecx
372         movl    TD_PCB(%ecx),%ecx
373         movl    $fusufault,PCB_ONFAULT(%ecx)
374         movl    4(%esp),%edx
375
376         cmpl    $VM_MAX_USER_ADDRESS-2,%edx
377         ja      fusufault
378
379         movzwl  (%edx),%eax
380         movl    $0,PCB_ONFAULT(%ecx)
381         ret
382
383 /*
384  * fubyte - MP SAFE
385  */
386 ENTRY(fubyte)
387         movl    PCPU(curthread),%ecx
388         movl    TD_PCB(%ecx),%ecx
389         movl    $fusufault,PCB_ONFAULT(%ecx)
390         movl    4(%esp),%edx
391
392         cmpl    $VM_MAX_USER_ADDRESS-1,%edx
393         ja      fusufault
394
395         movzbl  (%edx),%eax
396         movl    $0,PCB_ONFAULT(%ecx)
397         ret
398
399         ALIGN_TEXT
400 fusufault:
401         movl    PCPU(curthread),%ecx
402         movl    TD_PCB(%ecx),%ecx
403         xorl    %eax,%eax
404         movl    %eax,PCB_ONFAULT(%ecx)
405         decl    %eax
406         ret
407
408 /*
409  * su{byte,sword,word} - MP SAFE (if not I386_CPU)
410  *
411  *      Write a byte (word, longword) to user memory
412  */
413 ENTRY(suword)
414         movl    PCPU(curthread),%ecx
415         movl    TD_PCB(%ecx),%ecx
416         movl    $fusufault,PCB_ONFAULT(%ecx)
417         movl    4(%esp),%edx
418
419 #if defined(I386_CPU)
420
421 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
422         cmpl    $CPUCLASS_386,cpu_class
423         jne     2f                              /* we only have to set the right segment selector */
424 #endif /* I486_CPU || I586_CPU || I686_CPU */
425
426         /* XXX - page boundary crossing is still not handled */
427         movl    %edx,%eax
428         shrl    $IDXSHIFT,%edx
429         andb    $0xfc,%dl
430
431         leal    PTmap(%edx),%ecx
432         shrl    $IDXSHIFT,%ecx
433         andb    $0xfc,%cl
434         testb   $PG_V,PTmap(%ecx)               /* PTE page must be valid */
435         je      4f
436         movb    PTmap(%edx),%dl
437         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
438         cmpb    $PG_V|PG_RW|PG_U,%dl
439         je      1f
440
441 4:
442         /* simulate a trap */
443         pushl   %eax
444         call    trapwrite
445         popl    %edx                            /* remove junk parameter from stack */
446         testl   %eax,%eax
447         jnz     fusufault
448 1:
449         movl    4(%esp),%edx
450 #endif
451
452 2:
453         cmpl    $VM_MAX_USER_ADDRESS-4,%edx     /* verify address validity */
454         ja      fusufault
455
456         movl    8(%esp),%eax
457         movl    %eax,(%edx)
458         xorl    %eax,%eax
459         movl    PCPU(curthread),%ecx
460         movl    TD_PCB(%ecx),%ecx
461         movl    %eax,PCB_ONFAULT(%ecx)
462         ret
463
464 /*
465  * susword - MP SAFE (if not I386_CPU)
466  */
467 ENTRY(susword)
468         movl    PCPU(curthread),%ecx
469         movl    TD_PCB(%ecx),%ecx
470         movl    $fusufault,PCB_ONFAULT(%ecx)
471         movl    4(%esp),%edx
472
473 #if defined(I386_CPU)
474
475 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
476         cmpl    $CPUCLASS_386,cpu_class
477         jne     2f
478 #endif /* I486_CPU || I586_CPU || I686_CPU */
479
480         /* XXX - page boundary crossing is still not handled */
481         movl    %edx,%eax
482         shrl    $IDXSHIFT,%edx
483         andb    $0xfc,%dl
484
485         leal    PTmap(%edx),%ecx
486         shrl    $IDXSHIFT,%ecx
487         andb    $0xfc,%cl
488         testb   $PG_V,PTmap(%ecx)               /* PTE page must be valid */
489         je      4f
490         movb    PTmap(%edx),%dl
491         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
492         cmpb    $PG_V|PG_RW|PG_U,%dl
493         je      1f
494
495 4:
496         /* simulate a trap */
497         pushl   %eax
498         call    trapwrite
499         popl    %edx                            /* remove junk parameter from stack */
500         testl   %eax,%eax
501         jnz     fusufault
502 1:
503         movl    4(%esp),%edx
504 #endif
505
506 2:
507         cmpl    $VM_MAX_USER_ADDRESS-2,%edx     /* verify address validity */
508         ja      fusufault
509
510         movw    8(%esp),%ax
511         movw    %ax,(%edx)
512         xorl    %eax,%eax
513         movl    PCPU(curthread),%ecx                    /* restore trashed register */
514         movl    TD_PCB(%ecx),%ecx
515         movl    %eax,PCB_ONFAULT(%ecx)
516         ret
517
518 /*
519  * subyte - MP SAFE (if not I386_CPU)
520  */
521 ENTRY(subyte)
522         movl    PCPU(curthread),%ecx
523         movl    TD_PCB(%ecx),%ecx
524         movl    $fusufault,PCB_ONFAULT(%ecx)
525         movl    4(%esp),%edx
526
527 #if defined(I386_CPU)
528
529 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
530         cmpl    $CPUCLASS_386,cpu_class
531         jne     2f
532 #endif /* I486_CPU || I586_CPU || I686_CPU */
533
534         movl    %edx,%eax
535         shrl    $IDXSHIFT,%edx
536         andb    $0xfc,%dl
537
538         leal    PTmap(%edx),%ecx
539         shrl    $IDXSHIFT,%ecx
540         andb    $0xfc,%cl
541         testb   $PG_V,PTmap(%ecx)               /* PTE page must be valid */
542         je      4f
543         movb    PTmap(%edx),%dl
544         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
545         cmpb    $PG_V|PG_RW|PG_U,%dl
546         je      1f
547
548 4:
549         /* simulate a trap */
550         pushl   %eax
551         call    trapwrite
552         popl    %edx                            /* remove junk parameter from stack */
553         testl   %eax,%eax
554         jnz     fusufault
555 1:
556         movl    4(%esp),%edx
557 #endif
558
559 2:
560         cmpl    $VM_MAX_USER_ADDRESS-1,%edx     /* verify address validity */
561         ja      fusufault
562
563         movb    8(%esp),%al
564         movb    %al,(%edx)
565         xorl    %eax,%eax
566         movl    PCPU(curthread),%ecx            /* restore trashed register */
567         movl    TD_PCB(%ecx),%ecx
568         movl    %eax,PCB_ONFAULT(%ecx)
569         ret
570
571 /*
572  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
573  *
574  *      copy a string from from to to, stop when a 0 character is reached.
575  *      return ENAMETOOLONG if string is longer than maxlen, and
576  *      EFAULT on protection violations. If lencopied is non-zero,
577  *      return the actual length in *lencopied.
578  */
579 ENTRY(copyinstr)
580         pushl   %esi
581         pushl   %edi
582         movl    PCPU(curthread),%ecx
583         movl    TD_PCB(%ecx),%ecx
584         movl    $cpystrflt,PCB_ONFAULT(%ecx)
585
586         movl    12(%esp),%esi                   /* %esi = from */
587         movl    16(%esp),%edi                   /* %edi = to */
588         movl    20(%esp),%edx                   /* %edx = maxlen */
589
590         movl    $VM_MAX_USER_ADDRESS,%eax
591
592         /* make sure 'from' is within bounds */
593         subl    %esi,%eax
594         jbe     cpystrflt
595
596         /* restrict maxlen to <= VM_MAX_USER_ADDRESS-from */
597         cmpl    %edx,%eax
598         jae     1f
599         movl    %eax,%edx
600         movl    %eax,20(%esp)
601 1:
602         incl    %edx
603         cld
604
605 2:
606         decl    %edx
607         jz      3f
608
609         lodsb
610         stosb
611         orb     %al,%al
612         jnz     2b
613
614         /* Success -- 0 byte reached */
615         decl    %edx
616         xorl    %eax,%eax
617         jmp     cpystrflt_x
618 3:
619         /* edx is zero - return ENAMETOOLONG or EFAULT */
620         cmpl    $VM_MAX_USER_ADDRESS,%esi
621         jae     cpystrflt
622 4:
623         movl    $ENAMETOOLONG,%eax
624         jmp     cpystrflt_x
625
626 cpystrflt:
627         movl    $EFAULT,%eax
628
629 cpystrflt_x:
630         /* set *lencopied and return %eax */
631         movl    PCPU(curthread),%ecx
632         movl    TD_PCB(%ecx),%ecx
633         movl    $0,PCB_ONFAULT(%ecx)
634         movl    20(%esp),%ecx
635         subl    %edx,%ecx
636         movl    24(%esp),%edx
637         testl   %edx,%edx
638         jz      1f
639         movl    %ecx,(%edx)
640 1:
641         popl    %edi
642         popl    %esi
643         ret
644
645
646 /*
647  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
648  */
649 ENTRY(copystr)
650         pushl   %esi
651         pushl   %edi
652
653         movl    12(%esp),%esi                   /* %esi = from */
654         movl    16(%esp),%edi                   /* %edi = to */
655         movl    20(%esp),%edx                   /* %edx = maxlen */
656         incl    %edx
657         cld
658 1:
659         decl    %edx
660         jz      4f
661         lodsb
662         stosb
663         orb     %al,%al
664         jnz     1b
665
666         /* Success -- 0 byte reached */
667         decl    %edx
668         xorl    %eax,%eax
669         jmp     6f
670 4:
671         /* edx is zero -- return ENAMETOOLONG */
672         movl    $ENAMETOOLONG,%eax
673
674 6:
675         /* set *lencopied and return %eax */
676         movl    20(%esp),%ecx
677         subl    %edx,%ecx
678         movl    24(%esp),%edx
679         testl   %edx,%edx
680         jz      7f
681         movl    %ecx,(%edx)
682 7:
683         popl    %edi
684         popl    %esi
685         ret
686
687 ENTRY(bcmp)
688         pushl   %edi
689         pushl   %esi
690         movl    12(%esp),%edi
691         movl    16(%esp),%esi
692         movl    20(%esp),%edx
693         xorl    %eax,%eax
694
695         movl    %edx,%ecx
696         shrl    $2,%ecx
697         cld                                     /* compare forwards */
698         repe
699         cmpsl
700         jne     1f
701
702         movl    %edx,%ecx
703         andl    $3,%ecx
704         repe
705         cmpsb
706         je      2f
707 1:
708         incl    %eax
709 2:
710         popl    %esi
711         popl    %edi
712         ret
713
714
715 /*
716  * Handling of special 386 registers and descriptor tables etc
717  */
718 /* void lgdt(struct region_descriptor *rdp); */
719 ENTRY(lgdt)
720         /* reload the descriptor table */
721         movl    4(%esp),%eax
722         lgdt    (%eax)
723
724         /* flush the prefetch q */
725         jmp     1f
726         nop
727 1:
728         /* reload "stale" selectors */
729         movl    $KDSEL,%eax
730         mov     %ax,%ds
731         mov     %ax,%es
732         mov     %ax,%gs
733         mov     %ax,%ss
734         movl    $KPSEL,%eax
735         mov     %ax,%fs
736         mov     %ax,%gs
737
738         /* reload code selector by turning return into intersegmental return */
739         movl    (%esp),%eax
740         pushl   %eax
741         movl    $KCSEL,4(%esp)
742         lret
743
744 /*
745  * void lidt(struct region_descriptor *rdp);
746  */
747 ENTRY(lidt)
748         movl    4(%esp),%eax
749         lidt    (%eax)
750         ret
751
752 /*
753  * void lldt(u_short sel)
754  */
755 ENTRY(lldt)
756         lldt    4(%esp)
757         ret
758
759 /*
760  * void ltr(u_short sel)
761  */
762 ENTRY(ltr)
763         ltr     4(%esp)
764         ret
765
766 /* ssdtosd(*ssdp,*sdp) */
767 ENTRY(ssdtosd)
768         pushl   %ebx
769         movl    8(%esp),%ecx
770         movl    8(%ecx),%ebx
771         shll    $16,%ebx
772         movl    (%ecx),%edx
773         roll    $16,%edx
774         movb    %dh,%bl
775         movb    %dl,%bh
776         rorl    $8,%ebx
777         movl    4(%ecx),%eax
778         movw    %ax,%dx
779         andl    $0xf0000,%eax
780         orl     %eax,%ebx
781         movl    12(%esp),%ecx
782         movl    %edx,(%ecx)
783         movl    %ebx,4(%ecx)
784         popl    %ebx
785         ret
786
787 /* load_cr0(cr0) */
788 ENTRY(load_cr0)
789         movl    4(%esp),%eax
790         movl    %eax,%cr0
791         ret
792
793 /* rcr0() */
794 ENTRY(rcr0)
795         movl    %cr0,%eax
796         ret
797
798 /* rcr3() */
799 ENTRY(rcr3)
800         movl    %cr3,%eax
801         ret
802
803 /* void load_cr3(caddr_t cr3) */
804 ENTRY(load_cr3)
805 #if defined(SWTCH_OPTIM_STATS)
806         incl    _tlb_flush_count
807 #endif
808         movl    4(%esp),%eax
809         movl    %eax,%cr3
810         ret
811
812 /* rcr4() */
813 ENTRY(rcr4)
814         movl    %cr4,%eax
815         ret
816
817 /* void load_cr4(caddr_t cr4) */
818 ENTRY(load_cr4)
819         movl    4(%esp),%eax
820         movl    %eax,%cr4
821         ret
822
823 /* void reset_dbregs() */
824 ENTRY(reset_dbregs)
825         movl    $0,%eax
826         movl    %eax,%dr7     /* disable all breapoints first */
827         movl    %eax,%dr0
828         movl    %eax,%dr1
829         movl    %eax,%dr2
830         movl    %eax,%dr3
831         movl    %eax,%dr6
832         ret
833
834 /*****************************************************************************/
835 /* setjump, longjump                                                         */
836 /*****************************************************************************/
837
838 ENTRY(setjmp)
839         movl    4(%esp),%eax
840         movl    %ebx,(%eax)                     /* save ebx */
841         movl    %esp,4(%eax)                    /* save esp */
842         movl    %ebp,8(%eax)                    /* save ebp */
843         movl    %esi,12(%eax)                   /* save esi */
844         movl    %edi,16(%eax)                   /* save edi */
845         movl    (%esp),%edx                     /* get rta */
846         movl    %edx,20(%eax)                   /* save eip */
847         xorl    %eax,%eax                       /* return(0); */
848         ret
849
850 ENTRY(longjmp)
851         movl    4(%esp),%eax
852         movl    (%eax),%ebx                     /* restore ebx */
853         movl    4(%eax),%esp                    /* restore esp */
854         movl    8(%eax),%ebp                    /* restore ebp */
855         movl    12(%eax),%esi                   /* restore esi */
856         movl    16(%eax),%edi                   /* restore edi */
857         movl    20(%eax),%edx                   /* get rta */
858         movl    %edx,(%esp)                     /* put in return frame */
859         xorl    %eax,%eax                       /* return(1); */
860         incl    %eax
861         ret
862
863 /*
864  * Support for BB-profiling (gcc -a).  The kernbb program will extract
865  * the data from the kernel.
866  */
867
868         .data
869         ALIGN_DATA
870         .globl bbhead
871 bbhead:
872         .long 0
873
874         .text
875 NON_GPROF_ENTRY(__bb_init_func)
876         movl    4(%esp),%eax
877         movl    $1,(%eax)
878         movl    bbhead,%edx
879         movl    %edx,16(%eax)
880         movl    %eax,bbhead
881         .byte   0xc3                            /* avoid macro for `ret' */