support.s revision 314210
1/*- 2 * Copyright (c) 1993 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: stable/11/sys/i386/i386/support.s 314210 2017-02-24 16:02:01Z kib $ 30 */ 31 32#include <machine/asmacros.h> 33#include <machine/cputypes.h> 34#include <machine/pmap.h> 35#include <machine/specialreg.h> 36 37#include "assym.s" 38 39#define IDXSHIFT 10 40 41 .text 42 43/* 44 * bcopy family 45 * void bzero(void *buf, u_int len) 46 */ 47ENTRY(bzero) 48 pushl %edi 49 movl 8(%esp),%edi 50 movl 12(%esp),%ecx 51 xorl %eax,%eax 52 shrl $2,%ecx 53 cld 54 rep 55 stosl 56 movl 12(%esp),%ecx 57 andl $3,%ecx 58 rep 59 stosb 60 popl %edi 61 ret 62END(bzero) 63 64ENTRY(sse2_pagezero) 65 pushl %ebx 66 movl 8(%esp),%ecx 67 movl %ecx,%eax 68 addl $4096,%eax 69 xor %ebx,%ebx 701: 71 movnti %ebx,(%ecx) 72 addl $4,%ecx 73 cmpl %ecx,%eax 74 jne 1b 75 sfence 76 popl %ebx 77 ret 78END(sse2_pagezero) 79 80ENTRY(i686_pagezero) 81 pushl %edi 82 pushl %ebx 83 84 movl 12(%esp),%edi 85 movl $1024,%ecx 86 cld 87 88 ALIGN_TEXT 891: 90 xorl %eax,%eax 91 repe 92 scasl 93 jnz 2f 94 95 popl %ebx 96 popl %edi 97 ret 98 99 ALIGN_TEXT 100 1012: 102 incl %ecx 103 subl $4,%edi 104 105 movl %ecx,%edx 106 cmpl $16,%ecx 107 108 jge 3f 109 110 movl %edi,%ebx 111 andl $0x3f,%ebx 112 shrl %ebx 113 shrl %ebx 114 movl $16,%ecx 115 subl %ebx,%ecx 116 1173: 118 subl %ecx,%edx 119 rep 120 stosl 121 122 movl %edx,%ecx 123 testl %edx,%edx 124 jnz 1b 125 126 popl %ebx 127 popl %edi 128 ret 129END(i686_pagezero) 130 131/* fillw(pat, base, cnt) */ 132ENTRY(fillw) 133 pushl %edi 134 movl 8(%esp),%eax 135 movl 12(%esp),%edi 136 movl 16(%esp),%ecx 137 cld 138 rep 139 stosw 140 popl %edi 141 ret 142END(fillw) 143 144ENTRY(bcopyb) 145 pushl %esi 146 pushl %edi 147 movl 12(%esp),%esi 148 movl 16(%esp),%edi 149 movl 20(%esp),%ecx 150 movl %edi,%eax 151 subl %esi,%eax 152 cmpl %ecx,%eax /* overlapping && src < dst? */ 153 jb 1f 154 cld /* nope, copy forwards */ 155 rep 156 movsb 157 popl %edi 158 popl %esi 159 ret 160 161 ALIGN_TEXT 1621: 163 addl %ecx,%edi /* copy backwards. */ 164 addl %ecx,%esi 165 decl %edi 166 decl %esi 167 std 168 rep 169 movsb 170 popl %edi 171 popl %esi 172 cld 173 ret 174END(bcopyb) 175 176/* 177 * bcopy(src, dst, cnt) 178 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 179 */ 180ENTRY(bcopy) 181 pushl %ebp 182 movl %esp,%ebp 183 pushl %esi 184 pushl %edi 185 movl 8(%ebp),%esi 186 movl 12(%ebp),%edi 187 movl 16(%ebp),%ecx 188 189 movl %edi,%eax 190 subl %esi,%eax 191 cmpl %ecx,%eax /* overlapping && src < dst? */ 192 jb 1f 193 194 shrl $2,%ecx /* copy by 32-bit words */ 195 cld /* nope, copy forwards */ 196 rep 197 movsl 198 movl 16(%ebp),%ecx 199 andl $3,%ecx /* any bytes left? */ 200 rep 201 movsb 202 popl %edi 203 popl %esi 204 popl %ebp 205 ret 206 207 ALIGN_TEXT 2081: 209 addl %ecx,%edi /* copy backwards */ 210 addl %ecx,%esi 211 decl %edi 212 decl %esi 213 andl $3,%ecx /* any fractional bytes? */ 214 std 215 rep 216 movsb 217 movl 16(%ebp),%ecx /* copy remainder by 32-bit words */ 218 shrl $2,%ecx 219 subl $3,%esi 220 subl $3,%edi 221 rep 222 movsl 223 popl %edi 224 popl %esi 225 cld 226 popl %ebp 227 ret 228END(bcopy) 229 230/* 231 * Note: memcpy does not support overlapping copies 232 */ 233ENTRY(memcpy) 234 pushl %edi 235 pushl %esi 236 movl 12(%esp),%edi 237 movl 16(%esp),%esi 238 movl 20(%esp),%ecx 239 movl %edi,%eax 240 shrl $2,%ecx /* copy by 32-bit words */ 241 cld /* nope, copy forwards */ 242 rep 243 movsl 244 movl 20(%esp),%ecx 245 andl $3,%ecx /* any bytes left? */ 246 rep 247 movsb 248 popl %esi 249 popl %edi 250 ret 251END(memcpy) 252 253/*****************************************************************************/ 254/* copyout and fubyte family */ 255/*****************************************************************************/ 256/* 257 * Access user memory from inside the kernel. These routines and possibly 258 * the math- and DOS emulators should be the only places that do this. 259 * 260 * We have to access the memory with user's permissions, so use a segment 261 * selector with RPL 3. For writes to user space we have to additionally 262 * check the PTE for write permission, because the 386 does not check 263 * write permissions when we are executing with EPL 0. The 486 does check 264 * this if the WP bit is set in CR0, so we can use a simpler version here. 265 * 266 * These routines set curpcb->pcb_onfault for the time they execute. When a 267 * protection violation occurs inside the functions, the trap handler 268 * returns to *curpcb->pcb_onfault instead of the function. 269 */ 270 271/* 272 * copyout(from_kernel, to_user, len) - MP SAFE 273 */ 274ENTRY(copyout) 275 movl PCPU(CURPCB),%eax 276 movl $copyout_fault,PCB_ONFAULT(%eax) 277 pushl %esi 278 pushl %edi 279 pushl %ebx 280 movl 16(%esp),%esi 281 movl 20(%esp),%edi 282 movl 24(%esp),%ebx 283 testl %ebx,%ebx /* anything to do? */ 284 jz done_copyout 285 286 /* 287 * Check explicitly for non-user addresses. If 486 write protection 288 * is being used, this check is essential because we are in kernel 289 * mode so the h/w does not provide any protection against writing 290 * kernel addresses. 291 */ 292 293 /* 294 * First, prevent address wrapping. 295 */ 296 movl %edi,%eax 297 addl %ebx,%eax 298 jc copyout_fault 299/* 300 * XXX STOP USING VM_MAXUSER_ADDRESS. 301 * It is an end address, not a max, so every time it is used correctly it 302 * looks like there is an off by one error, and of course it caused an off 303 * by one error in several places. 304 */ 305 cmpl $VM_MAXUSER_ADDRESS,%eax 306 ja copyout_fault 307 308 /* bcopy(%esi, %edi, %ebx) */ 309 movl %ebx,%ecx 310 311 shrl $2,%ecx 312 cld 313 rep 314 movsl 315 movb %bl,%cl 316 andb $3,%cl 317 rep 318 movsb 319 320done_copyout: 321 popl %ebx 322 popl %edi 323 popl %esi 324 xorl %eax,%eax 325 movl PCPU(CURPCB),%edx 326 movl %eax,PCB_ONFAULT(%edx) 327 ret 328END(copyout) 329 330 ALIGN_TEXT 331copyout_fault: 332 popl %ebx 333 popl %edi 334 popl %esi 335 movl PCPU(CURPCB),%edx 336 movl $0,PCB_ONFAULT(%edx) 337 movl $EFAULT,%eax 338 ret 339 340/* 341 * copyin(from_user, to_kernel, len) - MP SAFE 342 */ 343ENTRY(copyin) 344 movl PCPU(CURPCB),%eax 345 movl $copyin_fault,PCB_ONFAULT(%eax) 346 pushl %esi 347 pushl %edi 348 movl 12(%esp),%esi /* caddr_t from */ 349 movl 16(%esp),%edi /* caddr_t to */ 350 movl 20(%esp),%ecx /* size_t len */ 351 352 /* 353 * make sure address is valid 354 */ 355 movl %esi,%edx 356 addl %ecx,%edx 357 jc copyin_fault 358 cmpl $VM_MAXUSER_ADDRESS,%edx 359 ja copyin_fault 360 361 movb %cl,%al 362 shrl $2,%ecx /* copy longword-wise */ 363 cld 364 rep 365 movsl 366 movb %al,%cl 367 andb $3,%cl /* copy remaining bytes */ 368 rep 369 movsb 370 371 popl %edi 372 popl %esi 373 xorl %eax,%eax 374 movl PCPU(CURPCB),%edx 375 movl %eax,PCB_ONFAULT(%edx) 376 ret 377END(copyin) 378 379 ALIGN_TEXT 380copyin_fault: 381 popl %edi 382 popl %esi 383 movl PCPU(CURPCB),%edx 384 movl $0,PCB_ONFAULT(%edx) 385 movl $EFAULT,%eax 386 ret 387 388/* 389 * casueword. Compare and set user word. Returns -1 on fault, 390 * 0 on non-faulting access. The current value is in *oldp. 391 */ 392ALTENTRY(casueword32) 393ENTRY(casueword) 394 movl PCPU(CURPCB),%ecx 395 movl $fusufault,PCB_ONFAULT(%ecx) 396 movl 4(%esp),%edx /* dst */ 397 movl 8(%esp),%eax /* old */ 398 movl 16(%esp),%ecx /* new */ 399 400 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 401 ja fusufault 402 403#ifdef SMP 404 lock 405#endif 406 cmpxchgl %ecx,(%edx) /* Compare and set. */ 407 408 /* 409 * The old value is in %eax. If the store succeeded it will be the 410 * value we expected (old) from before the store, otherwise it will 411 * be the current value. 412 */ 413 414 movl PCPU(CURPCB),%ecx 415 movl $0,PCB_ONFAULT(%ecx) 416 movl 12(%esp),%edx /* oldp */ 417 movl %eax,(%edx) 418 xorl %eax,%eax 419 ret 420END(casueword32) 421END(casueword) 422 423/* 424 * Fetch (load) a 32-bit word, a 16-bit word, or an 8-bit byte from user 425 * memory. 426 */ 427 428ALTENTRY(fueword32) 429ENTRY(fueword) 430 movl PCPU(CURPCB),%ecx 431 movl $fusufault,PCB_ONFAULT(%ecx) 432 movl 4(%esp),%edx /* from */ 433 434 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 435 ja fusufault 436 437 movl (%edx),%eax 438 movl $0,PCB_ONFAULT(%ecx) 439 movl 8(%esp),%edx 440 movl %eax,(%edx) 441 xorl %eax,%eax 442 ret 443END(fueword32) 444END(fueword) 445 446/* 447 * fuswintr() and suswintr() are specialized variants of fuword16() and 448 * suword16(), respectively. They are called from the profiling code, 449 * potentially at interrupt time. If they fail, that's okay; good things 450 * will happen later. They always fail for now, until the trap code is 451 * able to deal with this. 452 */ 453ALTENTRY(suswintr) 454ENTRY(fuswintr) 455 movl $-1,%eax 456 ret 457END(suswintr) 458END(fuswintr) 459 460ENTRY(fuword16) 461 movl PCPU(CURPCB),%ecx 462 movl $fusufault,PCB_ONFAULT(%ecx) 463 movl 4(%esp),%edx 464 465 cmpl $VM_MAXUSER_ADDRESS-2,%edx 466 ja fusufault 467 468 movzwl (%edx),%eax 469 movl $0,PCB_ONFAULT(%ecx) 470 ret 471END(fuword16) 472 473ENTRY(fubyte) 474 movl PCPU(CURPCB),%ecx 475 movl $fusufault,PCB_ONFAULT(%ecx) 476 movl 4(%esp),%edx 477 478 cmpl $VM_MAXUSER_ADDRESS-1,%edx 479 ja fusufault 480 481 movzbl (%edx),%eax 482 movl $0,PCB_ONFAULT(%ecx) 483 ret 484END(fubyte) 485 486 ALIGN_TEXT 487fusufault: 488 movl PCPU(CURPCB),%ecx 489 xorl %eax,%eax 490 movl %eax,PCB_ONFAULT(%ecx) 491 decl %eax 492 ret 493 494/* 495 * Store a 32-bit word, a 16-bit word, or an 8-bit byte to user memory. 496 * All these functions are MPSAFE. 497 */ 498 499ALTENTRY(suword32) 500ENTRY(suword) 501 movl PCPU(CURPCB),%ecx 502 movl $fusufault,PCB_ONFAULT(%ecx) 503 movl 4(%esp),%edx 504 505 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 506 ja fusufault 507 508 movl 8(%esp),%eax 509 movl %eax,(%edx) 510 xorl %eax,%eax 511 movl PCPU(CURPCB),%ecx 512 movl %eax,PCB_ONFAULT(%ecx) 513 ret 514END(suword32) 515END(suword) 516 517ENTRY(suword16) 518 movl PCPU(CURPCB),%ecx 519 movl $fusufault,PCB_ONFAULT(%ecx) 520 movl 4(%esp),%edx 521 522 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 523 ja fusufault 524 525 movw 8(%esp),%ax 526 movw %ax,(%edx) 527 xorl %eax,%eax 528 movl PCPU(CURPCB),%ecx /* restore trashed register */ 529 movl %eax,PCB_ONFAULT(%ecx) 530 ret 531END(suword16) 532 533ENTRY(subyte) 534 movl PCPU(CURPCB),%ecx 535 movl $fusufault,PCB_ONFAULT(%ecx) 536 movl 4(%esp),%edx 537 538 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 539 ja fusufault 540 541 movb 8(%esp),%al 542 movb %al,(%edx) 543 xorl %eax,%eax 544 movl PCPU(CURPCB),%ecx /* restore trashed register */ 545 movl %eax,PCB_ONFAULT(%ecx) 546 ret 547END(subyte) 548 549/* 550 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE 551 * 552 * copy a string from from to to, stop when a 0 character is reached. 553 * return ENAMETOOLONG if string is longer than maxlen, and 554 * EFAULT on protection violations. If lencopied is non-zero, 555 * return the actual length in *lencopied. 556 */ 557ENTRY(copyinstr) 558 pushl %esi 559 pushl %edi 560 movl PCPU(CURPCB),%ecx 561 movl $cpystrflt,PCB_ONFAULT(%ecx) 562 563 movl 12(%esp),%esi /* %esi = from */ 564 movl 16(%esp),%edi /* %edi = to */ 565 movl 20(%esp),%edx /* %edx = maxlen */ 566 567 movl $VM_MAXUSER_ADDRESS,%eax 568 569 /* make sure 'from' is within bounds */ 570 subl %esi,%eax 571 jbe cpystrflt 572 573 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 574 cmpl %edx,%eax 575 jae 1f 576 movl %eax,%edx 577 movl %eax,20(%esp) 5781: 579 incl %edx 580 cld 581 5822: 583 decl %edx 584 jz 3f 585 586 lodsb 587 stosb 588 orb %al,%al 589 jnz 2b 590 591 /* Success -- 0 byte reached */ 592 decl %edx 593 xorl %eax,%eax 594 jmp cpystrflt_x 5953: 596 /* edx is zero - return ENAMETOOLONG or EFAULT */ 597 cmpl $VM_MAXUSER_ADDRESS,%esi 598 jae cpystrflt 5994: 600 movl $ENAMETOOLONG,%eax 601 jmp cpystrflt_x 602 603cpystrflt: 604 movl $EFAULT,%eax 605 606cpystrflt_x: 607 /* set *lencopied and return %eax */ 608 movl PCPU(CURPCB),%ecx 609 movl $0,PCB_ONFAULT(%ecx) 610 movl 20(%esp),%ecx 611 subl %edx,%ecx 612 movl 24(%esp),%edx 613 testl %edx,%edx 614 jz 1f 615 movl %ecx,(%edx) 6161: 617 popl %edi 618 popl %esi 619 ret 620END(copyinstr) 621 622/* 623 * copystr(from, to, maxlen, int *lencopied) - MP SAFE 624 */ 625ENTRY(copystr) 626 pushl %esi 627 pushl %edi 628 629 movl 12(%esp),%esi /* %esi = from */ 630 movl 16(%esp),%edi /* %edi = to */ 631 movl 20(%esp),%edx /* %edx = maxlen */ 632 incl %edx 633 cld 6341: 635 decl %edx 636 jz 4f 637 lodsb 638 stosb 639 orb %al,%al 640 jnz 1b 641 642 /* Success -- 0 byte reached */ 643 decl %edx 644 xorl %eax,%eax 645 jmp 6f 6464: 647 /* edx is zero -- return ENAMETOOLONG */ 648 movl $ENAMETOOLONG,%eax 649 6506: 651 /* set *lencopied and return %eax */ 652 movl 20(%esp),%ecx 653 subl %edx,%ecx 654 movl 24(%esp),%edx 655 testl %edx,%edx 656 jz 7f 657 movl %ecx,(%edx) 6587: 659 popl %edi 660 popl %esi 661 ret 662END(copystr) 663 664ENTRY(bcmp) 665 pushl %edi 666 pushl %esi 667 movl 12(%esp),%edi 668 movl 16(%esp),%esi 669 movl 20(%esp),%edx 670 671 movl %edx,%ecx 672 shrl $2,%ecx 673 cld /* compare forwards */ 674 repe 675 cmpsl 676 jne 1f 677 678 movl %edx,%ecx 679 andl $3,%ecx 680 repe 681 cmpsb 6821: 683 setne %al 684 movsbl %al,%eax 685 popl %esi 686 popl %edi 687 ret 688END(bcmp) 689 690/* 691 * Handling of special 386 registers and descriptor tables etc 692 */ 693/* void lgdt(struct region_descriptor *rdp); */ 694ENTRY(lgdt) 695 /* reload the descriptor table */ 696 movl 4(%esp),%eax 697 lgdt (%eax) 698 699 /* flush the prefetch q */ 700 jmp 1f 701 nop 7021: 703 /* reload "stale" selectors */ 704 movl $KDSEL,%eax 705 movl %eax,%ds 706 movl %eax,%es 707 movl %eax,%gs 708 movl %eax,%ss 709 movl $KPSEL,%eax 710 movl %eax,%fs 711 712 /* reload code selector by turning return into intersegmental return */ 713 movl (%esp),%eax 714 pushl %eax 715 movl $KCSEL,4(%esp) 716 MEXITCOUNT 717 lret 718END(lgdt) 719 720/* ssdtosd(*ssdp,*sdp) */ 721ENTRY(ssdtosd) 722 pushl %ebx 723 movl 8(%esp),%ecx 724 movl 8(%ecx),%ebx 725 shll $16,%ebx 726 movl (%ecx),%edx 727 roll $16,%edx 728 movb %dh,%bl 729 movb %dl,%bh 730 rorl $8,%ebx 731 movl 4(%ecx),%eax 732 movw %ax,%dx 733 andl $0xf0000,%eax 734 orl %eax,%ebx 735 movl 12(%esp),%ecx 736 movl %edx,(%ecx) 737 movl %ebx,4(%ecx) 738 popl %ebx 739 ret 740END(ssdtosd) 741 742/* void reset_dbregs() */ 743ENTRY(reset_dbregs) 744 movl $0,%eax 745 movl %eax,%dr7 /* disable all breakpoints first */ 746 movl %eax,%dr0 747 movl %eax,%dr1 748 movl %eax,%dr2 749 movl %eax,%dr3 750 movl %eax,%dr6 751 ret 752END(reset_dbregs) 753 754/*****************************************************************************/ 755/* setjump, longjump */ 756/*****************************************************************************/ 757 758ENTRY(setjmp) 759 movl 4(%esp),%eax 760 movl %ebx,(%eax) /* save ebx */ 761 movl %esp,4(%eax) /* save esp */ 762 movl %ebp,8(%eax) /* save ebp */ 763 movl %esi,12(%eax) /* save esi */ 764 movl %edi,16(%eax) /* save edi */ 765 movl (%esp),%edx /* get rta */ 766 movl %edx,20(%eax) /* save eip */ 767 xorl %eax,%eax /* return(0); */ 768 ret 769END(setjmp) 770 771ENTRY(longjmp) 772 movl 4(%esp),%eax 773 movl (%eax),%ebx /* restore ebx */ 774 movl 4(%eax),%esp /* restore esp */ 775 movl 8(%eax),%ebp /* restore ebp */ 776 movl 12(%eax),%esi /* restore esi */ 777 movl 16(%eax),%edi /* restore edi */ 778 movl 20(%eax),%edx /* get rta */ 779 movl %edx,(%esp) /* put in return frame */ 780 xorl %eax,%eax /* return(1); */ 781 incl %eax 782 ret 783END(longjmp) 784 785/* 786 * Support for reading MSRs in the safe manner. 787 */ 788ENTRY(rdmsr_safe) 789/* int rdmsr_safe(u_int msr, uint64_t *data) */ 790 movl PCPU(CURPCB),%ecx 791 movl $msr_onfault,PCB_ONFAULT(%ecx) 792 793 movl 4(%esp),%ecx 794 rdmsr 795 movl 8(%esp),%ecx 796 movl %eax,(%ecx) 797 movl %edx,4(%ecx) 798 xorl %eax,%eax 799 800 movl PCPU(CURPCB),%ecx 801 movl %eax,PCB_ONFAULT(%ecx) 802 803 ret 804 805/* 806 * Support for writing MSRs in the safe manner. 807 */ 808ENTRY(wrmsr_safe) 809/* int wrmsr_safe(u_int msr, uint64_t data) */ 810 movl PCPU(CURPCB),%ecx 811 movl $msr_onfault,PCB_ONFAULT(%ecx) 812 813 movl 4(%esp),%ecx 814 movl 8(%esp),%eax 815 movl 12(%esp),%edx 816 wrmsr 817 xorl %eax,%eax 818 819 movl PCPU(CURPCB),%ecx 820 movl %eax,PCB_ONFAULT(%ecx) 821 822 ret 823 824/* 825 * MSR operations fault handler 826 */ 827 ALIGN_TEXT 828msr_onfault: 829 movl PCPU(CURPCB),%ecx 830 movl $0,PCB_ONFAULT(%ecx) 831 movl $EFAULT,%eax 832 ret 833