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