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 * 4. 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/pmap.h> 37 38#include "assym.s" 39 40 .text 41 42/* 43 * bcopy family 44 * void bzero(void *buf, u_int len) 45 */ 46 47/* done */ 48ENTRY(bzero) 49 PUSH_FRAME_POINTER 50 movq %rsi,%rcx 51 xorl %eax,%eax 52 shrq $3,%rcx 53 cld 54 rep 55 stosq 56 movq %rsi,%rcx 57 andq $7,%rcx 58 rep 59 stosb 60 POP_FRAME_POINTER 61 ret 62END(bzero) 63 64/* Address: %rdi */ 65ENTRY(pagezero) 66 PUSH_FRAME_POINTER 67 movq $-PAGE_SIZE,%rdx 68 subq %rdx,%rdi 69 xorl %eax,%eax 701: 71 movnti %rax,(%rdi,%rdx) 72 movnti %rax,8(%rdi,%rdx) 73 movnti %rax,16(%rdi,%rdx) 74 movnti %rax,24(%rdi,%rdx) 75 addq $32,%rdx 76 jne 1b 77 sfence 78 POP_FRAME_POINTER 79 ret 80END(pagezero) 81 82ENTRY(bcmp) 83 PUSH_FRAME_POINTER 84 movq %rdx,%rcx 85 shrq $3,%rcx 86 cld /* compare forwards */ 87 repe 88 cmpsq 89 jne 1f 90 91 movq %rdx,%rcx 92 andq $7,%rcx 93 repe 94 cmpsb 951: 96 setne %al 97 movsbl %al,%eax 98 POP_FRAME_POINTER 99 ret 100END(bcmp) 101 102/* 103 * bcopy(src, dst, cnt) 104 * rdi, rsi, rdx 105 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 106 */ 107ENTRY(bcopy) 108 PUSH_FRAME_POINTER 109 xchgq %rsi,%rdi 110 movq %rdx,%rcx 111 112 movq %rdi,%rax 113 subq %rsi,%rax 114 cmpq %rcx,%rax /* overlapping && src < dst? */ 115 jb 1f 116 117 shrq $3,%rcx /* copy by 64-bit words */ 118 cld /* nope, copy forwards */ 119 rep 120 movsq 121 movq %rdx,%rcx 122 andq $7,%rcx /* any bytes left? */ 123 rep 124 movsb 125 POP_FRAME_POINTER 126 ret 127 128 /* ALIGN_TEXT */ 1291: 130 addq %rcx,%rdi /* copy backwards */ 131 addq %rcx,%rsi 132 decq %rdi 133 decq %rsi 134 andq $7,%rcx /* any fractional bytes? */ 135 std 136 rep 137 movsb 138 movq %rdx,%rcx /* copy remainder by 32-bit words */ 139 shrq $3,%rcx 140 subq $7,%rsi 141 subq $7,%rdi 142 rep 143 movsq 144 cld 145 POP_FRAME_POINTER 146 ret 147END(bcopy) 148 149/* 150 * Note: memcpy does not support overlapping copies 151 */ 152ENTRY(memcpy) 153 PUSH_FRAME_POINTER 154 movq %rdi,%rax 155 movq %rdx,%rcx 156 shrq $3,%rcx /* copy by 64-bit words */ 157 cld /* copy forwards */ 158 rep 159 movsq 160 movq %rdx,%rcx 161 andq $7,%rcx /* any bytes left? */ 162 rep 163 movsb 164 POP_FRAME_POINTER 165 ret 166END(memcpy) 167 168/* 169 * pagecopy(%rdi=from, %rsi=to) 170 */ 171ENTRY(pagecopy) 172 PUSH_FRAME_POINTER 173 movq $-PAGE_SIZE,%rax 174 movq %rax,%rdx 175 subq %rax,%rdi 176 subq %rax,%rsi 1771: 178 prefetchnta (%rdi,%rax) 179 addq $64,%rax 180 jne 1b 1812: 182 movq (%rdi,%rdx),%rax 183 movnti %rax,(%rsi,%rdx) 184 movq 8(%rdi,%rdx),%rax 185 movnti %rax,8(%rsi,%rdx) 186 movq 16(%rdi,%rdx),%rax 187 movnti %rax,16(%rsi,%rdx) 188 movq 24(%rdi,%rdx),%rax 189 movnti %rax,24(%rsi,%rdx) 190 addq $32,%rdx 191 jne 2b 192 sfence 193 POP_FRAME_POINTER 194 ret 195END(pagecopy) 196 197/* fillw(pat, base, cnt) */ 198/* %rdi,%rsi, %rdx */ 199ENTRY(fillw) 200 PUSH_FRAME_POINTER 201 movq %rdi,%rax 202 movq %rsi,%rdi 203 movq %rdx,%rcx 204 cld 205 rep 206 stosw 207 POP_FRAME_POINTER 208 ret 209END(fillw) 210 211/*****************************************************************************/ 212/* copyout and fubyte family */ 213/*****************************************************************************/ 214/* 215 * Access user memory from inside the kernel. These routines should be 216 * the only places that do this. 217 * 218 * These routines set curpcb->pcb_onfault for the time they execute. When a 219 * protection violation occurs inside the functions, the trap handler 220 * returns to *curpcb->pcb_onfault instead of the function. 221 */ 222 223/* 224 * copyout(from_kernel, to_user, len) - MP SAFE 225 * %rdi, %rsi, %rdx 226 */ 227ENTRY(copyout) 228 PUSH_FRAME_POINTER 229 movq PCPU(CURPCB),%rax 230 movq $copyout_fault,PCB_ONFAULT(%rax) 231 testq %rdx,%rdx /* anything to do? */ 232 jz done_copyout 233 234 /* 235 * Check explicitly for non-user addresses. If 486 write protection 236 * is being used, this check is essential because we are in kernel 237 * mode so the h/w does not provide any protection against writing 238 * kernel addresses. 239 */ 240 241 /* 242 * First, prevent address wrapping. 243 */ 244 movq %rsi,%rax 245 addq %rdx,%rax 246 jc copyout_fault 247/* 248 * XXX STOP USING VM_MAXUSER_ADDRESS. 249 * It is an end address, not a max, so every time it is used correctly it 250 * looks like there is an off by one error, and of course it caused an off 251 * by one error in several places. 252 */ 253 movq $VM_MAXUSER_ADDRESS,%rcx 254 cmpq %rcx,%rax 255 ja copyout_fault 256 257 xchgq %rdi,%rsi 258 /* bcopy(%rsi, %rdi, %rdx) */ 259 movq %rdx,%rcx 260 261 shrq $3,%rcx 262 cld 263 rep 264 movsq 265 movb %dl,%cl 266 andb $7,%cl 267 rep 268 movsb 269 270done_copyout: 271 xorl %eax,%eax 272 movq PCPU(CURPCB),%rdx 273 movq %rax,PCB_ONFAULT(%rdx) 274 POP_FRAME_POINTER 275 ret 276 277 ALIGN_TEXT 278copyout_fault: 279 movq PCPU(CURPCB),%rdx 280 movq $0,PCB_ONFAULT(%rdx) 281 movq $EFAULT,%rax 282 POP_FRAME_POINTER 283 ret 284END(copyout) 285 286/* 287 * copyin(from_user, to_kernel, len) - MP SAFE 288 * %rdi, %rsi, %rdx 289 */ 290ENTRY(copyin) 291 PUSH_FRAME_POINTER 292 movq PCPU(CURPCB),%rax 293 movq $copyin_fault,PCB_ONFAULT(%rax) 294 testq %rdx,%rdx /* anything to do? */ 295 jz done_copyin 296 297 /* 298 * make sure address is valid 299 */ 300 movq %rdi,%rax 301 addq %rdx,%rax 302 jc copyin_fault 303 movq $VM_MAXUSER_ADDRESS,%rcx 304 cmpq %rcx,%rax 305 ja copyin_fault 306 307 xchgq %rdi,%rsi 308 movq %rdx,%rcx 309 movb %cl,%al 310 shrq $3,%rcx /* copy longword-wise */ 311 cld 312 rep 313 movsq 314 movb %al,%cl 315 andb $7,%cl /* copy remaining bytes */ 316 rep 317 movsb 318 319done_copyin: 320 xorl %eax,%eax 321 movq PCPU(CURPCB),%rdx 322 movq %rax,PCB_ONFAULT(%rdx) 323 POP_FRAME_POINTER 324 ret 325 326 ALIGN_TEXT 327copyin_fault: 328 movq PCPU(CURPCB),%rdx 329 movq $0,PCB_ONFAULT(%rdx) 330 movq $EFAULT,%rax 331 POP_FRAME_POINTER 332 ret 333END(copyin) 334 335/* 336 * casueword32. Compare and set user integer. Returns -1 on fault, 337 * 0 if access was successful. Old value is written to *oldp. 338 * dst = %rdi, old = %esi, oldp = %rdx, new = %ecx 339 */ 340ENTRY(casueword32) 341 PUSH_FRAME_POINTER 342 movq PCPU(CURPCB),%r8 343 movq $fusufault,PCB_ONFAULT(%r8) 344 345 movq $VM_MAXUSER_ADDRESS-4,%rax 346 cmpq %rax,%rdi /* verify address is valid */ 347 ja fusufault 348 349 movl %esi,%eax /* old */ 350#ifdef SMP 351 lock 352#endif 353 cmpxchgl %ecx,(%rdi) /* new = %ecx */ 354 355 /* 356 * The old value is in %eax. If the store succeeded it will be the 357 * value we expected (old) from before the store, otherwise it will 358 * be the current value. Save %eax into %esi to prepare the return 359 * value. 360 */ 361 movl %eax,%esi 362 xorl %eax,%eax 363 movq %rax,PCB_ONFAULT(%r8) 364 365 /* 366 * Access the oldp after the pcb_onfault is cleared, to correctly 367 * catch corrupted pointer. 368 */ 369 movl %esi,(%rdx) /* oldp = %rdx */ 370 POP_FRAME_POINTER 371 ret 372END(casueword32) 373 374/* 375 * casueword. Compare and set user long. Returns -1 on fault, 376 * 0 if access was successful. Old value is written to *oldp. 377 * dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx 378 */ 379ENTRY(casueword) 380 PUSH_FRAME_POINTER 381 movq PCPU(CURPCB),%r8 382 movq $fusufault,PCB_ONFAULT(%r8) 383 384 movq $VM_MAXUSER_ADDRESS-4,%rax 385 cmpq %rax,%rdi /* verify address is valid */ 386 ja fusufault 387 388 movq %rsi,%rax /* old */ 389#ifdef SMP 390 lock 391#endif 392 cmpxchgq %rcx,(%rdi) /* new = %rcx */ 393 394 /* 395 * The old value is in %rax. If the store succeeded it will be the 396 * value we expected (old) from before the store, otherwise it will 397 * be the current value. 398 */ 399 movq %rax,%rsi 400 xorl %eax,%eax 401 movq %rax,PCB_ONFAULT(%r8) 402 movq %rsi,(%rdx) 403 POP_FRAME_POINTER 404 ret 405END(casueword) 406 407/* 408 * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit 409 * byte from user memory. 410 * addr = %rdi, valp = %rsi 411 */ 412 413ALTENTRY(fueword64) 414ENTRY(fueword) 415 PUSH_FRAME_POINTER 416 movq PCPU(CURPCB),%rcx 417 movq $fusufault,PCB_ONFAULT(%rcx) 418 419 movq $VM_MAXUSER_ADDRESS-8,%rax 420 cmpq %rax,%rdi /* verify address is valid */ 421 ja fusufault 422 423 xorl %eax,%eax 424 movq (%rdi),%r11 425 movq %rax,PCB_ONFAULT(%rcx) 426 movq %r11,(%rsi) 427 POP_FRAME_POINTER 428 ret 429END(fueword64) 430END(fueword) 431 432ENTRY(fueword32) 433 PUSH_FRAME_POINTER 434 movq PCPU(CURPCB),%rcx 435 movq $fusufault,PCB_ONFAULT(%rcx) 436 437 movq $VM_MAXUSER_ADDRESS-4,%rax 438 cmpq %rax,%rdi /* verify address is valid */ 439 ja fusufault 440 441 xorl %eax,%eax 442 movl (%rdi),%r11d 443 movq %rax,PCB_ONFAULT(%rcx) 444 movl %r11d,(%rsi) 445 POP_FRAME_POINTER 446 ret 447END(fueword32) 448 449/* 450 * fuswintr() and suswintr() are specialized variants of fuword16() and 451 * suword16(), respectively. They are called from the profiling code, 452 * potentially at interrupt time. If they fail, that's okay; good things 453 * will happen later. They always fail for now, until the trap code is 454 * able to deal with this. 455 */ 456ALTENTRY(suswintr) 457ENTRY(fuswintr) 458 movq $-1,%rax 459 ret 460END(suswintr) 461END(fuswintr) 462 463ENTRY(fuword16) 464 PUSH_FRAME_POINTER 465 movq PCPU(CURPCB),%rcx 466 movq $fusufault,PCB_ONFAULT(%rcx) 467 468 movq $VM_MAXUSER_ADDRESS-2,%rax 469 cmpq %rax,%rdi 470 ja fusufault 471 472 movzwl (%rdi),%eax 473 movq $0,PCB_ONFAULT(%rcx) 474 POP_FRAME_POINTER 475 ret 476END(fuword16) 477 478ENTRY(fubyte) 479 PUSH_FRAME_POINTER 480 movq PCPU(CURPCB),%rcx 481 movq $fusufault,PCB_ONFAULT(%rcx) 482 483 movq $VM_MAXUSER_ADDRESS-1,%rax 484 cmpq %rax,%rdi 485 ja fusufault 486 487 movzbl (%rdi),%eax 488 movq $0,PCB_ONFAULT(%rcx) 489 POP_FRAME_POINTER 490 ret 491END(fubyte) 492 493 ALIGN_TEXT 494fusufault: 495 movq PCPU(CURPCB),%rcx 496 xorl %eax,%eax 497 movq %rax,PCB_ONFAULT(%rcx) 498 decq %rax 499 POP_FRAME_POINTER 500 ret 501 502/* 503 * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to 504 * user memory. All these functions are MPSAFE. 505 * addr = %rdi, value = %rsi 506 */ 507ALTENTRY(suword64) 508ENTRY(suword) 509 PUSH_FRAME_POINTER 510 movq PCPU(CURPCB),%rcx 511 movq $fusufault,PCB_ONFAULT(%rcx) 512 513 movq $VM_MAXUSER_ADDRESS-8,%rax 514 cmpq %rax,%rdi /* verify address validity */ 515 ja fusufault 516 517 movq %rsi,(%rdi) 518 xorl %eax,%eax 519 movq PCPU(CURPCB),%rcx 520 movq %rax,PCB_ONFAULT(%rcx) 521 POP_FRAME_POINTER 522 ret 523END(suword64) 524END(suword) 525 526ENTRY(suword32) 527 PUSH_FRAME_POINTER 528 movq PCPU(CURPCB),%rcx 529 movq $fusufault,PCB_ONFAULT(%rcx) 530 531 movq $VM_MAXUSER_ADDRESS-4,%rax 532 cmpq %rax,%rdi /* verify address validity */ 533 ja fusufault 534 535 movl %esi,(%rdi) 536 xorl %eax,%eax 537 movq PCPU(CURPCB),%rcx 538 movq %rax,PCB_ONFAULT(%rcx) 539 POP_FRAME_POINTER 540 ret 541END(suword32) 542 543ENTRY(suword16) 544 PUSH_FRAME_POINTER 545 movq PCPU(CURPCB),%rcx 546 movq $fusufault,PCB_ONFAULT(%rcx) 547 548 movq $VM_MAXUSER_ADDRESS-2,%rax 549 cmpq %rax,%rdi /* verify address validity */ 550 ja fusufault 551 552 movw %si,(%rdi) 553 xorl %eax,%eax 554 movq PCPU(CURPCB),%rcx /* restore trashed register */ 555 movq %rax,PCB_ONFAULT(%rcx) 556 POP_FRAME_POINTER 557 ret 558END(suword16) 559 560ENTRY(subyte) 561 PUSH_FRAME_POINTER 562 movq PCPU(CURPCB),%rcx 563 movq $fusufault,PCB_ONFAULT(%rcx) 564 565 movq $VM_MAXUSER_ADDRESS-1,%rax 566 cmpq %rax,%rdi /* verify address validity */ 567 ja fusufault 568 569 movl %esi,%eax 570 movb %al,(%rdi) 571 xorl %eax,%eax 572 movq PCPU(CURPCB),%rcx /* restore trashed register */ 573 movq %rax,PCB_ONFAULT(%rcx) 574 POP_FRAME_POINTER 575 ret 576END(subyte) 577 578/* 579 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE 580 * %rdi, %rsi, %rdx, %rcx 581 * 582 * copy a string from from to to, stop when a 0 character is reached. 583 * return ENAMETOOLONG if string is longer than maxlen, and 584 * EFAULT on protection violations. If lencopied is non-zero, 585 * return the actual length in *lencopied. 586 */ 587ENTRY(copyinstr) 588 PUSH_FRAME_POINTER 589 movq %rdx,%r8 /* %r8 = maxlen */ 590 movq %rcx,%r9 /* %r9 = *len */ 591 xchgq %rdi,%rsi /* %rdi = from, %rsi = to */ 592 movq PCPU(CURPCB),%rcx 593 movq $cpystrflt,PCB_ONFAULT(%rcx) 594 595 movq $VM_MAXUSER_ADDRESS,%rax 596 597 /* make sure 'from' is within bounds */ 598 subq %rsi,%rax 599 jbe cpystrflt 600 601 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 602 cmpq %rdx,%rax 603 jae 1f 604 movq %rax,%rdx 605 movq %rax,%r8 6061: 607 incq %rdx 608 cld 609 6102: 611 decq %rdx 612 jz 3f 613 614 lodsb 615 stosb 616 orb %al,%al 617 jnz 2b 618 619 /* Success -- 0 byte reached */ 620 decq %rdx 621 xorl %eax,%eax 622 jmp cpystrflt_x 6233: 624 /* rdx is zero - return ENAMETOOLONG or EFAULT */ 625 movq $VM_MAXUSER_ADDRESS,%rax 626 cmpq %rax,%rsi 627 jae cpystrflt 6284: 629 movq $ENAMETOOLONG,%rax 630 jmp cpystrflt_x 631 632cpystrflt: 633 movq $EFAULT,%rax 634 635cpystrflt_x: 636 /* set *lencopied and return %eax */ 637 movq PCPU(CURPCB),%rcx 638 movq $0,PCB_ONFAULT(%rcx) 639 640 testq %r9,%r9 641 jz 1f 642 subq %rdx,%r8 643 movq %r8,(%r9) 6441: 645 POP_FRAME_POINTER 646 ret 647END(copyinstr) 648 649/* 650 * copystr(from, to, maxlen, int *lencopied) - MP SAFE 651 * %rdi, %rsi, %rdx, %rcx 652 */ 653ENTRY(copystr) 654 PUSH_FRAME_POINTER 655 movq %rdx,%r8 /* %r8 = maxlen */ 656 657 xchgq %rdi,%rsi 658 incq %rdx 659 cld 6601: 661 decq %rdx 662 jz 4f 663 lodsb 664 stosb 665 orb %al,%al 666 jnz 1b 667 668 /* Success -- 0 byte reached */ 669 decq %rdx 670 xorl %eax,%eax 671 jmp 6f 6724: 673 /* rdx is zero -- return ENAMETOOLONG */ 674 movq $ENAMETOOLONG,%rax 675 6766: 677 678 testq %rcx,%rcx 679 jz 7f 680 /* set *lencopied and return %rax */ 681 subq %rdx,%r8 682 movq %r8,(%rcx) 6837: 684 POP_FRAME_POINTER 685 ret 686END(copystr) 687 688/* 689 * Handling of special amd64 registers and descriptor tables etc 690 * %rdi 691 */ 692/* void lgdt(struct region_descriptor *rdp); */ 693ENTRY(lgdt) 694 /* reload the descriptor table */ 695 lgdt (%rdi) 696 697 /* flush the prefetch q */ 698 jmp 1f 699 nop 7001: 701 movl $KDSEL,%eax 702 movl %eax,%ds 703 movl %eax,%es 704 movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */ 705 movl %eax,%gs 706 movl %eax,%ss 707 708 /* reload code selector by turning return into intersegmental return */ 709 popq %rax 710 pushq $KCSEL 711 pushq %rax 712 MEXITCOUNT 713 lretq 714END(lgdt) 715 716/*****************************************************************************/ 717/* setjump, longjump */ 718/*****************************************************************************/ 719 720ENTRY(setjmp) 721 movq %rbx,0(%rdi) /* save rbx */ 722 movq %rsp,8(%rdi) /* save rsp */ 723 movq %rbp,16(%rdi) /* save rbp */ 724 movq %r12,24(%rdi) /* save r12 */ 725 movq %r13,32(%rdi) /* save r13 */ 726 movq %r14,40(%rdi) /* save r14 */ 727 movq %r15,48(%rdi) /* save r15 */ 728 movq 0(%rsp),%rdx /* get rta */ 729 movq %rdx,56(%rdi) /* save rip */ 730 xorl %eax,%eax /* return(0); */ 731 ret 732END(setjmp) 733 734ENTRY(longjmp) 735 movq 0(%rdi),%rbx /* restore rbx */ 736 movq 8(%rdi),%rsp /* restore rsp */ 737 movq 16(%rdi),%rbp /* restore rbp */ 738 movq 24(%rdi),%r12 /* restore r12 */ 739 movq 32(%rdi),%r13 /* restore r13 */ 740 movq 40(%rdi),%r14 /* restore r14 */ 741 movq 48(%rdi),%r15 /* restore r15 */ 742 movq 56(%rdi),%rdx /* get rta */ 743 movq %rdx,0(%rsp) /* put in return frame */ 744 xorl %eax,%eax /* return(1); */ 745 incl %eax 746 ret 747END(longjmp) 748 749/* 750 * Support for reading MSRs in the safe manner. 751 */ 752ENTRY(rdmsr_safe) 753/* int rdmsr_safe(u_int msr, uint64_t *data) */ 754 PUSH_FRAME_POINTER 755 movq PCPU(CURPCB),%r8 756 movq $msr_onfault,PCB_ONFAULT(%r8) 757 movl %edi,%ecx 758 rdmsr /* Read MSR pointed by %ecx. Returns 759 hi byte in edx, lo in %eax */ 760 salq $32,%rdx /* sign-shift %rdx left */ 761 movl %eax,%eax /* zero-extend %eax -> %rax */ 762 orq %rdx,%rax 763 movq %rax,(%rsi) 764 xorq %rax,%rax 765 movq %rax,PCB_ONFAULT(%r8) 766 POP_FRAME_POINTER 767 ret 768 769/* 770 * Support for writing MSRs in the safe manner. 771 */ 772ENTRY(wrmsr_safe) 773/* int wrmsr_safe(u_int msr, uint64_t data) */ 774 PUSH_FRAME_POINTER 775 movq PCPU(CURPCB),%r8 776 movq $msr_onfault,PCB_ONFAULT(%r8) 777 movl %edi,%ecx 778 movl %esi,%eax 779 sarq $32,%rsi 780 movl %esi,%edx 781 wrmsr /* Write MSR pointed by %ecx. Accepts 782 hi byte in edx, lo in %eax. */ 783 xorq %rax,%rax 784 movq %rax,PCB_ONFAULT(%r8) 785 POP_FRAME_POINTER 786 ret 787 788/* 789 * MSR operations fault handler 790 */ 791 ALIGN_TEXT 792msr_onfault: 793 movq $0,PCB_ONFAULT(%r8) 794 movl $EFAULT,%eax 795 POP_FRAME_POINTER 796 ret 797