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