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