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