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