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