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 * 4. 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: stable/11/sys/amd64/amd64/support.S 361561 2020-05-27 18:55:24Z kib $ 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.s" 45 46 .text 47 48/* 49 * bcopy family 50 * void bzero(void *buf, u_int len) 51 */ 52 53/* done */ 54ENTRY(bzero) 55 PUSH_FRAME_POINTER 56 movq %rsi,%rcx 57 xorl %eax,%eax 58 shrq $3,%rcx 59 rep 60 stosq 61 movq %rsi,%rcx 62 andq $7,%rcx 63 rep 64 stosb 65 POP_FRAME_POINTER 66 ret 67END(bzero) 68 69/* Address: %rdi */ 70ENTRY(pagezero) 71 PUSH_FRAME_POINTER 72 movq $PAGE_SIZE/8,%rcx 73 xorl %eax,%eax 74 rep 75 stosq 76 POP_FRAME_POINTER 77 ret 78END(pagezero) 79 80ENTRY(bcmp) 81 PUSH_FRAME_POINTER 82 movq %rdx,%rcx 83 shrq $3,%rcx 84 repe 85 cmpsq 86 jne 1f 87 88 movq %rdx,%rcx 89 andq $7,%rcx 90 repe 91 cmpsb 921: 93 setne %al 94 movsbl %al,%eax 95 POP_FRAME_POINTER 96 ret 97END(bcmp) 98 99/* 100 * bcopy(src, dst, cnt) 101 * rdi, rsi, rdx 102 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 103 */ 104ENTRY(bcopy) 105 PUSH_FRAME_POINTER 106 xchgq %rsi,%rdi 107 movq %rdx,%rcx 108 109 movq %rdi,%rax 110 subq %rsi,%rax 111 cmpq %rcx,%rax /* overlapping && src < dst? */ 112 jb 1f 113 114 shrq $3,%rcx /* copy by 64-bit words */ 115 rep 116 movsq 117 movq %rdx,%rcx 118 andq $7,%rcx /* any bytes left? */ 119 rep 120 movsb 121 POP_FRAME_POINTER 122 ret 123 124 /* ALIGN_TEXT */ 1251: 126 addq %rcx,%rdi /* copy backwards */ 127 addq %rcx,%rsi 128 decq %rdi 129 decq %rsi 130 andq $7,%rcx /* any fractional bytes? */ 131 std 132 rep 133 movsb 134 movq %rdx,%rcx /* copy remainder by 32-bit words */ 135 shrq $3,%rcx 136 subq $7,%rsi 137 subq $7,%rdi 138 rep 139 movsq 140 cld 141 POP_FRAME_POINTER 142 ret 143END(bcopy) 144 145/* 146 * Note: memcpy does not support overlapping copies 147 */ 148ENTRY(memcpy) 149 PUSH_FRAME_POINTER 150 movq %rdi,%rax 151 movq %rdx,%rcx 152 shrq $3,%rcx /* copy by 64-bit words */ 153 rep 154 movsq 155 movq %rdx,%rcx 156 andq $7,%rcx /* any bytes left? */ 157 rep 158 movsb 159 POP_FRAME_POINTER 160 ret 161END(memcpy) 162 163/* 164 * pagecopy(%rdi=from, %rsi=to) 165 */ 166ENTRY(pagecopy) 167 PUSH_FRAME_POINTER 168 movq $-PAGE_SIZE,%rax 169 movq %rax,%rdx 170 subq %rax,%rdi 171 subq %rax,%rsi 1721: 173 prefetchnta (%rdi,%rax) 174 addq $64,%rax 175 jne 1b 1762: 177 movq (%rdi,%rdx),%rax 178 movnti %rax,(%rsi,%rdx) 179 movq 8(%rdi,%rdx),%rax 180 movnti %rax,8(%rsi,%rdx) 181 movq 16(%rdi,%rdx),%rax 182 movnti %rax,16(%rsi,%rdx) 183 movq 24(%rdi,%rdx),%rax 184 movnti %rax,24(%rsi,%rdx) 185 addq $32,%rdx 186 jne 2b 187 sfence 188 POP_FRAME_POINTER 189 ret 190END(pagecopy) 191 192/* fillw(pat, base, cnt) */ 193/* %rdi,%rsi, %rdx */ 194ENTRY(fillw) 195 PUSH_FRAME_POINTER 196 movq %rdi,%rax 197 movq %rsi,%rdi 198 movq %rdx,%rcx 199 rep 200 stosw 201 POP_FRAME_POINTER 202 ret 203END(fillw) 204 205/*****************************************************************************/ 206/* copyout and fubyte family */ 207/*****************************************************************************/ 208/* 209 * Access user memory from inside the kernel. These routines should be 210 * the only places that do this. 211 * 212 * These routines set curpcb->pcb_onfault for the time they execute. When a 213 * protection violation occurs inside the functions, the trap handler 214 * returns to *curpcb->pcb_onfault instead of the function. 215 */ 216 217/* 218 * copyout(from_kernel, to_user, len) 219 * %rdi, %rsi, %rdx 220 */ 221ENTRY(copyout) 222 PUSH_FRAME_POINTER 223 movq PCPU(CURPCB),%rax 224 movq $copyout_fault,PCB_ONFAULT(%rax) 225 testq %rdx,%rdx /* anything to do? */ 226 jz done_copyout 227 228 /* 229 * Check explicitly for non-user addresses. This check is essential 230 * because it prevents usermode from writing into the kernel. We do 231 * not verify anywhere else that the user did not specify a rogue 232 * address. 233 */ 234 /* 235 * First, prevent address wrapping. 236 */ 237 movq %rsi,%rax 238 addq %rdx,%rax 239 jc copyout_fault 240/* 241 * XXX STOP USING VM_MAXUSER_ADDRESS. 242 * It is an end address, not a max, so every time it is used correctly it 243 * looks like there is an off by one error, and of course it caused an off 244 * by one error in several places. 245 */ 246 movq $VM_MAXUSER_ADDRESS,%rcx 247 cmpq %rcx,%rax 248 ja copyout_fault 249 250 xchgq %rdi,%rsi 251 /* bcopy(%rsi, %rdi, %rdx) */ 252 movq %rdx,%rcx 253 254 shrq $3,%rcx 255 rep 256 movsq 257 movb %dl,%cl 258 andb $7,%cl 259 rep 260 movsb 261 262done_copyout: 263 xorl %eax,%eax 264 movq PCPU(CURPCB),%rdx 265 movq %rax,PCB_ONFAULT(%rdx) 266 POP_FRAME_POINTER 267 ret 268 269 ALIGN_TEXT 270copyout_fault: 271 movq PCPU(CURPCB),%rdx 272 movq $0,PCB_ONFAULT(%rdx) 273 movq $EFAULT,%rax 274 POP_FRAME_POINTER 275 ret 276END(copyout) 277 278/* 279 * copyin(from_user, to_kernel, len) 280 * %rdi, %rsi, %rdx 281 */ 282ENTRY(copyin) 283 PUSH_FRAME_POINTER 284 movq PCPU(CURPCB),%rax 285 movq $copyin_fault,PCB_ONFAULT(%rax) 286 testq %rdx,%rdx /* anything to do? */ 287 jz done_copyin 288 289 /* 290 * make sure address is valid 291 */ 292 movq %rdi,%rax 293 addq %rdx,%rax 294 jc copyin_fault 295 movq $VM_MAXUSER_ADDRESS,%rcx 296 cmpq %rcx,%rax 297 ja copyin_fault 298 299 xchgq %rdi,%rsi 300 movq %rdx,%rcx 301 movb %cl,%al 302 shrq $3,%rcx /* copy longword-wise */ 303 rep 304 movsq 305 movb %al,%cl 306 andb $7,%cl /* copy remaining bytes */ 307 rep 308 movsb 309 310done_copyin: 311 xorl %eax,%eax 312 movq PCPU(CURPCB),%rdx 313 movq %rax,PCB_ONFAULT(%rdx) 314 POP_FRAME_POINTER 315 ret 316 317 ALIGN_TEXT 318copyin_fault: 319 movq PCPU(CURPCB),%rdx 320 movq $0,PCB_ONFAULT(%rdx) 321 movq $EFAULT,%rax 322 POP_FRAME_POINTER 323 ret 324END(copyin) 325 326/* 327 * casueword32. Compare and set user integer. Returns -1 on fault, 328 * 0 if access was successful. Old value is written to *oldp. 329 * dst = %rdi, old = %esi, oldp = %rdx, new = %ecx 330 */ 331ENTRY(casueword32) 332 PUSH_FRAME_POINTER 333 movq PCPU(CURPCB),%r8 334 movq $fusufault,PCB_ONFAULT(%r8) 335 336 movq $VM_MAXUSER_ADDRESS-4,%rax 337 cmpq %rax,%rdi /* verify address is valid */ 338 ja fusufault 339 340 movl %esi,%eax /* old */ 341#ifdef SMP 342 lock 343#endif 344 cmpxchgl %ecx,(%rdi) /* new = %ecx */ 345 346 /* 347 * The old value is in %eax. If the store succeeded it will be the 348 * value we expected (old) from before the store, otherwise it will 349 * be the current value. Save %eax into %esi to prepare the return 350 * value. 351 */ 352 movl %eax,%esi 353 xorl %eax,%eax 354 movq %rax,PCB_ONFAULT(%r8) 355 356 /* 357 * Access the oldp after the pcb_onfault is cleared, to correctly 358 * catch corrupted pointer. 359 */ 360 movl %esi,(%rdx) /* oldp = %rdx */ 361 POP_FRAME_POINTER 362 ret 363END(casueword32) 364 365/* 366 * casueword. Compare and set user long. Returns -1 on fault, 367 * 0 if access was successful. Old value is written to *oldp. 368 * dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx 369 */ 370ENTRY(casueword) 371 PUSH_FRAME_POINTER 372 movq PCPU(CURPCB),%r8 373 movq $fusufault,PCB_ONFAULT(%r8) 374 375 movq $VM_MAXUSER_ADDRESS-4,%rax 376 cmpq %rax,%rdi /* verify address is valid */ 377 ja fusufault 378 379 movq %rsi,%rax /* old */ 380#ifdef SMP 381 lock 382#endif 383 cmpxchgq %rcx,(%rdi) /* new = %rcx */ 384 385 /* 386 * The old value is in %rax. If the store succeeded it will be the 387 * value we expected (old) from before the store, otherwise it will 388 * be the current value. 389 */ 390 movq %rax,%rsi 391 xorl %eax,%eax 392 movq %rax,PCB_ONFAULT(%r8) 393 movq %rsi,(%rdx) 394 POP_FRAME_POINTER 395 ret 396END(casueword) 397 398/* 399 * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit 400 * byte from user memory. 401 * addr = %rdi, valp = %rsi 402 */ 403 404ALTENTRY(fueword64) 405ENTRY(fueword) 406 PUSH_FRAME_POINTER 407 movq PCPU(CURPCB),%rcx 408 movq $fusufault,PCB_ONFAULT(%rcx) 409 410 movq $VM_MAXUSER_ADDRESS-8,%rax 411 cmpq %rax,%rdi /* verify address is valid */ 412 ja fusufault 413 414 xorl %eax,%eax 415 movq (%rdi),%r11 416 movq %rax,PCB_ONFAULT(%rcx) 417 movq %r11,(%rsi) 418 POP_FRAME_POINTER 419 ret 420END(fueword64) 421END(fueword) 422 423ENTRY(fueword32) 424 PUSH_FRAME_POINTER 425 movq PCPU(CURPCB),%rcx 426 movq $fusufault,PCB_ONFAULT(%rcx) 427 428 movq $VM_MAXUSER_ADDRESS-4,%rax 429 cmpq %rax,%rdi /* verify address is valid */ 430 ja fusufault 431 432 xorl %eax,%eax 433 movl (%rdi),%r11d 434 movq %rax,PCB_ONFAULT(%rcx) 435 movl %r11d,(%rsi) 436 POP_FRAME_POINTER 437 ret 438END(fueword32) 439 440/* 441 * fuswintr() and suswintr() are specialized variants of fuword16() and 442 * suword16(), respectively. They are called from the profiling code, 443 * potentially at interrupt time. If they fail, that's okay; good things 444 * will happen later. They always fail for now, until the trap code is 445 * able to deal with this. 446 */ 447ALTENTRY(suswintr) 448ENTRY(fuswintr) 449 movq $-1,%rax 450 ret 451END(suswintr) 452END(fuswintr) 453 454ENTRY(fuword16) 455 PUSH_FRAME_POINTER 456 movq PCPU(CURPCB),%rcx 457 movq $fusufault,PCB_ONFAULT(%rcx) 458 459 movq $VM_MAXUSER_ADDRESS-2,%rax 460 cmpq %rax,%rdi 461 ja fusufault 462 463 movzwl (%rdi),%eax 464 movq $0,PCB_ONFAULT(%rcx) 465 POP_FRAME_POINTER 466 ret 467END(fuword16) 468 469ENTRY(fubyte) 470 PUSH_FRAME_POINTER 471 movq PCPU(CURPCB),%rcx 472 movq $fusufault,PCB_ONFAULT(%rcx) 473 474 movq $VM_MAXUSER_ADDRESS-1,%rax 475 cmpq %rax,%rdi 476 ja fusufault 477 478 movzbl (%rdi),%eax 479 movq $0,PCB_ONFAULT(%rcx) 480 POP_FRAME_POINTER 481 ret 482END(fubyte) 483 484 ALIGN_TEXT 485fusufault: 486 movq PCPU(CURPCB),%rcx 487 xorl %eax,%eax 488 movq %rax,PCB_ONFAULT(%rcx) 489 decq %rax 490 POP_FRAME_POINTER 491 ret 492 493/* 494 * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to 495 * user memory. 496 * addr = %rdi, value = %rsi 497 */ 498ALTENTRY(suword64) 499ENTRY(suword) 500 PUSH_FRAME_POINTER 501 movq PCPU(CURPCB),%rcx 502 movq $fusufault,PCB_ONFAULT(%rcx) 503 504 movq $VM_MAXUSER_ADDRESS-8,%rax 505 cmpq %rax,%rdi /* verify address validity */ 506 ja fusufault 507 508 movq %rsi,(%rdi) 509 xorl %eax,%eax 510 movq PCPU(CURPCB),%rcx 511 movq %rax,PCB_ONFAULT(%rcx) 512 POP_FRAME_POINTER 513 ret 514END(suword64) 515END(suword) 516 517ENTRY(suword32) 518 PUSH_FRAME_POINTER 519 movq PCPU(CURPCB),%rcx 520 movq $fusufault,PCB_ONFAULT(%rcx) 521 522 movq $VM_MAXUSER_ADDRESS-4,%rax 523 cmpq %rax,%rdi /* verify address validity */ 524 ja fusufault 525 526 movl %esi,(%rdi) 527 xorl %eax,%eax 528 movq PCPU(CURPCB),%rcx 529 movq %rax,PCB_ONFAULT(%rcx) 530 POP_FRAME_POINTER 531 ret 532END(suword32) 533 534ENTRY(suword16) 535 PUSH_FRAME_POINTER 536 movq PCPU(CURPCB),%rcx 537 movq $fusufault,PCB_ONFAULT(%rcx) 538 539 movq $VM_MAXUSER_ADDRESS-2,%rax 540 cmpq %rax,%rdi /* verify address validity */ 541 ja fusufault 542 543 movw %si,(%rdi) 544 xorl %eax,%eax 545 movq PCPU(CURPCB),%rcx /* restore trashed register */ 546 movq %rax,PCB_ONFAULT(%rcx) 547 POP_FRAME_POINTER 548 ret 549END(suword16) 550 551ENTRY(subyte) 552 PUSH_FRAME_POINTER 553 movq PCPU(CURPCB),%rcx 554 movq $fusufault,PCB_ONFAULT(%rcx) 555 556 movq $VM_MAXUSER_ADDRESS-1,%rax 557 cmpq %rax,%rdi /* verify address validity */ 558 ja fusufault 559 560 movl %esi,%eax 561 movb %al,(%rdi) 562 xorl %eax,%eax 563 movq PCPU(CURPCB),%rcx /* restore trashed register */ 564 movq %rax,PCB_ONFAULT(%rcx) 565 POP_FRAME_POINTER 566 ret 567END(subyte) 568 569/* 570 * copyinstr(from, to, maxlen, int *lencopied) 571 * %rdi, %rsi, %rdx, %rcx 572 * 573 * copy a string from 'from' to 'to', stop when a 0 character is reached. 574 * return ENAMETOOLONG if string is longer than maxlen, and 575 * EFAULT on protection violations. If lencopied is non-zero, 576 * return the actual length in *lencopied. 577 */ 578ENTRY(copyinstr) 579 PUSH_FRAME_POINTER 580 movq %rdx,%r8 /* %r8 = maxlen */ 581 movq %rcx,%r9 /* %r9 = *len */ 582 xchgq %rdi,%rsi /* %rdi = from, %rsi = to */ 583 movq PCPU(CURPCB),%rcx 584 movq $cpystrflt,PCB_ONFAULT(%rcx) 585 586 movq $VM_MAXUSER_ADDRESS,%rax 587 588 /* make sure 'from' is within bounds */ 589 subq %rsi,%rax 590 jbe cpystrflt 591 592 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 593 cmpq %rdx,%rax 594 jae 1f 595 movq %rax,%rdx 596 movq %rax,%r8 5971: 598 incq %rdx 599 6002: 601 decq %rdx 602 jz 3f 603 604 lodsb 605 stosb 606 orb %al,%al 607 jnz 2b 608 609 /* Success -- 0 byte reached */ 610 decq %rdx 611 xorl %eax,%eax 612 jmp cpystrflt_x 6133: 614 /* rdx is zero - return ENAMETOOLONG or EFAULT */ 615 movq $VM_MAXUSER_ADDRESS,%rax 616 cmpq %rax,%rsi 617 jae cpystrflt 6184: 619 movq $ENAMETOOLONG,%rax 620 jmp cpystrflt_x 621 622cpystrflt: 623 movq $EFAULT,%rax 624 625cpystrflt_x: 626 /* set *lencopied and return %eax */ 627 movq PCPU(CURPCB),%rcx 628 movq $0,PCB_ONFAULT(%rcx) 629 630 testq %r9,%r9 631 jz 1f 632 subq %rdx,%r8 633 movq %r8,(%r9) 6341: 635 POP_FRAME_POINTER 636 ret 637END(copyinstr) 638 639/* 640 * copystr(from, to, maxlen, int *lencopied) 641 * %rdi, %rsi, %rdx, %rcx 642 */ 643ENTRY(copystr) 644 PUSH_FRAME_POINTER 645 movq %rdx,%r8 /* %r8 = maxlen */ 646 647 xchgq %rdi,%rsi 648 incq %rdx 6491: 650 decq %rdx 651 jz 4f 652 lodsb 653 stosb 654 orb %al,%al 655 jnz 1b 656 657 /* Success -- 0 byte reached */ 658 decq %rdx 659 xorl %eax,%eax 660 jmp 6f 6614: 662 /* rdx is zero -- return ENAMETOOLONG */ 663 movq $ENAMETOOLONG,%rax 664 6656: 666 667 testq %rcx,%rcx 668 jz 7f 669 /* set *lencopied and return %rax */ 670 subq %rdx,%r8 671 movq %r8,(%rcx) 6727: 673 POP_FRAME_POINTER 674 ret 675END(copystr) 676 677/* 678 * Handling of special amd64 registers and descriptor tables etc 679 */ 680/* void lgdt(struct region_descriptor *rdp); */ 681ENTRY(lgdt) 682 /* reload the descriptor table */ 683 lgdt (%rdi) 684 685 /* flush the prefetch q */ 686 jmp 1f 687 nop 6881: 689 movl $KDSEL,%eax 690 movl %eax,%ds 691 movl %eax,%es 692 movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */ 693 movl %eax,%gs 694 movl %eax,%ss 695 696 /* reload code selector by turning return into intersegmental return */ 697 popq %rax 698 pushq $KCSEL 699 pushq %rax 700 MEXITCOUNT 701 lretq 702END(lgdt) 703 704/*****************************************************************************/ 705/* setjump, longjump */ 706/*****************************************************************************/ 707 708ENTRY(setjmp) 709 movq %rbx,0(%rdi) /* save rbx */ 710 movq %rsp,8(%rdi) /* save rsp */ 711 movq %rbp,16(%rdi) /* save rbp */ 712 movq %r12,24(%rdi) /* save r12 */ 713 movq %r13,32(%rdi) /* save r13 */ 714 movq %r14,40(%rdi) /* save r14 */ 715 movq %r15,48(%rdi) /* save r15 */ 716 movq 0(%rsp),%rdx /* get rta */ 717 movq %rdx,56(%rdi) /* save rip */ 718 xorl %eax,%eax /* return(0); */ 719 ret 720END(setjmp) 721 722ENTRY(longjmp) 723 movq 0(%rdi),%rbx /* restore rbx */ 724 movq 8(%rdi),%rsp /* restore rsp */ 725 movq 16(%rdi),%rbp /* restore rbp */ 726 movq 24(%rdi),%r12 /* restore r12 */ 727 movq 32(%rdi),%r13 /* restore r13 */ 728 movq 40(%rdi),%r14 /* restore r14 */ 729 movq 48(%rdi),%r15 /* restore r15 */ 730 movq 56(%rdi),%rdx /* get rta */ 731 movq %rdx,0(%rsp) /* put in return frame */ 732 xorl %eax,%eax /* return(1); */ 733 incl %eax 734 ret 735END(longjmp) 736 737/* 738 * Support for reading MSRs in the safe manner. 739 */ 740ENTRY(rdmsr_safe) 741/* int rdmsr_safe(u_int msr, uint64_t *data) */ 742 PUSH_FRAME_POINTER 743 movq PCPU(CURPCB),%r8 744 movq $msr_onfault,PCB_ONFAULT(%r8) 745 movl %edi,%ecx 746 rdmsr /* Read MSR pointed by %ecx. Returns 747 hi byte in edx, lo in %eax */ 748 salq $32,%rdx /* sign-shift %rdx left */ 749 movl %eax,%eax /* zero-extend %eax -> %rax */ 750 orq %rdx,%rax 751 movq %rax,(%rsi) 752 xorq %rax,%rax 753 movq %rax,PCB_ONFAULT(%r8) 754 POP_FRAME_POINTER 755 ret 756 757/* 758 * Support for writing MSRs in the safe manner. 759 */ 760ENTRY(wrmsr_safe) 761/* int wrmsr_safe(u_int msr, uint64_t data) */ 762 PUSH_FRAME_POINTER 763 movq PCPU(CURPCB),%r8 764 movq $msr_onfault,PCB_ONFAULT(%r8) 765 movl %edi,%ecx 766 movl %esi,%eax 767 sarq $32,%rsi 768 movl %esi,%edx 769 wrmsr /* Write MSR pointed by %ecx. Accepts 770 hi byte in edx, lo in %eax. */ 771 xorq %rax,%rax 772 movq %rax,PCB_ONFAULT(%r8) 773 POP_FRAME_POINTER 774 ret 775 776/* 777 * MSR operations fault handler 778 */ 779 ALIGN_TEXT 780msr_onfault: 781 movq $0,PCB_ONFAULT(%r8) 782 movl $EFAULT,%eax 783 POP_FRAME_POINTER 784 ret 785 786/* 787 * void pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3); 788 * Invalidates address space addressed by ucr3, then returns to kcr3. 789 * Done in assembler to ensure no other memory accesses happen while 790 * on ucr3. 791 */ 792 ALIGN_TEXT 793ENTRY(pmap_pti_pcid_invalidate) 794 pushfq 795 cli 796 movq %rdi,%cr3 /* to user page table */ 797 movq %rsi,%cr3 /* back to kernel */ 798 popfq 799 retq 800 801/* 802 * void pmap_pti_pcid_invlpg(uint64_t ucr3, uint64_t kcr3, vm_offset_t va); 803 * Invalidates virtual address va in address space ucr3, then returns to kcr3. 804 */ 805 ALIGN_TEXT 806ENTRY(pmap_pti_pcid_invlpg) 807 pushfq 808 cli 809 movq %rdi,%cr3 /* to user page table */ 810 invlpg (%rdx) 811 movq %rsi,%cr3 /* back to kernel */ 812 popfq 813 retq 814 815/* 816 * void pmap_pti_pcid_invlrng(uint64_t ucr3, uint64_t kcr3, vm_offset_t sva, 817 * vm_offset_t eva); 818 * Invalidates virtual addresses between sva and eva in address space ucr3, 819 * then returns to kcr3. 820 */ 821 ALIGN_TEXT 822ENTRY(pmap_pti_pcid_invlrng) 823 pushfq 824 cli 825 movq %rdi,%cr3 /* to user page table */ 8261: invlpg (%rdx) 827 addq $PAGE_SIZE,%rdx 828 cmpq %rdx,%rcx 829 ja 1b 830 movq %rsi,%cr3 /* back to kernel */ 831 popfq 832 retq 833 834 .altmacro 835 .macro rsb_seq_label l 836rsb_seq_\l: 837 .endm 838 .macro rsb_call_label l 839 call rsb_seq_\l 840 .endm 841 .macro rsb_seq count 842 ll=1 843 .rept \count 844 rsb_call_label %(ll) 845 nop 846 rsb_seq_label %(ll) 847 addq $8,%rsp 848 ll=ll+1 849 .endr 850 .endm 851 852ENTRY(rsb_flush) 853 rsb_seq 32 854 ret 855 856/* all callers already saved %rax, %rdx, and %rcx */ 857ENTRY(handle_ibrs_entry) 858 cmpb $0,hw_ibrs_ibpb_active(%rip) 859 je 1f 860 movl $MSR_IA32_SPEC_CTRL,%ecx 861 rdmsr 862 orl $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax 863 orl $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32,%edx 864 wrmsr 865 movb $1,PCPU(IBPB_SET) 866 testl $CPUID_STDEXT_SMEP,cpu_stdext_feature(%rip) 867 je rsb_flush 8681: ret 869END(handle_ibrs_entry) 870 871ENTRY(handle_ibrs_exit) 872 cmpb $0,PCPU(IBPB_SET) 873 je 1f 874 movl $MSR_IA32_SPEC_CTRL,%ecx 875 rdmsr 876 andl $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax 877 andl $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx 878 wrmsr 879 movb $0,PCPU(IBPB_SET) 8801: ret 881END(handle_ibrs_exit) 882 883/* registers-neutral version, but needs stack */ 884ENTRY(handle_ibrs_exit_rs) 885 cmpb $0,PCPU(IBPB_SET) 886 je 1f 887 pushq %rax 888 pushq %rdx 889 pushq %rcx 890 movl $MSR_IA32_SPEC_CTRL,%ecx 891 rdmsr 892 andl $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax 893 andl $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx 894 wrmsr 895 popq %rcx 896 popq %rdx 897 popq %rax 898 movb $0,PCPU(IBPB_SET) 8991: ret 900END(handle_ibrs_exit_rs) 901 902 .noaltmacro 903 904/* 905 * Flush L1D cache. Load enough of the data from the kernel text 906 * to flush existing L1D content. 907 * 908 * N.B. The function does not follow ABI calling conventions, it corrupts %rbx. 909 * The vmm.ko caller expects that only %rax, %rdx, %rbx, %rcx, %r9, and %rflags 910 * registers are clobbered. The NMI handler caller only needs %r13 preserved. 911 */ 912ENTRY(flush_l1d_sw) 913#define L1D_FLUSH_SIZE (64 * 1024) 914 movq $KERNBASE, %r9 915 movq $-L1D_FLUSH_SIZE, %rcx 916 /* 917 * pass 1: Preload TLB. 918 * Kernel text is mapped using superpages. TLB preload is 919 * done for the benefit of older CPUs which split 2M page 920 * into 4k TLB entries. 921 */ 9221: movb L1D_FLUSH_SIZE(%r9, %rcx), %al 923 addq $PAGE_SIZE, %rcx 924 jne 1b 925 xorl %eax, %eax 926 cpuid 927 movq $-L1D_FLUSH_SIZE, %rcx 928 /* pass 2: Read each cache line. */ 9292: movb L1D_FLUSH_SIZE(%r9, %rcx), %al 930 addq $64, %rcx 931 jne 2b 932 lfence 933 ret 934#undef L1D_FLUSH_SIZE 935END(flush_l1d_sw) 936 937ENTRY(mds_handler_void) 938 retq 939END(mds_handler_void) 940 941ENTRY(mds_handler_verw) 942 subq $8, %rsp 943 movw %ds, (%rsp) 944 verw (%rsp) 945 addq $8, %rsp 946 retq 947END(mds_handler_verw) 948 949ENTRY(mds_handler_ivb) 950 pushq %rax 951 pushq %rdx 952 pushq %rcx 953 954 movq %cr0, %rax 955 testb $CR0_TS, %al 956 je 1f 957 clts 9581: movq PCPU(MDS_BUF), %rdx 959 movdqa %xmm0, PCPU(MDS_TMP) 960 pxor %xmm0, %xmm0 961 962 lfence 963 orpd (%rdx), %xmm0 964 orpd (%rdx), %xmm0 965 mfence 966 movl $40, %ecx 967 addq $16, %rdx 9682: movntdq %xmm0, (%rdx) 969 addq $16, %rdx 970 decl %ecx 971 jnz 2b 972 mfence 973 974 movdqa PCPU(MDS_TMP),%xmm0 975 testb $CR0_TS, %al 976 je 3f 977 movq %rax, %cr0 9783: popq %rcx 979 popq %rdx 980 popq %rax 981 retq 982END(mds_handler_ivb) 983 984ENTRY(mds_handler_bdw) 985 pushq %rax 986 pushq %rbx 987 pushq %rcx 988 pushq %rdi 989 pushq %rsi 990 991 movq %cr0, %rax 992 testb $CR0_TS, %al 993 je 1f 994 clts 9951: movq PCPU(MDS_BUF), %rbx 996 movdqa %xmm0, PCPU(MDS_TMP) 997 pxor %xmm0, %xmm0 998 999 movq %rbx, %rdi 1000 movq %rbx, %rsi 1001 movl $40, %ecx 10022: movntdq %xmm0, (%rbx) 1003 addq $16, %rbx 1004 decl %ecx 1005 jnz 2b 1006 mfence 1007 movl $1536, %ecx 1008 rep; movsb 1009 lfence 1010 1011 movdqa PCPU(MDS_TMP),%xmm0 1012 testb $CR0_TS, %al 1013 je 3f 1014 movq %rax, %cr0 10153: popq %rsi 1016 popq %rdi 1017 popq %rcx 1018 popq %rbx 1019 popq %rax 1020 retq 1021END(mds_handler_bdw) 1022 1023ENTRY(mds_handler_skl_sse) 1024 pushq %rax 1025 pushq %rdx 1026 pushq %rcx 1027 pushq %rdi 1028 1029 movq %cr0, %rax 1030 testb $CR0_TS, %al 1031 je 1f 1032 clts 10331: movq PCPU(MDS_BUF), %rdi 1034 movq PCPU(MDS_BUF64), %rdx 1035 movdqa %xmm0, PCPU(MDS_TMP) 1036 pxor %xmm0, %xmm0 1037 1038 lfence 1039 orpd (%rdx), %xmm0 1040 orpd (%rdx), %xmm0 1041 xorl %eax, %eax 10422: clflushopt 5376(%rdi, %rax, 8) 1043 addl $8, %eax 1044 cmpl $8 * 12, %eax 1045 jb 2b 1046 sfence 1047 movl $6144, %ecx 1048 xorl %eax, %eax 1049 rep; stosb 1050 mfence 1051 1052 movdqa PCPU(MDS_TMP), %xmm0 1053 testb $CR0_TS, %al 1054 je 3f 1055 movq %rax, %cr0 10563: popq %rdi 1057 popq %rcx 1058 popq %rdx 1059 popq %rax 1060 retq 1061END(mds_handler_skl_sse) 1062 1063ENTRY(mds_handler_skl_avx) 1064 pushq %rax 1065 pushq %rdx 1066 pushq %rcx 1067 pushq %rdi 1068 1069 movq %cr0, %rax 1070 testb $CR0_TS, %al 1071 je 1f 1072 clts 10731: movq PCPU(MDS_BUF), %rdi 1074 movq PCPU(MDS_BUF64), %rdx 1075 vmovdqa %ymm0, PCPU(MDS_TMP) 1076 vpxor %ymm0, %ymm0, %ymm0 1077 1078 lfence 1079 vorpd (%rdx), %ymm0, %ymm0 1080 vorpd (%rdx), %ymm0, %ymm0 1081 xorl %eax, %eax 10822: clflushopt 5376(%rdi, %rax, 8) 1083 addl $8, %eax 1084 cmpl $8 * 12, %eax 1085 jb 2b 1086 sfence 1087 movl $6144, %ecx 1088 xorl %eax, %eax 1089 rep; stosb 1090 mfence 1091 1092 vmovdqa PCPU(MDS_TMP), %ymm0 1093 testb $CR0_TS, %al 1094 je 3f 1095 movq %rax, %cr0 10963: popq %rdi 1097 popq %rcx 1098 popq %rdx 1099 popq %rax 1100 retq 1101END(mds_handler_skl_avx) 1102 1103ENTRY(mds_handler_skl_avx512) 1104 pushq %rax 1105 pushq %rdx 1106 pushq %rcx 1107 pushq %rdi 1108 1109 movq %cr0, %rax 1110 testb $CR0_TS, %al 1111 je 1f 1112 clts 11131: movq PCPU(MDS_BUF), %rdi 1114 movq PCPU(MDS_BUF64), %rdx 1115 vmovdqa64 %zmm0, PCPU(MDS_TMP) 1116 vpxor %zmm0, %zmm0, %zmm0 1117 1118 lfence 1119 vorpd (%rdx), %zmm0, %zmm0 1120 vorpd (%rdx), %zmm0, %zmm0 1121 xorl %eax, %eax 11222: clflushopt 5376(%rdi, %rax, 8) 1123 addl $8, %eax 1124 cmpl $8 * 12, %eax 1125 jb 2b 1126 sfence 1127 movl $6144, %ecx 1128 xorl %eax, %eax 1129 rep; stosb 1130 mfence 1131 1132 vmovdqa64 PCPU(MDS_TMP), %zmm0 1133 testb $CR0_TS, %al 1134 je 3f 1135 movq %rax, %cr0 11363: popq %rdi 1137 popq %rcx 1138 popq %rdx 1139 popq %rax 1140 retq 1141END(mds_handler_skl_avx512) 1142 1143ENTRY(mds_handler_silvermont) 1144 pushq %rax 1145 pushq %rdx 1146 pushq %rcx 1147 1148 movq %cr0, %rax 1149 testb $CR0_TS, %al 1150 je 1f 1151 clts 11521: movq PCPU(MDS_BUF), %rdx 1153 movdqa %xmm0, PCPU(MDS_TMP) 1154 pxor %xmm0, %xmm0 1155 1156 movl $16, %ecx 11572: movntdq %xmm0, (%rdx) 1158 addq $16, %rdx 1159 decl %ecx 1160 jnz 2b 1161 mfence 1162 1163 movdqa PCPU(MDS_TMP),%xmm0 1164 testb $CR0_TS, %al 1165 je 3f 1166 movq %rax, %cr0 11673: popq %rcx 1168 popq %rdx 1169 popq %rax 1170 retq 1171END(mds_handler_silvermont) 1172