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