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)
127 movq -8(%rdi,%rdx),%r8
128 movq -8(%rsi,%rdx),%r9
140 movl -4(%rdi,%rdx),%r8d
141 movl -4(%rsi,%rdx),%r9d
153 movzwl -2(%rdi,%rdx),%r8d
154 movzwl -2(%rsi,%rdx),%r9d
180 movq -16(%rdi,%rdx),%r8
181 movq -16(%rsi,%rdx),%r9
184 movq -8(%rdi,%rdx),%r8
185 movq -8(%rsi,%rdx),%r9
217 * Mismatch was found.
219 * Before we compute it we narrow down the range (16 -> 8 -> 4 bytes).
236 leaq -8(%rdi,%rdx),%rdi
237 leaq -8(%rsi,%rdx),%rsi
241 leaq -16(%rdi,%rdx),%rdi
242 leaq -16(%rsi,%rdx),%rsi
251 leaq -4(%rdi,%rdx),%rdi
252 leaq -4(%rsi,%rdx),%rsi
265 * We have up to 4 bytes to inspect.
292 * memmove(dst, src, cnt)
297 * Register state at entry is supposed to be as follows:
302 * The macro possibly clobbers the above and: rcx, r8, r9, 10
303 * It does not clobber rax nor r11.
305 .macro MEMMOVE erms overlap begin end
309 * For sizes 0..32 all data is read before it is written, so there
310 * is no correctness issue with direction of copying.
318 cmpq %rcx,%r8 /* overlapping && src < dst? */
349 movq -16(%rsi,%rcx),%r9
350 movq -8(%rsi,%rcx),%r10
353 movq %r9,-16(%rdi,%rcx)
354 movq %r10,-8(%rdi,%rcx)
362 movq -8(%rsi,%rcx),%r8
364 movq %r8,-8(%rdi,%rcx,)
372 movl -4(%rsi,%rcx),%r8d
374 movl %r8d,-4(%rdi,%rcx)
382 movzwl -2(%rsi,%rcx),%r8d
384 movw %r8w,-2(%rdi,%rcx)
405 shrq $3,%rcx /* copy by 64-bit words */
409 andl $7,%ecx /* any bytes left? */
420 leaq -16(%rdx,%rcx),%rdx
422 leaq 16(%rdi,%rcx),%rdi
423 leaq 16(%rsi,%rcx),%rsi
431 shrq $3,%rcx /* copy by 64-bit words */
437 andl $7,%ecx /* any bytes left? */
452 leaq -8(%rdi,%rcx),%rdi
453 leaq -8(%rsi,%rcx),%rsi
527 leaq -1(%rdi,%rcx),%rdi
528 leaq -1(%rsi,%rcx),%rsi
533 leaq -8(%rdi,%rcx),%rdi
534 leaq -8(%rsi,%rcx),%rsi
559 MEMMOVE erms=0 overlap=1 begin=MEMMOVE_BEGIN end=MEMMOVE_END
563 MEMMOVE erms=1 overlap=1 begin=MEMMOVE_BEGIN end=MEMMOVE_END
567 * memcpy(dst, src, len)
570 * Note: memcpy does not support overlapping copies
573 MEMMOVE erms=0 overlap=0 begin=MEMMOVE_BEGIN end=MEMMOVE_END
577 MEMMOVE erms=1 overlap=0 begin=MEMMOVE_BEGIN end=MEMMOVE_END
581 * memset(dst, c, len)
589 movabs $0x0101010101010101,%r10
609 movq %r10,-16(%rdi,%rcx)
610 movq %r10,-8(%rdi,%rcx)
620 movq %r10,-16(%rdi,%rcx)
621 movq %r10,-8(%rdi,%rcx)
629 movq %r10,-8(%rdi,%rcx)
637 movl %r10d,-4(%rdi,%rcx)
645 movw %r10w,-2(%rdi,%rcx)
678 movq %r10,-8(%rdi,%rdx)
688 leaq -16(%rcx,%r8),%rcx
690 leaq 16(%rdi,%r8),%rdi
702 /* fillw(pat, base, cnt) */
703 /* %rdi,%rsi, %rdx */
715 /*****************************************************************************/
716 /* copyout and fubyte family */
717 /*****************************************************************************/
719 * Access user memory from inside the kernel. These routines should be
720 * the only places that do this.
722 * These routines set curpcb->pcb_onfault for the time they execute. When a
723 * protection violation occurs inside the functions, the trap handler
724 * returns to *curpcb->pcb_onfault instead of the function.
727 .macro SMAP_DISABLE smap
734 .macro SMAP_ENABLE smap
740 .macro COPYINOUT_BEGIN
744 movq %rax,PCB_ONFAULT(%r11)
748 .macro COPYINOUT_SMAP_END
754 * copyout(from_kernel, to_user, len)
757 .macro COPYOUT smap erms
759 movq PCPU(CURPCB),%r11
760 movq $copy_fault,PCB_ONFAULT(%r11)
763 * Check explicitly for non-user addresses.
764 * First, prevent address wrapping.
770 * XXX STOP USING VM_MAXUSER_ADDRESS.
771 * It is an end address, not a max, so every time it is used correctly it
772 * looks like there is an off by one error, and of course it caused an off
773 * by one error in several places.
775 movq $VM_MAXUSER_ADDRESS,%rcx
780 * Set return value to zero. Remaining failure mode goes through
786 * Set up arguments for MEMMOVE.
796 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_SMAP_END
798 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_END
803 ENTRY(copyout_nosmap_std)
804 COPYOUT smap=0 erms=0
805 END(copyout_nosmap_std)
807 ENTRY(copyout_smap_std)
808 COPYOUT smap=1 erms=0
809 END(copyout_smap_std)
811 ENTRY(copyout_nosmap_erms)
812 COPYOUT smap=0 erms=1
813 END(copyout_nosmap_erms)
815 ENTRY(copyout_smap_erms)
816 COPYOUT smap=1 erms=1
817 END(copyout_smap_erms)
820 * copyin(from_user, to_kernel, len)
823 .macro COPYIN smap erms
825 movq PCPU(CURPCB),%r11
826 movq $copy_fault,PCB_ONFAULT(%r11)
829 * make sure address is valid
834 movq $VM_MAXUSER_ADDRESS,%rcx
847 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_SMAP_END
849 MEMMOVE erms=\erms overlap=0 begin=COPYINOUT_BEGIN end=COPYINOUT_END
854 ENTRY(copyin_nosmap_std)
856 END(copyin_nosmap_std)
858 ENTRY(copyin_smap_std)
862 ENTRY(copyin_nosmap_erms)
864 END(copyin_nosmap_erms)
866 ENTRY(copyin_smap_erms)
868 END(copyin_smap_erms)
872 testl $CPUID_STDEXT_SMAP,cpu_stdext_feature(%rip)
875 1: movq $0,PCB_ONFAULT(%r11)
881 * casueword32. Compare and set user integer. Returns -1 on fault,
882 * 0 if access was successful. Old value is written to *oldp.
883 * dst = %rdi, old = %esi, oldp = %rdx, new = %ecx
885 ENTRY(casueword32_nosmap)
887 movq PCPU(CURPCB),%r8
888 movq $fusufault,PCB_ONFAULT(%r8)
890 movq $VM_MAXUSER_ADDRESS-4,%rax
891 cmpq %rax,%rdi /* verify address is valid */
894 movl %esi,%eax /* old */
898 cmpxchgl %ecx,(%rdi) /* new = %ecx */
902 * The old value is in %eax. If the store succeeded it will be the
903 * value we expected (old) from before the store, otherwise it will
904 * be the current value. Save %eax into %esi to prepare the return
909 movq %rax,PCB_ONFAULT(%r8)
912 * Access the oldp after the pcb_onfault is cleared, to correctly
913 * catch corrupted pointer.
915 movl %esi,(%rdx) /* oldp = %rdx */
919 END(casueword32_nosmap)
921 ENTRY(casueword32_smap)
923 movq PCPU(CURPCB),%r8
924 movq $fusufault,PCB_ONFAULT(%r8)
926 movq $VM_MAXUSER_ADDRESS-4,%rax
927 cmpq %rax,%rdi /* verify address is valid */
930 movl %esi,%eax /* old */
935 cmpxchgl %ecx,(%rdi) /* new = %ecx */
940 * The old value is in %eax. If the store succeeded it will be the
941 * value we expected (old) from before the store, otherwise it will
942 * be the current value. Save %eax into %esi to prepare the return
947 movq %rax,PCB_ONFAULT(%r8)
950 * Access the oldp after the pcb_onfault is cleared, to correctly
951 * catch corrupted pointer.
953 movl %esi,(%rdx) /* oldp = %rdx */
957 END(casueword32_smap)
960 * casueword. Compare and set user long. Returns -1 on fault,
961 * 0 if access was successful. Old value is written to *oldp.
962 * dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx
964 ENTRY(casueword_nosmap)
966 movq PCPU(CURPCB),%r8
967 movq $fusufault,PCB_ONFAULT(%r8)
969 movq $VM_MAXUSER_ADDRESS-4,%rax
970 cmpq %rax,%rdi /* verify address is valid */
973 movq %rsi,%rax /* old */
977 cmpxchgq %rcx,(%rdi) /* new = %rcx */
981 * The old value is in %rax. If the store succeeded it will be the
982 * value we expected (old) from before the store, otherwise it will
983 * be the current value.
987 movq %rax,PCB_ONFAULT(%r8)
992 END(casueword_nosmap)
994 ENTRY(casueword_smap)
996 movq PCPU(CURPCB),%r8
997 movq $fusufault,PCB_ONFAULT(%r8)
999 movq $VM_MAXUSER_ADDRESS-4,%rax
1000 cmpq %rax,%rdi /* verify address is valid */
1003 movq %rsi,%rax /* old */
1008 cmpxchgq %rcx,(%rdi) /* new = %rcx */
1013 * The old value is in %rax. If the store succeeded it will be the
1014 * value we expected (old) from before the store, otherwise it will
1015 * be the current value.
1019 movq %rax,PCB_ONFAULT(%r8)
1027 * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
1028 * byte from user memory.
1029 * addr = %rdi, valp = %rsi
1032 ENTRY(fueword_nosmap)
1034 movq PCPU(CURPCB),%rcx
1035 movq $fusufault,PCB_ONFAULT(%rcx)
1037 movq $VM_MAXUSER_ADDRESS-8,%rax
1038 cmpq %rax,%rdi /* verify address is valid */
1043 movq %rax,PCB_ONFAULT(%rcx)
1051 movq PCPU(CURPCB),%rcx
1052 movq $fusufault,PCB_ONFAULT(%rcx)
1054 movq $VM_MAXUSER_ADDRESS-8,%rax
1055 cmpq %rax,%rdi /* verify address is valid */
1062 movq %rax,PCB_ONFAULT(%rcx)
1068 ENTRY(fueword32_nosmap)
1070 movq PCPU(CURPCB),%rcx
1071 movq $fusufault,PCB_ONFAULT(%rcx)
1073 movq $VM_MAXUSER_ADDRESS-4,%rax
1074 cmpq %rax,%rdi /* verify address is valid */
1079 movq %rax,PCB_ONFAULT(%rcx)
1083 END(fueword32_nosmap)
1085 ENTRY(fueword32_smap)
1087 movq PCPU(CURPCB),%rcx
1088 movq $fusufault,PCB_ONFAULT(%rcx)
1090 movq $VM_MAXUSER_ADDRESS-4,%rax
1091 cmpq %rax,%rdi /* verify address is valid */
1098 movq %rax,PCB_ONFAULT(%rcx)
1104 ENTRY(fuword16_nosmap)
1106 movq PCPU(CURPCB),%rcx
1107 movq $fusufault,PCB_ONFAULT(%rcx)
1109 movq $VM_MAXUSER_ADDRESS-2,%rax
1114 movq $0,PCB_ONFAULT(%rcx)
1117 END(fuword16_nosmap)
1119 ENTRY(fuword16_smap)
1121 movq PCPU(CURPCB),%rcx
1122 movq $fusufault,PCB_ONFAULT(%rcx)
1124 movq $VM_MAXUSER_ADDRESS-2,%rax
1131 movq $0,PCB_ONFAULT(%rcx)
1136 ENTRY(fubyte_nosmap)
1138 movq PCPU(CURPCB),%rcx
1139 movq $fusufault,PCB_ONFAULT(%rcx)
1141 movq $VM_MAXUSER_ADDRESS-1,%rax
1146 movq $0,PCB_ONFAULT(%rcx)
1153 movq PCPU(CURPCB),%rcx
1154 movq $fusufault,PCB_ONFAULT(%rcx)
1156 movq $VM_MAXUSER_ADDRESS-1,%rax
1163 movq $0,PCB_ONFAULT(%rcx)
1169 * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
1171 * addr = %rdi, value = %rsi
1173 ENTRY(suword_nosmap)
1175 movq PCPU(CURPCB),%rcx
1176 movq $fusufault,PCB_ONFAULT(%rcx)
1178 movq $VM_MAXUSER_ADDRESS-8,%rax
1179 cmpq %rax,%rdi /* verify address validity */
1184 movq PCPU(CURPCB),%rcx
1185 movq %rax,PCB_ONFAULT(%rcx)
1192 movq PCPU(CURPCB),%rcx
1193 movq $fusufault,PCB_ONFAULT(%rcx)
1195 movq $VM_MAXUSER_ADDRESS-8,%rax
1196 cmpq %rax,%rdi /* verify address validity */
1203 movq PCPU(CURPCB),%rcx
1204 movq %rax,PCB_ONFAULT(%rcx)
1209 ENTRY(suword32_nosmap)
1211 movq PCPU(CURPCB),%rcx
1212 movq $fusufault,PCB_ONFAULT(%rcx)
1214 movq $VM_MAXUSER_ADDRESS-4,%rax
1215 cmpq %rax,%rdi /* verify address validity */
1220 movq PCPU(CURPCB),%rcx
1221 movq %rax,PCB_ONFAULT(%rcx)
1224 END(suword32_nosmap)
1226 ENTRY(suword32_smap)
1228 movq PCPU(CURPCB),%rcx
1229 movq $fusufault,PCB_ONFAULT(%rcx)
1231 movq $VM_MAXUSER_ADDRESS-4,%rax
1232 cmpq %rax,%rdi /* verify address validity */
1239 movq PCPU(CURPCB),%rcx
1240 movq %rax,PCB_ONFAULT(%rcx)
1245 ENTRY(suword16_nosmap)
1247 movq PCPU(CURPCB),%rcx
1248 movq $fusufault,PCB_ONFAULT(%rcx)
1250 movq $VM_MAXUSER_ADDRESS-2,%rax
1251 cmpq %rax,%rdi /* verify address validity */
1256 movq %rax,PCB_ONFAULT(%rcx)
1259 END(suword16_nosmap)
1261 ENTRY(suword16_smap)
1263 movq PCPU(CURPCB),%rcx
1264 movq $fusufault,PCB_ONFAULT(%rcx)
1266 movq $VM_MAXUSER_ADDRESS-2,%rax
1267 cmpq %rax,%rdi /* verify address validity */
1274 movq %rax,PCB_ONFAULT(%rcx)
1279 ENTRY(subyte_nosmap)
1281 movq PCPU(CURPCB),%rcx
1282 movq $fusufault,PCB_ONFAULT(%rcx)
1284 movq $VM_MAXUSER_ADDRESS-1,%rax
1285 cmpq %rax,%rdi /* verify address validity */
1291 movq %rax,PCB_ONFAULT(%rcx)
1298 movq PCPU(CURPCB),%rcx
1299 movq $fusufault,PCB_ONFAULT(%rcx)
1301 movq $VM_MAXUSER_ADDRESS-1,%rax
1302 cmpq %rax,%rdi /* verify address validity */
1310 movq %rax,PCB_ONFAULT(%rcx)
1317 testl $CPUID_STDEXT_SMAP,cpu_stdext_feature(%rip)
1320 1: movq PCPU(CURPCB),%rcx
1322 movq %rax,PCB_ONFAULT(%rcx)
1328 * copyinstr(from, to, maxlen, int *lencopied)
1329 * %rdi, %rsi, %rdx, %rcx
1331 * copy a string from 'from' to 'to', stop when a 0 character is reached.
1332 * return ENAMETOOLONG if string is longer than maxlen, and
1333 * EFAULT on protection violations. If lencopied is non-zero,
1334 * return the actual length in *lencopied.
1336 .macro COPYINSTR smap
1338 movq %rdx,%r8 /* %r8 = maxlen */
1339 movq PCPU(CURPCB),%r9
1340 movq $cpystrflt,PCB_ONFAULT(%r9)
1342 movq $VM_MAXUSER_ADDRESS,%rax
1344 /* make sure 'from' is within bounds */
1350 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1358 jz copyinstr_toolong
1360 jz copyinstr_toolong_smap
1372 /* Success -- 0 byte reached */
1376 /* set *lencopied and return %eax */
1377 movq %rax,PCB_ONFAULT(%r9)
1394 ENTRY(copyinstr_nosmap)
1396 END(copyinstr_nosmap)
1398 ENTRY(copyinstr_smap)
1403 testl $CPUID_STDEXT_SMAP,cpu_stdext_feature(%rip)
1406 1: movl $EFAULT,%eax
1408 /* set *lencopied and return %eax */
1409 movq $0,PCB_ONFAULT(%r9)
1419 copyinstr_toolong_smap:
1422 /* rdx is zero - return ENAMETOOLONG or EFAULT */
1423 movq $VM_MAXUSER_ADDRESS,%rax
1426 movl $ENAMETOOLONG,%eax
1430 * copystr(from, to, maxlen, int *lencopied)
1431 * %rdi, %rsi, %rdx, %rcx
1435 movq %rdx,%r8 /* %r8 = maxlen */
1448 /* Success -- 0 byte reached */
1454 /* set *lencopied and return %rax */
1461 /* rdx is zero -- return ENAMETOOLONG */
1462 movl $ENAMETOOLONG,%eax
1467 * Handling of special amd64 registers and descriptor tables etc
1469 /* void lgdt(struct region_descriptor *rdp); */
1471 /* reload the descriptor table */
1474 /* flush the prefetch q */
1481 movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */
1485 /* reload code selector by turning return into intersegmental return */
1493 /*****************************************************************************/
1494 /* setjump, longjump */
1495 /*****************************************************************************/
1498 movq %rbx,0(%rdi) /* save rbx */
1499 movq %rsp,8(%rdi) /* save rsp */
1500 movq %rbp,16(%rdi) /* save rbp */
1501 movq %r12,24(%rdi) /* save r12 */
1502 movq %r13,32(%rdi) /* save r13 */
1503 movq %r14,40(%rdi) /* save r14 */
1504 movq %r15,48(%rdi) /* save r15 */
1505 movq 0(%rsp),%rdx /* get rta */
1506 movq %rdx,56(%rdi) /* save rip */
1507 xorl %eax,%eax /* return(0); */
1512 movq 0(%rdi),%rbx /* restore rbx */
1513 movq 8(%rdi),%rsp /* restore rsp */
1514 movq 16(%rdi),%rbp /* restore rbp */
1515 movq 24(%rdi),%r12 /* restore r12 */
1516 movq 32(%rdi),%r13 /* restore r13 */
1517 movq 40(%rdi),%r14 /* restore r14 */
1518 movq 48(%rdi),%r15 /* restore r15 */
1519 movq 56(%rdi),%rdx /* get rta */
1520 movq %rdx,0(%rsp) /* put in return frame */
1521 xorl %eax,%eax /* return(1); */
1527 * Support for reading MSRs in the safe manner. (Instead of panic on #gp,
1531 /* int rdmsr_safe(u_int msr, uint64_t *data) */
1533 movq PCPU(CURPCB),%r8
1534 movq $msr_onfault,PCB_ONFAULT(%r8)
1536 rdmsr /* Read MSR pointed by %ecx. Returns
1537 hi byte in edx, lo in %eax */
1538 salq $32,%rdx /* sign-shift %rdx left */
1539 movl %eax,%eax /* zero-extend %eax -> %rax */
1543 movq %rax,PCB_ONFAULT(%r8)
1548 * Support for writing MSRs in the safe manner. (Instead of panic on #gp,
1552 /* int wrmsr_safe(u_int msr, uint64_t data) */
1554 movq PCPU(CURPCB),%r8
1555 movq $msr_onfault,PCB_ONFAULT(%r8)
1560 wrmsr /* Write MSR pointed by %ecx. Accepts
1561 hi byte in edx, lo in %eax. */
1563 movq %rax,PCB_ONFAULT(%r8)
1568 * MSR operations fault handler
1572 movq $0,PCB_ONFAULT(%r8)
1578 * void pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3);
1579 * Invalidates address space addressed by ucr3, then returns to kcr3.
1580 * Done in assembler to ensure no other memory accesses happen while
1584 ENTRY(pmap_pti_pcid_invalidate)
1587 movq %rdi,%cr3 /* to user page table */
1588 movq %rsi,%cr3 /* back to kernel */
1593 * void pmap_pti_pcid_invlpg(uint64_t ucr3, uint64_t kcr3, vm_offset_t va);
1594 * Invalidates virtual address va in address space ucr3, then returns to kcr3.
1597 ENTRY(pmap_pti_pcid_invlpg)
1600 movq %rdi,%cr3 /* to user page table */
1602 movq %rsi,%cr3 /* back to kernel */
1607 * void pmap_pti_pcid_invlrng(uint64_t ucr3, uint64_t kcr3, vm_offset_t sva,
1609 * Invalidates virtual addresses between sva and eva in address space ucr3,
1610 * then returns to kcr3.
1613 ENTRY(pmap_pti_pcid_invlrng)
1616 movq %rdi,%cr3 /* to user page table */
1618 addq $PAGE_SIZE,%rdx
1621 movq %rsi,%cr3 /* back to kernel */
1626 .macro rsb_seq_label l
1629 .macro rsb_call_label l
1632 .macro rsb_seq count
1635 rsb_call_label %(ll)
1647 /* all callers already saved %rax, %rdx, and %rcx */
1648 ENTRY(handle_ibrs_entry)
1649 cmpb $0,hw_ibrs_ibpb_active(%rip)
1651 movl $MSR_IA32_SPEC_CTRL,%ecx
1653 orl $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1654 orl $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32,%edx
1656 movb $1,PCPU(IBPB_SET)
1657 testl $CPUID_STDEXT_SMEP,cpu_stdext_feature(%rip)
1660 END(handle_ibrs_entry)
1662 ENTRY(handle_ibrs_exit)
1663 cmpb $0,PCPU(IBPB_SET)
1665 movl $MSR_IA32_SPEC_CTRL,%ecx
1667 andl $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1668 andl $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1670 movb $0,PCPU(IBPB_SET)
1672 END(handle_ibrs_exit)
1674 /* registers-neutral version, but needs stack */
1675 ENTRY(handle_ibrs_exit_rs)
1676 cmpb $0,PCPU(IBPB_SET)
1681 movl $MSR_IA32_SPEC_CTRL,%ecx
1683 andl $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
1684 andl $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
1689 movb $0,PCPU(IBPB_SET)
1691 END(handle_ibrs_exit_rs)
1696 * Flush L1D cache. Load enough of the data from the kernel text
1697 * to flush existing L1D content.
1699 * N.B. The function does not follow ABI calling conventions, it corrupts %rbx.
1700 * The vmm.ko caller expects that only %rax, %rdx, %rbx, %rcx, %r9, and %rflags
1701 * registers are clobbered. The NMI handler caller only needs %r13 preserved.
1704 #define L1D_FLUSH_SIZE (64 * 1024)
1706 movq $-L1D_FLUSH_SIZE, %rcx
1708 * pass 1: Preload TLB.
1709 * Kernel text is mapped using superpages. TLB preload is
1710 * done for the benefit of older CPUs which split 2M page
1711 * into 4k TLB entries.
1713 1: movb L1D_FLUSH_SIZE(%r9, %rcx), %al
1714 addq $PAGE_SIZE, %rcx
1718 movq $-L1D_FLUSH_SIZE, %rcx
1719 /* pass 2: Read each cache line. */
1720 2: movb L1D_FLUSH_SIZE(%r9, %rcx), %al
1725 #undef L1D_FLUSH_SIZE
1728 ENTRY(flush_l1d_sw_abi)
1733 END(flush_l1d_sw_abi)
1735 ENTRY(mds_handler_void)
1737 END(mds_handler_void)
1739 ENTRY(mds_handler_verw)
1745 END(mds_handler_verw)
1747 ENTRY(mds_handler_ivb)
1756 1: movq PCPU(MDS_BUF), %rdx
1757 movdqa %xmm0, PCPU(MDS_TMP)
1766 2: movntdq %xmm0, (%rdx)
1772 movdqa PCPU(MDS_TMP),%xmm0
1780 END(mds_handler_ivb)
1782 ENTRY(mds_handler_bdw)
1793 1: movq PCPU(MDS_BUF), %rbx
1794 movdqa %xmm0, PCPU(MDS_TMP)
1800 2: movntdq %xmm0, (%rbx)
1809 movdqa PCPU(MDS_TMP),%xmm0
1819 END(mds_handler_bdw)
1821 ENTRY(mds_handler_skl_sse)
1831 1: movq PCPU(MDS_BUF), %rdi
1832 movq PCPU(MDS_BUF64), %rdx
1833 movdqa %xmm0, PCPU(MDS_TMP)
1840 2: clflushopt 5376(%rdi, %rax, 8)
1850 movdqa PCPU(MDS_TMP), %xmm0
1859 END(mds_handler_skl_sse)
1861 ENTRY(mds_handler_skl_avx)
1871 1: movq PCPU(MDS_BUF), %rdi
1872 movq PCPU(MDS_BUF64), %rdx
1873 vmovdqa %ymm0, PCPU(MDS_TMP)
1874 vpxor %ymm0, %ymm0, %ymm0
1877 vorpd (%rdx), %ymm0, %ymm0
1878 vorpd (%rdx), %ymm0, %ymm0
1880 2: clflushopt 5376(%rdi, %rax, 8)
1890 vmovdqa PCPU(MDS_TMP), %ymm0
1899 END(mds_handler_skl_avx)
1901 ENTRY(mds_handler_skl_avx512)
1911 1: movq PCPU(MDS_BUF), %rdi
1912 movq PCPU(MDS_BUF64), %rdx
1913 vmovdqa64 %zmm0, PCPU(MDS_TMP)
1914 vpxor %zmm0, %zmm0, %zmm0
1917 vorpd (%rdx), %zmm0, %zmm0
1918 vorpd (%rdx), %zmm0, %zmm0
1920 2: clflushopt 5376(%rdi, %rax, 8)
1930 vmovdqa64 PCPU(MDS_TMP), %zmm0
1939 END(mds_handler_skl_avx512)
1941 ENTRY(mds_handler_silvermont)
1950 1: movq PCPU(MDS_BUF), %rdx
1951 movdqa %xmm0, PCPU(MDS_TMP)
1955 2: movntdq %xmm0, (%rdx)
1961 movdqa PCPU(MDS_TMP),%xmm0
1969 END(mds_handler_silvermont)