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