support.s revision 69971
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 69971 2000-12-13 09:23:53Z jake $ 34 */ 35 36#include "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 49_bcopy_vector: 50 .long _generic_bcopy 51 .globl _bzero 52_bzero: 53 .long _generic_bzero 54 .globl _copyin_vector 55_copyin_vector: 56 .long _generic_copyin 57 .globl _copyout_vector 58_copyout_vector: 59 .long _generic_copyout 60 .globl _ovbcopy_vector 61_ovbcopy_vector: 62 .long _generic_bcopy 63#if defined(I586_CPU) && NNPX > 0 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#if defined(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) && NNPX > 0 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 cmpl $256+184,%ecx /* empirical; not quite 2*108 more */ 247 jb intreg_i586_bzero 248 sarb $1,kernel_fpu_lock 249 jc intreg_i586_bzero 250 smsw %ax 251 clts 252 subl $108,%esp 253 fnsave 0(%esp) 254 jmp i586_bz2 255 256i586_bz1: 257 sarb $1,kernel_fpu_lock 258 jc intreg_i586_bzero 259 smsw %ax 260 clts 261 fninit /* XXX should avoid needing this */ 262i586_bz2: 263 fldz 264 265 /* 266 * Align to an 8 byte boundary (misalignment in the main loop would 267 * cost a factor of >= 2). Avoid jumps (at little cost if it is 268 * already aligned) by always zeroing 8 bytes and using the part up 269 * to the _next_ alignment position. 270 */ 271 fstl 0(%edx) 272 addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */ 273 addl $8,%edx 274 andl $~7,%edx 275 subl %edx,%ecx 276 277 /* 278 * Similarly align `len' to a multiple of 8. 279 */ 280 fstl -8(%edx,%ecx) 281 decl %ecx 282 andl $~7,%ecx 283 284 /* 285 * This wouldn't be any faster if it were unrolled, since the loop 286 * control instructions are much faster than the fstl and/or done 287 * in parallel with it so their overhead is insignificant. 288 */ 289fpureg_i586_bzero_loop: 290 fstl 0(%edx) 291 addl $8,%edx 292 subl $8,%ecx 293 cmpl $8,%ecx 294 jae fpureg_i586_bzero_loop 295 296 cmpl $0,PCPU(NPXPROC) 297 je i586_bz3 298 frstor 0(%esp) 299 addl $108,%esp 300 lmsw %ax 301 movb $0xfe,kernel_fpu_lock 302 ret 303 304i586_bz3: 305 fstp %st(0) 306 lmsw %ax 307 movb $0xfe,kernel_fpu_lock 308 ret 309 310intreg_i586_bzero: 311 /* 312 * `rep stos' seems to be the best method in practice for small 313 * counts. Fancy methods usually take too long to start up due 314 * to cache and BTB misses. 315 */ 316 pushl %edi 317 movl %edx,%edi 318 xorl %eax,%eax 319 shrl $2,%ecx 320 cld 321 rep 322 stosl 323 movl 12(%esp),%ecx 324 andl $3,%ecx 325 jne 1f 326 popl %edi 327 ret 328 3291: 330 rep 331 stosb 332 popl %edi 333 ret 334#endif /* I586_CPU && NNPX > 0 */ 335 336ENTRY(i686_pagezero) 337 pushl %edi 338 pushl %ebx 339 340 movl 12(%esp), %edi 341 movl $1024, %ecx 342 cld 343 344 ALIGN_TEXT 3451: 346 xorl %eax, %eax 347 repe 348 scasl 349 jnz 2f 350 351 popl %ebx 352 popl %edi 353 ret 354 355 ALIGN_TEXT 356 3572: 358 incl %ecx 359 subl $4, %edi 360 361 movl %ecx, %edx 362 cmpl $16, %ecx 363 364 jge 3f 365 366 movl %edi, %ebx 367 andl $0x3f, %ebx 368 shrl %ebx 369 shrl %ebx 370 movl $16, %ecx 371 subl %ebx, %ecx 372 3733: 374 subl %ecx, %edx 375 rep 376 stosl 377 378 movl %edx, %ecx 379 testl %edx, %edx 380 jnz 1b 381 382 popl %ebx 383 popl %edi 384 ret 385 386/* fillw(pat, base, cnt) */ 387ENTRY(fillw) 388 pushl %edi 389 movl 8(%esp),%eax 390 movl 12(%esp),%edi 391 movl 16(%esp),%ecx 392 cld 393 rep 394 stosw 395 popl %edi 396 ret 397 398ENTRY(bcopyb) 399 pushl %esi 400 pushl %edi 401 movl 12(%esp),%esi 402 movl 16(%esp),%edi 403 movl 20(%esp),%ecx 404 movl %edi,%eax 405 subl %esi,%eax 406 cmpl %ecx,%eax /* overlapping && src < dst? */ 407 jb 1f 408 cld /* nope, copy forwards */ 409 rep 410 movsb 411 popl %edi 412 popl %esi 413 ret 414 415 ALIGN_TEXT 4161: 417 addl %ecx,%edi /* copy backwards. */ 418 addl %ecx,%esi 419 decl %edi 420 decl %esi 421 std 422 rep 423 movsb 424 popl %edi 425 popl %esi 426 cld 427 ret 428 429ENTRY(bcopy) 430 MEXITCOUNT 431 jmp *_bcopy_vector 432 433ENTRY(ovbcopy) 434 MEXITCOUNT 435 jmp *_ovbcopy_vector 436 437/* 438 * generic_bcopy(src, dst, cnt) 439 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 440 */ 441ENTRY(generic_bcopy) 442 pushl %esi 443 pushl %edi 444 movl 12(%esp),%esi 445 movl 16(%esp),%edi 446 movl 20(%esp),%ecx 447 448 movl %edi,%eax 449 subl %esi,%eax 450 cmpl %ecx,%eax /* overlapping && src < dst? */ 451 jb 1f 452 453 shrl $2,%ecx /* copy by 32-bit words */ 454 cld /* nope, copy forwards */ 455 rep 456 movsl 457 movl 20(%esp),%ecx 458 andl $3,%ecx /* any bytes left? */ 459 rep 460 movsb 461 popl %edi 462 popl %esi 463 ret 464 465 ALIGN_TEXT 4661: 467 addl %ecx,%edi /* copy backwards */ 468 addl %ecx,%esi 469 decl %edi 470 decl %esi 471 andl $3,%ecx /* any fractional bytes? */ 472 std 473 rep 474 movsb 475 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 476 shrl $2,%ecx 477 subl $3,%esi 478 subl $3,%edi 479 rep 480 movsl 481 popl %edi 482 popl %esi 483 cld 484 ret 485 486#if defined(I586_CPU) && NNPX > 0 487ENTRY(i586_bcopy) 488 pushl %esi 489 pushl %edi 490 movl 12(%esp),%esi 491 movl 16(%esp),%edi 492 movl 20(%esp),%ecx 493 494 movl %edi,%eax 495 subl %esi,%eax 496 cmpl %ecx,%eax /* overlapping && src < dst? */ 497 jb 1f 498 499 cmpl $1024,%ecx 500 jb small_i586_bcopy 501 502 sarb $1,kernel_fpu_lock 503 jc small_i586_bcopy 504 cmpl $0,PCPU(NPXPROC) 505 je i586_bc1 506 smsw %dx 507 clts 508 subl $108,%esp 509 fnsave 0(%esp) 510 jmp 4f 511 512i586_bc1: 513 smsw %dx 514 clts 515 fninit /* XXX should avoid needing this */ 516 517 ALIGN_TEXT 5184: 519 pushl %ecx 520#define DCACHE_SIZE 8192 521 cmpl $(DCACHE_SIZE-512)/2,%ecx 522 jbe 2f 523 movl $(DCACHE_SIZE-512)/2,%ecx 5242: 525 subl %ecx,0(%esp) 526 cmpl $256,%ecx 527 jb 5f /* XXX should prefetch if %ecx >= 32 */ 528 pushl %esi 529 pushl %ecx 530 ALIGN_TEXT 5313: 532 movl 0(%esi),%eax 533 movl 32(%esi),%eax 534 movl 64(%esi),%eax 535 movl 96(%esi),%eax 536 movl 128(%esi),%eax 537 movl 160(%esi),%eax 538 movl 192(%esi),%eax 539 movl 224(%esi),%eax 540 addl $256,%esi 541 subl $256,%ecx 542 cmpl $256,%ecx 543 jae 3b 544 popl %ecx 545 popl %esi 5465: 547 ALIGN_TEXT 548large_i586_bcopy_loop: 549 fildq 0(%esi) 550 fildq 8(%esi) 551 fildq 16(%esi) 552 fildq 24(%esi) 553 fildq 32(%esi) 554 fildq 40(%esi) 555 fildq 48(%esi) 556 fildq 56(%esi) 557 fistpq 56(%edi) 558 fistpq 48(%edi) 559 fistpq 40(%edi) 560 fistpq 32(%edi) 561 fistpq 24(%edi) 562 fistpq 16(%edi) 563 fistpq 8(%edi) 564 fistpq 0(%edi) 565 addl $64,%esi 566 addl $64,%edi 567 subl $64,%ecx 568 cmpl $64,%ecx 569 jae large_i586_bcopy_loop 570 popl %eax 571 addl %eax,%ecx 572 cmpl $64,%ecx 573 jae 4b 574 575 cmpl $0,PCPU(NPXPROC) 576 je i586_bc2 577 frstor 0(%esp) 578 addl $108,%esp 579i586_bc2: 580 lmsw %dx 581 movb $0xfe,kernel_fpu_lock 582 583/* 584 * This is a duplicate of the main part of generic_bcopy. See the comments 585 * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and 586 * would mess up high resolution profiling. 587 */ 588 ALIGN_TEXT 589small_i586_bcopy: 590 shrl $2,%ecx 591 cld 592 rep 593 movsl 594 movl 20(%esp),%ecx 595 andl $3,%ecx 596 rep 597 movsb 598 popl %edi 599 popl %esi 600 ret 601 602 ALIGN_TEXT 6031: 604 addl %ecx,%edi 605 addl %ecx,%esi 606 decl %edi 607 decl %esi 608 andl $3,%ecx 609 std 610 rep 611 movsb 612 movl 20(%esp),%ecx 613 shrl $2,%ecx 614 subl $3,%esi 615 subl $3,%edi 616 rep 617 movsl 618 popl %edi 619 popl %esi 620 cld 621 ret 622#endif /* I586_CPU && NNPX > 0 */ 623 624/* 625 * Note: memcpy does not support overlapping copies 626 */ 627ENTRY(memcpy) 628 pushl %edi 629 pushl %esi 630 movl 12(%esp),%edi 631 movl 16(%esp),%esi 632 movl 20(%esp),%ecx 633 movl %edi,%eax 634 shrl $2,%ecx /* copy by 32-bit words */ 635 cld /* nope, copy forwards */ 636 rep 637 movsl 638 movl 20(%esp),%ecx 639 andl $3,%ecx /* any bytes left? */ 640 rep 641 movsb 642 popl %esi 643 popl %edi 644 ret 645 646 647/*****************************************************************************/ 648/* copyout and fubyte family */ 649/*****************************************************************************/ 650/* 651 * Access user memory from inside the kernel. These routines and possibly 652 * the math- and DOS emulators should be the only places that do this. 653 * 654 * We have to access the memory with user's permissions, so use a segment 655 * selector with RPL 3. For writes to user space we have to additionally 656 * check the PTE for write permission, because the 386 does not check 657 * write permissions when we are executing with EPL 0. The 486 does check 658 * this if the WP bit is set in CR0, so we can use a simpler version here. 659 * 660 * These routines set curpcb->onfault for the time they execute. When a 661 * protection violation occurs inside the functions, the trap handler 662 * returns to *curpcb->onfault instead of the function. 663 */ 664 665/* 666 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU) 667 */ 668ENTRY(copyout) 669 MEXITCOUNT 670 jmp *_copyout_vector 671 672ENTRY(generic_copyout) 673 movl PCPU(CURPCB),%eax 674 movl $copyout_fault,PCB_ONFAULT(%eax) 675 pushl %esi 676 pushl %edi 677 pushl %ebx 678 movl 16(%esp),%esi 679 movl 20(%esp),%edi 680 movl 24(%esp),%ebx 681 testl %ebx,%ebx /* anything to do? */ 682 jz done_copyout 683 684 /* 685 * Check explicitly for non-user addresses. If 486 write protection 686 * is being used, this check is essential because we are in kernel 687 * mode so the h/w does not provide any protection against writing 688 * kernel addresses. 689 */ 690 691 /* 692 * First, prevent address wrapping. 693 */ 694 movl %edi,%eax 695 addl %ebx,%eax 696 jc copyout_fault 697/* 698 * XXX STOP USING VM_MAXUSER_ADDRESS. 699 * It is an end address, not a max, so every time it is used correctly it 700 * looks like there is an off by one error, and of course it caused an off 701 * by one error in several places. 702 */ 703 cmpl $VM_MAXUSER_ADDRESS,%eax 704 ja copyout_fault 705 706#if defined(I386_CPU) 707 708#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 709 cmpl $CPUCLASS_386,_cpu_class 710 jne 3f 711#endif 712/* 713 * We have to check each PTE for user write permission. 714 * The checking may cause a page fault, so it is important to set 715 * up everything for return via copyout_fault before here. 716 */ 717 /* compute number of pages */ 718 movl %edi,%ecx 719 andl $PAGE_MASK,%ecx 720 addl %ebx,%ecx 721 decl %ecx 722 shrl $IDXSHIFT+2,%ecx 723 incl %ecx 724 725 /* compute PTE offset for start address */ 726 movl %edi,%edx 727 shrl $IDXSHIFT,%edx 728 andb $0xfc,%dl 729 7301: 731 /* check PTE for each page */ 732 leal _PTmap(%edx),%eax 733 shrl $IDXSHIFT,%eax 734 andb $0xfc,%al 735 testb $PG_V,_PTmap(%eax) /* PTE page must be valid */ 736 je 4f 737 movb _PTmap(%edx),%al 738 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */ 739 cmpb $PG_V|PG_RW|PG_U,%al 740 je 2f 741 7424: 743 /* simulate a trap */ 744 pushl %edx 745 pushl %ecx 746 shll $IDXSHIFT,%edx 747 pushl %edx 748 call _trapwrite /* trapwrite(addr) */ 749 popl %edx 750 popl %ecx 751 popl %edx 752 753 testl %eax,%eax /* if not ok, return EFAULT */ 754 jnz copyout_fault 755 7562: 757 addl $4,%edx 758 decl %ecx 759 jnz 1b /* check next page */ 760#endif /* I386_CPU */ 761 762 /* bcopy(%esi, %edi, %ebx) */ 7633: 764 movl %ebx,%ecx 765 766#if defined(I586_CPU) && NNPX > 0 767 ALIGN_TEXT 768slow_copyout: 769#endif 770 shrl $2,%ecx 771 cld 772 rep 773 movsl 774 movb %bl,%cl 775 andb $3,%cl 776 rep 777 movsb 778 779done_copyout: 780 popl %ebx 781 popl %edi 782 popl %esi 783 xorl %eax,%eax 784 movl PCPU(CURPCB),%edx 785 movl %eax,PCB_ONFAULT(%edx) 786 ret 787 788 ALIGN_TEXT 789copyout_fault: 790 popl %ebx 791 popl %edi 792 popl %esi 793 movl PCPU(CURPCB),%edx 794 movl $0,PCB_ONFAULT(%edx) 795 movl $EFAULT,%eax 796 ret 797 798#if defined(I586_CPU) && NNPX > 0 799ENTRY(i586_copyout) 800 /* 801 * Duplicated from generic_copyout. Could be done a bit better. 802 */ 803 movl PCPU(CURPCB),%eax 804 movl $copyout_fault,PCB_ONFAULT(%eax) 805 pushl %esi 806 pushl %edi 807 pushl %ebx 808 movl 16(%esp),%esi 809 movl 20(%esp),%edi 810 movl 24(%esp),%ebx 811 testl %ebx,%ebx /* anything to do? */ 812 jz done_copyout 813 814 /* 815 * Check explicitly for non-user addresses. If 486 write protection 816 * is being used, this check is essential because we are in kernel 817 * mode so the h/w does not provide any protection against writing 818 * kernel addresses. 819 */ 820 821 /* 822 * First, prevent address wrapping. 823 */ 824 movl %edi,%eax 825 addl %ebx,%eax 826 jc copyout_fault 827/* 828 * XXX STOP USING VM_MAXUSER_ADDRESS. 829 * It is an end address, not a max, so every time it is used correctly it 830 * looks like there is an off by one error, and of course it caused an off 831 * by one error in several places. 832 */ 833 cmpl $VM_MAXUSER_ADDRESS,%eax 834 ja copyout_fault 835 836 /* bcopy(%esi, %edi, %ebx) */ 8373: 838 movl %ebx,%ecx 839 /* 840 * End of duplicated code. 841 */ 842 843 cmpl $1024,%ecx 844 jb slow_copyout 845 846 pushl %ecx 847 call _fastmove 848 addl $4,%esp 849 jmp done_copyout 850#endif /* I586_CPU && NNPX > 0 */ 851 852/* 853 * copyin(from_user, to_kernel, len) - MP SAFE 854 */ 855ENTRY(copyin) 856 MEXITCOUNT 857 jmp *_copyin_vector 858 859ENTRY(generic_copyin) 860 movl PCPU(CURPCB),%eax 861 movl $copyin_fault,PCB_ONFAULT(%eax) 862 pushl %esi 863 pushl %edi 864 movl 12(%esp),%esi /* caddr_t from */ 865 movl 16(%esp),%edi /* caddr_t to */ 866 movl 20(%esp),%ecx /* size_t len */ 867 868 /* 869 * make sure address is valid 870 */ 871 movl %esi,%edx 872 addl %ecx,%edx 873 jc copyin_fault 874 cmpl $VM_MAXUSER_ADDRESS,%edx 875 ja copyin_fault 876 877#if defined(I586_CPU) && NNPX > 0 878 ALIGN_TEXT 879slow_copyin: 880#endif 881 movb %cl,%al 882 shrl $2,%ecx /* copy longword-wise */ 883 cld 884 rep 885 movsl 886 movb %al,%cl 887 andb $3,%cl /* copy remaining bytes */ 888 rep 889 movsb 890 891#if defined(I586_CPU) && NNPX > 0 892 ALIGN_TEXT 893done_copyin: 894#endif 895 popl %edi 896 popl %esi 897 xorl %eax,%eax 898 movl PCPU(CURPCB),%edx 899 movl %eax,PCB_ONFAULT(%edx) 900 ret 901 902 ALIGN_TEXT 903copyin_fault: 904 popl %edi 905 popl %esi 906 movl PCPU(CURPCB),%edx 907 movl $0,PCB_ONFAULT(%edx) 908 movl $EFAULT,%eax 909 ret 910 911#if defined(I586_CPU) && NNPX > 0 912ENTRY(i586_copyin) 913 /* 914 * Duplicated from generic_copyin. Could be done a bit better. 915 */ 916 movl PCPU(CURPCB),%eax 917 movl $copyin_fault,PCB_ONFAULT(%eax) 918 pushl %esi 919 pushl %edi 920 movl 12(%esp),%esi /* caddr_t from */ 921 movl 16(%esp),%edi /* caddr_t to */ 922 movl 20(%esp),%ecx /* size_t len */ 923 924 /* 925 * make sure address is valid 926 */ 927 movl %esi,%edx 928 addl %ecx,%edx 929 jc copyin_fault 930 cmpl $VM_MAXUSER_ADDRESS,%edx 931 ja copyin_fault 932 /* 933 * End of duplicated code. 934 */ 935 936 cmpl $1024,%ecx 937 jb slow_copyin 938 939 pushl %ebx /* XXX prepare for fastmove_fault */ 940 pushl %ecx 941 call _fastmove 942 addl $8,%esp 943 jmp done_copyin 944#endif /* I586_CPU && NNPX > 0 */ 945 946#if defined(I586_CPU) && NNPX > 0 947/* fastmove(src, dst, len) 948 src in %esi 949 dst in %edi 950 len in %ecx XXX changed to on stack for profiling 951 uses %eax and %edx for tmp. storage 952 */ 953/* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */ 954ENTRY(fastmove) 955 pushl %ebp 956 movl %esp,%ebp 957 subl $PCB_SAVEFPU_SIZE+3*4,%esp 958 959 movl 8(%ebp),%ecx 960 cmpl $63,%ecx 961 jbe fastmove_tail 962 963 testl $7,%esi /* check if src addr is multiple of 8 */ 964 jnz fastmove_tail 965 966 testl $7,%edi /* check if dst addr is multiple of 8 */ 967 jnz fastmove_tail 968 969/* if (npxproc != NULL) { */ 970 cmpl $0,PCPU(NPXPROC) 971 je 6f 972/* fnsave(&curpcb->pcb_savefpu); */ 973 movl PCPU(CURPCB),%eax 974 fnsave PCB_SAVEFPU(%eax) 975/* npxproc = NULL; */ 976 movl $0,PCPU(NPXPROC) 977/* } */ 9786: 979/* now we own the FPU. */ 980 981/* 982 * The process' FP state is saved in the pcb, but if we get 983 * switched, the cpu_switch() will store our FP state in the 984 * pcb. It should be possible to avoid all the copying for 985 * this, e.g., by setting a flag to tell cpu_switch() to 986 * save the state somewhere else. 987 */ 988/* tmp = curpcb->pcb_savefpu; */ 989 movl %ecx,-12(%ebp) 990 movl %esi,-8(%ebp) 991 movl %edi,-4(%ebp) 992 movl %esp,%edi 993 movl PCPU(CURPCB),%esi 994 addl $PCB_SAVEFPU,%esi 995 cld 996 movl $PCB_SAVEFPU_SIZE>>2,%ecx 997 rep 998 movsl 999 movl -12(%ebp),%ecx 1000 movl -8(%ebp),%esi 1001 movl -4(%ebp),%edi 1002/* stop_emulating(); */ 1003 clts 1004/* npxproc = curproc; */ 1005 movl PCPU(CURPROC),%eax 1006 movl %eax,PCPU(NPXPROC) 1007 movl PCPU(CURPCB),%eax 1008 movl $fastmove_fault,PCB_ONFAULT(%eax) 10094: 1010 movl %ecx,-12(%ebp) 1011 cmpl $1792,%ecx 1012 jbe 2f 1013 movl $1792,%ecx 10142: 1015 subl %ecx,-12(%ebp) 1016 cmpl $256,%ecx 1017 jb 5f 1018 movl %ecx,-8(%ebp) 1019 movl %esi,-4(%ebp) 1020 ALIGN_TEXT 10213: 1022 movl 0(%esi),%eax 1023 movl 32(%esi),%eax 1024 movl 64(%esi),%eax 1025 movl 96(%esi),%eax 1026 movl 128(%esi),%eax 1027 movl 160(%esi),%eax 1028 movl 192(%esi),%eax 1029 movl 224(%esi),%eax 1030 addl $256,%esi 1031 subl $256,%ecx 1032 cmpl $256,%ecx 1033 jae 3b 1034 movl -8(%ebp),%ecx 1035 movl -4(%ebp),%esi 10365: 1037 ALIGN_TEXT 1038fastmove_loop: 1039 fildq 0(%esi) 1040 fildq 8(%esi) 1041 fildq 16(%esi) 1042 fildq 24(%esi) 1043 fildq 32(%esi) 1044 fildq 40(%esi) 1045 fildq 48(%esi) 1046 fildq 56(%esi) 1047 fistpq 56(%edi) 1048 fistpq 48(%edi) 1049 fistpq 40(%edi) 1050 fistpq 32(%edi) 1051 fistpq 24(%edi) 1052 fistpq 16(%edi) 1053 fistpq 8(%edi) 1054 fistpq 0(%edi) 1055 addl $-64,%ecx 1056 addl $64,%esi 1057 addl $64,%edi 1058 cmpl $63,%ecx 1059 ja fastmove_loop 1060 movl -12(%ebp),%eax 1061 addl %eax,%ecx 1062 cmpl $64,%ecx 1063 jae 4b 1064 1065/* curpcb->pcb_savefpu = tmp; */ 1066 movl %ecx,-12(%ebp) 1067 movl %esi,-8(%ebp) 1068 movl %edi,-4(%ebp) 1069 movl PCPU(CURPCB),%edi 1070 addl $PCB_SAVEFPU,%edi 1071 movl %esp,%esi 1072 cld 1073 movl $PCB_SAVEFPU_SIZE>>2,%ecx 1074 rep 1075 movsl 1076 movl -12(%ebp),%ecx 1077 movl -8(%ebp),%esi 1078 movl -4(%ebp),%edi 1079 1080/* start_emulating(); */ 1081 smsw %ax 1082 orb $CR0_TS,%al 1083 lmsw %ax 1084/* npxproc = NULL; */ 1085 movl $0,PCPU(NPXPROC) 1086 1087 ALIGN_TEXT 1088fastmove_tail: 1089 movl PCPU(CURPCB),%eax 1090 movl $fastmove_tail_fault,PCB_ONFAULT(%eax) 1091 1092 movb %cl,%al 1093 shrl $2,%ecx /* copy longword-wise */ 1094 cld 1095 rep 1096 movsl 1097 movb %al,%cl 1098 andb $3,%cl /* copy remaining bytes */ 1099 rep 1100 movsb 1101 1102 movl %ebp,%esp 1103 popl %ebp 1104 ret 1105 1106 ALIGN_TEXT 1107fastmove_fault: 1108 movl PCPU(CURPCB),%edi 1109 addl $PCB_SAVEFPU,%edi 1110 movl %esp,%esi 1111 cld 1112 movl $PCB_SAVEFPU_SIZE>>2,%ecx 1113 rep 1114 movsl 1115 1116 smsw %ax 1117 orb $CR0_TS,%al 1118 lmsw %ax 1119 movl $0,PCPU(NPXPROC) 1120 1121fastmove_tail_fault: 1122 movl %ebp,%esp 1123 popl %ebp 1124 addl $8,%esp 1125 popl %ebx 1126 popl %edi 1127 popl %esi 1128 movl PCPU(CURPCB),%edx 1129 movl $0,PCB_ONFAULT(%edx) 1130 movl $EFAULT,%eax 1131 ret 1132#endif /* I586_CPU && NNPX > 0 */ 1133 1134/* 1135 * fu{byte,sword,word} - MP SAFE 1136 * 1137 * Fetch a byte (sword, word) from user memory 1138 */ 1139ENTRY(fuword) 1140 movl PCPU(CURPCB),%ecx 1141 movl $fusufault,PCB_ONFAULT(%ecx) 1142 movl 4(%esp),%edx /* from */ 1143 1144 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 1145 ja fusufault 1146 1147 movl (%edx),%eax 1148 movl $0,PCB_ONFAULT(%ecx) 1149 ret 1150 1151/* 1152 * These two routines are called from the profiling code, potentially 1153 * at interrupt time. If they fail, that's okay, good things will 1154 * happen later. Fail all the time for now - until the trap code is 1155 * able to deal with this. 1156 */ 1157ALTENTRY(suswintr) 1158ENTRY(fuswintr) 1159 movl $-1,%eax 1160 ret 1161 1162/* 1163 * fusword - MP SAFE 1164 */ 1165ENTRY(fusword) 1166 movl PCPU(CURPCB),%ecx 1167 movl $fusufault,PCB_ONFAULT(%ecx) 1168 movl 4(%esp),%edx 1169 1170 cmpl $VM_MAXUSER_ADDRESS-2,%edx 1171 ja fusufault 1172 1173 movzwl (%edx),%eax 1174 movl $0,PCB_ONFAULT(%ecx) 1175 ret 1176 1177/* 1178 * fubyte - MP SAFE 1179 */ 1180ENTRY(fubyte) 1181 movl PCPU(CURPCB),%ecx 1182 movl $fusufault,PCB_ONFAULT(%ecx) 1183 movl 4(%esp),%edx 1184 1185 cmpl $VM_MAXUSER_ADDRESS-1,%edx 1186 ja fusufault 1187 1188 movzbl (%edx),%eax 1189 movl $0,PCB_ONFAULT(%ecx) 1190 ret 1191 1192 ALIGN_TEXT 1193fusufault: 1194 movl PCPU(CURPCB),%ecx 1195 xorl %eax,%eax 1196 movl %eax,PCB_ONFAULT(%ecx) 1197 decl %eax 1198 ret 1199 1200/* 1201 * su{byte,sword,word} - MP SAFE (if not I386_CPU) 1202 * 1203 * Write a byte (word, longword) to user memory 1204 */ 1205ENTRY(suword) 1206 movl PCPU(CURPCB),%ecx 1207 movl $fusufault,PCB_ONFAULT(%ecx) 1208 movl 4(%esp),%edx 1209 1210#if defined(I386_CPU) 1211 1212#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 1213 cmpl $CPUCLASS_386,_cpu_class 1214 jne 2f /* we only have to set the right segment selector */ 1215#endif /* I486_CPU || I586_CPU || I686_CPU */ 1216 1217 /* XXX - page boundary crossing is still not handled */ 1218 movl %edx,%eax 1219 shrl $IDXSHIFT,%edx 1220 andb $0xfc,%dl 1221 1222 leal _PTmap(%edx),%ecx 1223 shrl $IDXSHIFT,%ecx 1224 andb $0xfc,%cl 1225 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */ 1226 je 4f 1227 movb _PTmap(%edx),%dl 1228 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */ 1229 cmpb $PG_V|PG_RW|PG_U,%dl 1230 je 1f 1231 12324: 1233 /* simulate a trap */ 1234 pushl %eax 1235 call _trapwrite 1236 popl %edx /* remove junk parameter from stack */ 1237 testl %eax,%eax 1238 jnz fusufault 12391: 1240 movl 4(%esp),%edx 1241#endif 1242 12432: 1244 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 1245 ja fusufault 1246 1247 movl 8(%esp),%eax 1248 movl %eax,(%edx) 1249 xorl %eax,%eax 1250 movl PCPU(CURPCB),%ecx 1251 movl %eax,PCB_ONFAULT(%ecx) 1252 ret 1253 1254/* 1255 * susword - MP SAFE (if not I386_CPU) 1256 */ 1257ENTRY(susword) 1258 movl PCPU(CURPCB),%ecx 1259 movl $fusufault,PCB_ONFAULT(%ecx) 1260 movl 4(%esp),%edx 1261 1262#if defined(I386_CPU) 1263 1264#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 1265 cmpl $CPUCLASS_386,_cpu_class 1266 jne 2f 1267#endif /* I486_CPU || I586_CPU || I686_CPU */ 1268 1269 /* XXX - page boundary crossing is still not handled */ 1270 movl %edx,%eax 1271 shrl $IDXSHIFT,%edx 1272 andb $0xfc,%dl 1273 1274 leal _PTmap(%edx),%ecx 1275 shrl $IDXSHIFT,%ecx 1276 andb $0xfc,%cl 1277 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */ 1278 je 4f 1279 movb _PTmap(%edx),%dl 1280 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */ 1281 cmpb $PG_V|PG_RW|PG_U,%dl 1282 je 1f 1283 12844: 1285 /* simulate a trap */ 1286 pushl %eax 1287 call _trapwrite 1288 popl %edx /* remove junk parameter from stack */ 1289 testl %eax,%eax 1290 jnz fusufault 12911: 1292 movl 4(%esp),%edx 1293#endif 1294 12952: 1296 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 1297 ja fusufault 1298 1299 movw 8(%esp),%ax 1300 movw %ax,(%edx) 1301 xorl %eax,%eax 1302 movl PCPU(CURPCB),%ecx /* restore trashed register */ 1303 movl %eax,PCB_ONFAULT(%ecx) 1304 ret 1305 1306/* 1307 * su[i]byte - MP SAFE (if not I386_CPU) 1308 */ 1309ALTENTRY(suibyte) 1310ENTRY(subyte) 1311 movl PCPU(CURPCB),%ecx 1312 movl $fusufault,PCB_ONFAULT(%ecx) 1313 movl 4(%esp),%edx 1314 1315#if defined(I386_CPU) 1316 1317#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 1318 cmpl $CPUCLASS_386,_cpu_class 1319 jne 2f 1320#endif /* I486_CPU || I586_CPU || I686_CPU */ 1321 1322 movl %edx,%eax 1323 shrl $IDXSHIFT,%edx 1324 andb $0xfc,%dl 1325 1326 leal _PTmap(%edx),%ecx 1327 shrl $IDXSHIFT,%ecx 1328 andb $0xfc,%cl 1329 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */ 1330 je 4f 1331 movb _PTmap(%edx),%dl 1332 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */ 1333 cmpb $PG_V|PG_RW|PG_U,%dl 1334 je 1f 1335 13364: 1337 /* simulate a trap */ 1338 pushl %eax 1339 call _trapwrite 1340 popl %edx /* remove junk parameter from stack */ 1341 testl %eax,%eax 1342 jnz fusufault 13431: 1344 movl 4(%esp),%edx 1345#endif 1346 13472: 1348 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 1349 ja fusufault 1350 1351 movb 8(%esp),%al 1352 movb %al,(%edx) 1353 xorl %eax,%eax 1354 movl PCPU(CURPCB),%ecx /* restore trashed register */ 1355 movl %eax,PCB_ONFAULT(%ecx) 1356 ret 1357 1358/* 1359 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE 1360 * 1361 * copy a string from from to to, stop when a 0 character is reached. 1362 * return ENAMETOOLONG if string is longer than maxlen, and 1363 * EFAULT on protection violations. If lencopied is non-zero, 1364 * return the actual length in *lencopied. 1365 */ 1366ENTRY(copyinstr) 1367 pushl %esi 1368 pushl %edi 1369 movl PCPU(CURPCB),%ecx 1370 movl $cpystrflt,PCB_ONFAULT(%ecx) 1371 1372 movl 12(%esp),%esi /* %esi = from */ 1373 movl 16(%esp),%edi /* %edi = to */ 1374 movl 20(%esp),%edx /* %edx = maxlen */ 1375 1376 movl $VM_MAXUSER_ADDRESS,%eax 1377 1378 /* make sure 'from' is within bounds */ 1379 subl %esi,%eax 1380 jbe cpystrflt 1381 1382 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 1383 cmpl %edx,%eax 1384 jae 1f 1385 movl %eax,%edx 1386 movl %eax,20(%esp) 13871: 1388 incl %edx 1389 cld 1390 13912: 1392 decl %edx 1393 jz 3f 1394 1395 lodsb 1396 stosb 1397 orb %al,%al 1398 jnz 2b 1399 1400 /* Success -- 0 byte reached */ 1401 decl %edx 1402 xorl %eax,%eax 1403 jmp cpystrflt_x 14043: 1405 /* edx is zero - return ENAMETOOLONG or EFAULT */ 1406 cmpl $VM_MAXUSER_ADDRESS,%esi 1407 jae cpystrflt 14084: 1409 movl $ENAMETOOLONG,%eax 1410 jmp cpystrflt_x 1411 1412cpystrflt: 1413 movl $EFAULT,%eax 1414 1415cpystrflt_x: 1416 /* set *lencopied and return %eax */ 1417 movl PCPU(CURPCB),%ecx 1418 movl $0,PCB_ONFAULT(%ecx) 1419 movl 20(%esp),%ecx 1420 subl %edx,%ecx 1421 movl 24(%esp),%edx 1422 testl %edx,%edx 1423 jz 1f 1424 movl %ecx,(%edx) 14251: 1426 popl %edi 1427 popl %esi 1428 ret 1429 1430 1431/* 1432 * copystr(from, to, maxlen, int *lencopied) - MP SAFE 1433 */ 1434ENTRY(copystr) 1435 pushl %esi 1436 pushl %edi 1437 1438 movl 12(%esp),%esi /* %esi = from */ 1439 movl 16(%esp),%edi /* %edi = to */ 1440 movl 20(%esp),%edx /* %edx = maxlen */ 1441 incl %edx 1442 cld 14431: 1444 decl %edx 1445 jz 4f 1446 lodsb 1447 stosb 1448 orb %al,%al 1449 jnz 1b 1450 1451 /* Success -- 0 byte reached */ 1452 decl %edx 1453 xorl %eax,%eax 1454 jmp 6f 14554: 1456 /* edx is zero -- return ENAMETOOLONG */ 1457 movl $ENAMETOOLONG,%eax 1458 14596: 1460 /* set *lencopied and return %eax */ 1461 movl 20(%esp),%ecx 1462 subl %edx,%ecx 1463 movl 24(%esp),%edx 1464 testl %edx,%edx 1465 jz 7f 1466 movl %ecx,(%edx) 14677: 1468 popl %edi 1469 popl %esi 1470 ret 1471 1472ENTRY(bcmp) 1473 pushl %edi 1474 pushl %esi 1475 movl 12(%esp),%edi 1476 movl 16(%esp),%esi 1477 movl 20(%esp),%edx 1478 xorl %eax,%eax 1479 1480 movl %edx,%ecx 1481 shrl $2,%ecx 1482 cld /* compare forwards */ 1483 repe 1484 cmpsl 1485 jne 1f 1486 1487 movl %edx,%ecx 1488 andl $3,%ecx 1489 repe 1490 cmpsb 1491 je 2f 14921: 1493 incl %eax 14942: 1495 popl %esi 1496 popl %edi 1497 ret 1498 1499 1500/* 1501 * Handling of special 386 registers and descriptor tables etc 1502 */ 1503/* void lgdt(struct region_descriptor *rdp); */ 1504ENTRY(lgdt) 1505 /* reload the descriptor table */ 1506 movl 4(%esp),%eax 1507 lgdt (%eax) 1508 1509 /* flush the prefetch q */ 1510 jmp 1f 1511 nop 15121: 1513 /* reload "stale" selectors */ 1514 movl $KDSEL,%eax 1515 mov %ax,%ds 1516 mov %ax,%es 1517 mov %ax,%gs 1518 mov %ax,%ss 1519#ifdef SMP 1520 movl $KPSEL,%eax 1521#endif 1522 mov %ax,%fs 1523 1524 /* reload code selector by turning return into intersegmental return */ 1525 movl (%esp),%eax 1526 pushl %eax 1527 movl $KCSEL,4(%esp) 1528 lret 1529 1530/* 1531 * void lidt(struct region_descriptor *rdp); 1532 */ 1533ENTRY(lidt) 1534 movl 4(%esp),%eax 1535 lidt (%eax) 1536 ret 1537 1538/* 1539 * void lldt(u_short sel) 1540 */ 1541ENTRY(lldt) 1542 lldt 4(%esp) 1543 ret 1544 1545/* 1546 * void ltr(u_short sel) 1547 */ 1548ENTRY(ltr) 1549 ltr 4(%esp) 1550 ret 1551 1552/* ssdtosd(*ssdp,*sdp) */ 1553ENTRY(ssdtosd) 1554 pushl %ebx 1555 movl 8(%esp),%ecx 1556 movl 8(%ecx),%ebx 1557 shll $16,%ebx 1558 movl (%ecx),%edx 1559 roll $16,%edx 1560 movb %dh,%bl 1561 movb %dl,%bh 1562 rorl $8,%ebx 1563 movl 4(%ecx),%eax 1564 movw %ax,%dx 1565 andl $0xf0000,%eax 1566 orl %eax,%ebx 1567 movl 12(%esp),%ecx 1568 movl %edx,(%ecx) 1569 movl %ebx,4(%ecx) 1570 popl %ebx 1571 ret 1572 1573/* load_cr0(cr0) */ 1574ENTRY(load_cr0) 1575 movl 4(%esp),%eax 1576 movl %eax,%cr0 1577 ret 1578 1579/* rcr0() */ 1580ENTRY(rcr0) 1581 movl %cr0,%eax 1582 ret 1583 1584/* rcr3() */ 1585ENTRY(rcr3) 1586 movl %cr3,%eax 1587 ret 1588 1589/* void load_cr3(caddr_t cr3) */ 1590ENTRY(load_cr3) 1591#if defined(SWTCH_OPTIM_STATS) 1592 incl _tlb_flush_count 1593#endif 1594 movl 4(%esp),%eax 1595 movl %eax,%cr3 1596 ret 1597 1598/* rcr4() */ 1599ENTRY(rcr4) 1600 movl %cr4,%eax 1601 ret 1602 1603/* void load_cr4(caddr_t cr4) */ 1604ENTRY(load_cr4) 1605 movl 4(%esp),%eax 1606 movl %eax,%cr4 1607 ret 1608 1609/* void load_dr6(u_int dr6) */ 1610ENTRY(load_dr6) 1611 movl 4(%esp),%eax 1612 movl %eax,%dr6 1613 ret 1614 1615/* void reset_dbregs() */ 1616ENTRY(reset_dbregs) 1617 movl $0,%eax 1618 movl %eax,%dr7 /* disable all breapoints first */ 1619 movl %eax,%dr0 1620 movl %eax,%dr1 1621 movl %eax,%dr2 1622 movl %eax,%dr3 1623 movl %eax,%dr6 1624 ret 1625 1626/*****************************************************************************/ 1627/* setjump, longjump */ 1628/*****************************************************************************/ 1629 1630ENTRY(setjmp) 1631 movl 4(%esp),%eax 1632 movl %ebx,(%eax) /* save ebx */ 1633 movl %esp,4(%eax) /* save esp */ 1634 movl %ebp,8(%eax) /* save ebp */ 1635 movl %esi,12(%eax) /* save esi */ 1636 movl %edi,16(%eax) /* save edi */ 1637 movl (%esp),%edx /* get rta */ 1638 movl %edx,20(%eax) /* save eip */ 1639 xorl %eax,%eax /* return(0); */ 1640 ret 1641 1642ENTRY(longjmp) 1643 movl 4(%esp),%eax 1644 movl (%eax),%ebx /* restore ebx */ 1645 movl 4(%eax),%esp /* restore esp */ 1646 movl 8(%eax),%ebp /* restore ebp */ 1647 movl 12(%eax),%esi /* restore esi */ 1648 movl 16(%eax),%edi /* restore edi */ 1649 movl 20(%eax),%edx /* get rta */ 1650 movl %edx,(%esp) /* put in return frame */ 1651 xorl %eax,%eax /* return(1); */ 1652 incl %eax 1653 ret 1654 1655/* 1656 * Support for BB-profiling (gcc -a). The kernbb program will extract 1657 * the data from the kernel. 1658 */ 1659 1660 .data 1661 ALIGN_DATA 1662 .globl bbhead 1663bbhead: 1664 .long 0 1665 1666 .text 1667NON_GPROF_ENTRY(__bb_init_func) 1668 movl 4(%esp),%eax 1669 movl $1,(%eax) 1670 movl bbhead,%edx 1671 movl %edx,16(%eax) 1672 movl %eax,bbhead 1673 NON_GPROF_RET 1674