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