support.s revision 8214
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.21 1995/03/11 03:49:50 phk 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 * Note: memcpy does not support overlapping copies 358 */ 359ENTRY(memcpy) 360 pushl %edi 361 pushl %esi 362 movl 12(%esp),%edi 363 movl 16(%esp),%esi 364 movl 20(%esp),%ecx 365 movl %edi,%eax 366 shrl $2,%ecx /* copy by 32-bit words */ 367 cld /* nope, copy forwards */ 368 rep 369 movsl 370 movl 20(%esp),%ecx 371 andl $3,%ecx /* any bytes left? */ 372 rep 373 movsb 374 popl %esi 375 popl %edi 376 ret 377 378 379/*****************************************************************************/ 380/* copyout and fubyte family */ 381/*****************************************************************************/ 382/* 383 * Access user memory from inside the kernel. These routines and possibly 384 * the math- and DOS emulators should be the only places that do this. 385 * 386 * We have to access the memory with user's permissions, so use a segment 387 * selector with RPL 3. For writes to user space we have to additionally 388 * check the PTE for write permission, because the 386 does not check 389 * write permissions when we are executing with EPL 0. The 486 does check 390 * this if the WP bit is set in CR0, so we can use a simpler version here. 391 * 392 * These routines set curpcb->onfault for the time they execute. When a 393 * protection violation occurs inside the functions, the trap handler 394 * returns to *curpcb->onfault instead of the function. 395 */ 396 397 398ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 399 movl _curpcb,%eax 400 movl $copyout_fault,PCB_ONFAULT(%eax) 401 pushl %esi 402 pushl %edi 403 pushl %ebx 404 movl 16(%esp),%esi 405 movl 20(%esp),%edi 406 movl 24(%esp),%ebx 407 testl %ebx,%ebx /* anything to do? */ 408 jz done_copyout 409 410 /* 411 * Check explicitly for non-user addresses. If 486 write protection 412 * is being used, this check is essential because we are in kernel 413 * mode so the h/w does not provide any protection against writing 414 * kernel addresses. 415 */ 416 417 /* 418 * First, prevent address wrapping. 419 */ 420 movl %edi,%eax 421 addl %ebx,%eax 422 jc copyout_fault 423/* 424 * XXX STOP USING VM_MAXUSER_ADDRESS. 425 * It is an end address, not a max, so every time it is used correctly it 426 * looks like there is an off by one error, and of course it caused an off 427 * by one error in several places. 428 */ 429 cmpl $VM_MAXUSER_ADDRESS,%eax 430 ja copyout_fault 431 432#if defined(I386_CPU) 433 434#if defined(I486_CPU) || defined(I586_CPU) 435 cmpl $CPUCLASS_386,_cpu_class 436 jne 3f 437#endif 438/* 439 * We have to check each PTE for user write permission. 440 * The checking may cause a page fault, so it is important to set 441 * up everything for return via copyout_fault before here. 442 */ 443 /* compute number of pages */ 444 movl %edi,%ecx 445 andl $NBPG-1,%ecx 446 addl %ebx,%ecx 447 decl %ecx 448 shrl $IDXSHIFT+2,%ecx 449 incl %ecx 450 451 /* compute PTE offset for start address */ 452 movl %edi,%edx 453 shrl $IDXSHIFT,%edx 454 andb $0xfc,%dl 455 4561: /* check PTE for each page */ 457 movb _PTmap(%edx),%al 458 andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 459 cmpb $0x07,%al 460 je 2f 461 462 /* simulate a trap */ 463 pushl %edx 464 pushl %ecx 465 shll $IDXSHIFT,%edx 466 pushl %edx 467 call _trapwrite /* trapwrite(addr) */ 468 popl %edx 469 popl %ecx 470 popl %edx 471 472 testl %eax,%eax /* if not ok, return EFAULT */ 473 jnz copyout_fault 474 4752: 476 addl $4,%edx 477 decl %ecx 478 jnz 1b /* check next page */ 479#endif /* I386_CPU */ 480 481 /* bcopy(%esi, %edi, %ebx) */ 4823: 483 movl %ebx,%ecx 484 shrl $2,%ecx 485 cld 486 rep 487 movsl 488 movb %bl,%cl 489 andb $3,%cl 490 rep 491 movsb 492 493done_copyout: 494 popl %ebx 495 popl %edi 496 popl %esi 497 xorl %eax,%eax 498 movl _curpcb,%edx 499 movl %eax,PCB_ONFAULT(%edx) 500 ret 501 502 ALIGN_TEXT 503copyout_fault: 504 popl %ebx 505 popl %edi 506 popl %esi 507 movl _curpcb,%edx 508 movl $0,PCB_ONFAULT(%edx) 509 movl $EFAULT,%eax 510 ret 511 512/* copyin(from_user, to_kernel, len) */ 513ENTRY(copyin) 514 movl _curpcb,%eax 515 movl $copyin_fault,PCB_ONFAULT(%eax) 516 pushl %esi 517 pushl %edi 518 movl 12(%esp),%esi /* caddr_t from */ 519 movl 16(%esp),%edi /* caddr_t to */ 520 movl 20(%esp),%ecx /* size_t len */ 521 522 /* 523 * make sure address is valid 524 */ 525 movl %esi,%edx 526 addl %ecx,%edx 527 jc copyin_fault 528 cmpl $VM_MAXUSER_ADDRESS,%edx 529 ja copyin_fault 530 531 movb %cl,%al 532 shrl $2,%ecx /* copy longword-wise */ 533 cld 534 rep 535 movsl 536 movb %al,%cl 537 andb $3,%cl /* copy remaining bytes */ 538 rep 539 movsb 540 541 popl %edi 542 popl %esi 543 xorl %eax,%eax 544 movl _curpcb,%edx 545 movl %eax,PCB_ONFAULT(%edx) 546 ret 547 548 ALIGN_TEXT 549copyin_fault: 550 popl %edi 551 popl %esi 552 movl _curpcb,%edx 553 movl $0,PCB_ONFAULT(%edx) 554 movl $EFAULT,%eax 555 ret 556 557/* 558 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory 559 */ 560ALTENTRY(fuiword) 561ENTRY(fuword) 562 movl _curpcb,%ecx 563 movl $fusufault,PCB_ONFAULT(%ecx) 564 movl 4(%esp),%edx /* from */ 565 566 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 567 ja fusufault 568 569 movl (%edx),%eax 570 movl $0,PCB_ONFAULT(%ecx) 571 ret 572 573/* 574 * These two routines are called from the profiling code, potentially 575 * at interrupt time. If they fail, that's okay, good things will 576 * happen later. Fail all the time for now - until the trap code is 577 * able to deal with this. 578 */ 579ALTENTRY(suswintr) 580ENTRY(fuswintr) 581 movl $-1,%eax 582 ret 583 584ENTRY(fusword) 585 movl _curpcb,%ecx 586 movl $fusufault,PCB_ONFAULT(%ecx) 587 movl 4(%esp),%edx 588 589 cmpl $VM_MAXUSER_ADDRESS-2,%edx 590 ja fusufault 591 592 movzwl (%edx),%eax 593 movl $0,PCB_ONFAULT(%ecx) 594 ret 595 596ALTENTRY(fuibyte) 597ENTRY(fubyte) 598 movl _curpcb,%ecx 599 movl $fusufault,PCB_ONFAULT(%ecx) 600 movl 4(%esp),%edx 601 602 cmpl $VM_MAXUSER_ADDRESS-1,%edx 603 ja fusufault 604 605 movzbl (%edx),%eax 606 movl $0,PCB_ONFAULT(%ecx) 607 ret 608 609 ALIGN_TEXT 610fusufault: 611 movl _curpcb,%ecx 612 xorl %eax,%eax 613 movl %eax,PCB_ONFAULT(%ecx) 614 decl %eax 615 ret 616 617/* 618 * su{byte,sword,word}: write a byte (word, longword) to user memory 619 */ 620ALTENTRY(suiword) 621ENTRY(suword) 622 movl _curpcb,%ecx 623 movl $fusufault,PCB_ONFAULT(%ecx) 624 movl 4(%esp),%edx 625 626#if defined(I386_CPU) 627 628#if defined(I486_CPU) || defined(I586_CPU) 629 cmpl $CPUCLASS_386,_cpu_class 630 jne 2f /* we only have to set the right segment selector */ 631#endif /* I486_CPU || I586_CPU */ 632 633 /* XXX - page boundary crossing is still not handled */ 634 movl %edx,%eax 635 shrl $IDXSHIFT,%edx 636 andb $0xfc,%dl 637 movb _PTmap(%edx),%dl 638 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 639 cmpb $0x7,%dl 640 je 1f 641 642 /* simulate a trap */ 643 pushl %eax 644 call _trapwrite 645 popl %edx /* remove junk parameter from stack */ 646 movl _curpcb,%ecx /* restore trashed register */ 647 testl %eax,%eax 648 jnz fusufault 6491: 650 movl 4(%esp),%edx 651#endif 652 6532: 654 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 655 ja fusufault 656 657 movl 8(%esp),%eax 658 movl %eax,(%edx) 659 xorl %eax,%eax 660 movl %eax,PCB_ONFAULT(%ecx) 661 ret 662 663ENTRY(susword) 664 movl _curpcb,%ecx 665 movl $fusufault,PCB_ONFAULT(%ecx) 666 movl 4(%esp),%edx 667 668#if defined(I386_CPU) 669 670#if defined(I486_CPU) || defined(I586_CPU) 671 cmpl $CPUCLASS_386,_cpu_class 672 jne 2f 673#endif /* I486_CPU || I586_CPU */ 674 675 /* XXX - page boundary crossing is still not handled */ 676 movl %edx,%eax 677 shrl $IDXSHIFT,%edx 678 andb $0xfc,%dl 679 movb _PTmap(%edx),%dl 680 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 681 cmpb $0x7,%dl 682 je 1f 683 684 /* simulate a trap */ 685 pushl %eax 686 call _trapwrite 687 popl %edx /* remove junk parameter from stack */ 688 movl _curpcb,%ecx /* restore trashed register */ 689 testl %eax,%eax 690 jnz fusufault 6911: 692 movl 4(%esp),%edx 693#endif 694 6952: 696 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 697 ja fusufault 698 699 movw 8(%esp),%ax 700 movw %ax,(%edx) 701 xorl %eax,%eax 702 movl %eax,PCB_ONFAULT(%ecx) 703 ret 704 705ALTENTRY(suibyte) 706ENTRY(subyte) 707 movl _curpcb,%ecx 708 movl $fusufault,PCB_ONFAULT(%ecx) 709 movl 4(%esp),%edx 710 711#if defined(I386_CPU) 712 713#if defined(I486_CPU) || defined(I586_CPU) 714 cmpl $CPUCLASS_386,_cpu_class 715 jne 2f 716#endif /* I486_CPU || I586_CPU */ 717 718 movl %edx,%eax 719 shrl $IDXSHIFT,%edx 720 andb $0xfc,%dl 721 movb _PTmap(%edx),%dl 722 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 723 cmpb $0x7,%dl 724 je 1f 725 726 /* simulate a trap */ 727 pushl %eax 728 call _trapwrite 729 popl %edx /* remove junk parameter from stack */ 730 movl _curpcb,%ecx /* restore trashed register */ 731 testl %eax,%eax 732 jnz fusufault 7331: 734 movl 4(%esp),%edx 735#endif 736 7372: 738 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 739 ja fusufault 740 741 movb 8(%esp),%al 742 movb %al,(%edx) 743 xorl %eax,%eax 744 movl %eax,PCB_ONFAULT(%ecx) 745 ret 746 747/* 748 * copyoutstr(from, to, maxlen, int *lencopied) 749 * copy a string from from to to, stop when a 0 character is reached. 750 * return ENAMETOOLONG if string is longer than maxlen, and 751 * EFAULT on protection violations. If lencopied is non-zero, 752 * return the actual length in *lencopied. 753 */ 754ENTRY(copyoutstr) 755 pushl %esi 756 pushl %edi 757 movl _curpcb,%ecx 758 movl $cpystrflt,PCB_ONFAULT(%ecx) /* XXX rename copyoutstr_fault */ 759 760 movl 12(%esp),%esi /* %esi = from */ 761 movl 16(%esp),%edi /* %edi = to */ 762 movl 20(%esp),%edx /* %edx = maxlen */ 763 cld 764 765#if defined(I386_CPU) 766 767#if defined(I486_CPU) || defined(I586_CPU) 768 cmpl $CPUCLASS_386,_cpu_class 769 jne 5f 770#endif /* I486_CPU || I586_CPU */ 771 7721: 773 /* 774 * It suffices to check that the first byte is in user space, because 775 * we look at a page at a time and the end address is on a page 776 * boundary. 777 */ 778 cmpl $VM_MAXUSER_ADDRESS-1,%edi 779 ja cpystrflt 780 781 movl %edi,%eax 782 shrl $IDXSHIFT,%eax 783 andb $0xfc,%al 784 movb _PTmap(%eax),%al 785 andb $7,%al 786 cmpb $7,%al 787 je 2f 788 789 /* simulate trap */ 790 pushl %edx 791 pushl %edi 792 call _trapwrite 793 cld 794 popl %edi 795 popl %edx 796 testl %eax,%eax 797 jnz cpystrflt 798 7992: /* copy up to end of this page */ 800 movl %edi,%eax 801 andl $NBPG-1,%eax 802 movl $NBPG,%ecx 803 subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ 804 cmpl %ecx,%edx 805 jae 3f 806 movl %edx,%ecx /* ecx = min(ecx, edx) */ 8073: 808 testl %ecx,%ecx 809 jz 4f 810 decl %ecx 811 decl %edx 812 lodsb 813 stosb 814 orb %al,%al 815 jnz 3b 816 817 /* Success -- 0 byte reached */ 818 decl %edx 819 xorl %eax,%eax 820 jmp 6f 821 8224: /* next page */ 823 testl %edx,%edx 824 jnz 1b 825 826 /* edx is zero -- return ENAMETOOLONG */ 827 movl $ENAMETOOLONG,%eax 828 jmp cpystrflt_x 829#endif /* I386_CPU */ 830 831#if defined(I486_CPU) || defined(I586_CPU) 8325: 833 incl %edx 8341: 835 decl %edx 836 jz 2f 837 /* 838 * XXX - would be faster to rewrite this function to use 839 * strlen() and copyout(). 840 */ 841 cmpl $VM_MAXUSER_ADDRESS-1,%edi 842 ja cpystrflt 843 844 lodsb 845 stosb 846 orb %al,%al 847 jnz 1b 848 849 /* Success -- 0 byte reached */ 850 decl %edx 851 xorl %eax,%eax 852 jmp cpystrflt_x 8532: 854 /* edx is zero -- return ENAMETOOLONG */ 855 movl $ENAMETOOLONG,%eax 856 jmp cpystrflt_x 857 858#endif /* I486_CPU || I586_CPU */ 859 860 861/* 862 * copyinstr(from, to, maxlen, int *lencopied) 863 * copy a string from from to to, stop when a 0 character is reached. 864 * return ENAMETOOLONG if string is longer than maxlen, and 865 * EFAULT on protection violations. If lencopied is non-zero, 866 * return the actual length in *lencopied. 867 */ 868ENTRY(copyinstr) 869 pushl %esi 870 pushl %edi 871 movl _curpcb,%ecx 872 movl $cpystrflt,PCB_ONFAULT(%ecx) 873 874 movl 12(%esp),%esi /* %esi = from */ 875 movl 16(%esp),%edi /* %edi = to */ 876 movl 20(%esp),%edx /* %edx = maxlen */ 877 878 movl $VM_MAXUSER_ADDRESS,%eax 879 880 /* make sure 'from' is within bounds */ 881 subl %esi,%eax 882 jbe cpystrflt 883 884 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 885 cmpl %edx,%eax 886 jae 1f 887 movl %eax,%edx 888 movl %eax,20(%esp) 8891: 890 incl %edx 891 cld 892 8932: 894 decl %edx 895 jz 3f 896 897 lodsb 898 stosb 899 orb %al,%al 900 jnz 2b 901 902 /* Success -- 0 byte reached */ 903 decl %edx 904 xorl %eax,%eax 905 jmp cpystrflt_x 9063: 907 /* edx is zero - return ENAMETOOLONG or EFAULT */ 908 cmpl $VM_MAXUSER_ADDRESS,%esi 909 jae cpystrflt 9104: 911 movl $ENAMETOOLONG,%eax 912 jmp cpystrflt_x 913 914cpystrflt: 915 movl $EFAULT,%eax 916 917cpystrflt_x: 918 /* set *lencopied and return %eax */ 919 movl _curpcb,%ecx 920 movl $0,PCB_ONFAULT(%ecx) 921 movl 20(%esp),%ecx 922 subl %edx,%ecx 923 movl 24(%esp),%edx 924 testl %edx,%edx 925 jz 1f 926 movl %ecx,(%edx) 9271: 928 popl %edi 929 popl %esi 930 ret 931 932 933/* 934 * copystr(from, to, maxlen, int *lencopied) 935 */ 936ENTRY(copystr) 937 pushl %esi 938 pushl %edi 939 940 movl 12(%esp),%esi /* %esi = from */ 941 movl 16(%esp),%edi /* %edi = to */ 942 movl 20(%esp),%edx /* %edx = maxlen */ 943 incl %edx 944 cld 9451: 946 decl %edx 947 jz 4f 948 lodsb 949 stosb 950 orb %al,%al 951 jnz 1b 952 953 /* Success -- 0 byte reached */ 954 decl %edx 955 xorl %eax,%eax 956 jmp 6f 9574: 958 /* edx is zero -- return ENAMETOOLONG */ 959 movl $ENAMETOOLONG,%eax 960 9616: 962 /* set *lencopied and return %eax */ 963 movl 20(%esp),%ecx 964 subl %edx,%ecx 965 movl 24(%esp),%edx 966 testl %edx,%edx 967 jz 7f 968 movl %ecx,(%edx) 9697: 970 popl %edi 971 popl %esi 972 ret 973 974/* 975 * Miscellaneous kernel support functions 976 */ 977ENTRY(ffs) 978 bsfl 4(%esp),%eax 979 jz 1f 980 incl %eax 981 ret 9821: 983 xorl %eax,%eax 984 ret 985 986ENTRY(bcmp) 987 pushl %edi 988 pushl %esi 989 movl 12(%esp),%edi 990 movl 16(%esp),%esi 991 movl 20(%esp),%edx 992 xorl %eax,%eax 993 994 movl %edx,%ecx 995 shrl $2,%ecx 996 cld /* compare forwards */ 997 repe 998 cmpsl 999 jne 1f 1000 1001 movl %edx,%ecx 1002 andl $3,%ecx 1003 repe 1004 cmpsb 1005 je 2f 10061: 1007 incl %eax 10082: 1009 popl %esi 1010 popl %edi 1011 ret 1012 1013 1014/* 1015 * Handling of special 386 registers and descriptor tables etc 1016 */ 1017/* void lgdt(struct region_descriptor *rdp); */ 1018ENTRY(lgdt) 1019 /* reload the descriptor table */ 1020 movl 4(%esp),%eax 1021 lgdt (%eax) 1022 1023 /* flush the prefetch q */ 1024 jmp 1f 1025 nop 10261: 1027 /* reload "stale" selectors */ 1028 movl $KDSEL,%eax 1029 movl %ax,%ds 1030 movl %ax,%es 1031 movl %ax,%ss 1032 1033 /* reload code selector by turning return into intersegmental return */ 1034 movl (%esp),%eax 1035 pushl %eax 1036# movl $KCSEL,4(%esp) 1037 movl $8,4(%esp) 1038 lret 1039 1040/* 1041 * void lidt(struct region_descriptor *rdp); 1042 */ 1043ENTRY(lidt) 1044 movl 4(%esp),%eax 1045 lidt (%eax) 1046 ret 1047 1048/* 1049 * void lldt(u_short sel) 1050 */ 1051ENTRY(lldt) 1052 lldt 4(%esp) 1053 ret 1054 1055/* 1056 * void ltr(u_short sel) 1057 */ 1058ENTRY(ltr) 1059 ltr 4(%esp) 1060 ret 1061 1062/* ssdtosd(*ssdp,*sdp) */ 1063ENTRY(ssdtosd) 1064 pushl %ebx 1065 movl 8(%esp),%ecx 1066 movl 8(%ecx),%ebx 1067 shll $16,%ebx 1068 movl (%ecx),%edx 1069 roll $16,%edx 1070 movb %dh,%bl 1071 movb %dl,%bh 1072 rorl $8,%ebx 1073 movl 4(%ecx),%eax 1074 movw %ax,%dx 1075 andl $0xf0000,%eax 1076 orl %eax,%ebx 1077 movl 12(%esp),%ecx 1078 movl %edx,(%ecx) 1079 movl %ebx,4(%ecx) 1080 popl %ebx 1081 ret 1082 1083/* load_cr0(cr0) */ 1084ENTRY(load_cr0) 1085 movl 4(%esp),%eax 1086 movl %eax,%cr0 1087 ret 1088 1089/* rcr0() */ 1090ENTRY(rcr0) 1091 movl %cr0,%eax 1092 ret 1093 1094/* rcr3() */ 1095ENTRY(rcr3) 1096 movl %cr3,%eax 1097 ret 1098 1099/* void load_cr3(caddr_t cr3) */ 1100ENTRY(load_cr3) 1101 movl 4(%esp),%eax 1102 movl %eax,%cr3 1103 ret 1104 1105 1106/*****************************************************************************/ 1107/* setjump, longjump */ 1108/*****************************************************************************/ 1109 1110ENTRY(setjmp) 1111 movl 4(%esp),%eax 1112 movl %ebx,(%eax) /* save ebx */ 1113 movl %esp,4(%eax) /* save esp */ 1114 movl %ebp,8(%eax) /* save ebp */ 1115 movl %esi,12(%eax) /* save esi */ 1116 movl %edi,16(%eax) /* save edi */ 1117 movl (%esp),%edx /* get rta */ 1118 movl %edx,20(%eax) /* save eip */ 1119 xorl %eax,%eax /* return(0); */ 1120 ret 1121 1122ENTRY(longjmp) 1123 movl 4(%esp),%eax 1124 movl (%eax),%ebx /* restore ebx */ 1125 movl 4(%eax),%esp /* restore esp */ 1126 movl 8(%eax),%ebp /* restore ebp */ 1127 movl 12(%eax),%esi /* restore esi */ 1128 movl 16(%eax),%edi /* restore edi */ 1129 movl 20(%eax),%edx /* get rta */ 1130 movl %edx,(%esp) /* put in return frame */ 1131 xorl %eax,%eax /* return(1); */ 1132 incl %eax 1133 ret 1134 1135/* 1136 * Here for doing BB-profiling (gcc -a). 1137 * We rely on the "bbset" instead, but need a dummy function. 1138 */ 1139 .text 1140 .align 2 1141.globl ___bb_init_func 1142___bb_init_func: 1143 movl 4(%esp),%eax 1144 movl $1,(%eax) 1145 ret 1146