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