support.s revision 74738
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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: head/sys/i386/i386/support.s 74738 2001-03-24 08:27:57Z obrien $ 34 */ 35 36#include "opt_npx.h" 37 38#include <machine/asmacros.h> 39#include <machine/cputypes.h> 40#include <machine/pmap.h> 41#include <machine/specialreg.h> 42 43#include "assym.s" 44 45#define IDXSHIFT 10 46 47 .data 48 .globl bcopy_vector 49bcopy_vector: 50 .long generic_bcopy 51 .globl bzero 52bzero: 53 .long generic_bzero 54 .globl copyin_vector 55copyin_vector: 56 .long generic_copyin 57 .globl copyout_vector 58copyout_vector: 59 .long generic_copyout 60 .globl ovbcopy_vector 61ovbcopy_vector: 62 .long generic_bcopy 63#if defined(I586_CPU) && defined(DEV_NPX) 64kernel_fpu_lock: 65 .byte 0xfe 66 .space 3 67#endif 68 69 .text 70 71/* 72 * bcopy family 73 * void bzero(void *buf, u_int len) 74 */ 75 76ENTRY(generic_bzero) 77 pushl %edi 78 movl 8(%esp),%edi 79 movl 12(%esp),%ecx 80 xorl %eax,%eax 81 shrl $2,%ecx 82 cld 83 rep 84 stosl 85 movl 12(%esp),%ecx 86 andl $3,%ecx 87 rep 88 stosb 89 popl %edi 90 ret 91 92#ifdef I486_CPU 93ENTRY(i486_bzero) 94 movl 4(%esp),%edx 95 movl 8(%esp),%ecx 96 xorl %eax,%eax 97/* 98 * do 64 byte chunks first 99 * 100 * XXX this is probably over-unrolled at least for DX2's 101 */ 1022: 103 cmpl $64,%ecx 104 jb 3f 105 movl %eax,(%edx) 106 movl %eax,4(%edx) 107 movl %eax,8(%edx) 108 movl %eax,12(%edx) 109 movl %eax,16(%edx) 110 movl %eax,20(%edx) 111 movl %eax,24(%edx) 112 movl %eax,28(%edx) 113 movl %eax,32(%edx) 114 movl %eax,36(%edx) 115 movl %eax,40(%edx) 116 movl %eax,44(%edx) 117 movl %eax,48(%edx) 118 movl %eax,52(%edx) 119 movl %eax,56(%edx) 120 movl %eax,60(%edx) 121 addl $64,%edx 122 subl $64,%ecx 123 jnz 2b 124 ret 125 126/* 127 * do 16 byte chunks 128 */ 129 SUPERALIGN_TEXT 1303: 131 cmpl $16,%ecx 132 jb 4f 133 movl %eax,(%edx) 134 movl %eax,4(%edx) 135 movl %eax,8(%edx) 136 movl %eax,12(%edx) 137 addl $16,%edx 138 subl $16,%ecx 139 jnz 3b 140 ret 141 142/* 143 * do 4 byte chunks 144 */ 145 SUPERALIGN_TEXT 1464: 147 cmpl $4,%ecx 148 jb 5f 149 movl %eax,(%edx) 150 addl $4,%edx 151 subl $4,%ecx 152 jnz 4b 153 ret 154 155/* 156 * do 1 byte chunks 157 * a jump table seems to be faster than a loop or more range reductions 158 * 159 * XXX need a const section for non-text 160 */ 161 .data 162jtab: 163 .long do0 164 .long do1 165 .long do2 166 .long do3 167 168 .text 169 SUPERALIGN_TEXT 1705: 171 jmp *jtab(,%ecx,4) 172 173 SUPERALIGN_TEXT 174do3: 175 movw %ax,(%edx) 176 movb %al,2(%edx) 177 ret 178 179 SUPERALIGN_TEXT 180do2: 181 movw %ax,(%edx) 182 ret 183 184 SUPERALIGN_TEXT 185do1: 186 movb %al,(%edx) 187 ret 188 189 SUPERALIGN_TEXT 190do0: 191 ret 192#endif 193 194#if defined(I586_CPU) && defined(DEV_NPX) 195ENTRY(i586_bzero) 196 movl 4(%esp),%edx 197 movl 8(%esp),%ecx 198 199 /* 200 * The FPU register method is twice as fast as the integer register 201 * method unless the target is in the L1 cache and we pre-allocate a 202 * cache line for it (then the integer register method is 4-5 times 203 * faster). However, we never pre-allocate cache lines, since that 204 * would make the integer method 25% or more slower for the common 205 * case when the target isn't in either the L1 cache or the L2 cache. 206 * Thus we normally use the FPU register method unless the overhead 207 * would be too large. 208 */ 209 cmpl $256,%ecx /* empirical; clts, fninit, smsw cost a lot */ 210 jb intreg_i586_bzero 211 212 /* 213 * The FPU registers may belong to an application or to fastmove() 214 * or to another invocation of bcopy() or ourself in a higher level 215 * interrupt or trap handler. Preserving the registers is 216 * complicated since we avoid it if possible at all levels. We 217 * want to localize the complications even when that increases them. 218 * Here the extra work involves preserving CR0_TS in TS. 219 * `npxproc != NULL' is supposed to be the condition that all the 220 * FPU resources belong to an application, but npxproc and CR0_TS 221 * aren't set atomically enough for this condition to work in 222 * interrupt handlers. 223 * 224 * Case 1: FPU registers belong to the application: we must preserve 225 * the registers if we use them, so we only use the FPU register 226 * method if the target size is large enough to amortize the extra 227 * overhead for preserving them. CR0_TS must be preserved although 228 * it is very likely to end up as set. 229 * 230 * Case 2: FPU registers belong to fastmove(): fastmove() currently 231 * makes the registers look like they belong to an application so 232 * that cpu_switch() and savectx() don't have to know about it, so 233 * this case reduces to case 1. 234 * 235 * Case 3: FPU registers belong to the kernel: don't use the FPU 236 * register method. This case is unlikely, and supporting it would 237 * be more complicated and might take too much stack. 238 * 239 * Case 4: FPU registers don't belong to anyone: the FPU registers 240 * don't need to be preserved, so we always use the FPU register 241 * method. CR0_TS must be preserved although it is very likely to 242 * always end up as clear. 243 */ 244 cmpl $0,PCPU(NPXPROC) 245 je i586_bz1 246 247 /* 248 * XXX don't use the FPU for cases 1 and 2, since preemptive 249 * scheduling of ithreads broke these cases. Note that we can 250 * no longer get here from an interrupt handler, since the 251 * context sitch to the interrupt handler will have saved the 252 * FPU state. 253 */ 254 jmp intreg_i586_bzero 255 256 cmpl $256+184,%ecx /* empirical; not quite 2*108 more */ 257 jb intreg_i586_bzero 258 sarb $1,kernel_fpu_lock 259 jc intreg_i586_bzero 260 smsw %ax 261 clts 262 subl $108,%esp 263 fnsave 0(%esp) 264 jmp i586_bz2 265 266i586_bz1: 267 sarb $1,kernel_fpu_lock 268 jc intreg_i586_bzero 269 smsw %ax 270 clts 271 fninit /* XXX should avoid needing this */ 272i586_bz2: 273 fldz 274 275 /* 276 * Align to an 8 byte boundary (misalignment in the main loop would 277 * cost a factor of >= 2). Avoid jumps (at little cost if it is 278 * already aligned) by always zeroing 8 bytes and using the part up 279 * to the _next_ alignment position. 280 */ 281 fstl 0(%edx) 282 addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */ 283 addl $8,%edx 284 andl $~7,%edx 285 subl %edx,%ecx 286 287 /* 288 * Similarly align `len' to a multiple of 8. 289 */ 290 fstl -8(%edx,%ecx) 291 decl %ecx 292 andl $~7,%ecx 293 294 /* 295 * This wouldn't be any faster if it were unrolled, since the loop 296 * control instructions are much faster than the fstl and/or done 297 * in parallel with it so their overhead is insignificant. 298 */ 299fpureg_i586_bzero_loop: 300 fstl 0(%edx) 301 addl $8,%edx 302 subl $8,%ecx 303 cmpl $8,%ecx 304 jae fpureg_i586_bzero_loop 305 306 cmpl $0,PCPU(NPXPROC) 307 je i586_bz3 308 309 /* XXX check that the condition for cases 1-2 stayed false. */ 310i586_bzero_oops: 311 int $3 312 jmp i586_bzero_oops 313 314 frstor 0(%esp) 315 addl $108,%esp 316 lmsw %ax 317 movb $0xfe,kernel_fpu_lock 318 ret 319 320i586_bz3: 321 fstp %st(0) 322 lmsw %ax 323 movb $0xfe,kernel_fpu_lock 324 ret 325 326intreg_i586_bzero: 327 /* 328 * `rep stos' seems to be the best method in practice for small 329 * counts. Fancy methods usually take too long to start up due 330 * to cache and BTB misses. 331 */ 332 pushl %edi 333 movl %edx,%edi 334 xorl %eax,%eax 335 shrl $2,%ecx 336 cld 337 rep 338 stosl 339 movl 12(%esp),%ecx 340 andl $3,%ecx 341 jne 1f 342 popl %edi 343 ret 344 3451: 346 rep 347 stosb 348 popl %edi 349 ret 350#endif /* I586_CPU && defined(DEV_NPX) */ 351 352ENTRY(i686_pagezero) 353 pushl %edi 354 pushl %ebx 355 356 movl 12(%esp), %edi 357 movl $1024, %ecx 358 cld 359 360 ALIGN_TEXT 3611: 362 xorl %eax, %eax 363 repe 364 scasl 365 jnz 2f 366 367 popl %ebx 368 popl %edi 369 ret 370 371 ALIGN_TEXT 372 3732: 374 incl %ecx 375 subl $4, %edi 376 377 movl %ecx, %edx 378 cmpl $16, %ecx 379 380 jge 3f 381 382 movl %edi, %ebx 383 andl $0x3f, %ebx 384 shrl %ebx 385 shrl %ebx 386 movl $16, %ecx 387 subl %ebx, %ecx 388 3893: 390 subl %ecx, %edx 391 rep 392 stosl 393 394 movl %edx, %ecx 395 testl %edx, %edx 396 jnz 1b 397 398 popl %ebx 399 popl %edi 400 ret 401 402/* fillw(pat, base, cnt) */ 403ENTRY(fillw) 404 pushl %edi 405 movl 8(%esp),%eax 406 movl 12(%esp),%edi 407 movl 16(%esp),%ecx 408 cld 409 rep 410 stosw 411 popl %edi 412 ret 413 414ENTRY(bcopyb) 415 pushl %esi 416 pushl %edi 417 movl 12(%esp),%esi 418 movl 16(%esp),%edi 419 movl 20(%esp),%ecx 420 movl %edi,%eax 421 subl %esi,%eax 422 cmpl %ecx,%eax /* overlapping && src < dst? */ 423 jb 1f 424 cld /* nope, copy forwards */ 425 rep 426 movsb 427 popl %edi 428 popl %esi 429 ret 430 431 ALIGN_TEXT 4321: 433 addl %ecx,%edi /* copy backwards. */ 434 addl %ecx,%esi 435 decl %edi 436 decl %esi 437 std 438 rep 439 movsb 440 popl %edi 441 popl %esi 442 cld 443 ret 444 445ENTRY(bcopy) 446 MEXITCOUNT 447 jmp *bcopy_vector 448 449ENTRY(ovbcopy) 450 MEXITCOUNT 451 jmp *ovbcopy_vector 452 453/* 454 * generic_bcopy(src, dst, cnt) 455 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 456 */ 457ENTRY(generic_bcopy) 458 pushl %esi 459 pushl %edi 460 movl 12(%esp),%esi 461 movl 16(%esp),%edi 462 movl 20(%esp),%ecx 463 464 movl %edi,%eax 465 subl %esi,%eax 466 cmpl %ecx,%eax /* overlapping && src < dst? */ 467 jb 1f 468 469 shrl $2,%ecx /* copy by 32-bit words */ 470 cld /* nope, copy forwards */ 471 rep 472 movsl 473 movl 20(%esp),%ecx 474 andl $3,%ecx /* any bytes left? */ 475 rep 476 movsb 477 popl %edi 478 popl %esi 479 ret 480 481 ALIGN_TEXT 4821: 483 addl %ecx,%edi /* copy backwards */ 484 addl %ecx,%esi 485 decl %edi 486 decl %esi 487 andl $3,%ecx /* any fractional bytes? */ 488 std 489 rep 490 movsb 491 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 492 shrl $2,%ecx 493 subl $3,%esi 494 subl $3,%edi 495 rep 496 movsl 497 popl %edi 498 popl %esi 499 cld 500 ret 501 502#if defined(I586_CPU) && defined(DEV_NPX) 503ENTRY(i586_bcopy) 504 pushl %esi 505 pushl %edi 506 movl 12(%esp),%esi 507 movl 16(%esp),%edi 508 movl 20(%esp),%ecx 509 510 movl %edi,%eax 511 subl %esi,%eax 512 cmpl %ecx,%eax /* overlapping && src < dst? */ 513 jb 1f 514 515 cmpl $1024,%ecx 516 jb small_i586_bcopy 517 518 sarb $1,kernel_fpu_lock 519 jc small_i586_bcopy 520 cmpl $0,PCPU(NPXPROC) 521 je i586_bc1 522 523 /* XXX turn off handling of cases 1-2, as above. */ 524 movb $0xfe,kernel_fpu_lock 525 jmp small_i586_bcopy 526 527 smsw %dx 528 clts 529 subl $108,%esp 530 fnsave 0(%esp) 531 jmp 4f 532 533i586_bc1: 534 smsw %dx 535 clts 536 fninit /* XXX should avoid needing this */ 537 538 ALIGN_TEXT 5394: 540 pushl %ecx 541#define DCACHE_SIZE 8192 542 cmpl $(DCACHE_SIZE-512)/2,%ecx 543 jbe 2f 544 movl $(DCACHE_SIZE-512)/2,%ecx 5452: 546 subl %ecx,0(%esp) 547 cmpl $256,%ecx 548 jb 5f /* XXX should prefetch if %ecx >= 32 */ 549 pushl %esi 550 pushl %ecx 551 ALIGN_TEXT 5523: 553 movl 0(%esi),%eax 554 movl 32(%esi),%eax 555 movl 64(%esi),%eax 556 movl 96(%esi),%eax 557 movl 128(%esi),%eax 558 movl 160(%esi),%eax 559 movl 192(%esi),%eax 560 movl 224(%esi),%eax 561 addl $256,%esi 562 subl $256,%ecx 563 cmpl $256,%ecx 564 jae 3b 565 popl %ecx 566 popl %esi 5675: 568 ALIGN_TEXT 569large_i586_bcopy_loop: 570 fildq 0(%esi) 571 fildq 8(%esi) 572 fildq 16(%esi) 573 fildq 24(%esi) 574 fildq 32(%esi) 575 fildq 40(%esi) 576 fildq 48(%esi) 577 fildq 56(%esi) 578 fistpq 56(%edi) 579 fistpq 48(%edi) 580 fistpq 40(%edi) 581 fistpq 32(%edi) 582 fistpq 24(%edi) 583 fistpq 16(%edi) 584 fistpq 8(%edi) 585 fistpq 0(%edi) 586 addl $64,%esi 587 addl $64,%edi 588 subl $64,%ecx 589 cmpl $64,%ecx 590 jae large_i586_bcopy_loop 591 popl %eax 592 addl %eax,%ecx 593 cmpl $64,%ecx 594 jae 4b 595 596 cmpl $0,PCPU(NPXPROC) 597 je i586_bc2 598 599 /* XXX check that the condition for cases 1-2 stayed false. */ 600i586_bcopy_oops: 601 int $3 602 jmp i586_bcopy_oops 603 604 frstor 0(%esp) 605 addl $108,%esp 606i586_bc2: 607 lmsw %dx 608 movb $0xfe,kernel_fpu_lock 609 610/* 611 * This is a duplicate of the main part of generic_bcopy. See the comments 612 * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and 613 * would mess up high resolution profiling. 614 */ 615 ALIGN_TEXT 616small_i586_bcopy: 617 shrl $2,%ecx 618 cld 619 rep 620 movsl 621 movl 20(%esp),%ecx 622 andl $3,%ecx 623 rep 624 movsb 625 popl %edi 626 popl %esi 627 ret 628 629 ALIGN_TEXT 6301: 631 addl %ecx,%edi 632 addl %ecx,%esi 633 decl %edi 634 decl %esi 635 andl $3,%ecx 636 std 637 rep 638 movsb 639 movl 20(%esp),%ecx 640 shrl $2,%ecx 641 subl $3,%esi 642 subl $3,%edi 643 rep 644 movsl 645 popl %edi 646 popl %esi 647 cld 648 ret 649#endif /* I586_CPU && defined(DEV_NPX) */ 650 651/* 652 * Note: memcpy does not support overlapping copies 653 */ 654ENTRY(memcpy) 655 pushl %edi 656 pushl %esi 657 movl 12(%esp),%edi 658 movl 16(%esp),%esi 659 movl 20(%esp),%ecx 660 movl %edi,%eax 661 shrl $2,%ecx /* copy by 32-bit words */ 662 cld /* nope, copy forwards */ 663 rep 664 movsl 665 movl 20(%esp),%ecx 666 andl $3,%ecx /* any bytes left? */ 667 rep 668 movsb 669 popl %esi 670 popl %edi 671 ret 672 673 674/*****************************************************************************/ 675/* copyout and fubyte family */ 676/*****************************************************************************/ 677/* 678 * Access user memory from inside the kernel. These routines and possibly 679 * the math- and DOS emulators should be the only places that do this. 680 * 681 * We have to access the memory with user's permissions, so use a segment 682 * selector with RPL 3. For writes to user space we have to additionally 683 * check the PTE for write permission, because the 386 does not check 684 * write permissions when we are executing with EPL 0. The 486 does check 685 * this if the WP bit is set in CR0, so we can use a simpler version here. 686 * 687 * These routines set curpcb->onfault for the time they execute. When a 688 * protection violation occurs inside the functions, the trap handler 689 * returns to *curpcb->onfault instead of the function. 690 */ 691 692/* 693 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU) 694 */ 695ENTRY(copyout) 696 MEXITCOUNT 697 jmp *copyout_vector 698 699ENTRY(generic_copyout) 700 movl PCPU(CURPCB),%eax 701 movl $copyout_fault,PCB_ONFAULT(%eax) 702 pushl %esi 703 pushl %edi 704 pushl %ebx 705 movl 16(%esp),%esi 706 movl 20(%esp),%edi 707 movl 24(%esp),%ebx 708 testl %ebx,%ebx /* anything to do? */ 709 jz done_copyout 710 711 /* 712 * Check explicitly for non-user addresses. If 486 write protection 713 * is being used, this check is essential because we are in kernel 714 * mode so the h/w does not provide any protection against writing 715 * kernel addresses. 716 */ 717 718 /* 719 * First, prevent address wrapping. 720 */ 721 movl %edi,%eax 722 addl %ebx,%eax 723 jc copyout_fault 724/* 725 * XXX STOP USING VM_MAXUSER_ADDRESS. 726 * It is an end address, not a max, so every time it is used correctly it 727 * looks like there is an off by one error, and of course it caused an off 728 * by one error in several places. 729 */ 730 cmpl $VM_MAXUSER_ADDRESS,%eax 731 ja copyout_fault 732 733#ifdef I386_CPU 734 735/* 736 * We have to check each PTE for user write permission. 737 * The checking may cause a page fault, so it is important to set 738 * up everything for return via copyout_fault before here. 739 */ 740 /* compute number of pages */ 741 movl %edi,%ecx 742 andl $PAGE_MASK,%ecx 743 addl %ebx,%ecx 744 decl %ecx 745 shrl $IDXSHIFT+2,%ecx 746 incl %ecx 747 748 /* compute PTE offset for start address */ 749 movl %edi,%edx 750 shrl $IDXSHIFT,%edx 751 andb $0xfc,%dl 752 7531: 754 /* check PTE for each page */ 755 leal PTmap(%edx),%eax 756 shrl $IDXSHIFT,%eax 757 andb $0xfc,%al 758 testb $PG_V,PTmap(%eax) /* PTE page must be valid */ 759 je 4f 760 movb PTmap(%edx),%al 761 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */ 762 cmpb $PG_V|PG_RW|PG_U,%al 763 je 2f 764 7654: 766 /* simulate a trap */ 767 pushl %edx 768 pushl %ecx 769 shll $IDXSHIFT,%edx 770 pushl %edx 771 call trapwrite /* trapwrite(addr) */ 772 popl %edx 773 popl %ecx 774 popl %edx 775 776 testl %eax,%eax /* if not ok, return EFAULT */ 777 jnz copyout_fault 778 7792: 780 addl $4,%edx 781 decl %ecx 782 jnz 1b /* check next page */ 783#endif /* I386_CPU */ 784 785 /* bcopy(%esi, %edi, %ebx) */ 786 movl %ebx,%ecx 787 788#if defined(I586_CPU) && defined(DEV_NPX) 789 ALIGN_TEXT 790slow_copyout: 791#endif 792 shrl $2,%ecx 793 cld 794 rep 795 movsl 796 movb %bl,%cl 797 andb $3,%cl 798 rep 799 movsb 800 801done_copyout: 802 popl %ebx 803 popl %edi 804 popl %esi 805 xorl %eax,%eax 806 movl PCPU(CURPCB),%edx 807 movl %eax,PCB_ONFAULT(%edx) 808 ret 809 810 ALIGN_TEXT 811copyout_fault: 812 popl %ebx 813 popl %edi 814 popl %esi 815 movl PCPU(CURPCB),%edx 816 movl $0,PCB_ONFAULT(%edx) 817 movl $EFAULT,%eax 818 ret 819 820#if defined(I586_CPU) && defined(DEV_NPX) 821ENTRY(i586_copyout) 822 /* 823 * Duplicated from generic_copyout. Could be done a bit better. 824 */ 825 movl PCPU(CURPCB),%eax 826 movl $copyout_fault,PCB_ONFAULT(%eax) 827 pushl %esi 828 pushl %edi 829 pushl %ebx 830 movl 16(%esp),%esi 831 movl 20(%esp),%edi 832 movl 24(%esp),%ebx 833 testl %ebx,%ebx /* anything to do? */ 834 jz done_copyout 835 836 /* 837 * Check explicitly for non-user addresses. If 486 write protection 838 * is being used, this check is essential because we are in kernel 839 * mode so the h/w does not provide any protection against writing 840 * kernel addresses. 841 */ 842 843 /* 844 * First, prevent address wrapping. 845 */ 846 movl %edi,%eax 847 addl %ebx,%eax 848 jc copyout_fault 849/* 850 * XXX STOP USING VM_MAXUSER_ADDRESS. 851 * It is an end address, not a max, so every time it is used correctly it 852 * looks like there is an off by one error, and of course it caused an off 853 * by one error in several places. 854 */ 855 cmpl $VM_MAXUSER_ADDRESS,%eax 856 ja copyout_fault 857 858 /* bcopy(%esi, %edi, %ebx) */ 8593: 860 movl %ebx,%ecx 861 /* 862 * End of duplicated code. 863 */ 864 865 cmpl $1024,%ecx 866 jb slow_copyout 867 868 pushl %ecx 869 call fastmove 870 addl $4,%esp 871 jmp done_copyout 872#endif /* I586_CPU && defined(DEV_NPX) */ 873 874/* 875 * copyin(from_user, to_kernel, len) - MP SAFE 876 */ 877ENTRY(copyin) 878 MEXITCOUNT 879 jmp *copyin_vector 880 881ENTRY(generic_copyin) 882 movl PCPU(CURPCB),%eax 883 movl $copyin_fault,PCB_ONFAULT(%eax) 884 pushl %esi 885 pushl %edi 886 movl 12(%esp),%esi /* caddr_t from */ 887 movl 16(%esp),%edi /* caddr_t to */ 888 movl 20(%esp),%ecx /* size_t len */ 889 890 /* 891 * make sure address is valid 892 */ 893 movl %esi,%edx 894 addl %ecx,%edx 895 jc copyin_fault 896 cmpl $VM_MAXUSER_ADDRESS,%edx 897 ja copyin_fault 898 899#if defined(I586_CPU) && defined(DEV_NPX) 900 ALIGN_TEXT 901slow_copyin: 902#endif 903 movb %cl,%al 904 shrl $2,%ecx /* copy longword-wise */ 905 cld 906 rep 907 movsl 908 movb %al,%cl 909 andb $3,%cl /* copy remaining bytes */ 910 rep 911 movsb 912 913#if defined(I586_CPU) && defined(DEV_NPX) 914 ALIGN_TEXT 915done_copyin: 916#endif 917 popl %edi 918 popl %esi 919 xorl %eax,%eax 920 movl PCPU(CURPCB),%edx 921 movl %eax,PCB_ONFAULT(%edx) 922 ret 923 924 ALIGN_TEXT 925copyin_fault: 926 popl %edi 927 popl %esi 928 movl PCPU(CURPCB),%edx 929 movl $0,PCB_ONFAULT(%edx) 930 movl $EFAULT,%eax 931 ret 932 933#if defined(I586_CPU) && defined(DEV_NPX) 934ENTRY(i586_copyin) 935 /* 936 * Duplicated from generic_copyin. Could be done a bit better. 937 */ 938 movl PCPU(CURPCB),%eax 939 movl $copyin_fault,PCB_ONFAULT(%eax) 940 pushl %esi 941 pushl %edi 942 movl 12(%esp),%esi /* caddr_t from */ 943 movl 16(%esp),%edi /* caddr_t to */ 944 movl 20(%esp),%ecx /* size_t len */ 945 946 /* 947 * make sure address is valid 948 */ 949 movl %esi,%edx 950 addl %ecx,%edx 951 jc copyin_fault 952 cmpl $VM_MAXUSER_ADDRESS,%edx 953 ja copyin_fault 954 /* 955 * End of duplicated code. 956 */ 957 958 cmpl $1024,%ecx 959 jb slow_copyin 960 961 pushl %ebx /* XXX prepare for fastmove_fault */ 962 pushl %ecx 963 call fastmove 964 addl $8,%esp 965 jmp done_copyin 966#endif /* I586_CPU && defined(DEV_NPX) */ 967 968#if defined(I586_CPU) && defined(DEV_NPX) 969/* fastmove(src, dst, len) 970 src in %esi 971 dst in %edi 972 len in %ecx XXX changed to on stack for profiling 973 uses %eax and %edx for tmp. storage 974 */ 975/* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */ 976ENTRY(fastmove) 977 pushl %ebp 978 movl %esp,%ebp 979 subl $PCB_SAVEFPU_SIZE+3*4,%esp 980 981 movl 8(%ebp),%ecx 982 cmpl $63,%ecx 983 jbe fastmove_tail 984 985 testl $7,%esi /* check if src addr is multiple of 8 */ 986 jnz fastmove_tail 987 988 testl $7,%edi /* check if dst addr is multiple of 8 */ 989 jnz fastmove_tail 990 991 /* XXX grab FPU context atomically. */ 992 cli 993 994/* if (npxproc != NULL) { */ 995 cmpl $0,PCPU(NPXPROC) 996 je 6f 997/* fnsave(&curpcb->pcb_savefpu); */ 998 movl PCPU(CURPCB),%eax 999 fnsave PCB_SAVEFPU(%eax) 1000/* npxproc = NULL; */ 1001 movl $0,PCPU(NPXPROC) 1002/* } */ 10036: 1004/* now we own the FPU. */ 1005 1006/* 1007 * The process' FP state is saved in the pcb, but if we get 1008 * switched, the cpu_switch() will store our FP state in the 1009 * pcb. It should be possible to avoid all the copying for 1010 * this, e.g., by setting a flag to tell cpu_switch() to 1011 * save the state somewhere else. 1012 */ 1013/* tmp = curpcb->pcb_savefpu; */ 1014 movl %ecx,-12(%ebp) 1015 movl %esi,-8(%ebp) 1016 movl %edi,-4(%ebp) 1017 movl %esp,%edi 1018 movl PCPU(CURPCB),%esi 1019 addl $PCB_SAVEFPU,%esi 1020 cld 1021 movl $PCB_SAVEFPU_SIZE>>2,%ecx 1022 rep 1023 movsl 1024 movl -12(%ebp),%ecx 1025 movl -8(%ebp),%esi 1026 movl -4(%ebp),%edi 1027/* stop_emulating(); */ 1028 clts 1029/* npxproc = curproc; */ 1030 movl PCPU(CURPROC),%eax 1031 movl %eax,PCPU(NPXPROC) 1032 movl PCPU(CURPCB),%eax 1033 1034 /* XXX end of atomic FPU context grab. */ 1035 sti 1036 1037 movl $fastmove_fault,PCB_ONFAULT(%eax) 10384: 1039 movl %ecx,-12(%ebp) 1040 cmpl $1792,%ecx 1041 jbe 2f 1042 movl $1792,%ecx 10432: 1044 subl %ecx,-12(%ebp) 1045 cmpl $256,%ecx 1046 jb 5f 1047 movl %ecx,-8(%ebp) 1048 movl %esi,-4(%ebp) 1049 ALIGN_TEXT 10503: 1051 movl 0(%esi),%eax 1052 movl 32(%esi),%eax 1053 movl 64(%esi),%eax 1054 movl 96(%esi),%eax 1055 movl 128(%esi),%eax 1056 movl 160(%esi),%eax 1057 movl 192(%esi),%eax 1058 movl 224(%esi),%eax 1059 addl $256,%esi 1060 subl $256,%ecx 1061 cmpl $256,%ecx 1062 jae 3b 1063 movl -8(%ebp),%ecx 1064 movl -4(%ebp),%esi 10655: 1066 ALIGN_TEXT 1067fastmove_loop: 1068 fildq 0(%esi) 1069 fildq 8(%esi) 1070 fildq 16(%esi) 1071 fildq 24(%esi) 1072 fildq 32(%esi) 1073 fildq 40(%esi) 1074 fildq 48(%esi) 1075 fildq 56(%esi) 1076 fistpq 56(%edi) 1077 fistpq 48(%edi) 1078 fistpq 40(%edi) 1079 fistpq 32(%edi) 1080 fistpq 24(%edi) 1081 fistpq 16(%edi) 1082 fistpq 8(%edi) 1083 fistpq 0(%edi) 1084 addl $-64,%ecx 1085 addl $64,%esi 1086 addl $64,%edi 1087 cmpl $63,%ecx 1088 ja fastmove_loop 1089 movl -12(%ebp),%eax 1090 addl %eax,%ecx 1091 cmpl $64,%ecx 1092 jae 4b 1093 1094 /* XXX ungrab FPU context atomically. */ 1095 cli 1096 1097/* curpcb->pcb_savefpu = tmp; */ 1098 movl %ecx,-12(%ebp) 1099 movl %esi,-8(%ebp) 1100 movl %edi,-4(%ebp) 1101 movl PCPU(CURPCB),%edi 1102 addl $PCB_SAVEFPU,%edi 1103 movl %esp,%esi 1104 cld 1105 movl $PCB_SAVEFPU_SIZE>>2,%ecx 1106 rep 1107 movsl 1108 movl -12(%ebp),%ecx 1109 movl -8(%ebp),%esi 1110 movl -4(%ebp),%edi 1111 1112/* start_emulating(); */ 1113 smsw %ax 1114 orb $CR0_TS,%al 1115 lmsw %ax 1116/* npxproc = NULL; */ 1117 movl $0,PCPU(NPXPROC) 1118 1119 /* XXX end of atomic FPU context ungrab. */ 1120 sti 1121 1122 ALIGN_TEXT 1123fastmove_tail: 1124 movl PCPU(CURPCB),%eax 1125 movl $fastmove_tail_fault,PCB_ONFAULT(%eax) 1126 1127 movb %cl,%al 1128 shrl $2,%ecx /* copy longword-wise */ 1129 cld 1130 rep 1131 movsl 1132 movb %al,%cl 1133 andb $3,%cl /* copy remaining bytes */ 1134 rep 1135 movsb 1136 1137 movl %ebp,%esp 1138 popl %ebp 1139 ret 1140 1141 ALIGN_TEXT 1142fastmove_fault: 1143 /* XXX ungrab FPU context atomically. */ 1144 cli 1145 1146 movl PCPU(CURPCB),%edi 1147 addl $PCB_SAVEFPU,%edi 1148 movl %esp,%esi 1149 cld 1150 movl $PCB_SAVEFPU_SIZE>>2,%ecx 1151 rep 1152 movsl 1153 1154 smsw %ax 1155 orb $CR0_TS,%al 1156 lmsw %ax 1157 movl $0,PCPU(NPXPROC) 1158 1159 /* XXX end of atomic FPU context ungrab. */ 1160 sti 1161 1162fastmove_tail_fault: 1163 movl %ebp,%esp 1164 popl %ebp 1165 addl $8,%esp 1166 popl %ebx 1167 popl %edi 1168 popl %esi 1169 movl PCPU(CURPCB),%edx 1170 movl $0,PCB_ONFAULT(%edx) 1171 movl $EFAULT,%eax 1172 ret 1173#endif /* I586_CPU && defined(DEV_NPX) */ 1174 1175/* 1176 * fu{byte,sword,word} - MP SAFE 1177 * 1178 * Fetch a byte (sword, word) from user memory 1179 */ 1180ENTRY(fuword) 1181 movl PCPU(CURPCB),%ecx 1182 movl $fusufault,PCB_ONFAULT(%ecx) 1183 movl 4(%esp),%edx /* from */ 1184 1185 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 1186 ja fusufault 1187 1188 movl (%edx),%eax 1189 movl $0,PCB_ONFAULT(%ecx) 1190 ret 1191 1192/* 1193 * These two routines are called from the profiling code, potentially 1194 * at interrupt time. If they fail, that's okay, good things will 1195 * happen later. Fail all the time for now - until the trap code is 1196 * able to deal with this. 1197 */ 1198ALTENTRY(suswintr) 1199ENTRY(fuswintr) 1200 movl $-1,%eax 1201 ret 1202 1203/* 1204 * fusword - MP SAFE 1205 */ 1206ENTRY(fusword) 1207 movl PCPU(CURPCB),%ecx 1208 movl $fusufault,PCB_ONFAULT(%ecx) 1209 movl 4(%esp),%edx 1210 1211 cmpl $VM_MAXUSER_ADDRESS-2,%edx 1212 ja fusufault 1213 1214 movzwl (%edx),%eax 1215 movl $0,PCB_ONFAULT(%ecx) 1216 ret 1217 1218/* 1219 * fubyte - MP SAFE 1220 */ 1221ENTRY(fubyte) 1222 movl PCPU(CURPCB),%ecx 1223 movl $fusufault,PCB_ONFAULT(%ecx) 1224 movl 4(%esp),%edx 1225 1226 cmpl $VM_MAXUSER_ADDRESS-1,%edx 1227 ja fusufault 1228 1229 movzbl (%edx),%eax 1230 movl $0,PCB_ONFAULT(%ecx) 1231 ret 1232 1233 ALIGN_TEXT 1234fusufault: 1235 movl PCPU(CURPCB),%ecx 1236 xorl %eax,%eax 1237 movl %eax,PCB_ONFAULT(%ecx) 1238 decl %eax 1239 ret 1240 1241/* 1242 * su{byte,sword,word} - MP SAFE (if not I386_CPU) 1243 * 1244 * Write a byte (word, longword) to user memory 1245 */ 1246ENTRY(suword) 1247 movl PCPU(CURPCB),%ecx 1248 movl $fusufault,PCB_ONFAULT(%ecx) 1249 movl 4(%esp),%edx 1250 1251#ifdef I386_CPU 1252 1253 /* XXX - page boundary crossing is still not handled */ 1254 movl %edx,%eax 1255 shrl $IDXSHIFT,%edx 1256 andb $0xfc,%dl 1257 1258 leal PTmap(%edx),%ecx 1259 shrl $IDXSHIFT,%ecx 1260 andb $0xfc,%cl 1261 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */ 1262 je 4f 1263 movb PTmap(%edx),%dl 1264 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */ 1265 cmpb $PG_V|PG_RW|PG_U,%dl 1266 je 1f 1267 12684: 1269 /* simulate a trap */ 1270 pushl %eax 1271 call trapwrite 1272 popl %edx /* remove junk parameter from stack */ 1273 testl %eax,%eax 1274 jnz fusufault 12751: 1276 movl 4(%esp),%edx 1277#endif 1278 1279 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 1280 ja fusufault 1281 1282 movl 8(%esp),%eax 1283 movl %eax,(%edx) 1284 xorl %eax,%eax 1285 movl PCPU(CURPCB),%ecx 1286 movl %eax,PCB_ONFAULT(%ecx) 1287 ret 1288 1289/* 1290 * susword - MP SAFE (if not I386_CPU) 1291 */ 1292ENTRY(susword) 1293 movl PCPU(CURPCB),%ecx 1294 movl $fusufault,PCB_ONFAULT(%ecx) 1295 movl 4(%esp),%edx 1296 1297#ifdef I386_CPU 1298 1299 /* XXX - page boundary crossing is still not handled */ 1300 movl %edx,%eax 1301 shrl $IDXSHIFT,%edx 1302 andb $0xfc,%dl 1303 1304 leal _PTmap(%edx),%ecx 1305 shrl $IDXSHIFT,%ecx 1306 andb $0xfc,%cl 1307 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */ 1308 je 4f 1309 movb PTmap(%edx),%dl 1310 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */ 1311 cmpb $PG_V|PG_RW|PG_U,%dl 1312 je 1f 1313 13144: 1315 /* simulate a trap */ 1316 pushl %eax 1317 call trapwrite 1318 popl %edx /* remove junk parameter from stack */ 1319 testl %eax,%eax 1320 jnz fusufault 13211: 1322 movl 4(%esp),%edx 1323#endif 1324 1325 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 1326 ja fusufault 1327 1328 movw 8(%esp),%ax 1329 movw %ax,(%edx) 1330 xorl %eax,%eax 1331 movl PCPU(CURPCB),%ecx /* restore trashed register */ 1332 movl %eax,PCB_ONFAULT(%ecx) 1333 ret 1334 1335/* 1336 * su[i]byte - MP SAFE (if not I386_CPU) 1337 */ 1338ALTENTRY(suibyte) 1339ENTRY(subyte) 1340 movl PCPU(CURPCB),%ecx 1341 movl $fusufault,PCB_ONFAULT(%ecx) 1342 movl 4(%esp),%edx 1343 1344#ifdef I386_CPU 1345 1346 movl %edx,%eax 1347 shrl $IDXSHIFT,%edx 1348 andb $0xfc,%dl 1349 1350 leal PTmap(%edx),%ecx 1351 shrl $IDXSHIFT,%ecx 1352 andb $0xfc,%cl 1353 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */ 1354 je 4f 1355 movb PTmap(%edx),%dl 1356 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */ 1357 cmpb $PG_V|PG_RW|PG_U,%dl 1358 je 1f 1359 13604: 1361 /* simulate a trap */ 1362 pushl %eax 1363 call trapwrite 1364 popl %edx /* remove junk parameter from stack */ 1365 testl %eax,%eax 1366 jnz fusufault 13671: 1368 movl 4(%esp),%edx 1369#endif 1370 1371 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 1372 ja fusufault 1373 1374 movb 8(%esp),%al 1375 movb %al,(%edx) 1376 xorl %eax,%eax 1377 movl PCPU(CURPCB),%ecx /* restore trashed register */ 1378 movl %eax,PCB_ONFAULT(%ecx) 1379 ret 1380 1381/* 1382 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE 1383 * 1384 * copy a string from from to to, stop when a 0 character is reached. 1385 * return ENAMETOOLONG if string is longer than maxlen, and 1386 * EFAULT on protection violations. If lencopied is non-zero, 1387 * return the actual length in *lencopied. 1388 */ 1389ENTRY(copyinstr) 1390 pushl %esi 1391 pushl %edi 1392 movl PCPU(CURPCB),%ecx 1393 movl $cpystrflt,PCB_ONFAULT(%ecx) 1394 1395 movl 12(%esp),%esi /* %esi = from */ 1396 movl 16(%esp),%edi /* %edi = to */ 1397 movl 20(%esp),%edx /* %edx = maxlen */ 1398 1399 movl $VM_MAXUSER_ADDRESS,%eax 1400 1401 /* make sure 'from' is within bounds */ 1402 subl %esi,%eax 1403 jbe cpystrflt 1404 1405 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 1406 cmpl %edx,%eax 1407 jae 1f 1408 movl %eax,%edx 1409 movl %eax,20(%esp) 14101: 1411 incl %edx 1412 cld 1413 14142: 1415 decl %edx 1416 jz 3f 1417 1418 lodsb 1419 stosb 1420 orb %al,%al 1421 jnz 2b 1422 1423 /* Success -- 0 byte reached */ 1424 decl %edx 1425 xorl %eax,%eax 1426 jmp cpystrflt_x 14273: 1428 /* edx is zero - return ENAMETOOLONG or EFAULT */ 1429 cmpl $VM_MAXUSER_ADDRESS,%esi 1430 jae cpystrflt 14314: 1432 movl $ENAMETOOLONG,%eax 1433 jmp cpystrflt_x 1434 1435cpystrflt: 1436 movl $EFAULT,%eax 1437 1438cpystrflt_x: 1439 /* set *lencopied and return %eax */ 1440 movl PCPU(CURPCB),%ecx 1441 movl $0,PCB_ONFAULT(%ecx) 1442 movl 20(%esp),%ecx 1443 subl %edx,%ecx 1444 movl 24(%esp),%edx 1445 testl %edx,%edx 1446 jz 1f 1447 movl %ecx,(%edx) 14481: 1449 popl %edi 1450 popl %esi 1451 ret 1452 1453 1454/* 1455 * copystr(from, to, maxlen, int *lencopied) - MP SAFE 1456 */ 1457ENTRY(copystr) 1458 pushl %esi 1459 pushl %edi 1460 1461 movl 12(%esp),%esi /* %esi = from */ 1462 movl 16(%esp),%edi /* %edi = to */ 1463 movl 20(%esp),%edx /* %edx = maxlen */ 1464 incl %edx 1465 cld 14661: 1467 decl %edx 1468 jz 4f 1469 lodsb 1470 stosb 1471 orb %al,%al 1472 jnz 1b 1473 1474 /* Success -- 0 byte reached */ 1475 decl %edx 1476 xorl %eax,%eax 1477 jmp 6f 14784: 1479 /* edx is zero -- return ENAMETOOLONG */ 1480 movl $ENAMETOOLONG,%eax 1481 14826: 1483 /* set *lencopied and return %eax */ 1484 movl 20(%esp),%ecx 1485 subl %edx,%ecx 1486 movl 24(%esp),%edx 1487 testl %edx,%edx 1488 jz 7f 1489 movl %ecx,(%edx) 14907: 1491 popl %edi 1492 popl %esi 1493 ret 1494 1495ENTRY(bcmp) 1496 pushl %edi 1497 pushl %esi 1498 movl 12(%esp),%edi 1499 movl 16(%esp),%esi 1500 movl 20(%esp),%edx 1501 xorl %eax,%eax 1502 1503 movl %edx,%ecx 1504 shrl $2,%ecx 1505 cld /* compare forwards */ 1506 repe 1507 cmpsl 1508 jne 1f 1509 1510 movl %edx,%ecx 1511 andl $3,%ecx 1512 repe 1513 cmpsb 1514 je 2f 15151: 1516 incl %eax 15172: 1518 popl %esi 1519 popl %edi 1520 ret 1521 1522 1523/* 1524 * Handling of special 386 registers and descriptor tables etc 1525 */ 1526/* void lgdt(struct region_descriptor *rdp); */ 1527ENTRY(lgdt) 1528 /* reload the descriptor table */ 1529 movl 4(%esp),%eax 1530 lgdt (%eax) 1531 1532 /* flush the prefetch q */ 1533 jmp 1f 1534 nop 15351: 1536 /* reload "stale" selectors */ 1537 movl $KDSEL,%eax 1538 mov %ax,%ds 1539 mov %ax,%es 1540 mov %ax,%gs 1541 mov %ax,%ss 1542 movl $KPSEL,%eax 1543 mov %ax,%fs 1544 1545 /* reload code selector by turning return into intersegmental return */ 1546 movl (%esp),%eax 1547 pushl %eax 1548 movl $KCSEL,4(%esp) 1549 lret 1550 1551/* 1552 * void lidt(struct region_descriptor *rdp); 1553 */ 1554ENTRY(lidt) 1555 movl 4(%esp),%eax 1556 lidt (%eax) 1557 ret 1558 1559/* 1560 * void lldt(u_short sel) 1561 */ 1562ENTRY(lldt) 1563 lldt 4(%esp) 1564 ret 1565 1566/* 1567 * void ltr(u_short sel) 1568 */ 1569ENTRY(ltr) 1570 ltr 4(%esp) 1571 ret 1572 1573/* ssdtosd(*ssdp,*sdp) */ 1574ENTRY(ssdtosd) 1575 pushl %ebx 1576 movl 8(%esp),%ecx 1577 movl 8(%ecx),%ebx 1578 shll $16,%ebx 1579 movl (%ecx),%edx 1580 roll $16,%edx 1581 movb %dh,%bl 1582 movb %dl,%bh 1583 rorl $8,%ebx 1584 movl 4(%ecx),%eax 1585 movw %ax,%dx 1586 andl $0xf0000,%eax 1587 orl %eax,%ebx 1588 movl 12(%esp),%ecx 1589 movl %edx,(%ecx) 1590 movl %ebx,4(%ecx) 1591 popl %ebx 1592 ret 1593 1594/* load_cr0(cr0) */ 1595ENTRY(load_cr0) 1596 movl 4(%esp),%eax 1597 movl %eax,%cr0 1598 ret 1599 1600/* rcr0() */ 1601ENTRY(rcr0) 1602 movl %cr0,%eax 1603 ret 1604 1605/* rcr3() */ 1606ENTRY(rcr3) 1607 movl %cr3,%eax 1608 ret 1609 1610/* void load_cr3(caddr_t cr3) */ 1611ENTRY(load_cr3) 1612#ifdef SWTCH_OPTIM_STATS 1613 incl tlb_flush_count 1614#endif 1615 movl 4(%esp),%eax 1616 movl %eax,%cr3 1617 ret 1618 1619/* rcr4() */ 1620ENTRY(rcr4) 1621 movl %cr4,%eax 1622 ret 1623 1624/* void load_cr4(caddr_t cr4) */ 1625ENTRY(load_cr4) 1626 movl 4(%esp),%eax 1627 movl %eax,%cr4 1628 ret 1629 1630/* void load_dr6(u_int dr6) */ 1631ENTRY(load_dr6) 1632 movl 4(%esp),%eax 1633 movl %eax,%dr6 1634 ret 1635 1636/* void reset_dbregs() */ 1637ENTRY(reset_dbregs) 1638 movl $0,%eax 1639 movl %eax,%dr7 /* disable all breapoints first */ 1640 movl %eax,%dr0 1641 movl %eax,%dr1 1642 movl %eax,%dr2 1643 movl %eax,%dr3 1644 movl %eax,%dr6 1645 ret 1646 1647/*****************************************************************************/ 1648/* setjump, longjump */ 1649/*****************************************************************************/ 1650 1651ENTRY(setjmp) 1652 movl 4(%esp),%eax 1653 movl %ebx,(%eax) /* save ebx */ 1654 movl %esp,4(%eax) /* save esp */ 1655 movl %ebp,8(%eax) /* save ebp */ 1656 movl %esi,12(%eax) /* save esi */ 1657 movl %edi,16(%eax) /* save edi */ 1658 movl (%esp),%edx /* get rta */ 1659 movl %edx,20(%eax) /* save eip */ 1660 xorl %eax,%eax /* return(0); */ 1661 ret 1662 1663ENTRY(longjmp) 1664 movl 4(%esp),%eax 1665 movl (%eax),%ebx /* restore ebx */ 1666 movl 4(%eax),%esp /* restore esp */ 1667 movl 8(%eax),%ebp /* restore ebp */ 1668 movl 12(%eax),%esi /* restore esi */ 1669 movl 16(%eax),%edi /* restore edi */ 1670 movl 20(%eax),%edx /* get rta */ 1671 movl %edx,(%esp) /* put in return frame */ 1672 xorl %eax,%eax /* return(1); */ 1673 incl %eax 1674 ret 1675 1676/* 1677 * Support for BB-profiling (gcc -a). The kernbb program will extract 1678 * the data from the kernel. 1679 */ 1680 1681 .data 1682 ALIGN_DATA 1683 .globl bbhead 1684bbhead: 1685 .long 0 1686 1687 .text 1688NON_GPROF_ENTRY(__bb_init_func) 1689 movl 4(%esp),%eax 1690 movl $1,(%eax) 1691 movl bbhead,%edx 1692 movl %edx,16(%eax) 1693 movl %eax,bbhead 1694 NON_GPROF_RET 1695