support.s revision 18207
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 * $Id: support.s,v 1.37 1996/06/13 07:17:20 asami Exp $ 34 */ 35 36#include <sys/errno.h> 37 38#include <machine/asmacros.h> 39#include <machine/cputypes.h> 40#include <machine/specialreg.h> 41 42#include "assym.s" 43 44#define KDSEL 0x10 /* kernel data selector */ 45#define IDXSHIFT 10 46 47 48 .data 49 .globl _bzero 50_bzero: .long _generic_bzero 51 52 .text 53 54/* 55 * bcopy family 56 * void bzero(void *base, u_int cnt) 57 */ 58 59ENTRY(generic_bzero) 60 pushl %edi 61 movl 8(%esp),%edi 62 movl 12(%esp),%ecx 63 xorl %eax,%eax 64 shrl $2,%ecx 65 cld 66 rep 67 stosl 68 movl 12(%esp),%ecx 69 andl $3,%ecx 70 rep 71 stosb 72 popl %edi 73 ret 74 75#if defined(I486_CPU) 76ENTRY(i486_bzero) 77 movl 4(%esp),%edx 78 movl 8(%esp),%ecx 79 xorl %eax,%eax 80/* 81 * do 64 byte chunks first 82 * 83 * XXX this is probably over-unrolled at least for DX2's 84 */ 852: 86 cmpl $64,%ecx 87 jb 3f 88 movl %eax,(%edx) 89 movl %eax,4(%edx) 90 movl %eax,8(%edx) 91 movl %eax,12(%edx) 92 movl %eax,16(%edx) 93 movl %eax,20(%edx) 94 movl %eax,24(%edx) 95 movl %eax,28(%edx) 96 movl %eax,32(%edx) 97 movl %eax,36(%edx) 98 movl %eax,40(%edx) 99 movl %eax,44(%edx) 100 movl %eax,48(%edx) 101 movl %eax,52(%edx) 102 movl %eax,56(%edx) 103 movl %eax,60(%edx) 104 addl $64,%edx 105 subl $64,%ecx 106 jnz 2b 107 ret 108 109/* 110 * do 16 byte chunks 111 */ 112 SUPERALIGN_TEXT 1133: 114 cmpl $16,%ecx 115 jb 4f 116 movl %eax,(%edx) 117 movl %eax,4(%edx) 118 movl %eax,8(%edx) 119 movl %eax,12(%edx) 120 addl $16,%edx 121 subl $16,%ecx 122 jnz 3b 123 ret 124 125/* 126 * do 4 byte chunks 127 */ 128 SUPERALIGN_TEXT 1294: 130 cmpl $4,%ecx 131 jb 5f 132 movl %eax,(%edx) 133 addl $4,%edx 134 subl $4,%ecx 135 jnz 4b 136 ret 137 138/* 139 * do 1 byte chunks 140 * a jump table seems to be faster than a loop or more range reductions 141 * 142 * XXX need a const section for non-text 143 */ 144 SUPERALIGN_TEXT 145jtab: 146 .long do0 147 .long do1 148 .long do2 149 .long do3 150 151 SUPERALIGN_TEXT 1525: 153 jmp jtab(,%ecx,4) 154 155 SUPERALIGN_TEXT 156do3: 157 movw %ax,(%edx) 158 movb %al,2(%edx) 159 ret 160 161 SUPERALIGN_TEXT 162do2: 163 movw %ax,(%edx) 164 ret 165 166 SUPERALIGN_TEXT 167do1: 168 movb %al,(%edx) 169 170 SUPERALIGN_TEXT 171do0: 172 ret 173#endif 174 175#if 0 /* Actually lowers performance in real-world cases */ 176#if defined(I586_CPU) || defined(I686_CPU) 177ALTENTRY(i586_bzero) 178ENTRY(i686_bzero) 179 pushl %edi 180 movl 8(%esp),%edi /* destination pointer */ 181 movl 12(%esp),%edx /* size (in 8-bit words) */ 182 183 xorl %eax,%eax /* store data */ 184 cld 185 186/* If less than 100 bytes to write, skip tricky code. */ 187 cmpl $100,%edx 188 movl %edx,%ecx /* needed when branch is taken! */ 189 jl 2f 190 191/* First write 0-3 bytes to make the pointer 32-bit aligned. */ 192 movl %edi,%ecx /* Copy ptr to ecx... */ 193 negl %ecx /* ...and negate that and... */ 194 andl $3,%ecx /* ...mask to get byte count. */ 195 subl %ecx,%edx /* adjust global byte count */ 196 rep 197 stosb 198 199 subl $32,%edx /* offset count for unrolled loop */ 200 movl (%edi),%ecx /* Fetch destination cache line */ 201 202 .align 2,0x90 /* supply 0x90 for broken assemblers */ 2031: 204 movl 28(%edi),%ecx /* allocate cache line for destination */ 205 subl $32,%edx /* decr loop count */ 206 movl %eax,0(%edi) /* store words pairwise */ 207 movl %eax,4(%edi) 208 movl %eax,8(%edi) 209 movl %eax,12(%edi) 210 movl %eax,16(%edi) 211 movl %eax,20(%edi) 212 movl %eax,24(%edi) 213 movl %eax,28(%edi) 214 215 leal 32(%edi),%edi /* update destination pointer */ 216 jge 1b 217 leal 32(%edx),%ecx 218 219/* Write last 0-7 full 32-bit words (up to 8 words if loop was skipped). */ 2202: 221 shrl $2,%ecx 222 rep 223 stosl 224 225/* Finally write the last 0-3 bytes. */ 226 movl %edx,%ecx 227 andl $3,%ecx 228 rep 229 stosb 230 231 popl %edi 232 ret 233#endif 234#endif 235 236/* fillw(pat, base, cnt) */ 237ENTRY(fillw) 238 pushl %edi 239 movl 8(%esp),%eax 240 movl 12(%esp),%edi 241 movl 16(%esp),%ecx 242 cld 243 rep 244 stosw 245 popl %edi 246 ret 247 248ENTRY(bcopyb) 249bcopyb: 250 pushl %esi 251 pushl %edi 252 movl 12(%esp),%esi 253 movl 16(%esp),%edi 254 movl 20(%esp),%ecx 255 movl %edi,%eax 256 subl %esi,%eax 257 cmpl %ecx,%eax /* overlapping? */ 258 jb 1f 259 cld /* nope, copy forwards */ 260 rep 261 movsb 262 popl %edi 263 popl %esi 264 ret 265 266 ALIGN_TEXT 2671: 268 addl %ecx,%edi /* copy backwards. */ 269 addl %ecx,%esi 270 decl %edi 271 decl %esi 272 std 273 rep 274 movsb 275 popl %edi 276 popl %esi 277 cld 278 ret 279 280/* 281 * (ov)bcopy(src, dst, cnt) 282 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 283 */ 284ALTENTRY(ovbcopy) 285ENTRY(bcopy) 286bcopy: 287 pushl %esi 288 pushl %edi 289 movl 12(%esp),%esi 290 movl 16(%esp),%edi 291 movl 20(%esp),%ecx 292 293 movl %edi,%eax 294 subl %esi,%eax 295 cmpl %ecx,%eax /* overlapping? */ 296 jb 1f 297 shrl $2,%ecx /* copy by 32-bit words */ 298 cld /* nope, copy forwards */ 299 rep 300 movsl 301 movl 20(%esp),%ecx 302 andl $3,%ecx /* any bytes left? */ 303 rep 304 movsb 305 popl %edi 306 popl %esi 307 ret 308 309 ALIGN_TEXT 3101: 311 addl %ecx,%edi /* copy backwards */ 312 addl %ecx,%esi 313 decl %edi 314 decl %esi 315 andl $3,%ecx /* any fractional bytes? */ 316 std 317 rep 318 movsb 319 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 320 shrl $2,%ecx 321 subl $3,%esi 322 subl $3,%edi 323 rep 324 movsl 325 popl %edi 326 popl %esi 327 cld 328 ret 329 330 331/* 332 * Note: memcpy does not support overlapping copies 333 */ 334ENTRY(memcpy) 335 pushl %edi 336 pushl %esi 337 movl 12(%esp),%edi 338 movl 16(%esp),%esi 339 movl 20(%esp),%ecx 340 movl %edi,%eax 341 shrl $2,%ecx /* copy by 32-bit words */ 342 cld /* nope, copy forwards */ 343 rep 344 movsl 345 movl 20(%esp),%ecx 346 andl $3,%ecx /* any bytes left? */ 347 rep 348 movsb 349 popl %esi 350 popl %edi 351 ret 352 353 354/*****************************************************************************/ 355/* copyout and fubyte family */ 356/*****************************************************************************/ 357/* 358 * Access user memory from inside the kernel. These routines and possibly 359 * the math- and DOS emulators should be the only places that do this. 360 * 361 * We have to access the memory with user's permissions, so use a segment 362 * selector with RPL 3. For writes to user space we have to additionally 363 * check the PTE for write permission, because the 386 does not check 364 * write permissions when we are executing with EPL 0. The 486 does check 365 * this if the WP bit is set in CR0, so we can use a simpler version here. 366 * 367 * These routines set curpcb->onfault for the time they execute. When a 368 * protection violation occurs inside the functions, the trap handler 369 * returns to *curpcb->onfault instead of the function. 370 */ 371 372 373ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 374 movl _curpcb,%eax 375 movl $copyout_fault,PCB_ONFAULT(%eax) 376 pushl %esi 377 pushl %edi 378 pushl %ebx 379 movl 16(%esp),%esi 380 movl 20(%esp),%edi 381 movl 24(%esp),%ebx 382 testl %ebx,%ebx /* anything to do? */ 383 jz done_copyout 384 385 /* 386 * Check explicitly for non-user addresses. If 486 write protection 387 * is being used, this check is essential because we are in kernel 388 * mode so the h/w does not provide any protection against writing 389 * kernel addresses. 390 */ 391 392 /* 393 * First, prevent address wrapping. 394 */ 395 movl %edi,%eax 396 addl %ebx,%eax 397 jc copyout_fault 398/* 399 * XXX STOP USING VM_MAXUSER_ADDRESS. 400 * It is an end address, not a max, so every time it is used correctly it 401 * looks like there is an off by one error, and of course it caused an off 402 * by one error in several places. 403 */ 404 cmpl $VM_MAXUSER_ADDRESS,%eax 405 ja copyout_fault 406 407#if defined(I386_CPU) 408 409#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 410 cmpl $CPUCLASS_386,_cpu_class 411 jne 3f 412#endif 413/* 414 * We have to check each PTE for user write permission. 415 * The checking may cause a page fault, so it is important to set 416 * up everything for return via copyout_fault before here. 417 */ 418 /* compute number of pages */ 419 movl %edi,%ecx 420 andl $PAGE_MASK,%ecx 421 addl %ebx,%ecx 422 decl %ecx 423 shrl $IDXSHIFT+2,%ecx 424 incl %ecx 425 426 /* compute PTE offset for start address */ 427 movl %edi,%edx 428 shrl $IDXSHIFT,%edx 429 andb $0xfc,%dl 430 4311: /* check PTE for each page */ 432 movb _PTmap(%edx),%al 433 andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 434 cmpb $0x07,%al 435 je 2f 436 437 /* simulate a trap */ 438 pushl %edx 439 pushl %ecx 440 shll $IDXSHIFT,%edx 441 pushl %edx 442 call _trapwrite /* trapwrite(addr) */ 443 popl %edx 444 popl %ecx 445 popl %edx 446 447 testl %eax,%eax /* if not ok, return EFAULT */ 448 jnz copyout_fault 449 4502: 451 addl $4,%edx 452 decl %ecx 453 jnz 1b /* check next page */ 454#endif /* I386_CPU */ 455 456 /* bcopy(%esi, %edi, %ebx) */ 4573: 458 movl %ebx,%ecx 459#if defined(I586_CPU) && defined(I586_FAST_BCOPY) 460 cmpl $1024,%ecx 461 jbe slow_copyout 462 463#if defined(I386_CPU) || defined(I486_CPU) || defined(I686_CPU) 464 cmpl $CPUCLASS_586,_cpu_class 465 jne slow_copyout 466#endif /* I386_CPU || I486_CPU || I686_CPU */ 467 468 call fastmove 469 jmp done_copyout 470 471 ALIGN_TEXT 472slow_copyout: 473#endif /* I586_CPU && I586_FAST_BCOPY */ 474 shrl $2,%ecx 475 cld 476 rep 477 movsl 478 movb %bl,%cl 479 andb $3,%cl 480 rep 481 movsb 482 483done_copyout: 484 popl %ebx 485 popl %edi 486 popl %esi 487 xorl %eax,%eax 488 movl _curpcb,%edx 489 movl %eax,PCB_ONFAULT(%edx) 490 ret 491 492 ALIGN_TEXT 493copyout_fault: 494 popl %ebx 495 popl %edi 496 popl %esi 497 movl _curpcb,%edx 498 movl $0,PCB_ONFAULT(%edx) 499 movl $EFAULT,%eax 500 ret 501 502/* copyin(from_user, to_kernel, len) */ 503ENTRY(copyin) 504 movl _curpcb,%eax 505 movl $copyin_fault,PCB_ONFAULT(%eax) 506 pushl %esi 507 pushl %edi 508 movl 12(%esp),%esi /* caddr_t from */ 509 movl 16(%esp),%edi /* caddr_t to */ 510 movl 20(%esp),%ecx /* size_t len */ 511 512 /* 513 * make sure address is valid 514 */ 515 movl %esi,%edx 516 addl %ecx,%edx 517 jc copyin_fault 518 cmpl $VM_MAXUSER_ADDRESS,%edx 519 ja copyin_fault 520 521#if defined(I586_CPU) && defined(I586_FAST_BCOPY) 522 cmpl $1024,%ecx 523 jbe slow_copyin 524 525#if defined(I386_CPU) || defined(I486_CPU) || defined(I686_CPU) 526 cmpl $CPUCLASS_586,_cpu_class 527 jne slow_copyin 528#endif /* I386_CPU || I486_CPU || I686_CPU */ 529 530 call fastmove 531 jmp done_copyin 532 533 ALIGN_TEXT 534slow_copyin: 535#endif /* I586_CPU && I586_FAST_BCOPY */ 536 movb %cl,%al 537 shrl $2,%ecx /* copy longword-wise */ 538 cld 539 rep 540 movsl 541 movb %al,%cl 542 andb $3,%cl /* copy remaining bytes */ 543 rep 544 movsb 545 546#if defined(I586_CPU) && defined(I586_FAST_BCOPY) 547 ALIGN_TEXT 548done_copyin: 549#endif /* I586_CPU && I586_FAST_BCOPY */ 550 popl %edi 551 popl %esi 552 xorl %eax,%eax 553 movl _curpcb,%edx 554 movl %eax,PCB_ONFAULT(%edx) 555 ret 556 557 ALIGN_TEXT 558copyin_fault: 559 popl %edi 560 popl %esi 561 movl _curpcb,%edx 562 movl $0,PCB_ONFAULT(%edx) 563 movl $EFAULT,%eax 564 ret 565 566#if defined(I586_CPU) && defined(I586_FAST_BCOPY) 567/* fastmove(src, dst, len) 568 src in %esi 569 dst in %edi 570 len in %ecx 571 uses %eax and %edx for tmp. storage 572 */ 573 ALIGN_TEXT 574fastmove: 575 cmpl $63,%ecx 576 jbe 8f 577 578 testl $7,%esi /* check if src addr is multiple of 8 */ 579 jnz 8f 580 581 testl $7,%edi /* check if dst addr is multiple of 8 */ 582 jnz 8f 583 584 pushl %ebp 585 movl %esp,%ebp 586 subl $PCB_SAVEFPU_SIZE,%esp 587 588/* if (npxproc != NULL) { */ 589 cmpl $0,_npxproc 590 je 6f 591/* fnsave(&curpcb->pcb_savefpu); */ 592 movl _curpcb,%eax 593 fnsave PCB_SAVEFPU(%eax) 594/* npxproc = NULL; */ 595 movl $0,_npxproc 596/* } */ 5976: 598/* now we own the FPU. */ 599 600/* 601 * The process' FP state is saved in the pcb, but if we get 602 * switched, the cpu_switch() will store our FP state in the 603 * pcb. It should be possible to avoid all the copying for 604 * this, e.g., by setting a flag to tell cpu_switch() to 605 * save the state somewhere else. 606 */ 607/* tmp = curpcb->pcb_savefpu; */ 608 pushl %edi 609 pushl %esi 610 pushl %ecx 611 leal -PCB_SAVEFPU_SIZE(%ebp),%edi 612 movl _curpcb,%esi 613 addl $PCB_SAVEFPU,%esi 614 cld 615 movl $PCB_SAVEFPU_SIZE>>2,%ecx 616 rep 617 movsl 618 popl %ecx 619 popl %esi 620 popl %edi 621/* stop_emulating(); */ 622 clts 623/* npxproc = curproc; */ 624 movl _curproc,%eax 625 movl %eax,_npxproc 6264: 627 pushl %ecx 628 cmpl $1792,%ecx 629 jbe 2f 630 movl $1792,%ecx 6312: 632 subl %ecx,0(%esp) 633 cmpl $256,%ecx 634 jb 5f 635 pushl %esi 636 pushl %ecx 637 ALIGN_TEXT 6383: 639 movl 0(%esi),%eax 640 movl 32(%esi),%eax 641 movl 64(%esi),%eax 642 movl 96(%esi),%eax 643 movl 128(%esi),%eax 644 movl 160(%esi),%eax 645 movl 192(%esi),%eax 646 movl 224(%esi),%eax 647 addl $256,%esi 648 subl $256,%ecx 649 cmpl $256,%ecx 650 jae 3b 651 popl %ecx 652 popl %esi 6535: 654 ALIGN_TEXT 6557: 656 fildq 0(%esi) 657 fildq 8(%esi) 658 fildq 16(%esi) 659 fildq 24(%esi) 660 fildq 32(%esi) 661 fildq 40(%esi) 662 fildq 48(%esi) 663 fildq 56(%esi) 664 fistpq 56(%edi) 665 fistpq 48(%edi) 666 fistpq 40(%edi) 667 fistpq 32(%edi) 668 fistpq 24(%edi) 669 fistpq 16(%edi) 670 fistpq 8(%edi) 671 fistpq 0(%edi) 672 addl $-64,%ecx 673 addl $64,%esi 674 addl $64,%edi 675 cmpl $63,%ecx 676 ja 7b 677 popl %eax 678 addl %eax,%ecx 679 cmpl $64,%ecx 680 jae 4b 681 682/* curpcb->pcb_savefpu = tmp; */ 683 pushl %edi 684 pushl %esi 685 pushl %ecx 686 movl _curpcb,%edi 687 addl $PCB_SAVEFPU,%edi 688 leal -PCB_SAVEFPU_SIZE(%ebp),%esi 689 cld 690 movl $PCB_SAVEFPU_SIZE>>2,%ecx 691 rep 692 movsl 693 popl %ecx 694 popl %esi 695 popl %edi 696 697/* start_emulating(); */ 698 smsw %ax 699 orb $CR0_TS,%al 700 lmsw %ax 701/* npxproc = NULL; */ 702 movl $0,_npxproc 703 movl %ebp,%esp 704 popl %ebp 705 706 ALIGN_TEXT 7078: 708 movb %cl,%al 709 shrl $2,%ecx /* copy longword-wise */ 710 cld 711 rep 712 movsl 713 movb %al,%cl 714 andb $3,%cl /* copy remaining bytes */ 715 rep 716 movsb 717 718 ret 719#endif /* I586_CPU && I586_FAST_BCOPY */ 720 721/* 722 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory 723 */ 724ENTRY(fuword) 725 movl _curpcb,%ecx 726 movl $fusufault,PCB_ONFAULT(%ecx) 727 movl 4(%esp),%edx /* from */ 728 729 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 730 ja fusufault 731 732 movl (%edx),%eax 733 movl $0,PCB_ONFAULT(%ecx) 734 ret 735 736/* 737 * These two routines are called from the profiling code, potentially 738 * at interrupt time. If they fail, that's okay, good things will 739 * happen later. Fail all the time for now - until the trap code is 740 * able to deal with this. 741 */ 742ALTENTRY(suswintr) 743ENTRY(fuswintr) 744 movl $-1,%eax 745 ret 746 747ENTRY(fusword) 748 movl _curpcb,%ecx 749 movl $fusufault,PCB_ONFAULT(%ecx) 750 movl 4(%esp),%edx 751 752 cmpl $VM_MAXUSER_ADDRESS-2,%edx 753 ja fusufault 754 755 movzwl (%edx),%eax 756 movl $0,PCB_ONFAULT(%ecx) 757 ret 758 759ENTRY(fubyte) 760 movl _curpcb,%ecx 761 movl $fusufault,PCB_ONFAULT(%ecx) 762 movl 4(%esp),%edx 763 764 cmpl $VM_MAXUSER_ADDRESS-1,%edx 765 ja fusufault 766 767 movzbl (%edx),%eax 768 movl $0,PCB_ONFAULT(%ecx) 769 ret 770 771 ALIGN_TEXT 772fusufault: 773 movl _curpcb,%ecx 774 xorl %eax,%eax 775 movl %eax,PCB_ONFAULT(%ecx) 776 decl %eax 777 ret 778 779/* 780 * su{byte,sword,word}: write a byte (word, longword) to user memory 781 */ 782ENTRY(suword) 783 movl _curpcb,%ecx 784 movl $fusufault,PCB_ONFAULT(%ecx) 785 movl 4(%esp),%edx 786 787#if defined(I386_CPU) 788 789#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 790 cmpl $CPUCLASS_386,_cpu_class 791 jne 2f /* we only have to set the right segment selector */ 792#endif /* I486_CPU || I586_CPU || I686_CPU */ 793 794 /* XXX - page boundary crossing is still not handled */ 795 movl %edx,%eax 796 shrl $IDXSHIFT,%edx 797 andb $0xfc,%dl 798 movb _PTmap(%edx),%dl 799 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 800 cmpb $0x7,%dl 801 je 1f 802 803 /* simulate a trap */ 804 pushl %eax 805 call _trapwrite 806 popl %edx /* remove junk parameter from stack */ 807 movl _curpcb,%ecx /* restore trashed register */ 808 testl %eax,%eax 809 jnz fusufault 8101: 811 movl 4(%esp),%edx 812#endif 813 8142: 815 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 816 ja fusufault 817 818 movl 8(%esp),%eax 819 movl %eax,(%edx) 820 xorl %eax,%eax 821 movl %eax,PCB_ONFAULT(%ecx) 822 ret 823 824ENTRY(susword) 825 movl _curpcb,%ecx 826 movl $fusufault,PCB_ONFAULT(%ecx) 827 movl 4(%esp),%edx 828 829#if defined(I386_CPU) 830 831#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 832 cmpl $CPUCLASS_386,_cpu_class 833 jne 2f 834#endif /* I486_CPU || I586_CPU || I686_CPU */ 835 836 /* XXX - page boundary crossing is still not handled */ 837 movl %edx,%eax 838 shrl $IDXSHIFT,%edx 839 andb $0xfc,%dl 840 movb _PTmap(%edx),%dl 841 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 842 cmpb $0x7,%dl 843 je 1f 844 845 /* simulate a trap */ 846 pushl %eax 847 call _trapwrite 848 popl %edx /* remove junk parameter from stack */ 849 movl _curpcb,%ecx /* restore trashed register */ 850 testl %eax,%eax 851 jnz fusufault 8521: 853 movl 4(%esp),%edx 854#endif 855 8562: 857 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 858 ja fusufault 859 860 movw 8(%esp),%ax 861 movw %ax,(%edx) 862 xorl %eax,%eax 863 movl %eax,PCB_ONFAULT(%ecx) 864 ret 865 866ALTENTRY(suibyte) 867ENTRY(subyte) 868 movl _curpcb,%ecx 869 movl $fusufault,PCB_ONFAULT(%ecx) 870 movl 4(%esp),%edx 871 872#if defined(I386_CPU) 873 874#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 875 cmpl $CPUCLASS_386,_cpu_class 876 jne 2f 877#endif /* I486_CPU || I586_CPU || I686_CPU */ 878 879 movl %edx,%eax 880 shrl $IDXSHIFT,%edx 881 andb $0xfc,%dl 882 movb _PTmap(%edx),%dl 883 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 884 cmpb $0x7,%dl 885 je 1f 886 887 /* simulate a trap */ 888 pushl %eax 889 call _trapwrite 890 popl %edx /* remove junk parameter from stack */ 891 movl _curpcb,%ecx /* restore trashed register */ 892 testl %eax,%eax 893 jnz fusufault 8941: 895 movl 4(%esp),%edx 896#endif 897 8982: 899 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 900 ja fusufault 901 902 movb 8(%esp),%al 903 movb %al,(%edx) 904 xorl %eax,%eax 905 movl %eax,PCB_ONFAULT(%ecx) 906 ret 907 908/* 909 * copyinstr(from, to, maxlen, int *lencopied) 910 * copy a string from from to to, stop when a 0 character is reached. 911 * return ENAMETOOLONG if string is longer than maxlen, and 912 * EFAULT on protection violations. If lencopied is non-zero, 913 * return the actual length in *lencopied. 914 */ 915ENTRY(copyinstr) 916 pushl %esi 917 pushl %edi 918 movl _curpcb,%ecx 919 movl $cpystrflt,PCB_ONFAULT(%ecx) 920 921 movl 12(%esp),%esi /* %esi = from */ 922 movl 16(%esp),%edi /* %edi = to */ 923 movl 20(%esp),%edx /* %edx = maxlen */ 924 925 movl $VM_MAXUSER_ADDRESS,%eax 926 927 /* make sure 'from' is within bounds */ 928 subl %esi,%eax 929 jbe cpystrflt 930 931 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 932 cmpl %edx,%eax 933 jae 1f 934 movl %eax,%edx 935 movl %eax,20(%esp) 9361: 937 incl %edx 938 cld 939 9402: 941 decl %edx 942 jz 3f 943 944 lodsb 945 stosb 946 orb %al,%al 947 jnz 2b 948 949 /* Success -- 0 byte reached */ 950 decl %edx 951 xorl %eax,%eax 952 jmp cpystrflt_x 9533: 954 /* edx is zero - return ENAMETOOLONG or EFAULT */ 955 cmpl $VM_MAXUSER_ADDRESS,%esi 956 jae cpystrflt 9574: 958 movl $ENAMETOOLONG,%eax 959 jmp cpystrflt_x 960 961cpystrflt: 962 movl $EFAULT,%eax 963 964cpystrflt_x: 965 /* set *lencopied and return %eax */ 966 movl _curpcb,%ecx 967 movl $0,PCB_ONFAULT(%ecx) 968 movl 20(%esp),%ecx 969 subl %edx,%ecx 970 movl 24(%esp),%edx 971 testl %edx,%edx 972 jz 1f 973 movl %ecx,(%edx) 9741: 975 popl %edi 976 popl %esi 977 ret 978 979 980/* 981 * copystr(from, to, maxlen, int *lencopied) 982 */ 983ENTRY(copystr) 984 pushl %esi 985 pushl %edi 986 987 movl 12(%esp),%esi /* %esi = from */ 988 movl 16(%esp),%edi /* %edi = to */ 989 movl 20(%esp),%edx /* %edx = maxlen */ 990 incl %edx 991 cld 9921: 993 decl %edx 994 jz 4f 995 lodsb 996 stosb 997 orb %al,%al 998 jnz 1b 999 1000 /* Success -- 0 byte reached */ 1001 decl %edx 1002 xorl %eax,%eax 1003 jmp 6f 10044: 1005 /* edx is zero -- return ENAMETOOLONG */ 1006 movl $ENAMETOOLONG,%eax 1007 10086: 1009 /* set *lencopied and return %eax */ 1010 movl 20(%esp),%ecx 1011 subl %edx,%ecx 1012 movl 24(%esp),%edx 1013 testl %edx,%edx 1014 jz 7f 1015 movl %ecx,(%edx) 10167: 1017 popl %edi 1018 popl %esi 1019 ret 1020 1021ENTRY(bcmp) 1022 pushl %edi 1023 pushl %esi 1024 movl 12(%esp),%edi 1025 movl 16(%esp),%esi 1026 movl 20(%esp),%edx 1027 xorl %eax,%eax 1028 1029 movl %edx,%ecx 1030 shrl $2,%ecx 1031 cld /* compare forwards */ 1032 repe 1033 cmpsl 1034 jne 1f 1035 1036 movl %edx,%ecx 1037 andl $3,%ecx 1038 repe 1039 cmpsb 1040 je 2f 10411: 1042 incl %eax 10432: 1044 popl %esi 1045 popl %edi 1046 ret 1047 1048 1049/* 1050 * Handling of special 386 registers and descriptor tables etc 1051 */ 1052/* void lgdt(struct region_descriptor *rdp); */ 1053ENTRY(lgdt) 1054 /* reload the descriptor table */ 1055 movl 4(%esp),%eax 1056 lgdt (%eax) 1057 1058 /* flush the prefetch q */ 1059 jmp 1f 1060 nop 10611: 1062 /* reload "stale" selectors */ 1063 movl $KDSEL,%eax 1064 movl %ax,%ds 1065 movl %ax,%es 1066 movl %ax,%ss 1067 1068 /* reload code selector by turning return into intersegmental return */ 1069 movl (%esp),%eax 1070 pushl %eax 1071# movl $KCSEL,4(%esp) 1072 movl $8,4(%esp) 1073 lret 1074 1075/* 1076 * void lidt(struct region_descriptor *rdp); 1077 */ 1078ENTRY(lidt) 1079 movl 4(%esp),%eax 1080 lidt (%eax) 1081 ret 1082 1083/* 1084 * void lldt(u_short sel) 1085 */ 1086ENTRY(lldt) 1087 lldt 4(%esp) 1088 ret 1089 1090/* 1091 * void ltr(u_short sel) 1092 */ 1093ENTRY(ltr) 1094 ltr 4(%esp) 1095 ret 1096 1097/* ssdtosd(*ssdp,*sdp) */ 1098ENTRY(ssdtosd) 1099 pushl %ebx 1100 movl 8(%esp),%ecx 1101 movl 8(%ecx),%ebx 1102 shll $16,%ebx 1103 movl (%ecx),%edx 1104 roll $16,%edx 1105 movb %dh,%bl 1106 movb %dl,%bh 1107 rorl $8,%ebx 1108 movl 4(%ecx),%eax 1109 movw %ax,%dx 1110 andl $0xf0000,%eax 1111 orl %eax,%ebx 1112 movl 12(%esp),%ecx 1113 movl %edx,(%ecx) 1114 movl %ebx,4(%ecx) 1115 popl %ebx 1116 ret 1117 1118/* load_cr0(cr0) */ 1119ENTRY(load_cr0) 1120 movl 4(%esp),%eax 1121 movl %eax,%cr0 1122 ret 1123 1124/* rcr0() */ 1125ENTRY(rcr0) 1126 movl %cr0,%eax 1127 ret 1128 1129/* rcr3() */ 1130ENTRY(rcr3) 1131 movl %cr3,%eax 1132 ret 1133 1134/* void load_cr3(caddr_t cr3) */ 1135ENTRY(load_cr3) 1136 movl 4(%esp),%eax 1137 movl %eax,%cr3 1138 ret 1139 1140 1141/*****************************************************************************/ 1142/* setjump, longjump */ 1143/*****************************************************************************/ 1144 1145ENTRY(setjmp) 1146 movl 4(%esp),%eax 1147 movl %ebx,(%eax) /* save ebx */ 1148 movl %esp,4(%eax) /* save esp */ 1149 movl %ebp,8(%eax) /* save ebp */ 1150 movl %esi,12(%eax) /* save esi */ 1151 movl %edi,16(%eax) /* save edi */ 1152 movl (%esp),%edx /* get rta */ 1153 movl %edx,20(%eax) /* save eip */ 1154 xorl %eax,%eax /* return(0); */ 1155 ret 1156 1157ENTRY(longjmp) 1158 movl 4(%esp),%eax 1159 movl (%eax),%ebx /* restore ebx */ 1160 movl 4(%eax),%esp /* restore esp */ 1161 movl 8(%eax),%ebp /* restore ebp */ 1162 movl 12(%eax),%esi /* restore esi */ 1163 movl 16(%eax),%edi /* restore edi */ 1164 movl 20(%eax),%edx /* get rta */ 1165 movl %edx,(%esp) /* put in return frame */ 1166 xorl %eax,%eax /* return(1); */ 1167 incl %eax 1168 ret 1169 1170/* 1171 * Here for doing BB-profiling (gcc -a). 1172 * We rely on the "bbset" instead, but need a dummy function. 1173 */ 1174 .text 1175 .align 2 1176.globl ___bb_init_func 1177___bb_init_func: 1178 movl 4(%esp),%eax 1179 movl $1,(%eax) 1180 ret 1181