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