kernel: Make SMP support default (and non-optional).
[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  */
35
36 #include <machine/asmacros.h>
37 #include <machine/cputypes.h>
38 #include <machine/pmap.h>
39 #include <machine/specialreg.h>
40
41 #include "assym.s"
42
43 #define IDXSHIFT        10
44
45         .data
46
47         .globl  memcpy_vector
48 memcpy_vector:
49         .long   asm_generic_memcpy
50
51         .globl  bcopy_vector
52 bcopy_vector:
53         .long   asm_generic_bcopy
54
55         .globl  ovbcopy_vector
56 ovbcopy_vector:
57         .long   asm_generic_bcopy
58
59         .text
60
61 /* fillw(pat, base, cnt) */
62 ENTRY(fillw)
63         pushl   %edi
64         movl    8(%esp),%eax
65         movl    12(%esp),%edi
66         movl    16(%esp),%ecx
67         cld
68         rep
69         stosw
70         popl    %edi
71         ret
72
73 /*
74  * void bcopy(const void *s, void *d, size_t count)
75  *
76  * Normal bcopy() vector, an optimized bcopy may be installed in
77  * bcopy_vector.
78  */
79 ENTRY(bcopy)
80         pushl   %esi
81         pushl   %edi
82         movl    4+8(%esp),%esi                  /* caddr_t from */
83         movl    8+8(%esp),%edi                  /* caddr_t to */
84         movl    12+8(%esp),%ecx                 /* size_t  len */
85         call    *bcopy_vector
86         popl    %edi
87         popl    %esi
88         ret
89
90 /*
91  * Generic (integer-only) bcopy() vector.
92  */
93 ENTRY(generic_bcopy)
94         pushl   %esi
95         pushl   %edi
96         movl    4+8(%esp),%esi                  /* caddr_t from */
97         movl    8+8(%esp),%edi                  /* caddr_t to */
98         movl    12+8(%esp),%ecx                 /* size_t  len */
99         call    asm_generic_bcopy
100         popl    %edi
101         popl    %esi
102         ret
103
104 ENTRY(ovbcopy)
105         pushl   %esi
106         pushl   %edi
107         movl    4+8(%esp),%esi                  /* caddr_t from */
108         movl    8+8(%esp),%edi                  /* caddr_t to */
109         movl    12+8(%esp),%ecx                 /* size_t  len */
110         call    *ovbcopy_vector
111         popl    %edi
112         popl    %esi
113         ret
114
115 /*
116  * void *memcpy(void *d, const void *s, size_t count)
117  *
118  * Note: memcpy does not have to support overlapping copies.
119  *
120  * Note: (d, s) arguments reversed from bcopy, and memcpy() returns d
121  * while bcopy() returns void.
122  */
123 ENTRY(memcpy)
124         pushl   %esi
125         pushl   %edi
126         movl    4+8(%esp),%edi
127         movl    8+8(%esp),%esi
128         movl    12+8(%esp),%ecx
129         call    *memcpy_vector
130         movl    4+8(%esp),%eax
131         popl    %edi
132         popl    %esi
133         ret
134
135 /*
136  * A stack-based on-fault routine is used for more complex PCB_ONFAULT
137  * situations (such as memcpy/bcopy/bzero).  In this case the on-fault
138  * routine must be pushed on the stack.
139  */
140 stack_onfault:
141         ret
142
143 /*****************************************************************************/
144 /* copyout and fubyte family                                                 */
145 /*****************************************************************************/
146 /*
147  * Access user memory from inside the kernel. These routines and possibly
148  * the math- and DOS emulators should be the only places that do this.
149  *
150  * We have to access the memory with user's permissions, so use a segment
151  * selector with RPL 3. For writes to user space we have to additionally
152  * check the PTE for write permission, because the 386 does not check
153  * write permissions when we are executing with EPL 0. The 486 does check
154  * this if the WP bit is set in CR0, so we can use a simpler version here.
155  *
156  * These routines set curpcb->onfault for the time they execute. When a
157  * protection violation occurs inside the functions, the trap handler
158  * returns to *curpcb->onfault instead of the function.
159  */
160
161 /*
162  * copyout(from_kernel, to_user, len)  - MP SAFE
163  */
164 ENTRY(copyout)
165         movl    PCPU(curthread),%eax
166         movl    TD_PCB(%eax),%eax
167         pushl   %esi
168         pushl   %edi
169         pushl   %ebx
170         pushl   $copyout_fault2
171         movl    $stack_onfault,PCB_ONFAULT(%eax)
172         movl    %esp,PCB_ONFAULT_SP(%eax)
173         subl    $12,PCB_ONFAULT_SP(%eax)        /* call,ebx,stackedfault */
174                                                 /* for *memcpy_vector */
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         /*
204          * Convert copyout to memcpy_vector(dest:%edi, src:%esi, count:%ecx)
205          */
206         movl    %ebx,%ecx
207         call    *memcpy_vector
208
209 done_copyout:
210         /*
211          * non-error return
212          */
213         addl    $4,%esp
214         movl    PCPU(curthread),%edx
215         xorl    %eax,%eax
216         movl    TD_PCB(%edx),%edx
217         popl    %ebx
218         popl    %edi
219         popl    %esi
220         movl    %eax,PCB_ONFAULT(%edx)
221         ret
222
223         ALIGN_TEXT
224 copyout_fault1:
225         addl    $4,%esp         /* skip pushed copyout_fault vector */
226 copyout_fault2:
227         popl    %ebx
228         popl    %edi
229         popl    %esi
230         movl    PCPU(curthread),%edx
231         movl    TD_PCB(%edx),%edx
232         movl    $0,PCB_ONFAULT(%edx)
233         movl    $EFAULT,%eax
234         ret
235
236 /*
237  * copyin(from_user, to_kernel, len) - MP SAFE
238  */
239
240 ENTRY(copyin)
241         movl    PCPU(curthread),%eax
242         movl    TD_PCB(%eax),%eax
243         pushl   %esi
244         pushl   %edi
245         pushl   $copyin_fault2
246         movl    $stack_onfault,PCB_ONFAULT(%eax)
247         movl    %esp,PCB_ONFAULT_SP(%eax)
248         subl    $12,PCB_ONFAULT_SP(%eax)        /* call,ebx,stackedfault */
249                                                 /* for *memcpy_vector */
250         movl    4+12(%esp),%esi                 /* caddr_t from */
251         movl    8+12(%esp),%edi                 /* caddr_t to */
252         movl    12+12(%esp),%ecx                /* size_t  len */
253
254         /*
255          * make sure address is valid
256          */
257         movl    %esi,%edx
258         addl    %ecx,%edx
259         jc      copyin_fault1
260         cmpl    $VM_MAX_USER_ADDRESS,%edx
261         ja      copyin_fault1
262
263         /*
264          * Call memcpy(destination:%edi, source:%esi, bytes:%ecx)
265          */
266         call    *memcpy_vector
267
268         /*
269          * return 0 (no error)
270          */
271         addl    $4,%esp
272         movl    PCPU(curthread),%edx
273         xorl    %eax,%eax
274         movl    TD_PCB(%edx),%edx
275         popl    %edi
276         popl    %esi
277         movl    %eax,PCB_ONFAULT(%edx)
278         ret
279
280         /*
281          * return EFAULT
282          */
283         ALIGN_TEXT
284 copyin_fault1:
285         addl    $4,%esp         /* skip pushed copyin_fault vector */
286 copyin_fault2:
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  * casuword.  Compare and set user word.  Returns -1 or the current value.
297  */
298
299 ENTRY(casuword)
300         movl    PCPU(curthread),%ecx
301         movl    TD_PCB(%ecx),%ecx
302         movl    $fusufault,PCB_ONFAULT(%ecx)
303         movl    %esp,PCB_ONFAULT_SP(%ecx)
304         movl    4(%esp),%edx                    /* dst */
305         movl    8(%esp),%eax                    /* old */
306         movl    12(%esp),%ecx                   /* new */
307
308         cmpl    $VM_MAX_USER_ADDRESS-4,%edx     /* verify address is valid */
309         ja      fusufault
310
311         lock
312         cmpxchgl %ecx,(%edx)                    /* Compare and set. */
313
314         /*
315          * The old value is in %eax.  If the store succeeded it will be the
316          * value we expected (old) from before the store, otherwise it will
317          * be the current value.
318          */
319
320         movl    PCPU(curthread),%ecx
321         movl    TD_PCB(%ecx),%ecx
322         movl    $0,PCB_ONFAULT(%ecx)
323         ret
324 END(casuword)
325
326 /*
327  * fu{byte,sword,word} - MP SAFE
328  *
329  *      Fetch a byte (sword, word) from user memory
330  */
331 ENTRY(fuword)
332         movl    PCPU(curthread),%ecx
333         movl    TD_PCB(%ecx),%ecx
334         movl    $fusufault,PCB_ONFAULT(%ecx)
335         movl    %esp,PCB_ONFAULT_SP(%ecx)
336         movl    4(%esp),%edx                    /* from */
337
338         cmpl    $VM_MAX_USER_ADDRESS-4,%edx     /* verify address is valid */
339         ja      fusufault
340
341         movl    (%edx),%eax
342         movl    $0,PCB_ONFAULT(%ecx)
343         ret
344
345 /*
346  * fusword - MP SAFE
347  */
348 ENTRY(fusword)
349         movl    PCPU(curthread),%ecx
350         movl    TD_PCB(%ecx),%ecx
351         movl    $fusufault,PCB_ONFAULT(%ecx)
352         movl    %esp,PCB_ONFAULT_SP(%ecx)
353         movl    4(%esp),%edx
354
355         cmpl    $VM_MAX_USER_ADDRESS-2,%edx
356         ja      fusufault
357
358         movzwl  (%edx),%eax
359         movl    $0,PCB_ONFAULT(%ecx)
360         ret
361
362 /*
363  * fubyte - MP SAFE
364  */
365 ENTRY(fubyte)
366         movl    PCPU(curthread),%ecx
367         movl    TD_PCB(%ecx),%ecx
368         movl    $fusufault,PCB_ONFAULT(%ecx)
369         movl    %esp,PCB_ONFAULT_SP(%ecx)
370         movl    4(%esp),%edx
371
372         cmpl    $VM_MAX_USER_ADDRESS-1,%edx
373         ja      fusufault
374
375         movzbl  (%edx),%eax
376         movl    $0,PCB_ONFAULT(%ecx)
377         ret
378
379         ALIGN_TEXT
380 fusufault:
381         movl    PCPU(curthread),%ecx
382         movl    TD_PCB(%ecx),%ecx
383         xorl    %eax,%eax
384         movl    %eax,PCB_ONFAULT(%ecx)
385         decl    %eax
386         ret
387
388 /*
389  * su{byte,sword,word,word32} - MP SAFE
390  *
391  *      Write a long to user memory
392  */
393 ENTRY(suword)
394         movl    PCPU(curthread),%ecx
395         movl    TD_PCB(%ecx),%ecx
396         movl    $fusufault,PCB_ONFAULT(%ecx)
397         movl    %esp,PCB_ONFAULT_SP(%ecx)
398         movl    4(%esp),%edx
399
400         cmpl    $VM_MAX_USER_ADDRESS-4,%edx     /* verify address validity */
401         ja      fusufault
402
403         movl    8(%esp),%eax
404         movl    %eax,(%edx)
405         xorl    %eax,%eax
406         movl    PCPU(curthread),%ecx
407         movl    TD_PCB(%ecx),%ecx
408         movl    %eax,PCB_ONFAULT(%ecx)
409         ret
410
411 /*
412  * Write an integer to user memory
413  */
414 ENTRY(suword32)
415         movl    PCPU(curthread),%ecx
416         movl    TD_PCB(%ecx),%ecx
417         movl    $fusufault,PCB_ONFAULT(%ecx)
418         movl    %esp,PCB_ONFAULT_SP(%ecx)
419         movl    4(%esp),%edx
420
421         cmpl    $VM_MAX_USER_ADDRESS-4,%edx     /* verify address validity */
422         ja      fusufault
423
424         movl    8(%esp),%eax
425         movl    %eax,(%edx)
426         xorl    %eax,%eax
427         movl    PCPU(curthread),%ecx
428         movl    TD_PCB(%ecx),%ecx
429         movl    %eax,PCB_ONFAULT(%ecx)
430         ret
431
432 /*
433  * susword - MP SAFE
434  */
435 ENTRY(susword)
436         movl    PCPU(curthread),%ecx
437         movl    TD_PCB(%ecx),%ecx
438         movl    $fusufault,PCB_ONFAULT(%ecx)
439         movl    %esp,PCB_ONFAULT_SP(%ecx)
440         movl    4(%esp),%edx
441
442         cmpl    $VM_MAX_USER_ADDRESS-2,%edx     /* verify address validity */
443         ja      fusufault
444
445         movw    8(%esp),%ax
446         movw    %ax,(%edx)
447         xorl    %eax,%eax
448         movl    PCPU(curthread),%ecx                    /* restore trashed register */
449         movl    TD_PCB(%ecx),%ecx
450         movl    %eax,PCB_ONFAULT(%ecx)
451         ret
452
453 /*
454  * subyte - MP SAFE
455  */
456 ENTRY(subyte)
457         movl    PCPU(curthread),%ecx
458         movl    TD_PCB(%ecx),%ecx
459         movl    $fusufault,PCB_ONFAULT(%ecx)
460         movl    %esp,PCB_ONFAULT_SP(%ecx)
461         movl    4(%esp),%edx
462
463         cmpl    $VM_MAX_USER_ADDRESS-1,%edx     /* verify address validity */
464         ja      fusufault
465
466         movb    8(%esp),%al
467         movb    %al,(%edx)
468         xorl    %eax,%eax
469         movl    PCPU(curthread),%ecx            /* restore trashed register */
470         movl    TD_PCB(%ecx),%ecx
471         movl    %eax,PCB_ONFAULT(%ecx)
472         ret
473
474 /*
475  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
476  *
477  *      copy a string from from to to, stop when a 0 character is reached.
478  *      return ENAMETOOLONG if string is longer than maxlen, and
479  *      EFAULT on protection violations. If lencopied is non-zero,
480  *      return the actual length in *lencopied.
481  */
482 ENTRY(copyinstr)
483         pushl   %esi
484         pushl   %edi
485         movl    PCPU(curthread),%ecx
486         movl    TD_PCB(%ecx),%ecx
487         movl    $cpystrflt,PCB_ONFAULT(%ecx)
488         movl    %esp,PCB_ONFAULT_SP(%ecx)
489
490         movl    12(%esp),%esi                   /* %esi = from */
491         movl    16(%esp),%edi                   /* %edi = to */
492         movl    20(%esp),%edx                   /* %edx = maxlen */
493
494         movl    $VM_MAX_USER_ADDRESS,%eax
495
496         /* make sure 'from' is within bounds */
497         subl    %esi,%eax
498         jbe     cpystrflt
499
500         /* restrict maxlen to <= VM_MAX_USER_ADDRESS-from */
501         cmpl    %edx,%eax
502         jae     1f
503         movl    %eax,%edx
504         movl    %eax,20(%esp)
505 1:
506         incl    %edx
507         cld
508
509 2:
510         decl    %edx
511         jz      3f
512
513         lodsb
514         stosb
515         orb     %al,%al
516         jnz     2b
517
518         /* Success -- 0 byte reached */
519         decl    %edx
520         xorl    %eax,%eax
521         jmp     cpystrflt_x
522 3:
523         /* edx is zero - return ENAMETOOLONG or EFAULT */
524         cmpl    $VM_MAX_USER_ADDRESS,%esi
525         jae     cpystrflt
526 4:
527         movl    $ENAMETOOLONG,%eax
528         jmp     cpystrflt_x
529
530 cpystrflt:
531         movl    $EFAULT,%eax
532
533 cpystrflt_x:
534         /* set *lencopied and return %eax */
535         movl    PCPU(curthread),%ecx
536         movl    TD_PCB(%ecx),%ecx
537         movl    $0,PCB_ONFAULT(%ecx)
538         movl    20(%esp),%ecx
539         subl    %edx,%ecx
540         movl    24(%esp),%edx
541         testl   %edx,%edx
542         jz      1f
543         movl    %ecx,(%edx)
544 1:
545         popl    %edi
546         popl    %esi
547         ret
548
549
550 /*
551  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
552  */
553 ENTRY(copystr)
554         pushl   %esi
555         pushl   %edi
556
557         movl    12(%esp),%esi                   /* %esi = from */
558         movl    16(%esp),%edi                   /* %edi = to */
559         movl    20(%esp),%edx                   /* %edx = maxlen */
560         incl    %edx
561         cld
562 1:
563         decl    %edx
564         jz      4f
565         lodsb
566         stosb
567         orb     %al,%al
568         jnz     1b
569
570         /* Success -- 0 byte reached */
571         decl    %edx
572         xorl    %eax,%eax
573         jmp     6f
574 4:
575         /* edx is zero -- return ENAMETOOLONG */
576         movl    $ENAMETOOLONG,%eax
577
578 6:
579         /* set *lencopied and return %eax */
580         movl    20(%esp),%ecx
581         subl    %edx,%ecx
582         movl    24(%esp),%edx
583         testl   %edx,%edx
584         jz      7f
585         movl    %ecx,(%edx)
586 7:
587         popl    %edi
588         popl    %esi
589         ret
590
591 ENTRY(bcmp)
592         pushl   %edi
593         pushl   %esi
594         movl    12(%esp),%edi
595         movl    16(%esp),%esi
596         movl    20(%esp),%edx
597         xorl    %eax,%eax
598
599         movl    %edx,%ecx
600         shrl    $2,%ecx
601         cld                                     /* compare forwards */
602         repe
603         cmpsl
604         jne     1f
605
606         movl    %edx,%ecx
607         andl    $3,%ecx
608         repe
609         cmpsb
610         je      2f
611 1:
612         incl    %eax
613 2:
614         popl    %esi
615         popl    %edi
616         ret
617
618
619 /*
620  * Handling of special 386 registers and descriptor tables etc
621  */
622 /* void lgdt(struct region_descriptor *rdp); */
623 ENTRY(lgdt)
624         /* reload the descriptor table */
625         movl    4(%esp),%eax
626         lgdt    (%eax)
627
628         /* flush the prefetch q */
629         jmp     1f
630         nop
631 1:
632         /* reload "stale" selectors */
633         movl    $KDSEL,%eax
634         mov     %ax,%ds
635         mov     %ax,%es
636         mov     %ax,%gs
637         mov     %ax,%ss
638         movl    $KPSEL,%eax
639         mov     %ax,%fs
640         mov     %ax,%gs
641
642         /* reload code selector by turning return into intersegmental return */
643         movl    (%esp),%eax
644         pushl   %eax
645         movl    $KCSEL,4(%esp)
646         lret
647
648 /*
649  * void lidt(struct region_descriptor *rdp);
650  */
651 ENTRY(lidt)
652         movl    4(%esp),%eax
653         lidt    (%eax)
654         ret
655
656 /*
657  * void lldt(u_short sel)
658  */
659 ENTRY(lldt)
660         lldt    4(%esp)
661         ret
662
663 /*
664  * void ltr(u_short sel)
665  */
666 ENTRY(ltr)
667         ltr     4(%esp)
668         ret
669
670 /* ssdtosd(*ssdp,*sdp) */
671 ENTRY(ssdtosd)
672         pushl   %ebx
673         movl    8(%esp),%ecx
674         movl    8(%ecx),%ebx
675         shll    $16,%ebx
676         movl    (%ecx),%edx
677         roll    $16,%edx
678         movb    %dh,%bl
679         movb    %dl,%bh
680         rorl    $8,%ebx
681         movl    4(%ecx),%eax
682         movw    %ax,%dx
683         andl    $0xf0000,%eax
684         orl     %eax,%ebx
685         movl    12(%esp),%ecx
686         movl    %edx,(%ecx)
687         movl    %ebx,4(%ecx)
688         popl    %ebx
689         ret
690
691 /* load_cr0(cr0) */
692 ENTRY(load_cr0)
693         movl    4(%esp),%eax
694         movl    %eax,%cr0
695         ret
696
697 /* rcr0() */
698 ENTRY(rcr0)
699         movl    %cr0,%eax
700         ret
701
702 /* rcr3() */
703 ENTRY(rcr3)
704         movl    %cr3,%eax
705         ret
706
707 /* void load_cr3(caddr_t cr3) */
708 ENTRY(load_cr3)
709 #if defined(SWTCH_OPTIM_STATS)
710         incl    _tlb_flush_count
711 #endif
712         movl    4(%esp),%eax
713         movl    %eax,%cr3
714         ret
715
716 /* rcr4() */
717 ENTRY(rcr4)
718         movl    %cr4,%eax
719         ret
720
721 /* void load_cr4(caddr_t cr4) */
722 ENTRY(load_cr4)
723         movl    4(%esp),%eax
724         movl    %eax,%cr4
725         ret
726
727 /* void reset_dbregs() */
728 ENTRY(reset_dbregs)
729         movl    $0,%eax
730         movl    %eax,%dr7     /* disable all breapoints first */
731         movl    %eax,%dr0
732         movl    %eax,%dr1
733         movl    %eax,%dr2
734         movl    %eax,%dr3
735         movl    %eax,%dr6
736         ret
737
738 /*****************************************************************************/
739 /* setjump, longjump                                                         */
740 /*****************************************************************************/
741
742 ENTRY(setjmp)
743         movl    4(%esp),%eax
744         movl    %ebx,(%eax)                     /* save ebx */
745         movl    %esp,4(%eax)                    /* save esp */
746         movl    %ebp,8(%eax)                    /* save ebp */
747         movl    %esi,12(%eax)                   /* save esi */
748         movl    %edi,16(%eax)                   /* save edi */
749         movl    (%esp),%edx                     /* get rta */
750         movl    %edx,20(%eax)                   /* save eip */
751         xorl    %eax,%eax                       /* return(0); */
752         ret
753
754 ENTRY(longjmp)
755         movl    4(%esp),%eax
756         movl    (%eax),%ebx                     /* restore ebx */
757         movl    4(%eax),%esp                    /* restore esp */
758         movl    8(%eax),%ebp                    /* restore ebp */
759         movl    12(%eax),%esi                   /* restore esi */
760         movl    16(%eax),%edi                   /* restore edi */
761         movl    20(%eax),%edx                   /* get rta */
762         movl    %edx,(%esp)                     /* put in return frame */
763         xorl    %eax,%eax                       /* return(1); */
764         incl    %eax
765         ret
766
767 /*
768  * Support for reading MSRs in the safe manner.
769  */
770 ENTRY(rdmsr_safe)
771 /* int rdmsr_safe(u_int msr, uint64_t *data) */
772         movl    PCPU(curthread),%ecx
773         movl    TD_PCB(%ecx), %ecx
774         movl    $msr_onfault,PCB_ONFAULT(%ecx)
775         movl    %esp,PCB_ONFAULT_SP(%ecx)
776
777         movl    4(%esp),%ecx
778         rdmsr
779         movl    8(%esp),%ecx
780         movl    %eax,(%ecx)
781         movl    %edx,4(%ecx)
782         xorl    %eax,%eax
783
784         movl    PCPU(curthread),%ecx
785         movl    TD_PCB(%ecx), %ecx
786         movl    %eax,PCB_ONFAULT(%ecx)
787
788         ret
789
790 /*
791  * MSR operations fault handler
792  */
793         ALIGN_TEXT
794 msr_onfault:
795         movl    PCPU(curthread),%ecx
796         movl    TD_PCB(%ecx), %ecx
797         movl    $0,PCB_ONFAULT(%ecx)
798         movl    $EFAULT,%eax
799         ret
800
801 /*
802  * Support for BB-profiling (gcc -a).  The kernbb program will extract
803  * the data from the kernel.
804  */
805
806         .data
807         ALIGN_DATA
808         .globl bbhead
809 bbhead:
810         .long 0
811
812         .text
813 NON_GPROF_ENTRY(__bb_init_func)
814         movl    4(%esp),%eax
815         movl    $1,(%eax)
816         movl    bbhead,%edx
817         movl    %edx,16(%eax)
818         movl    %eax,bbhead
819         .byte   0xc3                            /* avoid macro for `ret' */