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