]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/i386/i386/support.s
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / i386 / 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  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include "opt_npx.h"
33
34 #include <machine/asmacros.h>
35 #include <machine/cputypes.h>
36 #include <machine/intr_machdep.h>
37 #include <machine/pmap.h>
38 #include <machine/specialreg.h>
39
40 #include "assym.s"
41
42 #define IDXSHIFT        10
43
44         .text
45
46 /*
47  * bcopy family
48  * void bzero(void *buf, u_int len)
49  */
50 ENTRY(bzero)
51         pushl   %edi
52         movl    8(%esp),%edi
53         movl    12(%esp),%ecx
54         xorl    %eax,%eax
55         shrl    $2,%ecx
56         cld
57         rep
58         stosl
59         movl    12(%esp),%ecx
60         andl    $3,%ecx
61         rep
62         stosb
63         popl    %edi
64         ret
65 END(bzero)      
66         
67 ENTRY(sse2_pagezero)
68         pushl   %ebx
69         movl    8(%esp),%ecx
70         movl    %ecx,%eax
71         addl    $4096,%eax
72         xor     %ebx,%ebx
73 1:
74         movnti  %ebx,(%ecx)
75         addl    $4,%ecx
76         cmpl    %ecx,%eax
77         jne     1b
78         sfence
79         popl    %ebx
80         ret
81 END(sse2_pagezero)
82
83 ENTRY(i686_pagezero)
84         pushl   %edi
85         pushl   %ebx
86
87         movl    12(%esp),%edi
88         movl    $1024,%ecx
89         cld
90
91         ALIGN_TEXT
92 1:
93         xorl    %eax,%eax
94         repe
95         scasl
96         jnz     2f
97
98         popl    %ebx
99         popl    %edi
100         ret
101
102         ALIGN_TEXT
103
104 2:
105         incl    %ecx
106         subl    $4,%edi
107
108         movl    %ecx,%edx
109         cmpl    $16,%ecx
110
111         jge     3f
112
113         movl    %edi,%ebx
114         andl    $0x3f,%ebx
115         shrl    %ebx
116         shrl    %ebx
117         movl    $16,%ecx
118         subl    %ebx,%ecx
119
120 3:
121         subl    %ecx,%edx
122         rep
123         stosl
124
125         movl    %edx,%ecx
126         testl   %edx,%edx
127         jnz     1b
128
129         popl    %ebx
130         popl    %edi
131         ret
132 END(i686_pagezero)
133
134 /* fillw(pat, base, cnt) */
135 ENTRY(fillw)
136         pushl   %edi
137         movl    8(%esp),%eax
138         movl    12(%esp),%edi
139         movl    16(%esp),%ecx
140         cld
141         rep
142         stosw
143         popl    %edi
144         ret
145 END(fillw)
146
147 ENTRY(bcopyb)
148         pushl   %esi
149         pushl   %edi
150         movl    12(%esp),%esi
151         movl    16(%esp),%edi
152         movl    20(%esp),%ecx
153         movl    %edi,%eax
154         subl    %esi,%eax
155         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
156         jb      1f
157         cld                                     /* nope, copy forwards */
158         rep
159         movsb
160         popl    %edi
161         popl    %esi
162         ret
163
164         ALIGN_TEXT
165 1:
166         addl    %ecx,%edi                       /* copy backwards. */
167         addl    %ecx,%esi
168         decl    %edi
169         decl    %esi
170         std
171         rep
172         movsb
173         popl    %edi
174         popl    %esi
175         cld
176         ret
177 END(bcopyb)
178
179 /*
180  * bcopy(src, dst, cnt)
181  *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
182  */
183 ENTRY(bcopy)
184         pushl   %ebp
185         movl    %esp,%ebp
186         pushl   %esi
187         pushl   %edi
188         movl    8(%ebp),%esi
189         movl    12(%ebp),%edi
190         movl    16(%ebp),%ecx
191
192         movl    %edi,%eax
193         subl    %esi,%eax
194         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
195         jb      1f
196
197         shrl    $2,%ecx                         /* copy by 32-bit words */
198         cld                                     /* nope, copy forwards */
199         rep
200         movsl
201         movl    16(%ebp),%ecx
202         andl    $3,%ecx                         /* any bytes left? */
203         rep
204         movsb
205         popl    %edi
206         popl    %esi
207         popl    %ebp
208         ret
209
210         ALIGN_TEXT
211 1:
212         addl    %ecx,%edi                       /* copy backwards */
213         addl    %ecx,%esi
214         decl    %edi
215         decl    %esi
216         andl    $3,%ecx                         /* any fractional bytes? */
217         std
218         rep
219         movsb
220         movl    16(%ebp),%ecx                   /* copy remainder by 32-bit words */
221         shrl    $2,%ecx
222         subl    $3,%esi
223         subl    $3,%edi
224         rep
225         movsl
226         popl    %edi
227         popl    %esi
228         cld
229         popl    %ebp
230         ret
231 END(bcopy)
232
233 /*
234  * Note: memcpy does not support overlapping copies
235  */
236 ENTRY(memcpy)
237         pushl   %edi
238         pushl   %esi
239         movl    12(%esp),%edi
240         movl    16(%esp),%esi
241         movl    20(%esp),%ecx
242         movl    %edi,%eax
243         shrl    $2,%ecx                         /* copy by 32-bit words */
244         cld                                     /* nope, copy forwards */
245         rep
246         movsl
247         movl    20(%esp),%ecx
248         andl    $3,%ecx                         /* any bytes left? */
249         rep
250         movsb
251         popl    %esi
252         popl    %edi
253         ret
254 END(memcpy)
255
256 /*****************************************************************************/
257 /* copyout and fubyte family                                                 */
258 /*****************************************************************************/
259 /*
260  * Access user memory from inside the kernel. These routines and possibly
261  * the math- and DOS emulators should be the only places that do this.
262  *
263  * We have to access the memory with user's permissions, so use a segment
264  * selector with RPL 3. For writes to user space we have to additionally
265  * check the PTE for write permission, because the 386 does not check
266  * write permissions when we are executing with EPL 0. The 486 does check
267  * this if the WP bit is set in CR0, so we can use a simpler version here.
268  *
269  * These routines set curpcb->pcb_onfault for the time they execute. When a
270  * protection violation occurs inside the functions, the trap handler
271  * returns to *curpcb->pcb_onfault instead of the function.
272  */
273
274 /*
275  * copyout(from_kernel, to_user, len)  - MP SAFE
276  */
277 ENTRY(copyout)
278         movl    PCPU(CURPCB),%eax
279         movl    $copyout_fault,PCB_ONFAULT(%eax)
280         pushl   %esi
281         pushl   %edi
282         pushl   %ebx
283         movl    16(%esp),%esi
284         movl    20(%esp),%edi
285         movl    24(%esp),%ebx
286         testl   %ebx,%ebx                       /* anything to do? */
287         jz      done_copyout
288
289         /*
290          * Check explicitly for non-user addresses.  If 486 write protection
291          * is being used, this check is essential because we are in kernel
292          * mode so the h/w does not provide any protection against writing
293          * kernel addresses.
294          */
295
296         /*
297          * First, prevent address wrapping.
298          */
299         movl    %edi,%eax
300         addl    %ebx,%eax
301         jc      copyout_fault
302 /*
303  * XXX STOP USING VM_MAXUSER_ADDRESS.
304  * It is an end address, not a max, so every time it is used correctly it
305  * looks like there is an off by one error, and of course it caused an off
306  * by one error in several places.
307  */
308         cmpl    $VM_MAXUSER_ADDRESS,%eax
309         ja      copyout_fault
310
311         /* bcopy(%esi, %edi, %ebx) */
312         movl    %ebx,%ecx
313
314         shrl    $2,%ecx
315         cld
316         rep
317         movsl
318         movb    %bl,%cl
319         andb    $3,%cl
320         rep
321         movsb
322
323 done_copyout:
324         popl    %ebx
325         popl    %edi
326         popl    %esi
327         xorl    %eax,%eax
328         movl    PCPU(CURPCB),%edx
329         movl    %eax,PCB_ONFAULT(%edx)
330         ret
331 END(copyout)
332
333         ALIGN_TEXT
334 copyout_fault:
335         popl    %ebx
336         popl    %edi
337         popl    %esi
338         movl    PCPU(CURPCB),%edx
339         movl    $0,PCB_ONFAULT(%edx)
340         movl    $EFAULT,%eax
341         ret
342
343 /*
344  * copyin(from_user, to_kernel, len) - MP SAFE
345  */
346 ENTRY(copyin)
347         movl    PCPU(CURPCB),%eax
348         movl    $copyin_fault,PCB_ONFAULT(%eax)
349         pushl   %esi
350         pushl   %edi
351         movl    12(%esp),%esi                   /* caddr_t from */
352         movl    16(%esp),%edi                   /* caddr_t to */
353         movl    20(%esp),%ecx                   /* size_t  len */
354
355         /*
356          * make sure address is valid
357          */
358         movl    %esi,%edx
359         addl    %ecx,%edx
360         jc      copyin_fault
361         cmpl    $VM_MAXUSER_ADDRESS,%edx
362         ja      copyin_fault
363
364         movb    %cl,%al
365         shrl    $2,%ecx                         /* copy longword-wise */
366         cld
367         rep
368         movsl
369         movb    %al,%cl
370         andb    $3,%cl                          /* copy remaining bytes */
371         rep
372         movsb
373
374         popl    %edi
375         popl    %esi
376         xorl    %eax,%eax
377         movl    PCPU(CURPCB),%edx
378         movl    %eax,PCB_ONFAULT(%edx)
379         ret
380 END(copyin)
381
382         ALIGN_TEXT
383 copyin_fault:
384         popl    %edi
385         popl    %esi
386         movl    PCPU(CURPCB),%edx
387         movl    $0,PCB_ONFAULT(%edx)
388         movl    $EFAULT,%eax
389         ret
390
391 /*
392  * casuword.  Compare and set user word.  Returns -1 or the current value.
393  */
394
395 ALTENTRY(casuword32)
396 ENTRY(casuword)
397         movl    PCPU(CURPCB),%ecx
398         movl    $fusufault,PCB_ONFAULT(%ecx)
399         movl    4(%esp),%edx                    /* dst */
400         movl    8(%esp),%eax                    /* old */
401         movl    12(%esp),%ecx                   /* new */
402
403         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address is valid */
404         ja      fusufault
405
406 #ifdef SMP
407         lock
408 #endif
409         cmpxchgl %ecx,(%edx)                    /* Compare and set. */
410
411         /*
412          * The old value is in %eax.  If the store succeeded it will be the
413          * value we expected (old) from before the store, otherwise it will
414          * be the current value.
415          */
416
417         movl    PCPU(CURPCB),%ecx
418         movl    $0,PCB_ONFAULT(%ecx)
419         ret
420 END(casuword32)
421 END(casuword)
422
423 /*
424  * Fetch (load) a 32-bit word, a 16-bit word, or an 8-bit byte from user
425  * memory.  All these functions are MPSAFE.
426  */
427
428 ALTENTRY(fuword32)
429 ENTRY(fuword)
430         movl    PCPU(CURPCB),%ecx
431         movl    $fusufault,PCB_ONFAULT(%ecx)
432         movl    4(%esp),%edx                    /* from */
433
434         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address is valid */
435         ja      fusufault
436
437         movl    (%edx),%eax
438         movl    $0,PCB_ONFAULT(%ecx)
439         ret
440 END(fuword32)
441 END(fuword)
442
443 /*
444  * fuswintr() and suswintr() are specialized variants of fuword16() and
445  * suword16(), respectively.  They are called from the profiling code,
446  * potentially at interrupt time.  If they fail, that's okay; good things
447  * will happen later.  They always fail for now, until the trap code is
448  * able to deal with this.
449  */
450 ALTENTRY(suswintr)
451 ENTRY(fuswintr)
452         movl    $-1,%eax
453         ret
454 END(suswintr)
455 END(fuswintr)
456
457 ENTRY(fuword16)
458         movl    PCPU(CURPCB),%ecx
459         movl    $fusufault,PCB_ONFAULT(%ecx)
460         movl    4(%esp),%edx
461
462         cmpl    $VM_MAXUSER_ADDRESS-2,%edx
463         ja      fusufault
464
465         movzwl  (%edx),%eax
466         movl    $0,PCB_ONFAULT(%ecx)
467         ret
468 END(fuword16)
469
470 ENTRY(fubyte)
471         movl    PCPU(CURPCB),%ecx
472         movl    $fusufault,PCB_ONFAULT(%ecx)
473         movl    4(%esp),%edx
474
475         cmpl    $VM_MAXUSER_ADDRESS-1,%edx
476         ja      fusufault
477
478         movzbl  (%edx),%eax
479         movl    $0,PCB_ONFAULT(%ecx)
480         ret
481 END(fubyte)
482
483         ALIGN_TEXT
484 fusufault:
485         movl    PCPU(CURPCB),%ecx
486         xorl    %eax,%eax
487         movl    %eax,PCB_ONFAULT(%ecx)
488         decl    %eax
489         ret
490
491 /*
492  * Store a 32-bit word, a 16-bit word, or an 8-bit byte to user memory.
493  * All these functions are MPSAFE.
494  */
495
496 ALTENTRY(suword32)
497 ENTRY(suword)
498         movl    PCPU(CURPCB),%ecx
499         movl    $fusufault,PCB_ONFAULT(%ecx)
500         movl    4(%esp),%edx
501
502         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address validity */
503         ja      fusufault
504
505         movl    8(%esp),%eax
506         movl    %eax,(%edx)
507         xorl    %eax,%eax
508         movl    PCPU(CURPCB),%ecx
509         movl    %eax,PCB_ONFAULT(%ecx)
510         ret
511 END(suword32)
512 END(suword)
513
514 ENTRY(suword16)
515         movl    PCPU(CURPCB),%ecx
516         movl    $fusufault,PCB_ONFAULT(%ecx)
517         movl    4(%esp),%edx
518
519         cmpl    $VM_MAXUSER_ADDRESS-2,%edx      /* verify address validity */
520         ja      fusufault
521
522         movw    8(%esp),%ax
523         movw    %ax,(%edx)
524         xorl    %eax,%eax
525         movl    PCPU(CURPCB),%ecx               /* restore trashed register */
526         movl    %eax,PCB_ONFAULT(%ecx)
527         ret
528 END(suword16)
529
530 ENTRY(subyte)
531         movl    PCPU(CURPCB),%ecx
532         movl    $fusufault,PCB_ONFAULT(%ecx)
533         movl    4(%esp),%edx
534
535         cmpl    $VM_MAXUSER_ADDRESS-1,%edx      /* verify address validity */
536         ja      fusufault
537
538         movb    8(%esp),%al
539         movb    %al,(%edx)
540         xorl    %eax,%eax
541         movl    PCPU(CURPCB),%ecx               /* restore trashed register */
542         movl    %eax,PCB_ONFAULT(%ecx)
543         ret
544 END(subyte)
545
546 /*
547  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
548  *
549  *      copy a string from from to to, stop when a 0 character is reached.
550  *      return ENAMETOOLONG if string is longer than maxlen, and
551  *      EFAULT on protection violations. If lencopied is non-zero,
552  *      return the actual length in *lencopied.
553  */
554 ENTRY(copyinstr)
555         pushl   %esi
556         pushl   %edi
557         movl    PCPU(CURPCB),%ecx
558         movl    $cpystrflt,PCB_ONFAULT(%ecx)
559
560         movl    12(%esp),%esi                   /* %esi = from */
561         movl    16(%esp),%edi                   /* %edi = to */
562         movl    20(%esp),%edx                   /* %edx = maxlen */
563
564         movl    $VM_MAXUSER_ADDRESS,%eax
565
566         /* make sure 'from' is within bounds */
567         subl    %esi,%eax
568         jbe     cpystrflt
569
570         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
571         cmpl    %edx,%eax
572         jae     1f
573         movl    %eax,%edx
574         movl    %eax,20(%esp)
575 1:
576         incl    %edx
577         cld
578
579 2:
580         decl    %edx
581         jz      3f
582
583         lodsb
584         stosb
585         orb     %al,%al
586         jnz     2b
587
588         /* Success -- 0 byte reached */
589         decl    %edx
590         xorl    %eax,%eax
591         jmp     cpystrflt_x
592 3:
593         /* edx is zero - return ENAMETOOLONG or EFAULT */
594         cmpl    $VM_MAXUSER_ADDRESS,%esi
595         jae     cpystrflt
596 4:
597         movl    $ENAMETOOLONG,%eax
598         jmp     cpystrflt_x
599
600 cpystrflt:
601         movl    $EFAULT,%eax
602
603 cpystrflt_x:
604         /* set *lencopied and return %eax */
605         movl    PCPU(CURPCB),%ecx
606         movl    $0,PCB_ONFAULT(%ecx)
607         movl    20(%esp),%ecx
608         subl    %edx,%ecx
609         movl    24(%esp),%edx
610         testl   %edx,%edx
611         jz      1f
612         movl    %ecx,(%edx)
613 1:
614         popl    %edi
615         popl    %esi
616         ret
617 END(copyinstr)
618
619 /*
620  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
621  */
622 ENTRY(copystr)
623         pushl   %esi
624         pushl   %edi
625
626         movl    12(%esp),%esi                   /* %esi = from */
627         movl    16(%esp),%edi                   /* %edi = to */
628         movl    20(%esp),%edx                   /* %edx = maxlen */
629         incl    %edx
630         cld
631 1:
632         decl    %edx
633         jz      4f
634         lodsb
635         stosb
636         orb     %al,%al
637         jnz     1b
638
639         /* Success -- 0 byte reached */
640         decl    %edx
641         xorl    %eax,%eax
642         jmp     6f
643 4:
644         /* edx is zero -- return ENAMETOOLONG */
645         movl    $ENAMETOOLONG,%eax
646
647 6:
648         /* set *lencopied and return %eax */
649         movl    20(%esp),%ecx
650         subl    %edx,%ecx
651         movl    24(%esp),%edx
652         testl   %edx,%edx
653         jz      7f
654         movl    %ecx,(%edx)
655 7:
656         popl    %edi
657         popl    %esi
658         ret
659 END(copystr)
660
661 ENTRY(bcmp)
662         pushl   %edi
663         pushl   %esi
664         movl    12(%esp),%edi
665         movl    16(%esp),%esi
666         movl    20(%esp),%edx
667
668         movl    %edx,%ecx
669         shrl    $2,%ecx
670         cld                                     /* compare forwards */
671         repe
672         cmpsl
673         jne     1f
674
675         movl    %edx,%ecx
676         andl    $3,%ecx
677         repe
678         cmpsb
679 1:
680         setne   %al
681         movsbl  %al,%eax
682         popl    %esi
683         popl    %edi
684         ret
685 END(bcmp)
686
687 /*
688  * Handling of special 386 registers and descriptor tables etc
689  */
690 /* void lgdt(struct region_descriptor *rdp); */
691 ENTRY(lgdt)
692 #ifndef XEN
693         /* reload the descriptor table */
694         movl    4(%esp),%eax
695         lgdt    (%eax)
696 #endif
697         
698         /* flush the prefetch q */
699         jmp     1f
700         nop
701 1:
702         /* reload "stale" selectors */
703         movl    $KDSEL,%eax
704         movl    %eax,%ds
705         movl    %eax,%es
706         movl    %eax,%gs
707         movl    %eax,%ss
708         movl    $KPSEL,%eax
709         movl    %eax,%fs
710
711         /* reload code selector by turning return into intersegmental return */
712         movl    (%esp),%eax
713         pushl   %eax
714         movl    $KCSEL,4(%esp)
715         MEXITCOUNT
716         lret
717 END(lgdt)
718
719 /* ssdtosd(*ssdp,*sdp) */
720 ENTRY(ssdtosd)
721         pushl   %ebx
722         movl    8(%esp),%ecx
723         movl    8(%ecx),%ebx
724         shll    $16,%ebx
725         movl    (%ecx),%edx
726         roll    $16,%edx
727         movb    %dh,%bl
728         movb    %dl,%bh
729         rorl    $8,%ebx
730         movl    4(%ecx),%eax
731         movw    %ax,%dx
732         andl    $0xf0000,%eax
733         orl     %eax,%ebx
734         movl    12(%esp),%ecx
735         movl    %edx,(%ecx)
736         movl    %ebx,4(%ecx)
737         popl    %ebx
738         ret
739 END(ssdtosd)
740
741 /* void reset_dbregs() */
742 ENTRY(reset_dbregs)
743         movl    $0,%eax
744         movl    %eax,%dr7     /* disable all breapoints first */
745         movl    %eax,%dr0
746         movl    %eax,%dr1
747         movl    %eax,%dr2
748         movl    %eax,%dr3
749         movl    %eax,%dr6
750         ret
751 END(reset_dbregs)
752
753 /*****************************************************************************/
754 /* setjump, longjump                                                         */
755 /*****************************************************************************/
756
757 ENTRY(setjmp)
758         movl    4(%esp),%eax
759         movl    %ebx,(%eax)                     /* save ebx */
760         movl    %esp,4(%eax)                    /* save esp */
761         movl    %ebp,8(%eax)                    /* save ebp */
762         movl    %esi,12(%eax)                   /* save esi */
763         movl    %edi,16(%eax)                   /* save edi */
764         movl    (%esp),%edx                     /* get rta */
765         movl    %edx,20(%eax)                   /* save eip */
766         xorl    %eax,%eax                       /* return(0); */
767         ret
768 END(setjmp)
769
770 ENTRY(longjmp)
771         movl    4(%esp),%eax
772         movl    (%eax),%ebx                     /* restore ebx */
773         movl    4(%eax),%esp                    /* restore esp */
774         movl    8(%eax),%ebp                    /* restore ebp */
775         movl    12(%eax),%esi                   /* restore esi */
776         movl    16(%eax),%edi                   /* restore edi */
777         movl    20(%eax),%edx                   /* get rta */
778         movl    %edx,(%esp)                     /* put in return frame */
779         xorl    %eax,%eax                       /* return(1); */
780         incl    %eax
781         ret
782 END(longjmp)
783
784 /*
785  * Support for reading MSRs in the safe manner.
786  */
787 ENTRY(rdmsr_safe)
788 /* int rdmsr_safe(u_int msr, uint64_t *data) */
789         movl    PCPU(CURPCB),%ecx
790         movl    $msr_onfault,PCB_ONFAULT(%ecx)
791
792         movl    4(%esp),%ecx
793         rdmsr
794         movl    8(%esp),%ecx
795         movl    %eax,(%ecx)
796         movl    %edx,4(%ecx)
797         xorl    %eax,%eax
798
799         movl    PCPU(CURPCB),%ecx
800         movl    %eax,PCB_ONFAULT(%ecx)
801
802         ret
803
804 /*
805  * Support for writing MSRs in the safe manner.
806  */
807 ENTRY(wrmsr_safe)
808 /* int wrmsr_safe(u_int msr, uint64_t data) */
809         movl    PCPU(CURPCB),%ecx
810         movl    $msr_onfault,PCB_ONFAULT(%ecx)
811
812         movl    4(%esp),%ecx
813         movl    8(%esp),%eax
814         movl    12(%esp),%edx
815         wrmsr
816         xorl    %eax,%eax
817
818         movl    PCPU(CURPCB),%ecx
819         movl    %eax,PCB_ONFAULT(%ecx)
820
821         ret
822
823 /*
824  * MSR operations fault handler
825  */
826         ALIGN_TEXT
827 msr_onfault:
828         movl    PCPU(CURPCB),%ecx
829         movl    $0,PCB_ONFAULT(%ecx)
830         movl    $EFAULT,%eax
831         ret