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