]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/support.S
MFS r353173:
[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  */
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, 10
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         setne   %cl
815
816         /*
817          * The old value is in %eax.  If the store succeeded it will be the
818          * value we expected (old) from before the store, otherwise it will
819          * be the current value.  Save %eax into %esi to prepare the return
820          * value.
821          */
822         movl    %eax,%esi
823         xorl    %eax,%eax
824         movq    %rax,PCB_ONFAULT(%r8)
825
826         /*
827          * Access the oldp after the pcb_onfault is cleared, to correctly
828          * catch corrupted pointer.
829          */
830         movl    %esi,(%rdx)                     /* oldp = %rdx */
831         POP_FRAME_POINTER
832         movzbl  %cl, %eax
833         ret
834 END(casueword32_nosmap)
835
836 ENTRY(casueword32_smap)
837         PUSH_FRAME_POINTER
838         movq    PCPU(CURPCB),%r8
839         movq    $fusufault,PCB_ONFAULT(%r8)
840
841         movq    $VM_MAXUSER_ADDRESS-4,%rax
842         cmpq    %rax,%rdi                       /* verify address is valid */
843         ja      fusufault
844
845         movl    %esi,%eax                       /* old */
846         stac
847 #ifdef SMP
848         lock
849 #endif
850         cmpxchgl %ecx,(%rdi)                    /* new = %ecx */
851         clac
852         setne   %cl
853
854         /*
855          * The old value is in %eax.  If the store succeeded it will be the
856          * value we expected (old) from before the store, otherwise it will
857          * be the current value.  Save %eax into %esi to prepare the return
858          * value.
859          */
860         movl    %eax,%esi
861         xorl    %eax,%eax
862         movq    %rax,PCB_ONFAULT(%r8)
863
864         /*
865          * Access the oldp after the pcb_onfault is cleared, to correctly
866          * catch corrupted pointer.
867          */
868         movl    %esi,(%rdx)                     /* oldp = %rdx */
869         POP_FRAME_POINTER
870         movzbl  %cl, %eax
871         ret
872 END(casueword32_smap)
873
874 /*
875  * casueword.  Compare and set user long.  Returns -1 on fault,
876  *        0 if access was successful.  Old value is written to *oldp.
877  *        dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx
878  */
879 ENTRY(casueword_nosmap)
880         PUSH_FRAME_POINTER
881         movq    PCPU(CURPCB),%r8
882         movq    $fusufault,PCB_ONFAULT(%r8)
883
884         movq    $VM_MAXUSER_ADDRESS-4,%rax
885         cmpq    %rax,%rdi                       /* verify address is valid */
886         ja      fusufault
887
888         movq    %rsi,%rax                       /* old */
889 #ifdef SMP
890         lock
891 #endif
892         cmpxchgq %rcx,(%rdi)                    /* new = %rcx */
893         setne   %cl
894
895         /*
896          * The old value is in %rax.  If the store succeeded it will be the
897          * value we expected (old) from before the store, otherwise it will
898          * be the current value.
899          */
900         movq    %rax,%rsi
901         xorl    %eax,%eax
902         movq    %rax,PCB_ONFAULT(%r8)
903         movq    %rsi,(%rdx)
904         POP_FRAME_POINTER
905         movzbl  %cl, %eax
906         ret
907 END(casueword_nosmap)
908
909 ENTRY(casueword_smap)
910         PUSH_FRAME_POINTER
911         movq    PCPU(CURPCB),%r8
912         movq    $fusufault,PCB_ONFAULT(%r8)
913
914         movq    $VM_MAXUSER_ADDRESS-4,%rax
915         cmpq    %rax,%rdi                       /* verify address is valid */
916         ja      fusufault
917
918         movq    %rsi,%rax                       /* old */
919         stac
920 #ifdef SMP
921         lock
922 #endif
923         cmpxchgq %rcx,(%rdi)                    /* new = %rcx */
924         clac
925         setne   %cl
926
927         /*
928          * The old value is in %rax.  If the store succeeded it will be the
929          * value we expected (old) from before the store, otherwise it will
930          * be the current value.
931          */
932         movq    %rax,%rsi
933         xorl    %eax,%eax
934         movq    %rax,PCB_ONFAULT(%r8)
935         movq    %rsi,(%rdx)
936         POP_FRAME_POINTER
937         movzbl  %cl, %eax
938         ret
939 END(casueword_smap)
940
941 /*
942  * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
943  * byte from user memory.
944  * addr = %rdi, valp = %rsi
945  */
946
947 ENTRY(fueword_nosmap)
948         PUSH_FRAME_POINTER
949         movq    PCPU(CURPCB),%rcx
950         movq    $fusufault,PCB_ONFAULT(%rcx)
951
952         movq    $VM_MAXUSER_ADDRESS-8,%rax
953         cmpq    %rax,%rdi                       /* verify address is valid */
954         ja      fusufault
955
956         xorl    %eax,%eax
957         movq    (%rdi),%r11
958         movq    %rax,PCB_ONFAULT(%rcx)
959         movq    %r11,(%rsi)
960         POP_FRAME_POINTER
961         ret
962 END(fueword_nosmap)
963
964 ENTRY(fueword_smap)
965         PUSH_FRAME_POINTER
966         movq    PCPU(CURPCB),%rcx
967         movq    $fusufault,PCB_ONFAULT(%rcx)
968
969         movq    $VM_MAXUSER_ADDRESS-8,%rax
970         cmpq    %rax,%rdi                       /* verify address is valid */
971         ja      fusufault
972
973         xorl    %eax,%eax
974         stac
975         movq    (%rdi),%r11
976         clac
977         movq    %rax,PCB_ONFAULT(%rcx)
978         movq    %r11,(%rsi)
979         POP_FRAME_POINTER
980         ret
981 END(fueword_smap)
982
983 ENTRY(fueword32_nosmap)
984         PUSH_FRAME_POINTER
985         movq    PCPU(CURPCB),%rcx
986         movq    $fusufault,PCB_ONFAULT(%rcx)
987
988         movq    $VM_MAXUSER_ADDRESS-4,%rax
989         cmpq    %rax,%rdi                       /* verify address is valid */
990         ja      fusufault
991
992         xorl    %eax,%eax
993         movl    (%rdi),%r11d
994         movq    %rax,PCB_ONFAULT(%rcx)
995         movl    %r11d,(%rsi)
996         POP_FRAME_POINTER
997         ret
998 END(fueword32_nosmap)
999
1000 ENTRY(fueword32_smap)
1001         PUSH_FRAME_POINTER
1002         movq    PCPU(CURPCB),%rcx
1003         movq    $fusufault,PCB_ONFAULT(%rcx)
1004
1005         movq    $VM_MAXUSER_ADDRESS-4,%rax
1006         cmpq    %rax,%rdi                       /* verify address is valid */
1007         ja      fusufault
1008
1009         xorl    %eax,%eax
1010         stac
1011         movl    (%rdi),%r11d
1012         clac
1013         movq    %rax,PCB_ONFAULT(%rcx)
1014         movl    %r11d,(%rsi)
1015         POP_FRAME_POINTER
1016         ret
1017 END(fueword32_smap)
1018
1019 ENTRY(fuword16_nosmap)
1020         PUSH_FRAME_POINTER
1021         movq    PCPU(CURPCB),%rcx
1022         movq    $fusufault,PCB_ONFAULT(%rcx)
1023
1024         movq    $VM_MAXUSER_ADDRESS-2,%rax
1025         cmpq    %rax,%rdi
1026         ja      fusufault
1027
1028         movzwl  (%rdi),%eax
1029         movq    $0,PCB_ONFAULT(%rcx)
1030         POP_FRAME_POINTER
1031         ret
1032 END(fuword16_nosmap)
1033
1034 ENTRY(fuword16_smap)
1035         PUSH_FRAME_POINTER
1036         movq    PCPU(CURPCB),%rcx
1037         movq    $fusufault,PCB_ONFAULT(%rcx)
1038
1039         movq    $VM_MAXUSER_ADDRESS-2,%rax
1040         cmpq    %rax,%rdi
1041         ja      fusufault
1042
1043         stac
1044         movzwl  (%rdi),%eax
1045         clac
1046         movq    $0,PCB_ONFAULT(%rcx)
1047         POP_FRAME_POINTER
1048         ret
1049 END(fuword16_smap)
1050
1051 ENTRY(fubyte_nosmap)
1052         PUSH_FRAME_POINTER
1053         movq    PCPU(CURPCB),%rcx
1054         movq    $fusufault,PCB_ONFAULT(%rcx)
1055
1056         movq    $VM_MAXUSER_ADDRESS-1,%rax
1057         cmpq    %rax,%rdi
1058         ja      fusufault
1059
1060         movzbl  (%rdi),%eax
1061         movq    $0,PCB_ONFAULT(%rcx)
1062         POP_FRAME_POINTER
1063         ret
1064 END(fubyte_nosmap)
1065
1066 ENTRY(fubyte_smap)
1067         PUSH_FRAME_POINTER
1068         movq    PCPU(CURPCB),%rcx
1069         movq    $fusufault,PCB_ONFAULT(%rcx)
1070
1071         movq    $VM_MAXUSER_ADDRESS-1,%rax
1072         cmpq    %rax,%rdi
1073         ja      fusufault
1074
1075         stac
1076         movzbl  (%rdi),%eax
1077         clac
1078         movq    $0,PCB_ONFAULT(%rcx)
1079         POP_FRAME_POINTER
1080         ret
1081 END(fubyte_smap)
1082
1083 /*
1084  * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
1085  * user memory.
1086  * addr = %rdi, value = %rsi
1087  */
1088 ENTRY(suword_nosmap)
1089         PUSH_FRAME_POINTER
1090         movq    PCPU(CURPCB),%rcx
1091         movq    $fusufault,PCB_ONFAULT(%rcx)
1092
1093         movq    $VM_MAXUSER_ADDRESS-8,%rax
1094         cmpq    %rax,%rdi                       /* verify address validity */
1095         ja      fusufault
1096
1097         movq    %rsi,(%rdi)
1098         xorl    %eax,%eax
1099         movq    PCPU(CURPCB),%rcx
1100         movq    %rax,PCB_ONFAULT(%rcx)
1101         POP_FRAME_POINTER
1102         ret
1103 END(suword_nosmap)
1104
1105 ENTRY(suword_smap)
1106         PUSH_FRAME_POINTER
1107         movq    PCPU(CURPCB),%rcx
1108         movq    $fusufault,PCB_ONFAULT(%rcx)
1109
1110         movq    $VM_MAXUSER_ADDRESS-8,%rax
1111         cmpq    %rax,%rdi                       /* verify address validity */
1112         ja      fusufault
1113
1114         stac
1115         movq    %rsi,(%rdi)
1116         clac
1117         xorl    %eax,%eax
1118         movq    PCPU(CURPCB),%rcx
1119         movq    %rax,PCB_ONFAULT(%rcx)
1120         POP_FRAME_POINTER
1121         ret
1122 END(suword_smap)
1123
1124 ENTRY(suword32_nosmap)
1125         PUSH_FRAME_POINTER
1126         movq    PCPU(CURPCB),%rcx
1127         movq    $fusufault,PCB_ONFAULT(%rcx)
1128
1129         movq    $VM_MAXUSER_ADDRESS-4,%rax
1130         cmpq    %rax,%rdi                       /* verify address validity */
1131         ja      fusufault
1132
1133         movl    %esi,(%rdi)
1134         xorl    %eax,%eax
1135         movq    PCPU(CURPCB),%rcx
1136         movq    %rax,PCB_ONFAULT(%rcx)
1137         POP_FRAME_POINTER
1138         ret
1139 END(suword32_nosmap)
1140
1141 ENTRY(suword32_smap)
1142         PUSH_FRAME_POINTER
1143         movq    PCPU(CURPCB),%rcx
1144         movq    $fusufault,PCB_ONFAULT(%rcx)
1145
1146         movq    $VM_MAXUSER_ADDRESS-4,%rax
1147         cmpq    %rax,%rdi                       /* verify address validity */
1148         ja      fusufault
1149
1150         stac
1151         movl    %esi,(%rdi)
1152         clac
1153         xorl    %eax,%eax
1154         movq    PCPU(CURPCB),%rcx
1155         movq    %rax,PCB_ONFAULT(%rcx)
1156         POP_FRAME_POINTER
1157         ret
1158 END(suword32_smap)
1159
1160 ENTRY(suword16_nosmap)
1161         PUSH_FRAME_POINTER
1162         movq    PCPU(CURPCB),%rcx
1163         movq    $fusufault,PCB_ONFAULT(%rcx)
1164
1165         movq    $VM_MAXUSER_ADDRESS-2,%rax
1166         cmpq    %rax,%rdi                       /* verify address validity */
1167         ja      fusufault
1168
1169         movw    %si,(%rdi)
1170         xorl    %eax,%eax
1171         movq    %rax,PCB_ONFAULT(%rcx)
1172         POP_FRAME_POINTER
1173         ret
1174 END(suword16_nosmap)
1175
1176 ENTRY(suword16_smap)
1177         PUSH_FRAME_POINTER
1178         movq    PCPU(CURPCB),%rcx
1179         movq    $fusufault,PCB_ONFAULT(%rcx)
1180
1181         movq    $VM_MAXUSER_ADDRESS-2,%rax
1182         cmpq    %rax,%rdi                       /* verify address validity */
1183         ja      fusufault
1184
1185         stac
1186         movw    %si,(%rdi)
1187         clac
1188         xorl    %eax,%eax
1189         movq    %rax,PCB_ONFAULT(%rcx)
1190         POP_FRAME_POINTER
1191         ret
1192 END(suword16_smap)
1193
1194 ENTRY(subyte_nosmap)
1195         PUSH_FRAME_POINTER
1196         movq    PCPU(CURPCB),%rcx
1197         movq    $fusufault,PCB_ONFAULT(%rcx)
1198
1199         movq    $VM_MAXUSER_ADDRESS-1,%rax
1200         cmpq    %rax,%rdi                       /* verify address validity */
1201         ja      fusufault
1202
1203         movl    %esi,%eax
1204         movb    %al,(%rdi)
1205         xorl    %eax,%eax
1206         movq    %rax,PCB_ONFAULT(%rcx)
1207         POP_FRAME_POINTER
1208         ret
1209 END(subyte_nosmap)
1210
1211 ENTRY(subyte_smap)
1212         PUSH_FRAME_POINTER
1213         movq    PCPU(CURPCB),%rcx
1214         movq    $fusufault,PCB_ONFAULT(%rcx)
1215
1216         movq    $VM_MAXUSER_ADDRESS-1,%rax
1217         cmpq    %rax,%rdi                       /* verify address validity */
1218         ja      fusufault
1219
1220         movl    %esi,%eax
1221         stac
1222         movb    %al,(%rdi)
1223         clac
1224         xorl    %eax,%eax
1225         movq    %rax,PCB_ONFAULT(%rcx)
1226         POP_FRAME_POINTER
1227         ret
1228 END(subyte_smap)
1229
1230         ALIGN_TEXT
1231         /* Fault entry clears PSL.AC */
1232 fusufault:
1233         movq    PCPU(CURPCB),%rcx
1234         xorl    %eax,%eax
1235         movq    %rax,PCB_ONFAULT(%rcx)
1236         decq    %rax
1237         POP_FRAME_POINTER
1238         ret
1239
1240 /*
1241  * copyinstr(from, to, maxlen, int *lencopied)
1242  *           %rdi, %rsi, %rdx, %rcx
1243  *
1244  *      copy a string from 'from' to 'to', stop when a 0 character is reached.
1245  *      return ENAMETOOLONG if string is longer than maxlen, and
1246  *      EFAULT on protection violations. If lencopied is non-zero,
1247  *      return the actual length in *lencopied.
1248  */
1249 .macro COPYINSTR smap
1250         PUSH_FRAME_POINTER
1251         movq    %rdx,%r8                        /* %r8 = maxlen */
1252         movq    PCPU(CURPCB),%r9
1253         movq    $cpystrflt,PCB_ONFAULT(%r9)
1254
1255         movq    $VM_MAXUSER_ADDRESS,%rax
1256
1257         /* make sure 'from' is within bounds */
1258         subq    %rdi,%rax
1259         jbe     cpystrflt
1260
1261         SMAP_DISABLE \smap
1262
1263         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1264         cmpq    %rdx,%rax
1265         jb      8f
1266 1:
1267         incq    %rdx
1268 2:
1269         decq    %rdx
1270 .if \smap == 0
1271         jz      copyinstr_toolong
1272 .else
1273         jz      copyinstr_toolong_smap
1274 .endif
1275
1276         movb    (%rdi),%al
1277         movb    %al,(%rsi)
1278         incq    %rsi
1279         incq    %rdi
1280         testb   %al,%al
1281         jnz     2b
1282
1283         SMAP_ENABLE \smap
1284
1285         /* Success -- 0 byte reached */
1286         decq    %rdx
1287         xorl    %eax,%eax
1288
1289         /* set *lencopied and return %eax */
1290         movq    %rax,PCB_ONFAULT(%r9)
1291
1292         testq   %rcx,%rcx
1293         jz      3f
1294         subq    %rdx,%r8
1295         movq    %r8,(%rcx)
1296 3:
1297         POP_FRAME_POINTER
1298         ret
1299         ALIGN_TEXT
1300 8:
1301         movq    %rax,%rdx
1302         movq    %rax,%r8
1303         jmp 1b
1304
1305 .endm
1306
1307 ENTRY(copyinstr_nosmap)
1308         COPYINSTR smap=0
1309 END(copyinstr_nosmap)
1310
1311 ENTRY(copyinstr_smap)
1312         COPYINSTR smap=1
1313 END(copyinstr_smap)
1314
1315 cpystrflt:
1316         /* Fault entry clears PSL.AC */
1317         movl    $EFAULT,%eax
1318 cpystrflt_x:
1319         /* set *lencopied and return %eax */
1320         movq    $0,PCB_ONFAULT(%r9)
1321
1322         testq   %rcx,%rcx
1323         jz      1f
1324         subq    %rdx,%r8
1325         movq    %r8,(%rcx)
1326 1:
1327         POP_FRAME_POINTER
1328         ret
1329
1330 copyinstr_toolong_smap:
1331         clac
1332 copyinstr_toolong:
1333         /* rdx is zero - return ENAMETOOLONG or EFAULT */
1334         movq    $VM_MAXUSER_ADDRESS,%rax
1335         cmpq    %rax,%rdi
1336         jae     cpystrflt
1337         movl    $ENAMETOOLONG,%eax
1338         jmp     cpystrflt_x
1339
1340 /*
1341  * copystr(from, to, maxlen, int *lencopied)
1342  *         %rdi, %rsi, %rdx, %rcx
1343  */
1344 ENTRY(copystr)
1345         PUSH_FRAME_POINTER
1346         movq    %rdx,%r8                        /* %r8 = maxlen */
1347
1348         incq    %rdx
1349 1:
1350         decq    %rdx
1351         jz      4f
1352         movb    (%rdi),%al
1353         movb    %al,(%rsi)
1354         incq    %rsi
1355         incq    %rdi
1356         testb   %al,%al
1357         jnz     1b
1358
1359         /* Success -- 0 byte reached */
1360         decq    %rdx
1361         xorl    %eax,%eax
1362 2:
1363         testq   %rcx,%rcx
1364         jz      3f
1365         /* set *lencopied and return %rax */
1366         subq    %rdx,%r8
1367         movq    %r8,(%rcx)
1368 3:
1369         POP_FRAME_POINTER
1370         ret
1371 4:
1372         /* rdx is zero -- return ENAMETOOLONG */
1373         movl    $ENAMETOOLONG,%eax
1374         jmp     2b
1375 END(copystr)
1376
1377 /*
1378  * Handling of special amd64 registers and descriptor tables etc
1379  */
1380 /* void lgdt(struct region_descriptor *rdp); */
1381 ENTRY(lgdt)
1382         /* reload the descriptor table */
1383         lgdt    (%rdi)
1384
1385         /* flush the prefetch q */
1386         jmp     1f
1387         nop
1388 1:
1389         movl    $KDSEL,%eax
1390         movl    %eax,%ds
1391         movl    %eax,%es
1392         movl    %eax,%fs        /* Beware, use wrmsr to set 64 bit base */
1393         movl    %eax,%gs
1394         movl    %eax,%ss
1395
1396         /* reload code selector by turning return into intersegmental return */
1397         popq    %rax
1398         pushq   $KCSEL
1399         pushq   %rax
1400         MEXITCOUNT
1401         lretq
1402 END(lgdt)
1403
1404 /*****************************************************************************/
1405 /* setjump, longjump                                                         */
1406 /*****************************************************************************/
1407
1408 ENTRY(setjmp)
1409         movq    %rbx,0(%rdi)                    /* save rbx */
1410         movq    %rsp,8(%rdi)                    /* save rsp */
1411         movq    %rbp,16(%rdi)                   /* save rbp */
1412         movq    %r12,24(%rdi)                   /* save r12 */
1413         movq    %r13,32(%rdi)                   /* save r13 */
1414         movq    %r14,40(%rdi)                   /* save r14 */
1415         movq    %r15,48(%rdi)                   /* save r15 */
1416         movq    0(%rsp),%rdx                    /* get rta */
1417         movq    %rdx,56(%rdi)                   /* save rip */
1418         xorl    %eax,%eax                       /* return(0); */
1419         ret
1420 END(setjmp)
1421
1422 ENTRY(longjmp)
1423         movq    0(%rdi),%rbx                    /* restore rbx */
1424         movq    8(%rdi),%rsp                    /* restore rsp */
1425         movq    16(%rdi),%rbp                   /* restore rbp */
1426         movq    24(%rdi),%r12                   /* restore r12 */
1427         movq    32(%rdi),%r13                   /* restore r13 */
1428         movq    40(%rdi),%r14                   /* restore r14 */
1429         movq    48(%rdi),%r15                   /* restore r15 */
1430         movq    56(%rdi),%rdx                   /* get rta */
1431         movq    %rdx,0(%rsp)                    /* put in return frame */
1432         xorl    %eax,%eax                       /* return(1); */
1433         incl    %eax
1434         ret
1435 END(longjmp)
1436
1437 /*
1438  * Support for reading MSRs in the safe manner.  (Instead of panic on #gp,
1439  * return an error.)
1440  */
1441 ENTRY(rdmsr_safe)
1442 /* int rdmsr_safe(u_int msr, uint64_t *data) */
1443         PUSH_FRAME_POINTER
1444         movq    PCPU(CURPCB),%r8
1445         movq    $msr_onfault,PCB_ONFAULT(%r8)
1446         movl    %edi,%ecx
1447         rdmsr                   /* Read MSR pointed by %ecx. Returns
1448                                    hi byte in edx, lo in %eax */
1449         salq    $32,%rdx        /* sign-shift %rdx left */
1450         movl    %eax,%eax       /* zero-extend %eax -> %rax */
1451         orq     %rdx,%rax
1452         movq    %rax,(%rsi)
1453         xorq    %rax,%rax
1454         movq    %rax,PCB_ONFAULT(%r8)
1455         POP_FRAME_POINTER
1456         ret
1457
1458 /*
1459  * Support for writing MSRs in the safe manner.  (Instead of panic on #gp,
1460  * return an error.)
1461  */
1462 ENTRY(wrmsr_safe)
1463 /* int wrmsr_safe(u_int msr, uint64_t data) */
1464         PUSH_FRAME_POINTER
1465         movq    PCPU(CURPCB),%r8
1466         movq    $msr_onfault,PCB_ONFAULT(%r8)
1467         movl    %edi,%ecx
1468         movl    %esi,%eax
1469         sarq    $32,%rsi
1470         movl    %esi,%edx
1471         wrmsr                   /* Write MSR pointed by %ecx. Accepts
1472                                    hi byte in edx, lo in %eax. */
1473         xorq    %rax,%rax
1474         movq    %rax,PCB_ONFAULT(%r8)
1475         POP_FRAME_POINTER
1476         ret
1477
1478 /*
1479  * MSR operations fault handler
1480  */
1481         ALIGN_TEXT
1482 msr_onfault:
1483         movq    $0,PCB_ONFAULT(%r8)
1484         movl    $EFAULT,%eax
1485         POP_FRAME_POINTER
1486         ret
1487
1488 /*
1489  * void pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3);
1490  * Invalidates address space addressed by ucr3, then returns to kcr3.
1491  * Done in assembler to ensure no other memory accesses happen while
1492  * on ucr3.
1493  */
1494         ALIGN_TEXT
1495 ENTRY(pmap_pti_pcid_invalidate)
1496         pushfq
1497         cli
1498         movq    %rdi,%cr3       /* to user page table */
1499         movq    %rsi,%cr3       /* back to kernel */
1500         popfq
1501         retq
1502
1503 /*
1504  * void pmap_pti_pcid_invlpg(uint64_t ucr3, uint64_t kcr3, vm_offset_t va);
1505  * Invalidates virtual address va in address space ucr3, then returns to kcr3.
1506  */
1507         ALIGN_TEXT
1508 ENTRY(pmap_pti_pcid_invlpg)
1509         pushfq
1510         cli
1511         movq    %rdi,%cr3       /* to user page table */
1512         invlpg  (%rdx)
1513         movq    %rsi,%cr3       /* back to kernel */
1514         popfq
1515         retq
1516
1517 /*
1518  * void pmap_pti_pcid_invlrng(uint64_t ucr3, uint64_t kcr3, vm_offset_t sva,
1519  *     vm_offset_t eva);
1520  * Invalidates virtual addresses between sva and eva in address space ucr3,
1521  * then returns to kcr3.
1522  */
1523         ALIGN_TEXT
1524 ENTRY(pmap_pti_pcid_invlrng)
1525         pushfq
1526         cli
1527         movq    %rdi,%cr3       /* to user page table */
1528 1:      invlpg  (%rdx)
1529         addq    $PAGE_SIZE,%rdx
1530         cmpq    %rdx,%rcx
1531         ja      1b
1532         movq    %rsi,%cr3       /* back to kernel */
1533         popfq
1534         retq
1535
1536         .altmacro
1537         .macro  ibrs_seq_label l
1538 handle_ibrs_\l:
1539         .endm
1540         .macro  ibrs_call_label l
1541         call    handle_ibrs_\l
1542         .endm
1543         .macro  ibrs_seq count
1544         ll=1
1545         .rept   \count
1546         ibrs_call_label %(ll)
1547         nop
1548         ibrs_seq_label %(ll)
1549         addq    $8,%rsp
1550         ll=ll+1
1551         .endr
1552         .endm
1553
1554 /* all callers already saved %rax, %rdx, and %rcx */
1555 ENTRY(handle_ibrs_entry)
1556         cmpb    $0,hw_ibrs_active(%rip)
1557         je      1f
1558         movl    $MSR_IA32_SPEC_CTRL,%ecx
1559         rdmsr
1560         orl     $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1561         orl     $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32,%edx
1562         wrmsr
1563         movb    $1,PCPU(IBPB_SET)
1564         testl   $CPUID_STDEXT_SMEP,cpu_stdext_feature(%rip)
1565         jne     1f
1566         ibrs_seq 32
1567 1:      ret
1568 END(handle_ibrs_entry)
1569
1570 ENTRY(handle_ibrs_exit)
1571         cmpb    $0,PCPU(IBPB_SET)
1572         je      1f
1573         movl    $MSR_IA32_SPEC_CTRL,%ecx
1574         rdmsr
1575         andl    $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1576         andl    $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1577         wrmsr
1578         movb    $0,PCPU(IBPB_SET)
1579 1:      ret
1580 END(handle_ibrs_exit)
1581
1582 /* registers-neutral version, but needs stack */
1583 ENTRY(handle_ibrs_exit_rs)
1584         cmpb    $0,PCPU(IBPB_SET)
1585         je      1f
1586         pushq   %rax
1587         pushq   %rdx
1588         pushq   %rcx
1589         movl    $MSR_IA32_SPEC_CTRL,%ecx
1590         rdmsr
1591         andl    $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1592         andl    $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1593         wrmsr
1594         popq    %rcx
1595         popq    %rdx
1596         popq    %rax
1597         movb    $0,PCPU(IBPB_SET)
1598 1:      ret
1599 END(handle_ibrs_exit_rs)
1600
1601         .noaltmacro
1602
1603 /*
1604  * Flush L1D cache.  Load enough of the data from the kernel text
1605  * to flush existing L1D content.
1606  *
1607  * N.B. The function does not follow ABI calling conventions, it corrupts %rbx.
1608  * The vmm.ko caller expects that only %rax, %rdx, %rbx, %rcx, %r9, and %rflags
1609  * registers are clobbered.  The NMI handler caller only needs %r13 preserved.
1610  */
1611 ENTRY(flush_l1d_sw)
1612 #define L1D_FLUSH_SIZE  (64 * 1024)
1613         movq    $KERNBASE, %r9
1614         movq    $-L1D_FLUSH_SIZE, %rcx
1615         /*
1616          * pass 1: Preload TLB.
1617          * Kernel text is mapped using superpages.  TLB preload is
1618          * done for the benefit of older CPUs which split 2M page
1619          * into 4k TLB entries.
1620          */
1621 1:      movb    L1D_FLUSH_SIZE(%r9, %rcx), %al
1622         addq    $PAGE_SIZE, %rcx
1623         jne     1b
1624         xorl    %eax, %eax
1625         cpuid
1626         movq    $-L1D_FLUSH_SIZE, %rcx
1627         /* pass 2: Read each cache line. */
1628 2:      movb    L1D_FLUSH_SIZE(%r9, %rcx), %al
1629         addq    $64, %rcx
1630         jne     2b
1631         lfence
1632         ret
1633 #undef  L1D_FLUSH_SIZE
1634 END(flush_l1d_sw)
1635
1636 ENTRY(flush_l1d_sw_abi)
1637         pushq   %rbx
1638         call    flush_l1d_sw
1639         popq    %rbx
1640         ret
1641 END(flush_l1d_sw_abi)
1642
1643 ENTRY(mds_handler_void)
1644         retq
1645 END(mds_handler_void)
1646
1647 ENTRY(mds_handler_verw)
1648         subq    $8, %rsp
1649         movw    %ds, (%rsp)
1650         verw    (%rsp)
1651         addq    $8, %rsp
1652         retq
1653 END(mds_handler_verw)
1654
1655 ENTRY(mds_handler_ivb)
1656         pushq   %rax
1657         pushq   %rdx
1658         pushq   %rcx
1659
1660         movq    %cr0, %rax
1661         testb   $CR0_TS, %al
1662         je      1f
1663         clts
1664 1:      movq    PCPU(MDS_BUF), %rdx
1665         movdqa  %xmm0, PCPU(MDS_TMP)
1666         pxor    %xmm0, %xmm0
1667
1668         lfence
1669         orpd    (%rdx), %xmm0
1670         orpd    (%rdx), %xmm0
1671         mfence
1672         movl    $40, %ecx
1673         addq    $16, %rdx
1674 2:      movntdq %xmm0, (%rdx)
1675         addq    $16, %rdx
1676         decl    %ecx
1677         jnz     2b
1678         mfence
1679
1680         movdqa  PCPU(MDS_TMP),%xmm0
1681         testb   $CR0_TS, %al
1682         je      3f
1683         movq    %rax, %cr0
1684 3:      popq    %rcx
1685         popq    %rdx
1686         popq    %rax
1687         retq
1688 END(mds_handler_ivb)
1689
1690 ENTRY(mds_handler_bdw)
1691         pushq   %rax
1692         pushq   %rbx
1693         pushq   %rcx
1694         pushq   %rdi
1695         pushq   %rsi
1696
1697         movq    %cr0, %rax
1698         testb   $CR0_TS, %al
1699         je      1f
1700         clts
1701 1:      movq    PCPU(MDS_BUF), %rbx
1702         movdqa  %xmm0, PCPU(MDS_TMP)
1703         pxor    %xmm0, %xmm0
1704
1705         movq    %rbx, %rdi
1706         movq    %rbx, %rsi
1707         movl    $40, %ecx
1708 2:      movntdq %xmm0, (%rbx)
1709         addq    $16, %rbx
1710         decl    %ecx
1711         jnz     2b
1712         mfence
1713         movl    $1536, %ecx
1714         rep; movsb
1715         lfence
1716
1717         movdqa  PCPU(MDS_TMP),%xmm0
1718         testb   $CR0_TS, %al
1719         je      3f
1720         movq    %rax, %cr0
1721 3:      popq    %rsi
1722         popq    %rdi
1723         popq    %rcx
1724         popq    %rbx
1725         popq    %rax
1726         retq
1727 END(mds_handler_bdw)
1728
1729 ENTRY(mds_handler_skl_sse)
1730         pushq   %rax
1731         pushq   %rdx
1732         pushq   %rcx
1733         pushq   %rdi
1734
1735         movq    %cr0, %rax
1736         testb   $CR0_TS, %al
1737         je      1f
1738         clts
1739 1:      movq    PCPU(MDS_BUF), %rdi
1740         movq    PCPU(MDS_BUF64), %rdx
1741         movdqa  %xmm0, PCPU(MDS_TMP)
1742         pxor    %xmm0, %xmm0
1743
1744         lfence
1745         orpd    (%rdx), %xmm0
1746         orpd    (%rdx), %xmm0
1747         xorl    %eax, %eax
1748 2:      clflushopt      5376(%rdi, %rax, 8)
1749         addl    $8, %eax
1750         cmpl    $8 * 12, %eax
1751         jb      2b
1752         sfence
1753         movl    $6144, %ecx
1754         xorl    %eax, %eax
1755         rep; stosb
1756         mfence
1757
1758         movdqa  PCPU(MDS_TMP), %xmm0
1759         testb   $CR0_TS, %al
1760         je      3f
1761         movq    %rax, %cr0
1762 3:      popq    %rdi
1763         popq    %rcx
1764         popq    %rdx
1765         popq    %rax
1766         retq
1767 END(mds_handler_skl_sse)
1768
1769 ENTRY(mds_handler_skl_avx)
1770         pushq   %rax
1771         pushq   %rdx
1772         pushq   %rcx
1773         pushq   %rdi
1774
1775         movq    %cr0, %rax
1776         testb   $CR0_TS, %al
1777         je      1f
1778         clts
1779 1:      movq    PCPU(MDS_BUF), %rdi
1780         movq    PCPU(MDS_BUF64), %rdx
1781         vmovdqa %ymm0, PCPU(MDS_TMP)
1782         vpxor   %ymm0, %ymm0, %ymm0
1783
1784         lfence
1785         vorpd   (%rdx), %ymm0, %ymm0
1786         vorpd   (%rdx), %ymm0, %ymm0
1787         xorl    %eax, %eax
1788 2:      clflushopt      5376(%rdi, %rax, 8)
1789         addl    $8, %eax
1790         cmpl    $8 * 12, %eax
1791         jb      2b
1792         sfence
1793         movl    $6144, %ecx
1794         xorl    %eax, %eax
1795         rep; stosb
1796         mfence
1797
1798         vmovdqa PCPU(MDS_TMP), %ymm0
1799         testb   $CR0_TS, %al
1800         je      3f
1801         movq    %rax, %cr0
1802 3:      popq    %rdi
1803         popq    %rcx
1804         popq    %rdx
1805         popq    %rax
1806         retq
1807 END(mds_handler_skl_avx)
1808
1809 ENTRY(mds_handler_skl_avx512)
1810         pushq   %rax
1811         pushq   %rdx
1812         pushq   %rcx
1813         pushq   %rdi
1814
1815         movq    %cr0, %rax
1816         testb   $CR0_TS, %al
1817         je      1f
1818         clts
1819 1:      movq    PCPU(MDS_BUF), %rdi
1820         movq    PCPU(MDS_BUF64), %rdx
1821         vmovdqa64       %zmm0, PCPU(MDS_TMP)
1822         vpxor   %zmm0, %zmm0, %zmm0
1823
1824         lfence
1825         vorpd   (%rdx), %zmm0, %zmm0
1826         vorpd   (%rdx), %zmm0, %zmm0
1827         xorl    %eax, %eax
1828 2:      clflushopt      5376(%rdi, %rax, 8)
1829         addl    $8, %eax
1830         cmpl    $8 * 12, %eax
1831         jb      2b
1832         sfence
1833         movl    $6144, %ecx
1834         xorl    %eax, %eax
1835         rep; stosb
1836         mfence
1837
1838         vmovdqa64       PCPU(MDS_TMP), %zmm0
1839         testb   $CR0_TS, %al
1840         je      3f
1841         movq    %rax, %cr0
1842 3:      popq    %rdi
1843         popq    %rcx
1844         popq    %rdx
1845         popq    %rax
1846         retq
1847 END(mds_handler_skl_avx512)
1848
1849 ENTRY(mds_handler_silvermont)
1850         pushq   %rax
1851         pushq   %rdx
1852         pushq   %rcx
1853
1854         movq    %cr0, %rax
1855         testb   $CR0_TS, %al
1856         je      1f
1857         clts
1858 1:      movq    PCPU(MDS_BUF), %rdx
1859         movdqa  %xmm0, PCPU(MDS_TMP)
1860         pxor    %xmm0, %xmm0
1861
1862         movl    $16, %ecx
1863 2:      movntdq %xmm0, (%rdx)
1864         addq    $16, %rdx
1865         decl    %ecx
1866         jnz     2b
1867         mfence
1868
1869         movdqa  PCPU(MDS_TMP),%xmm0
1870         testb   $CR0_TS, %al
1871         je      3f
1872         movq    %rax, %cr0
1873 3:      popq    %rcx
1874         popq    %rdx
1875         popq    %rax
1876         retq
1877 END(mds_handler_silvermont)