]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/support.S
Merge ^/vendor/clang/dist up to its last change, and resolve conflicts.
[FreeBSD/FreeBSD.git] / sys / amd64 / amd64 / support.S
1 /*-
2  * Copyright (c) 2018-2019 The FreeBSD Foundation
3  * Copyright (c) 2003 Peter Wemm.
4  * Copyright (c) 1993 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * Portions of this software were developed by
8  * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
9  * the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * $FreeBSD$
36  */
37
38 #include "opt_ddb.h"
39
40 #include <machine/asmacros.h>
41 #include <machine/specialreg.h>
42 #include <machine/pmap.h>
43
44 #include "assym.inc"
45
46         .text
47
48 /* Address: %rdi */
49 ENTRY(pagezero_std)
50         PUSH_FRAME_POINTER
51         movl    $PAGE_SIZE/8,%ecx
52         xorl    %eax,%eax
53         rep
54         stosq
55         POP_FRAME_POINTER
56         ret
57 END(pagezero_std)
58
59 ENTRY(pagezero_erms)
60         PUSH_FRAME_POINTER
61         movl    $PAGE_SIZE,%ecx
62         xorl    %eax,%eax
63         rep
64         stosb
65         POP_FRAME_POINTER
66         ret
67 END(pagezero_erms)
68
69 /*
70  * pagecopy(%rdi=from, %rsi=to)
71  */
72 ENTRY(pagecopy)
73         PUSH_FRAME_POINTER
74         movl    $PAGE_SIZE/8,%ecx
75         movq    %rdi,%r9
76         movq    %rsi,%rdi
77         movq    %r9,%rsi
78         rep
79         movsq
80         POP_FRAME_POINTER
81         ret
82 END(pagecopy)
83
84 /* Address: %rdi */
85 ENTRY(sse2_pagezero)
86         PUSH_FRAME_POINTER
87         movq    $-PAGE_SIZE,%rdx
88         subq    %rdx,%rdi
89         xorl    %eax,%eax
90         jmp     1f
91         /*
92          * The loop takes 29 bytes.  Ensure that it doesn't cross a 32-byte
93          * cache line.
94          */
95         .p2align 5,0x90
96 1:
97         movnti  %rax,(%rdi,%rdx)
98         movnti  %rax,8(%rdi,%rdx)
99         movnti  %rax,16(%rdi,%rdx)
100         movnti  %rax,24(%rdi,%rdx)
101         addq    $32,%rdx
102         jne     1b
103         sfence
104         POP_FRAME_POINTER
105         ret
106 END(sse2_pagezero)
107
108 /*
109  * memcmpy(b1, b2, len)
110  *         rdi,rsi,len
111  */
112 ENTRY(memcmp)
113         PUSH_FRAME_POINTER
114         cmpq    $16,%rdx
115         jae     5f
116 1:
117         testq   %rdx,%rdx
118         je      3f
119         xorl    %ecx,%ecx
120 2:
121         movzbl  (%rdi,%rcx,1),%eax
122         movzbl  (%rsi,%rcx,1),%r8d
123         cmpb    %r8b,%al
124         jne     4f
125         addq    $1,%rcx
126         cmpq    %rcx,%rdx
127         jz      3f
128         movzbl  (%rdi,%rcx,1),%eax
129         movzbl  (%rsi,%rcx,1),%r8d
130         cmpb    %r8b,%al
131         jne     4f
132         addq    $1,%rcx
133         cmpq    %rcx,%rdx
134         jz      3f
135         movzbl  (%rdi,%rcx,1),%eax
136         movzbl  (%rsi,%rcx,1),%r8d
137         cmpb    %r8b,%al
138         jne     4f
139         addq    $1,%rcx
140         cmpq    %rcx,%rdx
141         jz      3f
142         movzbl  (%rdi,%rcx,1),%eax
143         movzbl  (%rsi,%rcx,1),%r8d
144         cmpb    %r8b,%al
145         jne     4f
146         addq    $1,%rcx
147         cmpq    %rcx,%rdx
148         jne     2b
149 3:
150         xorl    %eax,%eax
151         POP_FRAME_POINTER
152         ret
153 4:
154         subl    %r8d,%eax
155         POP_FRAME_POINTER
156         ret
157 5:
158         cmpq    $32,%rdx
159         jae     7f
160 6:
161         /*
162          * 8 bytes
163          */
164         movq    (%rdi),%r8
165         movq    (%rsi),%r9
166         cmpq    %r8,%r9
167         jne     1b
168         leaq    8(%rdi),%rdi
169         leaq    8(%rsi),%rsi
170         subq    $8,%rdx
171         cmpq    $8,%rdx
172         jae     6b
173         jl      1b
174         jmp     3b
175 7:
176         /*
177          * 32 bytes
178          */
179         movq    (%rsi),%r8
180         movq    8(%rsi),%r9
181         subq    (%rdi),%r8
182         subq    8(%rdi),%r9
183         or      %r8,%r9
184         jnz     1b
185
186         movq    16(%rsi),%r8
187         movq    24(%rsi),%r9
188         subq    16(%rdi),%r8
189         subq    24(%rdi),%r9
190         or      %r8,%r9
191         jnz     1b
192
193         leaq    32(%rdi),%rdi
194         leaq    32(%rsi),%rsi
195         subq    $32,%rdx
196         cmpq    $32,%rdx
197         jae     7b
198         jnz     1b
199         jmp     3b
200 END(memcmp)
201
202 /*
203  * memmove(dst, src, cnt)
204  *         rdi, rsi, rdx
205  */
206
207 /*
208  * Register state at entry is supposed to be as follows:
209  * rdi - destination
210  * rsi - source
211  * rdx - count
212  *
213  * The macro possibly clobbers the above and: rcx, r8, r9, r10
214  * It does not clobber rax nor r11.
215  */
216 .macro MEMMOVE erms overlap begin end
217         \begin
218
219         /*
220          * For sizes 0..32 all data is read before it is written, so there
221          * is no correctness issue with direction of copying.
222          */
223         cmpq    $32,%rcx
224         jbe     101632f
225
226 .if \overlap == 1
227         movq    %rdi,%r8
228         subq    %rsi,%r8
229         cmpq    %rcx,%r8        /* overlapping && src < dst? */
230         jb      2f
231 .endif
232
233         cmpq    $256,%rcx
234         ja      1256f
235
236 103200:
237         movq    (%rsi),%rdx
238         movq    %rdx,(%rdi)
239         movq    8(%rsi),%rdx
240         movq    %rdx,8(%rdi)
241         movq    16(%rsi),%rdx
242         movq    %rdx,16(%rdi)
243         movq    24(%rsi),%rdx
244         movq    %rdx,24(%rdi)
245         leaq    32(%rsi),%rsi
246         leaq    32(%rdi),%rdi
247         subq    $32,%rcx
248         cmpq    $32,%rcx
249         jae     103200b
250         cmpb    $0,%cl
251         jne     101632f
252         \end
253         ret
254         ALIGN_TEXT
255 101632:
256         cmpb    $16,%cl
257         jl      100816f
258         movq    (%rsi),%rdx
259         movq    8(%rsi),%r8
260         movq    -16(%rsi,%rcx),%r9
261         movq    -8(%rsi,%rcx),%r10
262         movq    %rdx,(%rdi)
263         movq    %r8,8(%rdi)
264         movq    %r9,-16(%rdi,%rcx)
265         movq    %r10,-8(%rdi,%rcx)
266         \end
267         ret
268         ALIGN_TEXT
269 100816:
270         cmpb    $8,%cl
271         jl      100408f
272         movq    (%rsi),%rdx
273         movq    -8(%rsi,%rcx),%r8
274         movq    %rdx,(%rdi)
275         movq    %r8,-8(%rdi,%rcx,)
276         \end
277         ret
278         ALIGN_TEXT
279 100408:
280         cmpb    $4,%cl
281         jl      100204f
282         movl    (%rsi),%edx
283         movl    -4(%rsi,%rcx),%r8d
284         movl    %edx,(%rdi)
285         movl    %r8d,-4(%rdi,%rcx)
286         \end
287         ret
288         ALIGN_TEXT
289 100204:
290         cmpb    $2,%cl
291         jl      100001f
292         movzwl  (%rsi),%edx
293         movzwl  -2(%rsi,%rcx),%r8d
294         movw    %dx,(%rdi)
295         movw    %r8w,-2(%rdi,%rcx)
296         \end
297         ret
298         ALIGN_TEXT
299 100001:
300         cmpb    $1,%cl
301         jl      100000f
302         movb    (%rsi),%dl
303         movb    %dl,(%rdi)
304 100000:
305         \end
306         ret
307
308         ALIGN_TEXT
309 1256:
310         testb   $15,%dil
311         jnz     100f
312 .if \erms == 1
313         rep
314         movsb
315 .else
316         shrq    $3,%rcx                         /* copy by 64-bit words */
317         rep
318         movsq
319         movq    %rdx,%rcx
320         andl    $7,%ecx                         /* any bytes left? */
321         jne     100408b
322 .endif
323         \end
324         ret
325 100:
326         movq    (%rsi),%r8
327         movq    8(%rsi),%r9
328         movq    %rdi,%r10
329         movq    %rdi,%rcx
330         andq    $15,%rcx
331         leaq    -16(%rdx,%rcx),%rdx
332         neg     %rcx
333         leaq    16(%rdi,%rcx),%rdi
334         leaq    16(%rsi,%rcx),%rsi
335         movq    %rdx,%rcx
336 .if \erms == 1
337         rep
338         movsb
339         movq    %r8,(%r10)
340         movq    %r9,8(%r10)
341 .else
342         shrq    $3,%rcx                         /* copy by 64-bit words */
343         rep
344         movsq
345         movq    %r8,(%r10)
346         movq    %r9,8(%r10)
347         movq    %rdx,%rcx
348         andl    $7,%ecx                         /* any bytes left? */
349         jne     100408b
350 .endif
351         \end
352         ret
353
354 .if \overlap == 1
355         /*
356          * Copy backwards.
357          */
358         ALIGN_TEXT
359 2:
360         cmpq    $256,%rcx
361         ja      2256f
362
363         leaq    -8(%rdi,%rcx),%rdi
364         leaq    -8(%rsi,%rcx),%rsi
365
366         cmpq    $32,%rcx
367         jb      2016f
368
369 2032:
370         movq    (%rsi),%rdx
371         movq    %rdx,(%rdi)
372         movq    -8(%rsi),%rdx
373         movq    %rdx,-8(%rdi)
374         movq    -16(%rsi),%rdx
375         movq    %rdx,-16(%rdi)
376         movq    -24(%rsi),%rdx
377         movq    %rdx,-24(%rdi)
378         leaq    -32(%rsi),%rsi
379         leaq    -32(%rdi),%rdi
380         subq    $32,%rcx
381         cmpq    $32,%rcx
382         jae     2032b
383         cmpb    $0,%cl
384         jne     2016f
385         \end
386         ret
387         ALIGN_TEXT
388 2016:
389         cmpb    $16,%cl
390         jl      2008f
391         movq    (%rsi),%rdx
392         movq    %rdx,(%rdi)
393         movq    -8(%rsi),%rdx
394         movq    %rdx,-8(%rdi)
395         subb    $16,%cl
396         jz      2000f
397         leaq    -16(%rsi),%rsi
398         leaq    -16(%rdi),%rdi
399 2008:
400         cmpb    $8,%cl
401         jl      2004f
402         movq    (%rsi),%rdx
403         movq    %rdx,(%rdi)
404         subb    $8,%cl
405         jz      2000f
406         leaq    -8(%rsi),%rsi
407         leaq    -8(%rdi),%rdi
408 2004:
409         cmpb    $4,%cl
410         jl      2002f
411         movl    4(%rsi),%edx
412         movl    %edx,4(%rdi)
413         subb    $4,%cl
414         jz      2000f
415         leaq    -4(%rsi),%rsi
416         leaq    -4(%rdi),%rdi
417 2002:
418         cmpb    $2,%cl
419         jl      2001f
420         movw    6(%rsi),%dx
421         movw    %dx,6(%rdi)
422         subb    $2,%cl
423         jz      2000f
424         leaq    -2(%rsi),%rsi
425         leaq    -2(%rdi),%rdi
426 2001:
427         cmpb    $1,%cl
428         jl      2000f
429         movb    7(%rsi),%dl
430         movb    %dl,7(%rdi)
431 2000:
432         \end
433         ret
434         ALIGN_TEXT
435 2256:
436         std
437 .if \erms == 1
438         leaq    -1(%rdi,%rcx),%rdi
439         leaq    -1(%rsi,%rcx),%rsi
440         rep
441         movsb
442         cld
443 .else
444         leaq    -8(%rdi,%rcx),%rdi
445         leaq    -8(%rsi,%rcx),%rsi
446         shrq    $3,%rcx
447         rep
448         movsq
449         cld
450         movq    %rdx,%rcx
451         andb    $7,%cl
452         jne     2004b
453 .endif
454         \end
455         ret
456 .endif
457 .endm
458
459 .macro MEMMOVE_BEGIN
460         PUSH_FRAME_POINTER
461         movq    %rdi,%rax
462         movq    %rdx,%rcx
463 .endm
464
465 .macro MEMMOVE_END
466         POP_FRAME_POINTER
467 .endm
468
469 ENTRY(memmove_std)
470         MEMMOVE erms=0 overlap=1 begin=MEMMOVE_BEGIN end=MEMMOVE_END
471 END(memmove_std)
472
473 ENTRY(memmove_erms)
474         MEMMOVE erms=1 overlap=1 begin=MEMMOVE_BEGIN end=MEMMOVE_END
475 END(memmove_erms)
476
477 /*
478  * memcpy(dst, src, len)
479  *        rdi, rsi, rdx
480  *
481  * Note: memcpy does not support overlapping copies
482  */
483 ENTRY(memcpy_std)
484         MEMMOVE erms=0 overlap=0 begin=MEMMOVE_BEGIN end=MEMMOVE_END
485 END(memcpy_std)
486
487 ENTRY(memcpy_erms)
488         MEMMOVE erms=1 overlap=0 begin=MEMMOVE_BEGIN end=MEMMOVE_END
489 END(memcpy_erms)
490
491 /*
492  * memset(dst, c,   len)
493  *        rdi, rsi, rdx
494  */
495 .macro MEMSET erms
496         PUSH_FRAME_POINTER
497         movq    %rdi,%rax
498         movq    %rdx,%rcx
499         movzbq  %sil,%r8
500         movabs  $0x0101010101010101,%r10
501         imulq   %r8,%r10
502
503         cmpq    $32,%rcx
504         jbe     101632f
505
506         cmpq    $256,%rcx
507         ja      1256f
508
509 103200:
510         movq    %r10,(%rdi)
511         movq    %r10,8(%rdi)
512         movq    %r10,16(%rdi)
513         movq    %r10,24(%rdi)
514         leaq    32(%rdi),%rdi
515         subq    $32,%rcx
516         cmpq    $32,%rcx
517         ja      103200b
518         cmpb    $16,%cl
519         ja      201632f
520         movq    %r10,-16(%rdi,%rcx)
521         movq    %r10,-8(%rdi,%rcx)
522         POP_FRAME_POINTER
523         ret
524         ALIGN_TEXT
525 101632:
526         cmpb    $16,%cl
527         jl      100816f
528 201632:
529         movq    %r10,(%rdi)
530         movq    %r10,8(%rdi)
531         movq    %r10,-16(%rdi,%rcx)
532         movq    %r10,-8(%rdi,%rcx)
533         POP_FRAME_POINTER
534         ret
535         ALIGN_TEXT
536 100816:
537         cmpb    $8,%cl
538         jl      100408f
539         movq    %r10,(%rdi)
540         movq    %r10,-8(%rdi,%rcx)
541         POP_FRAME_POINTER
542         ret
543         ALIGN_TEXT
544 100408:
545         cmpb    $4,%cl
546         jl      100204f
547         movl    %r10d,(%rdi)
548         movl    %r10d,-4(%rdi,%rcx)
549         POP_FRAME_POINTER
550         ret
551         ALIGN_TEXT
552 100204:
553         cmpb    $2,%cl
554         jl      100001f
555         movw    %r10w,(%rdi)
556         movw    %r10w,-2(%rdi,%rcx)
557         POP_FRAME_POINTER
558         ret
559         ALIGN_TEXT
560 100001:
561         cmpb    $0,%cl
562         je      100000f
563         movb    %r10b,(%rdi)
564 100000:
565         POP_FRAME_POINTER
566         ret
567         ALIGN_TEXT
568 1256:
569         movq    %rdi,%r9
570         movq    %r10,%rax
571         testl   $15,%edi
572         jnz     3f
573 1:
574 .if \erms == 1
575         rep
576         stosb
577         movq    %r9,%rax
578 .else
579         movq    %rcx,%rdx
580         shrq    $3,%rcx
581         rep
582         stosq
583         movq    %r9,%rax
584         andl    $7,%edx
585         jnz     2f
586         POP_FRAME_POINTER
587         ret
588 2:
589         movq    %r10,-8(%rdi,%rdx)
590 .endif
591         POP_FRAME_POINTER
592         ret
593         ALIGN_TEXT
594 3:
595         movq    %r10,(%rdi)
596         movq    %r10,8(%rdi)
597         movq    %rdi,%r8
598         andq    $15,%r8
599         leaq    -16(%rcx,%r8),%rcx
600         neg     %r8
601         leaq    16(%rdi,%r8),%rdi
602         jmp     1b
603 .endm
604
605 ENTRY(memset_std)
606         MEMSET erms=0
607 END(memset_std)
608
609 ENTRY(memset_erms)
610         MEMSET erms=1
611 END(memset_erms)
612
613 /* fillw(pat, base, cnt) */
614 /*       %rdi,%rsi, %rdx */
615 ENTRY(fillw)
616         PUSH_FRAME_POINTER
617         movq    %rdi,%rax
618         movq    %rsi,%rdi
619         movq    %rdx,%rcx
620         rep
621         stosw
622         POP_FRAME_POINTER
623         ret
624 END(fillw)
625
626 /*****************************************************************************/
627 /* copyout and fubyte family                                                 */
628 /*****************************************************************************/
629 /*
630  * Access user memory from inside the kernel. These routines should be
631  * the only places that do this.
632  *
633  * These routines set curpcb->pcb_onfault for the time they execute. When a
634  * protection violation occurs inside the functions, the trap handler
635  * returns to *curpcb->pcb_onfault instead of the function.
636  */
637
638 .macro SMAP_DISABLE smap
639 .if     \smap
640         stac
641 .endif
642 .endm
643
644
645 .macro SMAP_ENABLE smap
646 .if     \smap
647         clac
648 .endif
649 .endm
650
651 .macro COPYINOUT_BEGIN
652 .endm
653
654 .macro COPYINOUT_END
655         movq    %rax,PCB_ONFAULT(%r11)
656         POP_FRAME_POINTER
657 .endm
658
659 .macro COPYINOUT_SMAP_END
660         SMAP_ENABLE smap=1
661         COPYINOUT_END
662 .endm
663
664 /*
665  * copyout(from_kernel, to_user, len)
666  *         %rdi,        %rsi,    %rdx
667  */
668 .macro  COPYOUT smap erms
669         PUSH_FRAME_POINTER
670         movq    PCPU(CURPCB),%r11
671         movq    $copy_fault,PCB_ONFAULT(%r11)
672
673         /*
674          * Check explicitly for non-user addresses.
675          * First, prevent address wrapping.
676          */
677         movq    %rsi,%rax
678         addq    %rdx,%rax
679         jc      copy_fault
680 /*
681  * XXX STOP USING VM_MAXUSER_ADDRESS.
682  * It is an end address, not a max, so every time it is used correctly it
683  * looks like there is an off by one error, and of course it caused an off
684  * by one error in several places.
685  */
686         movq    $VM_MAXUSER_ADDRESS,%rcx
687         cmpq    %rcx,%rax
688         ja      copy_fault
689
690         /*
691          * Set return value to zero. Remaining failure mode goes through
692          * copy_fault.
693          */
694         xorl    %eax,%eax
695
696         /*
697          * Set up arguments for MEMMOVE.
698          */
699         movq    %rdi,%r8
700         movq    %rsi,%rdi
701         movq    %r8,%rsi
702         movq    %rdx,%rcx
703
704
705         SMAP_DISABLE \smap
706 .if     \smap == 1
707         MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_SMAP_END
708 .else
709         MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_END
710 .endif
711         /* NOTREACHED */
712 .endm
713
714 ENTRY(copyout_nosmap_std)
715         COPYOUT smap=0 erms=0
716 END(copyout_nosmap_std)
717
718 ENTRY(copyout_smap_std)
719         COPYOUT smap=1 erms=0
720 END(copyout_smap_std)
721
722 ENTRY(copyout_nosmap_erms)
723         COPYOUT smap=0 erms=1
724 END(copyout_nosmap_erms)
725
726 ENTRY(copyout_smap_erms)
727         COPYOUT smap=1 erms=1
728 END(copyout_smap_erms)
729
730 /*
731  * copyin(from_user, to_kernel, len)
732  *        %rdi,      %rsi,      %rdx
733  */
734 .macro  COPYIN smap erms
735         PUSH_FRAME_POINTER
736         movq    PCPU(CURPCB),%r11
737         movq    $copy_fault,PCB_ONFAULT(%r11)
738
739         /*
740          * make sure address is valid
741          */
742         movq    %rdi,%rax
743         addq    %rdx,%rax
744         jc      copy_fault
745         movq    $VM_MAXUSER_ADDRESS,%rcx
746         cmpq    %rcx,%rax
747         ja      copy_fault
748
749         xorl    %eax,%eax
750
751         movq    %rdi,%r8
752         movq    %rsi,%rdi
753         movq    %r8,%rsi
754         movq    %rdx,%rcx
755
756         SMAP_DISABLE \smap
757 .if     \smap == 1
758         MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_SMAP_END
759 .else
760         MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_END
761 .endif
762         /* NOTREACHED */
763 .endm
764
765 ENTRY(copyin_nosmap_std)
766         COPYIN smap=0 erms=0
767 END(copyin_nosmap_std)
768
769 ENTRY(copyin_smap_std)
770         COPYIN smap=1 erms=0
771 END(copyin_smap_std)
772
773 ENTRY(copyin_nosmap_erms)
774         COPYIN smap=0 erms=1
775 END(copyin_nosmap_erms)
776
777 ENTRY(copyin_smap_erms)
778         COPYIN smap=1 erms=1
779 END(copyin_smap_erms)
780
781         ALIGN_TEXT
782         /* Trap entry clears PSL.AC */
783 copy_fault:
784         movq    $0,PCB_ONFAULT(%r11)
785         movl    $EFAULT,%eax
786         POP_FRAME_POINTER
787         ret
788
789 /*
790  * casueword32.  Compare and set user integer.  Returns -1 on fault,
791  *        0 if access was successful.  Old value is written to *oldp.
792  *        dst = %rdi, old = %esi, oldp = %rdx, new = %ecx
793  */
794 ENTRY(casueword32_nosmap)
795         PUSH_FRAME_POINTER
796         movq    PCPU(CURPCB),%r8
797         movq    $fusufault,PCB_ONFAULT(%r8)
798
799         movq    $VM_MAXUSER_ADDRESS-4,%rax
800         cmpq    %rax,%rdi                       /* verify address is valid */
801         ja      fusufault
802
803         movl    %esi,%eax                       /* old */
804 #ifdef SMP
805         lock
806 #endif
807         cmpxchgl %ecx,(%rdi)                    /* new = %ecx */
808         setne   %cl
809
810         /*
811          * The old value is in %eax.  If the store succeeded it will be the
812          * value we expected (old) from before the store, otherwise it will
813          * be the current value.  Save %eax into %esi to prepare the return
814          * value.
815          */
816         movl    %eax,%esi
817         xorl    %eax,%eax
818         movq    %rax,PCB_ONFAULT(%r8)
819
820         /*
821          * Access the oldp after the pcb_onfault is cleared, to correctly
822          * catch corrupted pointer.
823          */
824         movl    %esi,(%rdx)                     /* oldp = %rdx */
825         POP_FRAME_POINTER
826         movzbl  %cl, %eax
827         ret
828 END(casueword32_nosmap)
829
830 ENTRY(casueword32_smap)
831         PUSH_FRAME_POINTER
832         movq    PCPU(CURPCB),%r8
833         movq    $fusufault,PCB_ONFAULT(%r8)
834
835         movq    $VM_MAXUSER_ADDRESS-4,%rax
836         cmpq    %rax,%rdi                       /* verify address is valid */
837         ja      fusufault
838
839         movl    %esi,%eax                       /* old */
840         stac
841 #ifdef SMP
842         lock
843 #endif
844         cmpxchgl %ecx,(%rdi)                    /* new = %ecx */
845         clac
846         setne   %cl
847
848         /*
849          * The old value is in %eax.  If the store succeeded it will be the
850          * value we expected (old) from before the store, otherwise it will
851          * be the current value.  Save %eax into %esi to prepare the return
852          * value.
853          */
854         movl    %eax,%esi
855         xorl    %eax,%eax
856         movq    %rax,PCB_ONFAULT(%r8)
857
858         /*
859          * Access the oldp after the pcb_onfault is cleared, to correctly
860          * catch corrupted pointer.
861          */
862         movl    %esi,(%rdx)                     /* oldp = %rdx */
863         POP_FRAME_POINTER
864         movzbl  %cl, %eax
865         ret
866 END(casueword32_smap)
867
868 /*
869  * casueword.  Compare and set user long.  Returns -1 on fault,
870  *        0 if access was successful.  Old value is written to *oldp.
871  *        dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx
872  */
873 ENTRY(casueword_nosmap)
874         PUSH_FRAME_POINTER
875         movq    PCPU(CURPCB),%r8
876         movq    $fusufault,PCB_ONFAULT(%r8)
877
878         movq    $VM_MAXUSER_ADDRESS-4,%rax
879         cmpq    %rax,%rdi                       /* verify address is valid */
880         ja      fusufault
881
882         movq    %rsi,%rax                       /* old */
883 #ifdef SMP
884         lock
885 #endif
886         cmpxchgq %rcx,(%rdi)                    /* new = %rcx */
887         setne   %cl
888
889         /*
890          * The old value is in %rax.  If the store succeeded it will be the
891          * value we expected (old) from before the store, otherwise it will
892          * be the current value.
893          */
894         movq    %rax,%rsi
895         xorl    %eax,%eax
896         movq    %rax,PCB_ONFAULT(%r8)
897         movq    %rsi,(%rdx)
898         POP_FRAME_POINTER
899         movzbl  %cl, %eax
900         ret
901 END(casueword_nosmap)
902
903 ENTRY(casueword_smap)
904         PUSH_FRAME_POINTER
905         movq    PCPU(CURPCB),%r8
906         movq    $fusufault,PCB_ONFAULT(%r8)
907
908         movq    $VM_MAXUSER_ADDRESS-4,%rax
909         cmpq    %rax,%rdi                       /* verify address is valid */
910         ja      fusufault
911
912         movq    %rsi,%rax                       /* old */
913         stac
914 #ifdef SMP
915         lock
916 #endif
917         cmpxchgq %rcx,(%rdi)                    /* new = %rcx */
918         clac
919         setne   %cl
920
921         /*
922          * The old value is in %rax.  If the store succeeded it will be the
923          * value we expected (old) from before the store, otherwise it will
924          * be the current value.
925          */
926         movq    %rax,%rsi
927         xorl    %eax,%eax
928         movq    %rax,PCB_ONFAULT(%r8)
929         movq    %rsi,(%rdx)
930         POP_FRAME_POINTER
931         movzbl  %cl, %eax
932         ret
933 END(casueword_smap)
934
935 /*
936  * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
937  * byte from user memory.
938  * addr = %rdi, valp = %rsi
939  */
940
941 ENTRY(fueword_nosmap)
942         PUSH_FRAME_POINTER
943         movq    PCPU(CURPCB),%rcx
944         movq    $fusufault,PCB_ONFAULT(%rcx)
945
946         movq    $VM_MAXUSER_ADDRESS-8,%rax
947         cmpq    %rax,%rdi                       /* verify address is valid */
948         ja      fusufault
949
950         xorl    %eax,%eax
951         movq    (%rdi),%r11
952         movq    %rax,PCB_ONFAULT(%rcx)
953         movq    %r11,(%rsi)
954         POP_FRAME_POINTER
955         ret
956 END(fueword_nosmap)
957
958 ENTRY(fueword_smap)
959         PUSH_FRAME_POINTER
960         movq    PCPU(CURPCB),%rcx
961         movq    $fusufault,PCB_ONFAULT(%rcx)
962
963         movq    $VM_MAXUSER_ADDRESS-8,%rax
964         cmpq    %rax,%rdi                       /* verify address is valid */
965         ja      fusufault
966
967         xorl    %eax,%eax
968         stac
969         movq    (%rdi),%r11
970         clac
971         movq    %rax,PCB_ONFAULT(%rcx)
972         movq    %r11,(%rsi)
973         POP_FRAME_POINTER
974         ret
975 END(fueword_smap)
976
977 ENTRY(fueword32_nosmap)
978         PUSH_FRAME_POINTER
979         movq    PCPU(CURPCB),%rcx
980         movq    $fusufault,PCB_ONFAULT(%rcx)
981
982         movq    $VM_MAXUSER_ADDRESS-4,%rax
983         cmpq    %rax,%rdi                       /* verify address is valid */
984         ja      fusufault
985
986         xorl    %eax,%eax
987         movl    (%rdi),%r11d
988         movq    %rax,PCB_ONFAULT(%rcx)
989         movl    %r11d,(%rsi)
990         POP_FRAME_POINTER
991         ret
992 END(fueword32_nosmap)
993
994 ENTRY(fueword32_smap)
995         PUSH_FRAME_POINTER
996         movq    PCPU(CURPCB),%rcx
997         movq    $fusufault,PCB_ONFAULT(%rcx)
998
999         movq    $VM_MAXUSER_ADDRESS-4,%rax
1000         cmpq    %rax,%rdi                       /* verify address is valid */
1001         ja      fusufault
1002
1003         xorl    %eax,%eax
1004         stac
1005         movl    (%rdi),%r11d
1006         clac
1007         movq    %rax,PCB_ONFAULT(%rcx)
1008         movl    %r11d,(%rsi)
1009         POP_FRAME_POINTER
1010         ret
1011 END(fueword32_smap)
1012
1013 ENTRY(fuword16_nosmap)
1014         PUSH_FRAME_POINTER
1015         movq    PCPU(CURPCB),%rcx
1016         movq    $fusufault,PCB_ONFAULT(%rcx)
1017
1018         movq    $VM_MAXUSER_ADDRESS-2,%rax
1019         cmpq    %rax,%rdi
1020         ja      fusufault
1021
1022         movzwl  (%rdi),%eax
1023         movq    $0,PCB_ONFAULT(%rcx)
1024         POP_FRAME_POINTER
1025         ret
1026 END(fuword16_nosmap)
1027
1028 ENTRY(fuword16_smap)
1029         PUSH_FRAME_POINTER
1030         movq    PCPU(CURPCB),%rcx
1031         movq    $fusufault,PCB_ONFAULT(%rcx)
1032
1033         movq    $VM_MAXUSER_ADDRESS-2,%rax
1034         cmpq    %rax,%rdi
1035         ja      fusufault
1036
1037         stac
1038         movzwl  (%rdi),%eax
1039         clac
1040         movq    $0,PCB_ONFAULT(%rcx)
1041         POP_FRAME_POINTER
1042         ret
1043 END(fuword16_smap)
1044
1045 ENTRY(fubyte_nosmap)
1046         PUSH_FRAME_POINTER
1047         movq    PCPU(CURPCB),%rcx
1048         movq    $fusufault,PCB_ONFAULT(%rcx)
1049
1050         movq    $VM_MAXUSER_ADDRESS-1,%rax
1051         cmpq    %rax,%rdi
1052         ja      fusufault
1053
1054         movzbl  (%rdi),%eax
1055         movq    $0,PCB_ONFAULT(%rcx)
1056         POP_FRAME_POINTER
1057         ret
1058 END(fubyte_nosmap)
1059
1060 ENTRY(fubyte_smap)
1061         PUSH_FRAME_POINTER
1062         movq    PCPU(CURPCB),%rcx
1063         movq    $fusufault,PCB_ONFAULT(%rcx)
1064
1065         movq    $VM_MAXUSER_ADDRESS-1,%rax
1066         cmpq    %rax,%rdi
1067         ja      fusufault
1068
1069         stac
1070         movzbl  (%rdi),%eax
1071         clac
1072         movq    $0,PCB_ONFAULT(%rcx)
1073         POP_FRAME_POINTER
1074         ret
1075 END(fubyte_smap)
1076
1077 /*
1078  * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
1079  * user memory.
1080  * addr = %rdi, value = %rsi
1081  */
1082 ENTRY(suword_nosmap)
1083         PUSH_FRAME_POINTER
1084         movq    PCPU(CURPCB),%rcx
1085         movq    $fusufault,PCB_ONFAULT(%rcx)
1086
1087         movq    $VM_MAXUSER_ADDRESS-8,%rax
1088         cmpq    %rax,%rdi                       /* verify address validity */
1089         ja      fusufault
1090
1091         movq    %rsi,(%rdi)
1092         xorl    %eax,%eax
1093         movq    %rax,PCB_ONFAULT(%rcx)
1094         POP_FRAME_POINTER
1095         ret
1096 END(suword_nosmap)
1097
1098 ENTRY(suword_smap)
1099         PUSH_FRAME_POINTER
1100         movq    PCPU(CURPCB),%rcx
1101         movq    $fusufault,PCB_ONFAULT(%rcx)
1102
1103         movq    $VM_MAXUSER_ADDRESS-8,%rax
1104         cmpq    %rax,%rdi                       /* verify address validity */
1105         ja      fusufault
1106
1107         stac
1108         movq    %rsi,(%rdi)
1109         clac
1110         xorl    %eax,%eax
1111         movq    %rax,PCB_ONFAULT(%rcx)
1112         POP_FRAME_POINTER
1113         ret
1114 END(suword_smap)
1115
1116 ENTRY(suword32_nosmap)
1117         PUSH_FRAME_POINTER
1118         movq    PCPU(CURPCB),%rcx
1119         movq    $fusufault,PCB_ONFAULT(%rcx)
1120
1121         movq    $VM_MAXUSER_ADDRESS-4,%rax
1122         cmpq    %rax,%rdi                       /* verify address validity */
1123         ja      fusufault
1124
1125         movl    %esi,(%rdi)
1126         xorl    %eax,%eax
1127         movq    %rax,PCB_ONFAULT(%rcx)
1128         POP_FRAME_POINTER
1129         ret
1130 END(suword32_nosmap)
1131
1132 ENTRY(suword32_smap)
1133         PUSH_FRAME_POINTER
1134         movq    PCPU(CURPCB),%rcx
1135         movq    $fusufault,PCB_ONFAULT(%rcx)
1136
1137         movq    $VM_MAXUSER_ADDRESS-4,%rax
1138         cmpq    %rax,%rdi                       /* verify address validity */
1139         ja      fusufault
1140
1141         stac
1142         movl    %esi,(%rdi)
1143         clac
1144         xorl    %eax,%eax
1145         movq    %rax,PCB_ONFAULT(%rcx)
1146         POP_FRAME_POINTER
1147         ret
1148 END(suword32_smap)
1149
1150 ENTRY(suword16_nosmap)
1151         PUSH_FRAME_POINTER
1152         movq    PCPU(CURPCB),%rcx
1153         movq    $fusufault,PCB_ONFAULT(%rcx)
1154
1155         movq    $VM_MAXUSER_ADDRESS-2,%rax
1156         cmpq    %rax,%rdi                       /* verify address validity */
1157         ja      fusufault
1158
1159         movw    %si,(%rdi)
1160         xorl    %eax,%eax
1161         movq    %rax,PCB_ONFAULT(%rcx)
1162         POP_FRAME_POINTER
1163         ret
1164 END(suword16_nosmap)
1165
1166 ENTRY(suword16_smap)
1167         PUSH_FRAME_POINTER
1168         movq    PCPU(CURPCB),%rcx
1169         movq    $fusufault,PCB_ONFAULT(%rcx)
1170
1171         movq    $VM_MAXUSER_ADDRESS-2,%rax
1172         cmpq    %rax,%rdi                       /* verify address validity */
1173         ja      fusufault
1174
1175         stac
1176         movw    %si,(%rdi)
1177         clac
1178         xorl    %eax,%eax
1179         movq    %rax,PCB_ONFAULT(%rcx)
1180         POP_FRAME_POINTER
1181         ret
1182 END(suword16_smap)
1183
1184 ENTRY(subyte_nosmap)
1185         PUSH_FRAME_POINTER
1186         movq    PCPU(CURPCB),%rcx
1187         movq    $fusufault,PCB_ONFAULT(%rcx)
1188
1189         movq    $VM_MAXUSER_ADDRESS-1,%rax
1190         cmpq    %rax,%rdi                       /* verify address validity */
1191         ja      fusufault
1192
1193         movl    %esi,%eax
1194         movb    %al,(%rdi)
1195         xorl    %eax,%eax
1196         movq    %rax,PCB_ONFAULT(%rcx)
1197         POP_FRAME_POINTER
1198         ret
1199 END(subyte_nosmap)
1200
1201 ENTRY(subyte_smap)
1202         PUSH_FRAME_POINTER
1203         movq    PCPU(CURPCB),%rcx
1204         movq    $fusufault,PCB_ONFAULT(%rcx)
1205
1206         movq    $VM_MAXUSER_ADDRESS-1,%rax
1207         cmpq    %rax,%rdi                       /* verify address validity */
1208         ja      fusufault
1209
1210         movl    %esi,%eax
1211         stac
1212         movb    %al,(%rdi)
1213         clac
1214         xorl    %eax,%eax
1215         movq    %rax,PCB_ONFAULT(%rcx)
1216         POP_FRAME_POINTER
1217         ret
1218 END(subyte_smap)
1219
1220         ALIGN_TEXT
1221         /* Fault entry clears PSL.AC */
1222 fusufault:
1223         movq    PCPU(CURPCB),%rcx
1224         xorl    %eax,%eax
1225         movq    %rax,PCB_ONFAULT(%rcx)
1226         decq    %rax
1227         POP_FRAME_POINTER
1228         ret
1229
1230 /*
1231  * copyinstr(from, to, maxlen, int *lencopied)
1232  *           %rdi, %rsi, %rdx, %rcx
1233  *
1234  *      copy a string from 'from' to 'to', stop when a 0 character is reached.
1235  *      return ENAMETOOLONG if string is longer than maxlen, and
1236  *      EFAULT on protection violations. If lencopied is non-zero,
1237  *      return the actual length in *lencopied.
1238  */
1239 .macro COPYINSTR smap
1240         PUSH_FRAME_POINTER
1241         movq    %rdx,%r8                        /* %r8 = maxlen */
1242         movq    PCPU(CURPCB),%r9
1243         movq    $cpystrflt,PCB_ONFAULT(%r9)
1244
1245         movq    $VM_MAXUSER_ADDRESS,%rax
1246
1247         /* make sure 'from' is within bounds */
1248         subq    %rdi,%rax
1249         jbe     cpystrflt
1250
1251         SMAP_DISABLE \smap
1252
1253         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1254         cmpq    %rdx,%rax
1255         jb      8f
1256 1:
1257         incq    %rdx
1258 2:
1259         decq    %rdx
1260 .if \smap == 0
1261         jz      copyinstr_toolong
1262 .else
1263         jz      copyinstr_toolong_smap
1264 .endif
1265
1266         movb    (%rdi),%al
1267         movb    %al,(%rsi)
1268         incq    %rsi
1269         incq    %rdi
1270         testb   %al,%al
1271         jnz     2b
1272
1273         SMAP_ENABLE \smap
1274
1275         /* Success -- 0 byte reached */
1276         decq    %rdx
1277         xorl    %eax,%eax
1278
1279         /* set *lencopied and return %eax */
1280         movq    %rax,PCB_ONFAULT(%r9)
1281
1282         testq   %rcx,%rcx
1283         jz      3f
1284         subq    %rdx,%r8
1285         movq    %r8,(%rcx)
1286 3:
1287         POP_FRAME_POINTER
1288         ret
1289         ALIGN_TEXT
1290 8:
1291         movq    %rax,%rdx
1292         movq    %rax,%r8
1293         jmp 1b
1294
1295 .endm
1296
1297 ENTRY(copyinstr_nosmap)
1298         COPYINSTR smap=0
1299 END(copyinstr_nosmap)
1300
1301 ENTRY(copyinstr_smap)
1302         COPYINSTR smap=1
1303 END(copyinstr_smap)
1304
1305 cpystrflt:
1306         /* Fault entry clears PSL.AC */
1307         movl    $EFAULT,%eax
1308 cpystrflt_x:
1309         /* set *lencopied and return %eax */
1310         movq    $0,PCB_ONFAULT(%r9)
1311
1312         testq   %rcx,%rcx
1313         jz      1f
1314         subq    %rdx,%r8
1315         movq    %r8,(%rcx)
1316 1:
1317         POP_FRAME_POINTER
1318         ret
1319
1320 copyinstr_toolong_smap:
1321         clac
1322 copyinstr_toolong:
1323         /* rdx is zero - return ENAMETOOLONG or EFAULT */
1324         movq    $VM_MAXUSER_ADDRESS,%rax
1325         cmpq    %rax,%rdi
1326         jae     cpystrflt
1327         movl    $ENAMETOOLONG,%eax
1328         jmp     cpystrflt_x
1329
1330 /*
1331  * copystr(from, to, maxlen, int *lencopied)
1332  *         %rdi, %rsi, %rdx, %rcx
1333  */
1334 ENTRY(copystr)
1335         PUSH_FRAME_POINTER
1336         movq    %rdx,%r8                        /* %r8 = maxlen */
1337
1338         incq    %rdx
1339 1:
1340         decq    %rdx
1341         jz      4f
1342         movb    (%rdi),%al
1343         movb    %al,(%rsi)
1344         incq    %rsi
1345         incq    %rdi
1346         testb   %al,%al
1347         jnz     1b
1348
1349         /* Success -- 0 byte reached */
1350         decq    %rdx
1351         xorl    %eax,%eax
1352 2:
1353         testq   %rcx,%rcx
1354         jz      3f
1355         /* set *lencopied and return %rax */
1356         subq    %rdx,%r8
1357         movq    %r8,(%rcx)
1358 3:
1359         POP_FRAME_POINTER
1360         ret
1361 4:
1362         /* rdx is zero -- return ENAMETOOLONG */
1363         movl    $ENAMETOOLONG,%eax
1364         jmp     2b
1365 END(copystr)
1366
1367 /*
1368  * Handling of special amd64 registers and descriptor tables etc
1369  */
1370 /* void lgdt(struct region_descriptor *rdp); */
1371 ENTRY(lgdt)
1372         /* reload the descriptor table */
1373         lgdt    (%rdi)
1374
1375         /* flush the prefetch q */
1376         jmp     1f
1377         nop
1378 1:
1379         movl    $KDSEL,%eax
1380         movl    %eax,%ds
1381         movl    %eax,%es
1382         movl    %eax,%fs        /* Beware, use wrmsr to set 64 bit base */
1383         movl    %eax,%gs
1384         movl    %eax,%ss
1385
1386         /* reload code selector by turning return into intersegmental return */
1387         popq    %rax
1388         pushq   $KCSEL
1389         pushq   %rax
1390         MEXITCOUNT
1391         lretq
1392 END(lgdt)
1393
1394 /*****************************************************************************/
1395 /* setjump, longjump                                                         */
1396 /*****************************************************************************/
1397
1398 ENTRY(setjmp)
1399         movq    %rbx,0(%rdi)                    /* save rbx */
1400         movq    %rsp,8(%rdi)                    /* save rsp */
1401         movq    %rbp,16(%rdi)                   /* save rbp */
1402         movq    %r12,24(%rdi)                   /* save r12 */
1403         movq    %r13,32(%rdi)                   /* save r13 */
1404         movq    %r14,40(%rdi)                   /* save r14 */
1405         movq    %r15,48(%rdi)                   /* save r15 */
1406         movq    0(%rsp),%rdx                    /* get rta */
1407         movq    %rdx,56(%rdi)                   /* save rip */
1408         xorl    %eax,%eax                       /* return(0); */
1409         ret
1410 END(setjmp)
1411
1412 ENTRY(longjmp)
1413         movq    0(%rdi),%rbx                    /* restore rbx */
1414         movq    8(%rdi),%rsp                    /* restore rsp */
1415         movq    16(%rdi),%rbp                   /* restore rbp */
1416         movq    24(%rdi),%r12                   /* restore r12 */
1417         movq    32(%rdi),%r13                   /* restore r13 */
1418         movq    40(%rdi),%r14                   /* restore r14 */
1419         movq    48(%rdi),%r15                   /* restore r15 */
1420         movq    56(%rdi),%rdx                   /* get rta */
1421         movq    %rdx,0(%rsp)                    /* put in return frame */
1422         xorl    %eax,%eax                       /* return(1); */
1423         incl    %eax
1424         ret
1425 END(longjmp)
1426
1427 /*
1428  * Support for reading MSRs in the safe manner.  (Instead of panic on #gp,
1429  * return an error.)
1430  */
1431 ENTRY(rdmsr_safe)
1432 /* int rdmsr_safe(u_int msr, uint64_t *data) */
1433         PUSH_FRAME_POINTER
1434         movq    PCPU(CURPCB),%r8
1435         movq    $msr_onfault,PCB_ONFAULT(%r8)
1436         movl    %edi,%ecx
1437         rdmsr                   /* Read MSR pointed by %ecx. Returns
1438                                    hi byte in edx, lo in %eax */
1439         salq    $32,%rdx        /* sign-shift %rdx left */
1440         movl    %eax,%eax       /* zero-extend %eax -> %rax */
1441         orq     %rdx,%rax
1442         movq    %rax,(%rsi)
1443         xorq    %rax,%rax
1444         movq    %rax,PCB_ONFAULT(%r8)
1445         POP_FRAME_POINTER
1446         ret
1447
1448 /*
1449  * Support for writing MSRs in the safe manner.  (Instead of panic on #gp,
1450  * return an error.)
1451  */
1452 ENTRY(wrmsr_safe)
1453 /* int wrmsr_safe(u_int msr, uint64_t data) */
1454         PUSH_FRAME_POINTER
1455         movq    PCPU(CURPCB),%r8
1456         movq    $msr_onfault,PCB_ONFAULT(%r8)
1457         movl    %edi,%ecx
1458         movl    %esi,%eax
1459         sarq    $32,%rsi
1460         movl    %esi,%edx
1461         wrmsr                   /* Write MSR pointed by %ecx. Accepts
1462                                    hi byte in edx, lo in %eax. */
1463         xorq    %rax,%rax
1464         movq    %rax,PCB_ONFAULT(%r8)
1465         POP_FRAME_POINTER
1466         ret
1467
1468 /*
1469  * MSR operations fault handler
1470  */
1471         ALIGN_TEXT
1472 msr_onfault:
1473         movq    $0,PCB_ONFAULT(%r8)
1474         movl    $EFAULT,%eax
1475         POP_FRAME_POINTER
1476         ret
1477
1478 /*
1479  * void pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3);
1480  * Invalidates address space addressed by ucr3, then returns to kcr3.
1481  * Done in assembler to ensure no other memory accesses happen while
1482  * on ucr3.
1483  */
1484         ALIGN_TEXT
1485 ENTRY(pmap_pti_pcid_invalidate)
1486         pushfq
1487         cli
1488         movq    %rdi,%cr3       /* to user page table */
1489         movq    %rsi,%cr3       /* back to kernel */
1490         popfq
1491         retq
1492
1493 /*
1494  * void pmap_pti_pcid_invlpg(uint64_t ucr3, uint64_t kcr3, vm_offset_t va);
1495  * Invalidates virtual address va in address space ucr3, then returns to kcr3.
1496  */
1497         ALIGN_TEXT
1498 ENTRY(pmap_pti_pcid_invlpg)
1499         pushfq
1500         cli
1501         movq    %rdi,%cr3       /* to user page table */
1502         invlpg  (%rdx)
1503         movq    %rsi,%cr3       /* back to kernel */
1504         popfq
1505         retq
1506
1507 /*
1508  * void pmap_pti_pcid_invlrng(uint64_t ucr3, uint64_t kcr3, vm_offset_t sva,
1509  *     vm_offset_t eva);
1510  * Invalidates virtual addresses between sva and eva in address space ucr3,
1511  * then returns to kcr3.
1512  */
1513         ALIGN_TEXT
1514 ENTRY(pmap_pti_pcid_invlrng)
1515         pushfq
1516         cli
1517         movq    %rdi,%cr3       /* to user page table */
1518 1:      invlpg  (%rdx)
1519         addq    $PAGE_SIZE,%rdx
1520         cmpq    %rdx,%rcx
1521         ja      1b
1522         movq    %rsi,%cr3       /* back to kernel */
1523         popfq
1524         retq
1525
1526         .altmacro
1527         .macro  ibrs_seq_label l
1528 handle_ibrs_\l:
1529         .endm
1530         .macro  ibrs_call_label l
1531         call    handle_ibrs_\l
1532         .endm
1533         .macro  ibrs_seq count
1534         ll=1
1535         .rept   \count
1536         ibrs_call_label %(ll)
1537         nop
1538         ibrs_seq_label %(ll)
1539         addq    $8,%rsp
1540         ll=ll+1
1541         .endr
1542         .endm
1543
1544 /* all callers already saved %rax, %rdx, and %rcx */
1545 ENTRY(handle_ibrs_entry)
1546         cmpb    $0,hw_ibrs_active(%rip)
1547         je      1f
1548         movl    $MSR_IA32_SPEC_CTRL,%ecx
1549         rdmsr
1550         orl     $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1551         orl     $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32,%edx
1552         wrmsr
1553         movb    $1,PCPU(IBPB_SET)
1554         testl   $CPUID_STDEXT_SMEP,cpu_stdext_feature(%rip)
1555         jne     1f
1556         ibrs_seq 32
1557 1:      ret
1558 END(handle_ibrs_entry)
1559
1560 ENTRY(handle_ibrs_exit)
1561         cmpb    $0,PCPU(IBPB_SET)
1562         je      1f
1563         movl    $MSR_IA32_SPEC_CTRL,%ecx
1564         rdmsr
1565         andl    $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1566         andl    $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1567         wrmsr
1568         movb    $0,PCPU(IBPB_SET)
1569 1:      ret
1570 END(handle_ibrs_exit)
1571
1572 /* registers-neutral version, but needs stack */
1573 ENTRY(handle_ibrs_exit_rs)
1574         cmpb    $0,PCPU(IBPB_SET)
1575         je      1f
1576         pushq   %rax
1577         pushq   %rdx
1578         pushq   %rcx
1579         movl    $MSR_IA32_SPEC_CTRL,%ecx
1580         rdmsr
1581         andl    $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1582         andl    $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1583         wrmsr
1584         popq    %rcx
1585         popq    %rdx
1586         popq    %rax
1587         movb    $0,PCPU(IBPB_SET)
1588 1:      ret
1589 END(handle_ibrs_exit_rs)
1590
1591         .noaltmacro
1592
1593 /*
1594  * Flush L1D cache.  Load enough of the data from the kernel text
1595  * to flush existing L1D content.
1596  *
1597  * N.B. The function does not follow ABI calling conventions, it corrupts %rbx.
1598  * The vmm.ko caller expects that only %rax, %rdx, %rbx, %rcx, %r9, and %rflags
1599  * registers are clobbered.  The NMI handler caller only needs %r13 preserved.
1600  */
1601 ENTRY(flush_l1d_sw)
1602 #define L1D_FLUSH_SIZE  (64 * 1024)
1603         movq    $KERNBASE, %r9
1604         movq    $-L1D_FLUSH_SIZE, %rcx
1605         /*
1606          * pass 1: Preload TLB.
1607          * Kernel text is mapped using superpages.  TLB preload is
1608          * done for the benefit of older CPUs which split 2M page
1609          * into 4k TLB entries.
1610          */
1611 1:      movb    L1D_FLUSH_SIZE(%r9, %rcx), %al
1612         addq    $PAGE_SIZE, %rcx
1613         jne     1b
1614         xorl    %eax, %eax
1615         cpuid
1616         movq    $-L1D_FLUSH_SIZE, %rcx
1617         /* pass 2: Read each cache line. */
1618 2:      movb    L1D_FLUSH_SIZE(%r9, %rcx), %al
1619         addq    $64, %rcx
1620         jne     2b
1621         lfence
1622         ret
1623 #undef  L1D_FLUSH_SIZE
1624 END(flush_l1d_sw)
1625
1626 ENTRY(flush_l1d_sw_abi)
1627         pushq   %rbx
1628         call    flush_l1d_sw
1629         popq    %rbx
1630         ret
1631 END(flush_l1d_sw_abi)
1632
1633 ENTRY(mds_handler_void)
1634         retq
1635 END(mds_handler_void)
1636
1637 ENTRY(mds_handler_verw)
1638         subq    $8, %rsp
1639         movw    %ds, (%rsp)
1640         verw    (%rsp)
1641         addq    $8, %rsp
1642         retq
1643 END(mds_handler_verw)
1644
1645 ENTRY(mds_handler_ivb)
1646         pushq   %rax
1647         pushq   %rdx
1648         pushq   %rcx
1649
1650         movq    %cr0, %rax
1651         testb   $CR0_TS, %al
1652         je      1f
1653         clts
1654 1:      movq    PCPU(MDS_BUF), %rdx
1655         movdqa  %xmm0, PCPU(MDS_TMP)
1656         pxor    %xmm0, %xmm0
1657
1658         lfence
1659         orpd    (%rdx), %xmm0
1660         orpd    (%rdx), %xmm0
1661         mfence
1662         movl    $40, %ecx
1663         addq    $16, %rdx
1664 2:      movntdq %xmm0, (%rdx)
1665         addq    $16, %rdx
1666         decl    %ecx
1667         jnz     2b
1668         mfence
1669
1670         movdqa  PCPU(MDS_TMP),%xmm0
1671         testb   $CR0_TS, %al
1672         je      3f
1673         movq    %rax, %cr0
1674 3:      popq    %rcx
1675         popq    %rdx
1676         popq    %rax
1677         retq
1678 END(mds_handler_ivb)
1679
1680 ENTRY(mds_handler_bdw)
1681         pushq   %rax
1682         pushq   %rbx
1683         pushq   %rcx
1684         pushq   %rdi
1685         pushq   %rsi
1686
1687         movq    %cr0, %rax
1688         testb   $CR0_TS, %al
1689         je      1f
1690         clts
1691 1:      movq    PCPU(MDS_BUF), %rbx
1692         movdqa  %xmm0, PCPU(MDS_TMP)
1693         pxor    %xmm0, %xmm0
1694
1695         movq    %rbx, %rdi
1696         movq    %rbx, %rsi
1697         movl    $40, %ecx
1698 2:      movntdq %xmm0, (%rbx)
1699         addq    $16, %rbx
1700         decl    %ecx
1701         jnz     2b
1702         mfence
1703         movl    $1536, %ecx
1704         rep; movsb
1705         lfence
1706
1707         movdqa  PCPU(MDS_TMP),%xmm0
1708         testb   $CR0_TS, %al
1709         je      3f
1710         movq    %rax, %cr0
1711 3:      popq    %rsi
1712         popq    %rdi
1713         popq    %rcx
1714         popq    %rbx
1715         popq    %rax
1716         retq
1717 END(mds_handler_bdw)
1718
1719 ENTRY(mds_handler_skl_sse)
1720         pushq   %rax
1721         pushq   %rdx
1722         pushq   %rcx
1723         pushq   %rdi
1724
1725         movq    %cr0, %rax
1726         testb   $CR0_TS, %al
1727         je      1f
1728         clts
1729 1:      movq    PCPU(MDS_BUF), %rdi
1730         movq    PCPU(MDS_BUF64), %rdx
1731         movdqa  %xmm0, PCPU(MDS_TMP)
1732         pxor    %xmm0, %xmm0
1733
1734         lfence
1735         orpd    (%rdx), %xmm0
1736         orpd    (%rdx), %xmm0
1737         xorl    %eax, %eax
1738 2:      clflushopt      5376(%rdi, %rax, 8)
1739         addl    $8, %eax
1740         cmpl    $8 * 12, %eax
1741         jb      2b
1742         sfence
1743         movl    $6144, %ecx
1744         xorl    %eax, %eax
1745         rep; stosb
1746         mfence
1747
1748         movdqa  PCPU(MDS_TMP), %xmm0
1749         testb   $CR0_TS, %al
1750         je      3f
1751         movq    %rax, %cr0
1752 3:      popq    %rdi
1753         popq    %rcx
1754         popq    %rdx
1755         popq    %rax
1756         retq
1757 END(mds_handler_skl_sse)
1758
1759 ENTRY(mds_handler_skl_avx)
1760         pushq   %rax
1761         pushq   %rdx
1762         pushq   %rcx
1763         pushq   %rdi
1764
1765         movq    %cr0, %rax
1766         testb   $CR0_TS, %al
1767         je      1f
1768         clts
1769 1:      movq    PCPU(MDS_BUF), %rdi
1770         movq    PCPU(MDS_BUF64), %rdx
1771         vmovdqa %ymm0, PCPU(MDS_TMP)
1772         vpxor   %ymm0, %ymm0, %ymm0
1773
1774         lfence
1775         vorpd   (%rdx), %ymm0, %ymm0
1776         vorpd   (%rdx), %ymm0, %ymm0
1777         xorl    %eax, %eax
1778 2:      clflushopt      5376(%rdi, %rax, 8)
1779         addl    $8, %eax
1780         cmpl    $8 * 12, %eax
1781         jb      2b
1782         sfence
1783         movl    $6144, %ecx
1784         xorl    %eax, %eax
1785         rep; stosb
1786         mfence
1787
1788         vmovdqa PCPU(MDS_TMP), %ymm0
1789         testb   $CR0_TS, %al
1790         je      3f
1791         movq    %rax, %cr0
1792 3:      popq    %rdi
1793         popq    %rcx
1794         popq    %rdx
1795         popq    %rax
1796         retq
1797 END(mds_handler_skl_avx)
1798
1799 ENTRY(mds_handler_skl_avx512)
1800         pushq   %rax
1801         pushq   %rdx
1802         pushq   %rcx
1803         pushq   %rdi
1804
1805         movq    %cr0, %rax
1806         testb   $CR0_TS, %al
1807         je      1f
1808         clts
1809 1:      movq    PCPU(MDS_BUF), %rdi
1810         movq    PCPU(MDS_BUF64), %rdx
1811         vmovdqa64       %zmm0, PCPU(MDS_TMP)
1812         vpxord  %zmm0, %zmm0, %zmm0
1813
1814         lfence
1815         vorpd   (%rdx), %zmm0, %zmm0
1816         vorpd   (%rdx), %zmm0, %zmm0
1817         xorl    %eax, %eax
1818 2:      clflushopt      5376(%rdi, %rax, 8)
1819         addl    $8, %eax
1820         cmpl    $8 * 12, %eax
1821         jb      2b
1822         sfence
1823         movl    $6144, %ecx
1824         xorl    %eax, %eax
1825         rep; stosb
1826         mfence
1827
1828         vmovdqa64       PCPU(MDS_TMP), %zmm0
1829         testb   $CR0_TS, %al
1830         je      3f
1831         movq    %rax, %cr0
1832 3:      popq    %rdi
1833         popq    %rcx
1834         popq    %rdx
1835         popq    %rax
1836         retq
1837 END(mds_handler_skl_avx512)
1838
1839 ENTRY(mds_handler_silvermont)
1840         pushq   %rax
1841         pushq   %rdx
1842         pushq   %rcx
1843
1844         movq    %cr0, %rax
1845         testb   $CR0_TS, %al
1846         je      1f
1847         clts
1848 1:      movq    PCPU(MDS_BUF), %rdx
1849         movdqa  %xmm0, PCPU(MDS_TMP)
1850         pxor    %xmm0, %xmm0
1851
1852         movl    $16, %ecx
1853 2:      movntdq %xmm0, (%rdx)
1854         addq    $16, %rdx
1855         decl    %ecx
1856         jnz     2b
1857         mfence
1858
1859         movdqa  PCPU(MDS_TMP),%xmm0
1860         testb   $CR0_TS, %al
1861         je      3f
1862         movq    %rax, %cr0
1863 3:      popq    %rcx
1864         popq    %rdx
1865         popq    %rax
1866         retq
1867 END(mds_handler_silvermont)