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.
7 * Portions of this software were developed by
8 * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
9 * the FreeBSD Foundation.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
40 #include <machine/asmacros.h>
41 #include <machine/specialreg.h>
42 #include <machine/pmap.h>
51 movq $PAGE_SIZE/8,%rcx
70 * pagecopy(%rdi=from, %rsi=to)
74 movq $PAGE_SIZE/8,%rcx
92 * The loop takes 29 bytes. Ensure that it doesn't cross a 32-byte
97 movnti %rax,(%rdi,%rdx)
98 movnti %rax,8(%rdi,%rdx)
99 movnti %rax,16(%rdi,%rdx)
100 movnti %rax,24(%rdi,%rdx)
109 * memcmpy(b1, b2, len)
121 movzbl (%rdi,%rcx,1),%eax
122 movzbl (%rsi,%rcx,1),%r8d
128 movzbl (%rdi,%rcx,1),%eax
129 movzbl (%rsi,%rcx,1),%r8d
135 movzbl (%rdi,%rcx,1),%eax
136 movzbl (%rsi,%rcx,1),%r8d
142 movzbl (%rdi,%rcx,1),%eax
143 movzbl (%rsi,%rcx,1),%r8d
203 * memmove(dst, src, cnt)
205 * Adapted from bcopy written by:
206 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
210 * Register state at entry is supposed to be as follows:
215 * The macro possibly clobbers the above and: rcx, r8.
216 * It does not clobber rax, r10 nor r11.
218 .macro MEMMOVE erms overlap begin end
223 cmpq %rcx,%r8 /* overlapping && src < dst? */
305 shrq $3,%rcx /* copy by 64-bit words */
309 andb $7,%cl /* any bytes left? */
404 andq $7,%rcx /* any fractional bytes? */
409 movq %rdx,%rcx /* copy remainder by 32-bit words */
433 MEMMOVE erms=0 overlap=1 begin=MEMMOVE_BEGIN end=MEMMOVE_END
437 MEMMOVE erms=1 overlap=1 begin=MEMMOVE_BEGIN end=MEMMOVE_END
441 * memcpy(dst, src, len)
444 * Note: memcpy does not support overlapping copies
447 MEMMOVE erms=0 overlap=0 begin=MEMMOVE_BEGIN end=MEMMOVE_END
451 MEMMOVE erms=1 overlap=0 begin=MEMMOVE_BEGIN end=MEMMOVE_END
455 * memset(dst, c, len)
463 movabs $0x0101010101010101,%r10
483 movq %r10,-16(%rdi,%rcx)
484 movq %r10,-8(%rdi,%rcx)
494 movq %r10,-16(%rdi,%rcx)
495 movq %r10,-8(%rdi,%rcx)
503 movq %r10,-8(%rdi,%rcx)
511 movl %r10d,-4(%rdi,%rcx)
519 movw %r10w,-2(%rdi,%rcx)
552 movq %r10,-8(%rdi,%rdx)
562 leaq -16(%rcx,%r8),%rcx
564 leaq 16(%rdi,%r8),%rdi
576 /* fillw(pat, base, cnt) */
577 /* %rdi,%rsi, %rdx */
589 /*****************************************************************************/
590 /* copyout and fubyte family */
591 /*****************************************************************************/
593 * Access user memory from inside the kernel. These routines should be
594 * the only places that do this.
596 * These routines set curpcb->pcb_onfault for the time they execute. When a
597 * protection violation occurs inside the functions, the trap handler
598 * returns to *curpcb->pcb_onfault instead of the function.
601 .macro SMAP_DISABLE smap
608 .macro SMAP_ENABLE smap
614 .macro COPYINOUT_BEGIN
618 movq %rax,PCB_ONFAULT(%r11)
622 .macro COPYINOUT_SMAP_END
628 * copyout(from_kernel, to_user, len)
631 .macro COPYOUT smap erms
633 movq PCPU(CURPCB),%r11
634 movq $copy_fault,PCB_ONFAULT(%r11)
637 * Check explicitly for non-user addresses. If 486 write protection
638 * is being used, this check is essential because we are in kernel
639 * mode so the h/w does not provide any protection against writing
644 * First, prevent address wrapping.
650 * XXX STOP USING VM_MAXUSER_ADDRESS.
651 * It is an end address, not a max, so every time it is used correctly it
652 * looks like there is an off by one error, and of course it caused an off
653 * by one error in several places.
655 movq $VM_MAXUSER_ADDRESS,%rcx
660 * Set return value to zero. Remaining failure mode goes through
666 * Set up arguments for MEMMOVE.
676 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_SMAP_END
678 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_END
683 ENTRY(copyout_nosmap_std)
684 COPYOUT smap=0 erms=0
685 END(copyout_nosmap_std)
687 ENTRY(copyout_smap_std)
688 COPYOUT smap=1 erms=0
689 END(copyout_smap_std)
691 ENTRY(copyout_nosmap_erms)
692 COPYOUT smap=0 erms=1
693 END(copyout_nosmap_erms)
695 ENTRY(copyout_smap_erms)
696 COPYOUT smap=1 erms=1
697 END(copyout_smap_erms)
700 * copyin(from_user, to_kernel, len)
703 .macro COPYIN smap erms
705 movq PCPU(CURPCB),%r11
706 movq $copy_fault,PCB_ONFAULT(%r11)
709 * make sure address is valid
714 movq $VM_MAXUSER_ADDRESS,%rcx
727 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_SMAP_END
729 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_END
734 ENTRY(copyin_nosmap_std)
736 END(copyin_nosmap_std)
738 ENTRY(copyin_smap_std)
742 ENTRY(copyin_nosmap_erms)
744 END(copyin_nosmap_erms)
746 ENTRY(copyin_smap_erms)
748 END(copyin_smap_erms)
751 /* Trap entry clears PSL.AC */
753 movq $0,PCB_ONFAULT(%r11)
759 * casueword32. Compare and set user integer. Returns -1 on fault,
760 * 0 if access was successful. Old value is written to *oldp.
761 * dst = %rdi, old = %esi, oldp = %rdx, new = %ecx
763 ENTRY(casueword32_nosmap)
765 movq PCPU(CURPCB),%r8
766 movq $fusufault,PCB_ONFAULT(%r8)
768 movq $VM_MAXUSER_ADDRESS-4,%rax
769 cmpq %rax,%rdi /* verify address is valid */
772 movl %esi,%eax /* old */
776 cmpxchgl %ecx,(%rdi) /* new = %ecx */
779 * The old value is in %eax. If the store succeeded it will be the
780 * value we expected (old) from before the store, otherwise it will
781 * be the current value. Save %eax into %esi to prepare the return
786 movq %rax,PCB_ONFAULT(%r8)
789 * Access the oldp after the pcb_onfault is cleared, to correctly
790 * catch corrupted pointer.
792 movl %esi,(%rdx) /* oldp = %rdx */
795 END(casueword32_nosmap)
797 ENTRY(casueword32_smap)
799 movq PCPU(CURPCB),%r8
800 movq $fusufault,PCB_ONFAULT(%r8)
802 movq $VM_MAXUSER_ADDRESS-4,%rax
803 cmpq %rax,%rdi /* verify address is valid */
806 movl %esi,%eax /* old */
811 cmpxchgl %ecx,(%rdi) /* new = %ecx */
815 * The old value is in %eax. If the store succeeded it will be the
816 * value we expected (old) from before the store, otherwise it will
817 * be the current value. Save %eax into %esi to prepare the return
822 movq %rax,PCB_ONFAULT(%r8)
825 * Access the oldp after the pcb_onfault is cleared, to correctly
826 * catch corrupted pointer.
828 movl %esi,(%rdx) /* oldp = %rdx */
831 END(casueword32_smap)
834 * casueword. Compare and set user long. Returns -1 on fault,
835 * 0 if access was successful. Old value is written to *oldp.
836 * dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx
838 ENTRY(casueword_nosmap)
840 movq PCPU(CURPCB),%r8
841 movq $fusufault,PCB_ONFAULT(%r8)
843 movq $VM_MAXUSER_ADDRESS-4,%rax
844 cmpq %rax,%rdi /* verify address is valid */
847 movq %rsi,%rax /* old */
851 cmpxchgq %rcx,(%rdi) /* new = %rcx */
854 * The old value is in %rax. If the store succeeded it will be the
855 * value we expected (old) from before the store, otherwise it will
856 * be the current value.
860 movq %rax,PCB_ONFAULT(%r8)
864 END(casueword_nosmap)
866 ENTRY(casueword_smap)
868 movq PCPU(CURPCB),%r8
869 movq $fusufault,PCB_ONFAULT(%r8)
871 movq $VM_MAXUSER_ADDRESS-4,%rax
872 cmpq %rax,%rdi /* verify address is valid */
875 movq %rsi,%rax /* old */
880 cmpxchgq %rcx,(%rdi) /* new = %rcx */
884 * The old value is in %rax. If the store succeeded it will be the
885 * value we expected (old) from before the store, otherwise it will
886 * be the current value.
890 movq %rax,PCB_ONFAULT(%r8)
897 * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
898 * byte from user memory.
899 * addr = %rdi, valp = %rsi
902 ENTRY(fueword_nosmap)
904 movq PCPU(CURPCB),%rcx
905 movq $fusufault,PCB_ONFAULT(%rcx)
907 movq $VM_MAXUSER_ADDRESS-8,%rax
908 cmpq %rax,%rdi /* verify address is valid */
913 movq %rax,PCB_ONFAULT(%rcx)
921 movq PCPU(CURPCB),%rcx
922 movq $fusufault,PCB_ONFAULT(%rcx)
924 movq $VM_MAXUSER_ADDRESS-8,%rax
925 cmpq %rax,%rdi /* verify address is valid */
932 movq %rax,PCB_ONFAULT(%rcx)
938 ENTRY(fueword32_nosmap)
940 movq PCPU(CURPCB),%rcx
941 movq $fusufault,PCB_ONFAULT(%rcx)
943 movq $VM_MAXUSER_ADDRESS-4,%rax
944 cmpq %rax,%rdi /* verify address is valid */
949 movq %rax,PCB_ONFAULT(%rcx)
953 END(fueword32_nosmap)
955 ENTRY(fueword32_smap)
957 movq PCPU(CURPCB),%rcx
958 movq $fusufault,PCB_ONFAULT(%rcx)
960 movq $VM_MAXUSER_ADDRESS-4,%rax
961 cmpq %rax,%rdi /* verify address is valid */
968 movq %rax,PCB_ONFAULT(%rcx)
974 ENTRY(fuword16_nosmap)
976 movq PCPU(CURPCB),%rcx
977 movq $fusufault,PCB_ONFAULT(%rcx)
979 movq $VM_MAXUSER_ADDRESS-2,%rax
984 movq $0,PCB_ONFAULT(%rcx)
991 movq PCPU(CURPCB),%rcx
992 movq $fusufault,PCB_ONFAULT(%rcx)
994 movq $VM_MAXUSER_ADDRESS-2,%rax
1001 movq $0,PCB_ONFAULT(%rcx)
1006 ENTRY(fubyte_nosmap)
1008 movq PCPU(CURPCB),%rcx
1009 movq $fusufault,PCB_ONFAULT(%rcx)
1011 movq $VM_MAXUSER_ADDRESS-1,%rax
1016 movq $0,PCB_ONFAULT(%rcx)
1023 movq PCPU(CURPCB),%rcx
1024 movq $fusufault,PCB_ONFAULT(%rcx)
1026 movq $VM_MAXUSER_ADDRESS-1,%rax
1033 movq $0,PCB_ONFAULT(%rcx)
1039 * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
1041 * addr = %rdi, value = %rsi
1043 ENTRY(suword_nosmap)
1045 movq PCPU(CURPCB),%rcx
1046 movq $fusufault,PCB_ONFAULT(%rcx)
1048 movq $VM_MAXUSER_ADDRESS-8,%rax
1049 cmpq %rax,%rdi /* verify address validity */
1054 movq PCPU(CURPCB),%rcx
1055 movq %rax,PCB_ONFAULT(%rcx)
1062 movq PCPU(CURPCB),%rcx
1063 movq $fusufault,PCB_ONFAULT(%rcx)
1065 movq $VM_MAXUSER_ADDRESS-8,%rax
1066 cmpq %rax,%rdi /* verify address validity */
1073 movq PCPU(CURPCB),%rcx
1074 movq %rax,PCB_ONFAULT(%rcx)
1079 ENTRY(suword32_nosmap)
1081 movq PCPU(CURPCB),%rcx
1082 movq $fusufault,PCB_ONFAULT(%rcx)
1084 movq $VM_MAXUSER_ADDRESS-4,%rax
1085 cmpq %rax,%rdi /* verify address validity */
1090 movq PCPU(CURPCB),%rcx
1091 movq %rax,PCB_ONFAULT(%rcx)
1094 END(suword32_nosmap)
1096 ENTRY(suword32_smap)
1098 movq PCPU(CURPCB),%rcx
1099 movq $fusufault,PCB_ONFAULT(%rcx)
1101 movq $VM_MAXUSER_ADDRESS-4,%rax
1102 cmpq %rax,%rdi /* verify address validity */
1109 movq PCPU(CURPCB),%rcx
1110 movq %rax,PCB_ONFAULT(%rcx)
1115 ENTRY(suword16_nosmap)
1117 movq PCPU(CURPCB),%rcx
1118 movq $fusufault,PCB_ONFAULT(%rcx)
1120 movq $VM_MAXUSER_ADDRESS-2,%rax
1121 cmpq %rax,%rdi /* verify address validity */
1126 movq PCPU(CURPCB),%rcx /* restore trashed register */
1127 movq %rax,PCB_ONFAULT(%rcx)
1130 END(suword16_nosmap)
1132 ENTRY(suword16_smap)
1134 movq PCPU(CURPCB),%rcx
1135 movq $fusufault,PCB_ONFAULT(%rcx)
1137 movq $VM_MAXUSER_ADDRESS-2,%rax
1138 cmpq %rax,%rdi /* verify address validity */
1145 movq PCPU(CURPCB),%rcx /* restore trashed register */
1146 movq %rax,PCB_ONFAULT(%rcx)
1151 ENTRY(subyte_nosmap)
1153 movq PCPU(CURPCB),%rcx
1154 movq $fusufault,PCB_ONFAULT(%rcx)
1156 movq $VM_MAXUSER_ADDRESS-1,%rax
1157 cmpq %rax,%rdi /* verify address validity */
1163 movq PCPU(CURPCB),%rcx /* restore trashed register */
1164 movq %rax,PCB_ONFAULT(%rcx)
1171 movq PCPU(CURPCB),%rcx
1172 movq $fusufault,PCB_ONFAULT(%rcx)
1174 movq $VM_MAXUSER_ADDRESS-1,%rax
1175 cmpq %rax,%rdi /* verify address validity */
1183 movq PCPU(CURPCB),%rcx /* restore trashed register */
1184 movq %rax,PCB_ONFAULT(%rcx)
1190 /* Fault entry clears PSL.AC */
1192 movq PCPU(CURPCB),%rcx
1194 movq %rax,PCB_ONFAULT(%rcx)
1200 * copyinstr(from, to, maxlen, int *lencopied)
1201 * %rdi, %rsi, %rdx, %rcx
1203 * copy a string from 'from' to 'to', stop when a 0 character is reached.
1204 * return ENAMETOOLONG if string is longer than maxlen, and
1205 * EFAULT on protection violations. If lencopied is non-zero,
1206 * return the actual length in *lencopied.
1208 .macro COPYINSTR smap
1210 movq %rdx,%r8 /* %r8 = maxlen */
1211 movq PCPU(CURPCB),%r9
1212 movq $cpystrflt,PCB_ONFAULT(%r9)
1214 movq $VM_MAXUSER_ADDRESS,%rax
1216 /* make sure 'from' is within bounds */
1222 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1230 jz copyinstr_toolong
1232 jz copyinstr_toolong_smap
1244 /* Success -- 0 byte reached */
1248 /* set *lencopied and return %eax */
1249 movq %rax,PCB_ONFAULT(%r9)
1266 ENTRY(copyinstr_nosmap)
1268 END(copyinstr_nosmap)
1270 ENTRY(copyinstr_smap)
1275 /* Fault entry clears PSL.AC */
1278 /* set *lencopied and return %eax */
1279 movq $0,PCB_ONFAULT(%r9)
1289 copyinstr_toolong_smap:
1292 /* rdx is zero - return ENAMETOOLONG or EFAULT */
1293 movq $VM_MAXUSER_ADDRESS,%rax
1296 movl $ENAMETOOLONG,%eax
1300 * copystr(from, to, maxlen, int *lencopied)
1301 * %rdi, %rsi, %rdx, %rcx
1305 movq %rdx,%r8 /* %r8 = maxlen */
1318 /* Success -- 0 byte reached */
1324 /* set *lencopied and return %rax */
1331 /* rdx is zero -- return ENAMETOOLONG */
1332 movl $ENAMETOOLONG,%eax
1337 * Handling of special amd64 registers and descriptor tables etc
1339 /* void lgdt(struct region_descriptor *rdp); */
1341 /* reload the descriptor table */
1344 /* flush the prefetch q */
1351 movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */
1355 /* reload code selector by turning return into intersegmental return */
1363 /*****************************************************************************/
1364 /* setjump, longjump */
1365 /*****************************************************************************/
1368 movq %rbx,0(%rdi) /* save rbx */
1369 movq %rsp,8(%rdi) /* save rsp */
1370 movq %rbp,16(%rdi) /* save rbp */
1371 movq %r12,24(%rdi) /* save r12 */
1372 movq %r13,32(%rdi) /* save r13 */
1373 movq %r14,40(%rdi) /* save r14 */
1374 movq %r15,48(%rdi) /* save r15 */
1375 movq 0(%rsp),%rdx /* get rta */
1376 movq %rdx,56(%rdi) /* save rip */
1377 xorl %eax,%eax /* return(0); */
1382 movq 0(%rdi),%rbx /* restore rbx */
1383 movq 8(%rdi),%rsp /* restore rsp */
1384 movq 16(%rdi),%rbp /* restore rbp */
1385 movq 24(%rdi),%r12 /* restore r12 */
1386 movq 32(%rdi),%r13 /* restore r13 */
1387 movq 40(%rdi),%r14 /* restore r14 */
1388 movq 48(%rdi),%r15 /* restore r15 */
1389 movq 56(%rdi),%rdx /* get rta */
1390 movq %rdx,0(%rsp) /* put in return frame */
1391 xorl %eax,%eax /* return(1); */
1397 * Support for reading MSRs in the safe manner. (Instead of panic on #gp,
1401 /* int rdmsr_safe(u_int msr, uint64_t *data) */
1403 movq PCPU(CURPCB),%r8
1404 movq $msr_onfault,PCB_ONFAULT(%r8)
1406 rdmsr /* Read MSR pointed by %ecx. Returns
1407 hi byte in edx, lo in %eax */
1408 salq $32,%rdx /* sign-shift %rdx left */
1409 movl %eax,%eax /* zero-extend %eax -> %rax */
1413 movq %rax,PCB_ONFAULT(%r8)
1418 * Support for writing MSRs in the safe manner. (Instead of panic on #gp,
1422 /* int wrmsr_safe(u_int msr, uint64_t data) */
1424 movq PCPU(CURPCB),%r8
1425 movq $msr_onfault,PCB_ONFAULT(%r8)
1430 wrmsr /* Write MSR pointed by %ecx. Accepts
1431 hi byte in edx, lo in %eax. */
1433 movq %rax,PCB_ONFAULT(%r8)
1438 * MSR operations fault handler
1442 movq $0,PCB_ONFAULT(%r8)
1448 * void pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3);
1449 * Invalidates address space addressed by ucr3, then returns to kcr3.
1450 * Done in assembler to ensure no other memory accesses happen while
1454 ENTRY(pmap_pti_pcid_invalidate)
1457 movq %rdi,%cr3 /* to user page table */
1458 movq %rsi,%cr3 /* back to kernel */
1463 * void pmap_pti_pcid_invlpg(uint64_t ucr3, uint64_t kcr3, vm_offset_t va);
1464 * Invalidates virtual address va in address space ucr3, then returns to kcr3.
1467 ENTRY(pmap_pti_pcid_invlpg)
1470 movq %rdi,%cr3 /* to user page table */
1472 movq %rsi,%cr3 /* back to kernel */
1477 * void pmap_pti_pcid_invlrng(uint64_t ucr3, uint64_t kcr3, vm_offset_t sva,
1479 * Invalidates virtual addresses between sva and eva in address space ucr3,
1480 * then returns to kcr3.
1483 ENTRY(pmap_pti_pcid_invlrng)
1486 movq %rdi,%cr3 /* to user page table */
1488 addq $PAGE_SIZE,%rdx
1491 movq %rsi,%cr3 /* back to kernel */
1496 .macro ibrs_seq_label l
1499 .macro ibrs_call_label l
1502 .macro ibrs_seq count
1505 ibrs_call_label %(ll)
1507 ibrs_seq_label %(ll)
1513 /* all callers already saved %rax, %rdx, and %rcx */
1514 ENTRY(handle_ibrs_entry)
1515 cmpb $0,hw_ibrs_active(%rip)
1517 movl $MSR_IA32_SPEC_CTRL,%ecx
1519 orl $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1520 orl $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32,%edx
1522 movb $1,PCPU(IBPB_SET)
1523 testl $CPUID_STDEXT_SMEP,cpu_stdext_feature(%rip)
1527 END(handle_ibrs_entry)
1529 ENTRY(handle_ibrs_exit)
1530 cmpb $0,PCPU(IBPB_SET)
1532 movl $MSR_IA32_SPEC_CTRL,%ecx
1534 andl $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1535 andl $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1537 movb $0,PCPU(IBPB_SET)
1539 END(handle_ibrs_exit)
1541 /* registers-neutral version, but needs stack */
1542 ENTRY(handle_ibrs_exit_rs)
1543 cmpb $0,PCPU(IBPB_SET)
1548 movl $MSR_IA32_SPEC_CTRL,%ecx
1550 andl $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1551 andl $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1556 movb $0,PCPU(IBPB_SET)
1558 END(handle_ibrs_exit_rs)
1563 * Flush L1D cache. Load enough of the data from the kernel text
1564 * to flush existing L1D content.
1566 * N.B. The function does not follow ABI calling conventions, it corrupts %rbx.
1567 * The vmm.ko caller expects that only %rax, %rdx, %rbx, %rcx, %r9, and %rflags
1568 * registers are clobbered. The NMI handler caller only needs %r13 preserved.
1571 #define L1D_FLUSH_SIZE (64 * 1024)
1573 movq $-L1D_FLUSH_SIZE, %rcx
1575 * pass 1: Preload TLB.
1576 * Kernel text is mapped using superpages. TLB preload is
1577 * done for the benefit of older CPUs which split 2M page
1578 * into 4k TLB entries.
1580 1: movb L1D_FLUSH_SIZE(%r9, %rcx), %al
1581 addq $PAGE_SIZE, %rcx
1585 movq $-L1D_FLUSH_SIZE, %rcx
1586 /* pass 2: Read each cache line. */
1587 2: movb L1D_FLUSH_SIZE(%r9, %rcx), %al
1592 #undef L1D_FLUSH_SIZE
1595 ENTRY(mds_handler_void)
1597 END(mds_handler_void)
1599 ENTRY(mds_handler_verw)
1605 END(mds_handler_verw)
1607 ENTRY(mds_handler_ivb)
1616 1: movq PCPU(MDS_BUF), %rdx
1617 movdqa %xmm0, PCPU(MDS_TMP)
1626 2: movntdq %xmm0, (%rdx)
1632 movdqa PCPU(MDS_TMP),%xmm0
1640 END(mds_handler_ivb)
1642 ENTRY(mds_handler_bdw)
1653 1: movq PCPU(MDS_BUF), %rbx
1654 movdqa %xmm0, PCPU(MDS_TMP)
1660 2: movntdq %xmm0, (%rbx)
1669 movdqa PCPU(MDS_TMP),%xmm0
1679 END(mds_handler_bdw)
1681 ENTRY(mds_handler_skl_sse)
1691 1: movq PCPU(MDS_BUF), %rdi
1692 movq PCPU(MDS_BUF64), %rdx
1693 movdqa %xmm0, PCPU(MDS_TMP)
1700 2: clflushopt 5376(%rdi, %rax, 8)
1710 movdqa PCPU(MDS_TMP), %xmm0
1719 END(mds_handler_skl_sse)
1721 ENTRY(mds_handler_skl_avx)
1731 1: movq PCPU(MDS_BUF), %rdi
1732 movq PCPU(MDS_BUF64), %rdx
1733 vmovdqa %ymm0, PCPU(MDS_TMP)
1734 vpxor %ymm0, %ymm0, %ymm0
1737 vorpd (%rdx), %ymm0, %ymm0
1738 vorpd (%rdx), %ymm0, %ymm0
1740 2: clflushopt 5376(%rdi, %rax, 8)
1750 vmovdqa PCPU(MDS_TMP), %ymm0
1759 END(mds_handler_skl_avx)
1761 ENTRY(mds_handler_skl_avx512)
1771 1: movq PCPU(MDS_BUF), %rdi
1772 movq PCPU(MDS_BUF64), %rdx
1773 /* vmovdqa64 %zmm0, PCPU(MDS_TMP) */
1774 .byte 0x65, 0x62, 0xf1, 0xfd, 0x48, 0x7f, 0x04, 0x25
1776 /* vpxor %zmm0, %zmm0, %zmm0 */
1777 .byte 0x62, 0xf1, 0xfd, 0x48, 0xef, 0xc0
1780 /* vorpd (%rdx), %zmm0, %zmm0 */
1781 .byte 0x62, 0xf1, 0xfd, 0x48, 0x56, 0x02
1782 /* vorpd (%rdx), %zmm0, %zmm0 */
1783 .byte 0x62, 0xf1, 0xfd, 0x48, 0x56, 0x02
1785 2: clflushopt 5376(%rdi, %rax, 8)
1795 /* vmovdqa64 PCPU(MDS_TMP), %zmm0 */
1796 .byte 0x65, 0x62, 0xf1, 0xfd, 0x48, 0x6f, 0x04, 0x25
1806 END(mds_handler_skl_avx512)
1808 ENTRY(mds_handler_silvermont)
1817 1: movq PCPU(MDS_BUF), %rdx
1818 movdqa %xmm0, PCPU(MDS_TMP)
1822 2: movntdq %xmm0, (%rdx)
1828 movdqa PCPU(MDS_TMP),%xmm0
1836 END(mds_handler_silvermont)