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