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