support.s revision 6995
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.20 1995/02/12 09:13:27 davidg Exp $ 34 */ 35 36#include "assym.s" /* system definitions */ 37#include "errno.h" /* error return codes */ 38#include "machine/asmacros.h" /* miscellaneous asm macros */ 39#include "machine/cputypes.h" /* types of CPUs */ 40 41#define KDSEL 0x10 /* kernel data selector */ 42#define IDXSHIFT 10 43 44/* 45 * Support routines for GCC, general C-callable functions 46 */ 47ENTRY(__udivsi3) 48 movl 4(%esp),%eax 49 xorl %edx,%edx 50 divl 8(%esp) 51 ret 52 53ENTRY(__divsi3) 54 movl 4(%esp),%eax 55 cltd 56 idivl 8(%esp) 57 ret 58 59/* 60 * Support for reading real time clock registers 61 */ 62ENTRY(rtcin) /* rtcin(val) */ 63 movl 4(%esp),%eax 64 outb %al,$0x70 65 NOP 66 xorl %eax,%eax 67 inb $0x71,%al 68 NOP 69 ret 70 71/* 72 * bcopy family 73 */ 74 75/* 76 * void bzero(void *base, u_int cnt) 77 * Special code for I486 because stosl uses lots 78 * of clocks. Makes little or no difference on DX2 type 79 * machines, but stosl is about 1/2 as fast as 80 * memory moves on a standard DX !!!!! 81 */ 82ALTENTRY(blkclr) 83ENTRY(bzero) 84#if defined(I486_CPU) 85 cmpl $CPUCLASS_486,_cpu_class 86 jz 1f 87#endif 88 89 pushl %edi 90 movl 8(%esp),%edi 91 movl 12(%esp),%ecx 92 xorl %eax,%eax 93 shrl $2,%ecx 94 cld 95 rep 96 stosl 97 movl 12(%esp),%ecx 98 andl $3,%ecx 99 rep 100 stosb 101 popl %edi 102 ret 103 104#if defined(I486_CPU) 105 SUPERALIGN_TEXT 1061: 107 movl 4(%esp),%edx 108 movl 8(%esp),%ecx 109 xorl %eax,%eax 110/ 111/ do 64 byte chunks first 112/ 113/ XXX this is probably over-unrolled at least for DX2's 114/ 1152: 116 cmpl $64,%ecx 117 jb 3f 118 movl %eax,(%edx) 119 movl %eax,4(%edx) 120 movl %eax,8(%edx) 121 movl %eax,12(%edx) 122 movl %eax,16(%edx) 123 movl %eax,20(%edx) 124 movl %eax,24(%edx) 125 movl %eax,28(%edx) 126 movl %eax,32(%edx) 127 movl %eax,36(%edx) 128 movl %eax,40(%edx) 129 movl %eax,44(%edx) 130 movl %eax,48(%edx) 131 movl %eax,52(%edx) 132 movl %eax,56(%edx) 133 movl %eax,60(%edx) 134 addl $64,%edx 135 subl $64,%ecx 136 jnz 2b 137 ret 138 139/ 140/ do 16 byte chunks 141/ 142 SUPERALIGN_TEXT 1433: 144 cmpl $16,%ecx 145 jb 4f 146 movl %eax,(%edx) 147 movl %eax,4(%edx) 148 movl %eax,8(%edx) 149 movl %eax,12(%edx) 150 addl $16,%edx 151 subl $16,%ecx 152 jnz 3b 153 ret 154 155/ 156/ do 4 byte chunks 157/ 158 SUPERALIGN_TEXT 1594: 160 cmpl $4,%ecx 161 jb 5f 162 movl %eax,(%edx) 163 addl $4,%edx 164 subl $4,%ecx 165 jnz 4b 166 ret 167 168/ 169/ do 1 byte chunks 170/ a jump table seems to be faster than a loop or more range reductions 171/ 172/ XXX need a const section for non-text 173/ 174 SUPERALIGN_TEXT 175jtab: 176 .long do0 177 .long do1 178 .long do2 179 .long do3 180 181 SUPERALIGN_TEXT 1825: 183 jmp jtab(,%ecx,4) 184 185 SUPERALIGN_TEXT 186do3: 187 movw %ax,(%edx) 188 movb %al,2(%edx) 189 ret 190 191 SUPERALIGN_TEXT 192do2: 193 movw %ax,(%edx) 194 ret 195 196 SUPERALIGN_TEXT 197do1: 198 movb %al,(%edx) 199 200 SUPERALIGN_TEXT 201do0: 202 ret 203#endif /* I486_CPU */ 204 205/* fillw(pat, base, cnt) */ 206ENTRY(fillw) 207 pushl %edi 208 movl 8(%esp),%eax 209 movl 12(%esp),%edi 210 movl 16(%esp),%ecx 211 cld 212 rep 213 stosw 214 popl %edi 215 ret 216 217/* filli(pat, base, cnt) */ 218ENTRY(filli) 219 pushl %edi 220 movl 8(%esp),%eax 221 movl 12(%esp),%edi 222 movl 16(%esp),%ecx 223 cld 224 rep 225 stosl 226 popl %edi 227 ret 228 229ENTRY(bcopyb) 230bcopyb: 231 pushl %esi 232 pushl %edi 233 movl 12(%esp),%esi 234 movl 16(%esp),%edi 235 movl 20(%esp),%ecx 236 cmpl %esi,%edi /* potentially overlapping? */ 237 jnb 1f 238 cld /* nope, copy forwards */ 239 rep 240 movsb 241 popl %edi 242 popl %esi 243 ret 244 245 ALIGN_TEXT 2461: 247 addl %ecx,%edi /* copy backwards. */ 248 addl %ecx,%esi 249 std 250 decl %edi 251 decl %esi 252 rep 253 movsb 254 popl %edi 255 popl %esi 256 cld 257 ret 258 259ENTRY(bcopyw) 260bcopyw: 261 pushl %esi 262 pushl %edi 263 movl 12(%esp),%esi 264 movl 16(%esp),%edi 265 movl 20(%esp),%ecx 266 cmpl %esi,%edi /* potentially overlapping? */ 267 jnb 1f 268 shrl $1,%ecx /* copy by 16-bit words */ 269 cld /* nope, copy forwards */ 270 rep 271 movsw 272 adc %ecx,%ecx /* any bytes left? */ 273 rep 274 movsb 275 popl %edi 276 popl %esi 277 ret 278 279 ALIGN_TEXT 2801: 281 addl %ecx,%edi /* copy backwards */ 282 addl %ecx,%esi 283 andl $1,%ecx /* any fractional bytes? */ 284 decl %edi 285 decl %esi 286 std 287 rep 288 movsb 289 movl 20(%esp),%ecx /* copy remainder by 16-bit words */ 290 shrl $1,%ecx 291 decl %esi 292 decl %edi 293 rep 294 movsw 295 popl %edi 296 popl %esi 297 cld 298 ret 299 300ENTRY(bcopyx) 301 movl 16(%esp),%eax 302 cmpl $2,%eax 303 je bcopyw /* not _bcopyw, to avoid multiple mcounts */ 304 cmpl $4,%eax 305 je bcopy /* XXX the shared ret's break mexitcount */ 306 jmp bcopyb 307 308/* 309 * (ov)bcopy(src, dst, cnt) 310 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 311 */ 312ALTENTRY(ovbcopy) 313ENTRY(bcopy) 314bcopy: 315 pushl %esi 316 pushl %edi 317 movl 12(%esp),%esi 318 movl 16(%esp),%edi 319 movl 20(%esp),%ecx 320 cmpl %esi,%edi /* potentially overlapping? */ 321 jnb 1f 322 shrl $2,%ecx /* copy by 32-bit words */ 323 cld /* nope, copy forwards */ 324 rep 325 movsl 326 movl 20(%esp),%ecx 327 andl $3,%ecx /* any bytes left? */ 328 rep 329 movsb 330 popl %edi 331 popl %esi 332 ret 333 334 ALIGN_TEXT 3351: 336 addl %ecx,%edi /* copy backwards */ 337 addl %ecx,%esi 338 andl $3,%ecx /* any fractional bytes? */ 339 decl %edi 340 decl %esi 341 std 342 rep 343 movsb 344 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 345 shrl $2,%ecx 346 subl $3,%esi 347 subl $3,%edi 348 rep 349 movsl 350 popl %edi 351 popl %esi 352 cld 353 ret 354 355 356/*****************************************************************************/ 357/* copyout and fubyte family */ 358/*****************************************************************************/ 359/* 360 * Access user memory from inside the kernel. These routines and possibly 361 * the math- and DOS emulators should be the only places that do this. 362 * 363 * We have to access the memory with user's permissions, so use a segment 364 * selector with RPL 3. For writes to user space we have to additionally 365 * check the PTE for write permission, because the 386 does not check 366 * write permissions when we are executing with EPL 0. The 486 does check 367 * this if the WP bit is set in CR0, so we can use a simpler version here. 368 * 369 * These routines set curpcb->onfault for the time they execute. When a 370 * protection violation occurs inside the functions, the trap handler 371 * returns to *curpcb->onfault instead of the function. 372 */ 373 374 375ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 376 movl _curpcb,%eax 377 movl $copyout_fault,PCB_ONFAULT(%eax) 378 pushl %esi 379 pushl %edi 380 pushl %ebx 381 movl 16(%esp),%esi 382 movl 20(%esp),%edi 383 movl 24(%esp),%ebx 384 testl %ebx,%ebx /* anything to do? */ 385 jz done_copyout 386 387 /* 388 * Check explicitly for non-user addresses. If 486 write protection 389 * is being used, this check is essential because we are in kernel 390 * mode so the h/w does not provide any protection against writing 391 * kernel addresses. 392 */ 393 394 /* 395 * First, prevent address wrapping. 396 */ 397 movl %edi,%eax 398 addl %ebx,%eax 399 jc copyout_fault 400/* 401 * XXX STOP USING VM_MAXUSER_ADDRESS. 402 * It is an end address, not a max, so every time it is used correctly it 403 * looks like there is an off by one error, and of course it caused an off 404 * by one error in several places. 405 */ 406 cmpl $VM_MAXUSER_ADDRESS,%eax 407 ja copyout_fault 408 409#if defined(I386_CPU) 410 411#if defined(I486_CPU) || defined(I586_CPU) 412 cmpl $CPUCLASS_386,_cpu_class 413 jne 3f 414#endif 415/* 416 * We have to check each PTE for user write permission. 417 * The checking may cause a page fault, so it is important to set 418 * up everything for return via copyout_fault before here. 419 */ 420 /* compute number of pages */ 421 movl %edi,%ecx 422 andl $NBPG-1,%ecx 423 addl %ebx,%ecx 424 decl %ecx 425 shrl $IDXSHIFT+2,%ecx 426 incl %ecx 427 428 /* compute PTE offset for start address */ 429 movl %edi,%edx 430 shrl $IDXSHIFT,%edx 431 andb $0xfc,%dl 432 4331: /* check PTE for each page */ 434 movb _PTmap(%edx),%al 435 andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 436 cmpb $0x07,%al 437 je 2f 438 439 /* simulate a trap */ 440 pushl %edx 441 pushl %ecx 442 shll $IDXSHIFT,%edx 443 pushl %edx 444 call _trapwrite /* trapwrite(addr) */ 445 popl %edx 446 popl %ecx 447 popl %edx 448 449 testl %eax,%eax /* if not ok, return EFAULT */ 450 jnz copyout_fault 451 4522: 453 addl $4,%edx 454 decl %ecx 455 jnz 1b /* check next page */ 456#endif /* I386_CPU */ 457 458 /* bcopy(%esi, %edi, %ebx) */ 4593: 460 movl %ebx,%ecx 461 shrl $2,%ecx 462 cld 463 rep 464 movsl 465 movb %bl,%cl 466 andb $3,%cl 467 rep 468 movsb 469 470done_copyout: 471 popl %ebx 472 popl %edi 473 popl %esi 474 xorl %eax,%eax 475 movl _curpcb,%edx 476 movl %eax,PCB_ONFAULT(%edx) 477 ret 478 479 ALIGN_TEXT 480copyout_fault: 481 popl %ebx 482 popl %edi 483 popl %esi 484 movl _curpcb,%edx 485 movl $0,PCB_ONFAULT(%edx) 486 movl $EFAULT,%eax 487 ret 488 489/* copyin(from_user, to_kernel, len) */ 490ENTRY(copyin) 491 movl _curpcb,%eax 492 movl $copyin_fault,PCB_ONFAULT(%eax) 493 pushl %esi 494 pushl %edi 495 movl 12(%esp),%esi /* caddr_t from */ 496 movl 16(%esp),%edi /* caddr_t to */ 497 movl 20(%esp),%ecx /* size_t len */ 498 499 /* 500 * make sure address is valid 501 */ 502 movl %esi,%edx 503 addl %ecx,%edx 504 jc copyin_fault 505 cmpl $VM_MAXUSER_ADDRESS,%edx 506 ja copyin_fault 507 508 movb %cl,%al 509 shrl $2,%ecx /* copy longword-wise */ 510 cld 511 rep 512 movsl 513 movb %al,%cl 514 andb $3,%cl /* copy remaining bytes */ 515 rep 516 movsb 517 518 popl %edi 519 popl %esi 520 xorl %eax,%eax 521 movl _curpcb,%edx 522 movl %eax,PCB_ONFAULT(%edx) 523 ret 524 525 ALIGN_TEXT 526copyin_fault: 527 popl %edi 528 popl %esi 529 movl _curpcb,%edx 530 movl $0,PCB_ONFAULT(%edx) 531 movl $EFAULT,%eax 532 ret 533 534/* 535 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory 536 */ 537ALTENTRY(fuiword) 538ENTRY(fuword) 539 movl _curpcb,%ecx 540 movl $fusufault,PCB_ONFAULT(%ecx) 541 movl 4(%esp),%edx /* from */ 542 543 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 544 ja fusufault 545 546 movl (%edx),%eax 547 movl $0,PCB_ONFAULT(%ecx) 548 ret 549 550/* 551 * These two routines are called from the profiling code, potentially 552 * at interrupt time. If they fail, that's okay, good things will 553 * happen later. Fail all the time for now - until the trap code is 554 * able to deal with this. 555 */ 556ALTENTRY(suswintr) 557ENTRY(fuswintr) 558 movl $-1,%eax 559 ret 560 561ENTRY(fusword) 562 movl _curpcb,%ecx 563 movl $fusufault,PCB_ONFAULT(%ecx) 564 movl 4(%esp),%edx 565 566 cmpl $VM_MAXUSER_ADDRESS-2,%edx 567 ja fusufault 568 569 movzwl (%edx),%eax 570 movl $0,PCB_ONFAULT(%ecx) 571 ret 572 573ALTENTRY(fuibyte) 574ENTRY(fubyte) 575 movl _curpcb,%ecx 576 movl $fusufault,PCB_ONFAULT(%ecx) 577 movl 4(%esp),%edx 578 579 cmpl $VM_MAXUSER_ADDRESS-1,%edx 580 ja fusufault 581 582 movzbl (%edx),%eax 583 movl $0,PCB_ONFAULT(%ecx) 584 ret 585 586 ALIGN_TEXT 587fusufault: 588 movl _curpcb,%ecx 589 xorl %eax,%eax 590 movl %eax,PCB_ONFAULT(%ecx) 591 decl %eax 592 ret 593 594/* 595 * su{byte,sword,word}: write a byte (word, longword) to user memory 596 */ 597ALTENTRY(suiword) 598ENTRY(suword) 599 movl _curpcb,%ecx 600 movl $fusufault,PCB_ONFAULT(%ecx) 601 movl 4(%esp),%edx 602 603#if defined(I386_CPU) 604 605#if defined(I486_CPU) || defined(I586_CPU) 606 cmpl $CPUCLASS_386,_cpu_class 607 jne 2f /* we only have to set the right segment selector */ 608#endif /* I486_CPU || I586_CPU */ 609 610 /* XXX - page boundary crossing is still not handled */ 611 movl %edx,%eax 612 shrl $IDXSHIFT,%edx 613 andb $0xfc,%dl 614 movb _PTmap(%edx),%dl 615 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 616 cmpb $0x7,%dl 617 je 1f 618 619 /* simulate a trap */ 620 pushl %eax 621 call _trapwrite 622 popl %edx /* remove junk parameter from stack */ 623 movl _curpcb,%ecx /* restore trashed register */ 624 testl %eax,%eax 625 jnz fusufault 6261: 627 movl 4(%esp),%edx 628#endif 629 6302: 631 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 632 ja fusufault 633 634 movl 8(%esp),%eax 635 movl %eax,(%edx) 636 xorl %eax,%eax 637 movl %eax,PCB_ONFAULT(%ecx) 638 ret 639 640ENTRY(susword) 641 movl _curpcb,%ecx 642 movl $fusufault,PCB_ONFAULT(%ecx) 643 movl 4(%esp),%edx 644 645#if defined(I386_CPU) 646 647#if defined(I486_CPU) || defined(I586_CPU) 648 cmpl $CPUCLASS_386,_cpu_class 649 jne 2f 650#endif /* I486_CPU || I586_CPU */ 651 652 /* XXX - page boundary crossing is still not handled */ 653 movl %edx,%eax 654 shrl $IDXSHIFT,%edx 655 andb $0xfc,%dl 656 movb _PTmap(%edx),%dl 657 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 658 cmpb $0x7,%dl 659 je 1f 660 661 /* simulate a trap */ 662 pushl %eax 663 call _trapwrite 664 popl %edx /* remove junk parameter from stack */ 665 movl _curpcb,%ecx /* restore trashed register */ 666 testl %eax,%eax 667 jnz fusufault 6681: 669 movl 4(%esp),%edx 670#endif 671 6722: 673 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 674 ja fusufault 675 676 movw 8(%esp),%ax 677 movw %ax,(%edx) 678 xorl %eax,%eax 679 movl %eax,PCB_ONFAULT(%ecx) 680 ret 681 682ALTENTRY(suibyte) 683ENTRY(subyte) 684 movl _curpcb,%ecx 685 movl $fusufault,PCB_ONFAULT(%ecx) 686 movl 4(%esp),%edx 687 688#if defined(I386_CPU) 689 690#if defined(I486_CPU) || defined(I586_CPU) 691 cmpl $CPUCLASS_386,_cpu_class 692 jne 2f 693#endif /* I486_CPU || I586_CPU */ 694 695 movl %edx,%eax 696 shrl $IDXSHIFT,%edx 697 andb $0xfc,%dl 698 movb _PTmap(%edx),%dl 699 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 700 cmpb $0x7,%dl 701 je 1f 702 703 /* simulate a trap */ 704 pushl %eax 705 call _trapwrite 706 popl %edx /* remove junk parameter from stack */ 707 movl _curpcb,%ecx /* restore trashed register */ 708 testl %eax,%eax 709 jnz fusufault 7101: 711 movl 4(%esp),%edx 712#endif 713 7142: 715 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 716 ja fusufault 717 718 movb 8(%esp),%al 719 movb %al,(%edx) 720 xorl %eax,%eax 721 movl %eax,PCB_ONFAULT(%ecx) 722 ret 723 724/* 725 * copyoutstr(from, to, maxlen, int *lencopied) 726 * copy a string from from to to, stop when a 0 character is reached. 727 * return ENAMETOOLONG if string is longer than maxlen, and 728 * EFAULT on protection violations. If lencopied is non-zero, 729 * return the actual length in *lencopied. 730 */ 731ENTRY(copyoutstr) 732 pushl %esi 733 pushl %edi 734 movl _curpcb,%ecx 735 movl $cpystrflt,PCB_ONFAULT(%ecx) /* XXX rename copyoutstr_fault */ 736 737 movl 12(%esp),%esi /* %esi = from */ 738 movl 16(%esp),%edi /* %edi = to */ 739 movl 20(%esp),%edx /* %edx = maxlen */ 740 cld 741 742#if defined(I386_CPU) 743 744#if defined(I486_CPU) || defined(I586_CPU) 745 cmpl $CPUCLASS_386,_cpu_class 746 jne 5f 747#endif /* I486_CPU || I586_CPU */ 748 7491: 750 /* 751 * It suffices to check that the first byte is in user space, because 752 * we look at a page at a time and the end address is on a page 753 * boundary. 754 */ 755 cmpl $VM_MAXUSER_ADDRESS-1,%edi 756 ja cpystrflt 757 758 movl %edi,%eax 759 shrl $IDXSHIFT,%eax 760 andb $0xfc,%al 761 movb _PTmap(%eax),%al 762 andb $7,%al 763 cmpb $7,%al 764 je 2f 765 766 /* simulate trap */ 767 pushl %edx 768 pushl %edi 769 call _trapwrite 770 cld 771 popl %edi 772 popl %edx 773 testl %eax,%eax 774 jnz cpystrflt 775 7762: /* copy up to end of this page */ 777 movl %edi,%eax 778 andl $NBPG-1,%eax 779 movl $NBPG,%ecx 780 subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ 781 cmpl %ecx,%edx 782 jae 3f 783 movl %edx,%ecx /* ecx = min(ecx, edx) */ 7843: 785 testl %ecx,%ecx 786 jz 4f 787 decl %ecx 788 decl %edx 789 lodsb 790 stosb 791 orb %al,%al 792 jnz 3b 793 794 /* Success -- 0 byte reached */ 795 decl %edx 796 xorl %eax,%eax 797 jmp 6f 798 7994: /* next page */ 800 testl %edx,%edx 801 jnz 1b 802 803 /* edx is zero -- return ENAMETOOLONG */ 804 movl $ENAMETOOLONG,%eax 805 jmp cpystrflt_x 806#endif /* I386_CPU */ 807 808#if defined(I486_CPU) || defined(I586_CPU) 8095: 810 incl %edx 8111: 812 decl %edx 813 jz 2f 814 /* 815 * XXX - would be faster to rewrite this function to use 816 * strlen() and copyout(). 817 */ 818 cmpl $VM_MAXUSER_ADDRESS-1,%edi 819 ja cpystrflt 820 821 lodsb 822 stosb 823 orb %al,%al 824 jnz 1b 825 826 /* Success -- 0 byte reached */ 827 decl %edx 828 xorl %eax,%eax 829 jmp cpystrflt_x 8302: 831 /* edx is zero -- return ENAMETOOLONG */ 832 movl $ENAMETOOLONG,%eax 833 jmp cpystrflt_x 834 835#endif /* I486_CPU || I586_CPU */ 836 837 838/* 839 * copyinstr(from, to, maxlen, int *lencopied) 840 * copy a string from from to to, stop when a 0 character is reached. 841 * return ENAMETOOLONG if string is longer than maxlen, and 842 * EFAULT on protection violations. If lencopied is non-zero, 843 * return the actual length in *lencopied. 844 */ 845ENTRY(copyinstr) 846 pushl %esi 847 pushl %edi 848 movl _curpcb,%ecx 849 movl $cpystrflt,PCB_ONFAULT(%ecx) 850 851 movl 12(%esp),%esi /* %esi = from */ 852 movl 16(%esp),%edi /* %edi = to */ 853 movl 20(%esp),%edx /* %edx = maxlen */ 854 855 movl $VM_MAXUSER_ADDRESS,%eax 856 857 /* make sure 'from' is within bounds */ 858 subl %esi,%eax 859 jbe cpystrflt 860 861 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 862 cmpl %edx,%eax 863 jae 1f 864 movl %eax,%edx 865 movl %eax,20(%esp) 8661: 867 incl %edx 868 cld 869 8702: 871 decl %edx 872 jz 3f 873 874 lodsb 875 stosb 876 orb %al,%al 877 jnz 2b 878 879 /* Success -- 0 byte reached */ 880 decl %edx 881 xorl %eax,%eax 882 jmp cpystrflt_x 8833: 884 /* edx is zero - return ENAMETOOLONG or EFAULT */ 885 cmpl $VM_MAXUSER_ADDRESS,%esi 886 jae cpystrflt 8874: 888 movl $ENAMETOOLONG,%eax 889 jmp cpystrflt_x 890 891cpystrflt: 892 movl $EFAULT,%eax 893 894cpystrflt_x: 895 /* set *lencopied and return %eax */ 896 movl _curpcb,%ecx 897 movl $0,PCB_ONFAULT(%ecx) 898 movl 20(%esp),%ecx 899 subl %edx,%ecx 900 movl 24(%esp),%edx 901 testl %edx,%edx 902 jz 1f 903 movl %ecx,(%edx) 9041: 905 popl %edi 906 popl %esi 907 ret 908 909 910/* 911 * copystr(from, to, maxlen, int *lencopied) 912 */ 913ENTRY(copystr) 914 pushl %esi 915 pushl %edi 916 917 movl 12(%esp),%esi /* %esi = from */ 918 movl 16(%esp),%edi /* %edi = to */ 919 movl 20(%esp),%edx /* %edx = maxlen */ 920 incl %edx 921 cld 9221: 923 decl %edx 924 jz 4f 925 lodsb 926 stosb 927 orb %al,%al 928 jnz 1b 929 930 /* Success -- 0 byte reached */ 931 decl %edx 932 xorl %eax,%eax 933 jmp 6f 9344: 935 /* edx is zero -- return ENAMETOOLONG */ 936 movl $ENAMETOOLONG,%eax 937 9386: 939 /* set *lencopied and return %eax */ 940 movl 20(%esp),%ecx 941 subl %edx,%ecx 942 movl 24(%esp),%edx 943 testl %edx,%edx 944 jz 7f 945 movl %ecx,(%edx) 9467: 947 popl %edi 948 popl %esi 949 ret 950 951/* 952 * Miscellaneous kernel support functions 953 */ 954ENTRY(ffs) 955 bsfl 4(%esp),%eax 956 jz 1f 957 incl %eax 958 ret 9591: 960 xorl %eax,%eax 961 ret 962 963ENTRY(bcmp) 964 pushl %edi 965 pushl %esi 966 movl 12(%esp),%edi 967 movl 16(%esp),%esi 968 movl 20(%esp),%edx 969 xorl %eax,%eax 970 971 movl %edx,%ecx 972 shrl $2,%ecx 973 cld /* compare forwards */ 974 repe 975 cmpsl 976 jne 1f 977 978 movl %edx,%ecx 979 andl $3,%ecx 980 repe 981 cmpsb 982 je 2f 9831: 984 incl %eax 9852: 986 popl %esi 987 popl %edi 988 ret 989 990 991/* 992 * Handling of special 386 registers and descriptor tables etc 993 */ 994/* void lgdt(struct region_descriptor *rdp); */ 995ENTRY(lgdt) 996 /* reload the descriptor table */ 997 movl 4(%esp),%eax 998 lgdt (%eax) 999 1000 /* flush the prefetch q */ 1001 jmp 1f 1002 nop 10031: 1004 /* reload "stale" selectors */ 1005 movl $KDSEL,%eax 1006 movl %ax,%ds 1007 movl %ax,%es 1008 movl %ax,%ss 1009 1010 /* reload code selector by turning return into intersegmental return */ 1011 movl (%esp),%eax 1012 pushl %eax 1013# movl $KCSEL,4(%esp) 1014 movl $8,4(%esp) 1015 lret 1016 1017/* 1018 * void lidt(struct region_descriptor *rdp); 1019 */ 1020ENTRY(lidt) 1021 movl 4(%esp),%eax 1022 lidt (%eax) 1023 ret 1024 1025/* 1026 * void lldt(u_short sel) 1027 */ 1028ENTRY(lldt) 1029 lldt 4(%esp) 1030 ret 1031 1032/* 1033 * void ltr(u_short sel) 1034 */ 1035ENTRY(ltr) 1036 ltr 4(%esp) 1037 ret 1038 1039/* ssdtosd(*ssdp,*sdp) */ 1040ENTRY(ssdtosd) 1041 pushl %ebx 1042 movl 8(%esp),%ecx 1043 movl 8(%ecx),%ebx 1044 shll $16,%ebx 1045 movl (%ecx),%edx 1046 roll $16,%edx 1047 movb %dh,%bl 1048 movb %dl,%bh 1049 rorl $8,%ebx 1050 movl 4(%ecx),%eax 1051 movw %ax,%dx 1052 andl $0xf0000,%eax 1053 orl %eax,%ebx 1054 movl 12(%esp),%ecx 1055 movl %edx,(%ecx) 1056 movl %ebx,4(%ecx) 1057 popl %ebx 1058 ret 1059 1060/* load_cr0(cr0) */ 1061ENTRY(load_cr0) 1062 movl 4(%esp),%eax 1063 movl %eax,%cr0 1064 ret 1065 1066/* rcr0() */ 1067ENTRY(rcr0) 1068 movl %cr0,%eax 1069 ret 1070 1071/* rcr3() */ 1072ENTRY(rcr3) 1073 movl %cr3,%eax 1074 ret 1075 1076/* void load_cr3(caddr_t cr3) */ 1077ENTRY(load_cr3) 1078 movl 4(%esp),%eax 1079 movl %eax,%cr3 1080 ret 1081 1082 1083/*****************************************************************************/ 1084/* setjump, longjump */ 1085/*****************************************************************************/ 1086 1087ENTRY(setjmp) 1088 movl 4(%esp),%eax 1089 movl %ebx,(%eax) /* save ebx */ 1090 movl %esp,4(%eax) /* save esp */ 1091 movl %ebp,8(%eax) /* save ebp */ 1092 movl %esi,12(%eax) /* save esi */ 1093 movl %edi,16(%eax) /* save edi */ 1094 movl (%esp),%edx /* get rta */ 1095 movl %edx,20(%eax) /* save eip */ 1096 xorl %eax,%eax /* return(0); */ 1097 ret 1098 1099ENTRY(longjmp) 1100 movl 4(%esp),%eax 1101 movl (%eax),%ebx /* restore ebx */ 1102 movl 4(%eax),%esp /* restore esp */ 1103 movl 8(%eax),%ebp /* restore ebp */ 1104 movl 12(%eax),%esi /* restore esi */ 1105 movl 16(%eax),%edi /* restore edi */ 1106 movl 20(%eax),%edx /* get rta */ 1107 movl %edx,(%esp) /* put in return frame */ 1108 xorl %eax,%eax /* return(1); */ 1109 incl %eax 1110 ret 1111 1112/* 1113 * Here for doing BB-profiling (gcc -a). 1114 * We rely on the "bbset" instead, but need a dummy function. 1115 */ 1116 .text 1117 .align 2 1118.globl ___bb_init_func 1119___bb_init_func: 1120 movl 4(%esp),%eax 1121 movl $1,(%eax) 1122 ret 1123