support.s revision 1058
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.3 1994/01/31 23:47: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(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(outb) /* outb(port, val) */ 112 movl 4(%esp),%edx 113 movl 8(%esp),%eax 114 outb %al,%dx 115 NOP 116 ret 117 118ENTRY(outw) /* outw(port, val) */ 119 movl 4(%esp),%edx 120 movl 8(%esp),%eax 121 outw %ax,%dx 122 NOP 123 ret 124 125ENTRY(outsb) /* outsb(port, addr, cnt) */ 126 pushl %esi 127 movw 8(%esp),%dx 128 movl 12(%esp),%esi 129 movl 16(%esp),%ecx 130 cld 131 rep 132 outsb 133 NOP 134 movl %esi,%eax 135 popl %esi 136 ret 137 138ENTRY(outsw) /* outsw(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 outsw 146 NOP 147 movl %esi,%eax 148 popl %esi 149 ret 150 151/* 152 * bcopy family 153 */ 154/* void bzero(void *base, u_int cnt) */ 155ENTRY(bzero) 156 pushl %edi 157 movl 8(%esp),%edi 158 movl 12(%esp),%ecx 159 xorl %eax,%eax 160 shrl $2,%ecx 161 cld 162 rep 163 stosl 164 movl 12(%esp),%ecx 165 andl $3,%ecx 166 rep 167 stosb 168 popl %edi 169 ret 170 171/* fillw(pat, base, cnt) */ 172ENTRY(fillw) 173 pushl %edi 174 movl 8(%esp),%eax 175 movl 12(%esp),%edi 176 movl 16(%esp),%ecx 177 cld 178 rep 179 stosw 180 popl %edi 181 ret 182 183/* filli(pat, base, cnt) */ 184ENTRY(filli) 185filli: 186 pushl %edi 187 movl 8(%esp),%eax 188 movl 12(%esp),%edi 189 movl 16(%esp),%ecx 190 cld 191 rep 192 stosl 193 popl %edi 194 ret 195 196ENTRY(bcopyb) 197bcopyb: 198 pushl %esi 199 pushl %edi 200 movl 12(%esp),%esi 201 movl 16(%esp),%edi 202 movl 20(%esp),%ecx 203 cmpl %esi,%edi /* potentially overlapping? */ 204 jnb 1f 205 cld /* nope, copy forwards */ 206 rep 207 movsb 208 popl %edi 209 popl %esi 210 ret 211 212 ALIGN_TEXT 2131: 214 addl %ecx,%edi /* copy backwards. */ 215 addl %ecx,%esi 216 std 217 decl %edi 218 decl %esi 219 rep 220 movsb 221 popl %edi 222 popl %esi 223 cld 224 ret 225 226ENTRY(bcopyw) 227bcopyw: 228 pushl %esi 229 pushl %edi 230 movl 12(%esp),%esi 231 movl 16(%esp),%edi 232 movl 20(%esp),%ecx 233 cmpl %esi,%edi /* potentially overlapping? */ 234 jnb 1f 235 cld /* nope, copy forwards */ 236 shrl $1,%ecx /* copy by 16-bit words */ 237 rep 238 movsw 239 adc %ecx,%ecx /* any bytes left? */ 240 rep 241 movsb 242 popl %edi 243 popl %esi 244 ret 245 246 ALIGN_TEXT 2471: 248 addl %ecx,%edi /* copy backwards */ 249 addl %ecx,%esi 250 std 251 andl $1,%ecx /* any fractional bytes? */ 252 decl %edi 253 decl %esi 254 rep 255 movsb 256 movl 20(%esp),%ecx /* copy remainder by 16-bit words */ 257 shrl $1,%ecx 258 decl %esi 259 decl %edi 260 rep 261 movsw 262 popl %edi 263 popl %esi 264 cld 265 ret 266 267ENTRY(bcopyx) 268 movl 16(%esp),%eax 269 cmpl $2,%eax 270 je bcopyw /* not _bcopyw, to avoid multiple mcounts */ 271 cmpl $4,%eax 272 je bcopy 273 jmp bcopyb 274 275/* 276 * (ov)bcopy(src, dst, cnt) 277 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 278 */ 279ALTENTRY(ovbcopy) 280ENTRY(bcopy) 281bcopy: 282 pushl %esi 283 pushl %edi 284 movl 12(%esp),%esi 285 movl 16(%esp),%edi 286 movl 20(%esp),%ecx 287 cmpl %esi,%edi /* potentially overlapping? */ 288 jnb 1f 289 cld /* nope, copy forwards */ 290 shrl $2,%ecx /* copy by 32-bit words */ 291 rep 292 movsl 293 movl 20(%esp),%ecx 294 andl $3,%ecx /* any bytes left? */ 295 rep 296 movsb 297 popl %edi 298 popl %esi 299 ret 300 301 ALIGN_TEXT 3021: 303 addl %ecx,%edi /* copy backwards */ 304 addl %ecx,%esi 305 std 306 andl $3,%ecx /* any fractional bytes? */ 307 decl %edi 308 decl %esi 309 rep 310 movsb 311 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 312 shrl $2,%ecx 313 subl $3,%esi 314 subl $3,%edi 315 rep 316 movsl 317 popl %edi 318 popl %esi 319 cld 320 ret 321 322ALTENTRY(ntohl) 323ENTRY(htonl) 324 movl 4(%esp),%eax 325#ifdef i486 326/* XXX */ 327/* Since Gas 1.38 does not grok bswap this has been coded as the 328 * equivalent bytes. This can be changed back to bswap when we 329 * upgrade to a newer version of Gas 330 */ 331 /* bswap %eax */ 332 .byte 0x0f 333 .byte 0xc8 334#else 335 xchgb %al,%ah 336 roll $16,%eax 337 xchgb %al,%ah 338#endif 339 ret 340 341ALTENTRY(ntohs) 342ENTRY(htons) 343 movzwl 4(%esp),%eax 344 xchgb %al,%ah 345 ret 346 347/*****************************************************************************/ 348/* copyout and fubyte family */ 349/*****************************************************************************/ 350/* 351 * Access user memory from inside the kernel. These routines and possibly 352 * the math- and DOS emulators should be the only places that do this. 353 * 354 * We have to access the memory with user's permissions, so use a segment 355 * selector with RPL 3. For writes to user space we have to additionally 356 * check the PTE for write permission, because the 386 does not check 357 * write permissions when we are executing with EPL 0. The 486 does check 358 * this if the WP bit is set in CR0, so we can use a simpler version here. 359 * 360 * These routines set curpcb->onfault for the time they execute. When a 361 * protection violation occurs inside the functions, the trap handler 362 * returns to *curpcb->onfault instead of the function. 363 */ 364 365 366ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 367 movl _curpcb,%eax 368 movl $copyout_fault,PCB_ONFAULT(%eax) 369 pushl %esi 370 pushl %edi 371 pushl %ebx 372 movl 16(%esp),%esi 373 movl 20(%esp),%edi 374 movl 24(%esp),%ebx 375 orl %ebx,%ebx /* anything to do? */ 376 jz done_copyout 377 378 /* 379 * Check explicitly for non-user addresses. If 486 write protection 380 * is being used, this check is essential because we are in kernel 381 * mode so the h/w does not provide any protection against writing 382 * kernel addresses. 383 * 384 * Otherwise, it saves having to load and restore %es to get the 385 * usual segment-based protection (the destination segment for movs 386 * is always %es). The other explicit checks for user-writablility 387 * are not quite sufficient. They fail for the user area because 388 * we mapped the user area read/write to avoid having an #ifdef in 389 * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 390 * addresses including 0xff800000 and 0xfc000000). I'm not sure if 391 * this can be fixed. Marking the PTEs supervisor mode and the 392 * PDE's user mode would almost work, but there may be a problem 393 * with the self-referential PDE. 394 */ 395 movl %edi,%eax 396 addl %ebx,%eax 397 jc copyout_fault 398 cmpl $VM_MAXUSER_ADDRESS,%eax 399 ja copyout_fault 400 401#if defined(I386_CPU) 402 403#if defined(I486_CPU) || defined(I586_CPU) 404 cmpl $CPUCLASS_386,_cpu_class 405 jne 3f 406#endif 407/* 408 * We have to check each PTE for user write permission. 409 * The checking may cause a page fault, so it is important to set 410 * up everything for return via copyout_fault before here. 411 */ 412 /* compute number of pages */ 413 movl %edi,%ecx 414 andl $NBPG-1,%ecx 415 addl %ebx,%ecx 416 decl %ecx 417 shrl $IDXSHIFT+2,%ecx 418 incl %ecx 419 420 /* compute PTE offset for start address */ 421 movl %edi,%edx 422 shrl $IDXSHIFT,%edx 423 andb $0xfc,%dl 424 4251: /* check PTE for each page */ 426 movb _PTmap(%edx),%al 427 andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 428 cmpb $0x07,%al 429 je 2f 430 431 /* simulate a trap */ 432 pushl %edx 433 pushl %ecx 434 shll $IDXSHIFT,%edx 435 pushl %edx 436 call _trapwrite /* trapwrite(addr) */ 437 popl %edx 438 popl %ecx 439 popl %edx 440 441 orl %eax,%eax /* if not ok, return EFAULT */ 442 jnz copyout_fault 443 4442: 445 addl $4,%edx 446 decl %ecx 447 jnz 1b /* check next page */ 448#endif /* I386_CPU */ 449 450 /* bcopy(%esi, %edi, %ebx) */ 4513: 452 cld 453 movl %ebx,%ecx 454 shrl $2,%ecx 455 rep 456 movsl 457 movb %bl,%cl 458 andb $3,%cl /* XXX can we trust the rest of %ecx on clones? */ 459 rep 460 movsb 461 462done_copyout: 463 popl %ebx 464 popl %edi 465 popl %esi 466 xorl %eax,%eax 467 movl _curpcb,%edx 468 movl %eax,PCB_ONFAULT(%edx) 469 ret 470 471 ALIGN_TEXT 472copyout_fault: 473 popl %ebx 474 popl %edi 475 popl %esi 476 movl _curpcb,%edx 477 movl $0,PCB_ONFAULT(%edx) 478 movl $EFAULT,%eax 479 ret 480 481/* copyin(from_user, to_kernel, len) */ 482ENTRY(copyin) 483 movl _curpcb,%eax 484 movl $copyin_fault,PCB_ONFAULT(%eax) 485 pushl %esi 486 pushl %edi 487 movl 12(%esp),%esi /* caddr_t from */ 488 movl 16(%esp),%edi /* caddr_t to */ 489 movl 20(%esp),%ecx /* size_t len */ 490 491 movb %cl,%al 492 shrl $2,%ecx /* copy longword-wise */ 493 cld 494 gs 495 rep 496 movsl 497 movb %al,%cl 498 andb $3,%cl /* copy remaining bytes */ 499 gs 500 rep 501 movsb 502 503 popl %edi 504 popl %esi 505 xorl %eax,%eax 506 movl _curpcb,%edx 507 movl %eax,PCB_ONFAULT(%edx) 508 ret 509 510 ALIGN_TEXT 511copyin_fault: 512 popl %edi 513 popl %esi 514 movl _curpcb,%edx 515 movl $0,PCB_ONFAULT(%edx) 516 movl $EFAULT,%eax 517 ret 518 519/* 520 * fu{byte,sword,word} : fetch a byte(sword, word) from user memory 521 */ 522ALTENTRY(fuiword) 523ENTRY(fuword) 524 movl __udatasel,%ax 525 movl %ax,%gs 526 movl _curpcb,%ecx 527 movl $fusufault,PCB_ONFAULT(%ecx) 528 movl 4(%esp),%edx 529 gs 530 movl (%edx),%eax 531 movl $0,PCB_ONFAULT(%ecx) 532 ret 533 534ENTRY(fusword) 535 movl __udatasel,%ax 536 movl %ax,%gs 537 movl _curpcb,%ecx 538 movl $fusufault,PCB_ONFAULT(%ecx) 539 movl 4(%esp),%edx 540 gs 541 movzwl (%edx),%eax 542 movl $0,PCB_ONFAULT(%ecx) 543 ret 544 545ALTENTRY(fuibyte) 546ENTRY(fubyte) 547 movl __udatasel,%ax 548 movl %ax,%gs 549 movl _curpcb,%ecx 550 movl $fusufault,PCB_ONFAULT(%ecx) 551 movl 4(%esp),%edx 552 gs 553 movzbl (%edx),%eax 554 movl $0,PCB_ONFAULT(%ecx) 555 ret 556 557 ALIGN_TEXT 558fusufault: 559 movl _curpcb,%ecx 560 xorl %eax,%eax 561 movl %eax,PCB_ONFAULT(%ecx) 562 decl %eax 563 ret 564 565/* 566 * su{byte,sword,word}: write a byte(word, longword) to user memory 567 */ 568/* 569 * we only have to set the right segment selector. 570 */ 571ALTENTRY(suiword) 572ENTRY(suword) 573 movl __udatasel,%ax 574 movl %ax,%gs 575 movl _curpcb,%ecx 576 movl $fusufault,PCB_ONFAULT(%ecx) 577 movl 4(%esp),%edx 578 579#if defined(I386_CPU) 580 581#if defined(I486_CPU) || defined(I586_CPU) 582 cmpl $CPUCLASS_386,_cpu_class 583 jne 2f 584#endif /* I486_CPU || I586_CPU */ 585 586 movl %edx,%eax 587 shrl $IDXSHIFT,%edx 588 andb $0xfc,%dl 589 movb _PTmap(%edx),%dl 590 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 591 cmpb $0x7,%dl 592 je 1f 593 594 /* simulate a trap */ 595 pushl %eax 596 call _trapwrite 597 popl %edx /* remove junk parameter from stack */ 598 movl _curpcb,%ecx /* restore trashed register */ 599 orl %eax,%eax 600 jnz fusufault 6011: 602 movl 4(%esp),%edx 603#endif 604 6052: 606 movl 8(%esp),%eax 607 gs 608 movl %eax,(%edx) 609 xorl %eax,%eax 610 movl %eax,PCB_ONFAULT(%ecx) 611 ret 612 613ENTRY(susword) 614 movl __udatasel,%eax 615 movl %ax,%gs 616 movl _curpcb,%ecx 617 movl $fusufault,PCB_ONFAULT(%ecx) 618 movl 4(%esp),%edx 619 620#if defined(I386_CPU) 621 622#if defined(I486_CPU) || defined(I586_CPU) 623 cmpl $CPUCLASS_386,_cpu_class 624 jne 2f 625#endif /* I486_CPU || I586_CPU */ 626 627 movl %edx,%eax 628 shrl $IDXSHIFT,%edx 629 andb $0xfc,%dl 630 movb _PTmap(%edx),%dl 631 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 632 cmpb $0x7,%dl 633 je 1f 634 635 /* simulate a trap */ 636 pushl %eax 637 call _trapwrite 638 popl %edx /* remove junk parameter from stack */ 639 movl _curpcb,%ecx /* restore trashed register */ 640 orl %eax,%eax 641 jnz fusufault 6421: 643 movl 4(%esp),%edx 644#endif 645 6462: 647 movw 8(%esp),%ax 648 gs 649 movw %ax,(%edx) 650 xorl %eax,%eax 651 movl %eax,PCB_ONFAULT(%ecx) 652 ret 653 654ALTENTRY(suibyte) 655ENTRY(subyte) 656 movl _curpcb,%ecx 657 movl $fusufault,PCB_ONFAULT(%ecx) 658 movl 4(%esp),%edx 659 660#if defined(I386_CPU) 661 662#if defined(I486_CPU) || defined(I586_CPU) 663 cmpl $CPUCLASS_386,_cpu_class 664 jne 2f 665#endif /* I486_CPU || I586_CPU */ 666 667 movl %edx,%eax 668 shrl $IDXSHIFT,%edx 669 andb $0xfc,%dl 670 movb _PTmap(%edx),%dl 671 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 672 cmpb $0x7,%dl 673 je 1f 674 675 /* simulate a trap */ 676 pushl %eax 677 call _trapwrite 678 popl %edx /* remove junk parameter from stack */ 679 movl _curpcb,%ecx /* restore trashed register */ 680 orl %eax,%eax 681 jnz fusufault 6821: 683 movl 4(%esp),%edx 684#endif 685 6862: 687 movb 8(%esp),%al 688 gs 689 movb %al,(%edx) 690 xorl %eax,%eax 691 movl %eax,PCB_ONFAULT(%ecx) 692 ret 693 694/* 695 * copyoutstr(from, to, maxlen, int *lencopied) 696 * copy a string from from to to, stop when a 0 character is reached. 697 * return ENAMETOOLONG if string is longer than maxlen, and 698 * EFAULT on protection violations. If lencopied is non-zero, 699 * return the actual length in *lencopied. 700 */ 701ENTRY(copyoutstr) 702 pushl %esi 703 pushl %edi 704 movl _curpcb,%ecx 705 movl $cpystrflt,PCB_ONFAULT(%ecx) 706 707 movl 12(%esp),%esi /* %esi = from */ 708 movl 16(%esp),%edi /* %edi = to */ 709 movl 20(%esp),%edx /* %edx = maxlen */ 710 711#if defined(I386_CPU) 712 713#if defined(I486_CPU) || defined(I586_CPU) 714 cmpl $CPUCLASS_386,_cpu_class 715 jne 5f 716#endif /* I486_CPU || I586_CPU */ 717 7181: 719 /* 720 * It suffices to check that the first byte is in user space, because 721 * we look at a page at a time and the end address is on a page 722 * boundary. 723 */ 724 cmpl $VM_MAXUSER_ADDRESS,%edi 725 jae cpystrflt 726 727 movl %edi,%eax 728 shrl $IDXSHIFT,%eax 729 andb $0xfc,%al 730 movb _PTmap(%eax),%al 731 andb $7,%al 732 cmpb $7,%al 733 je 2f 734 735 /* simulate trap */ 736 pushl %edx 737 pushl %edi 738 call _trapwrite 739 popl %edi 740 popl %edx 741 orl %eax,%eax 742 jnz cpystrflt 743 7442: /* copy up to end of this page */ 745 movl %edi,%eax 746 andl $NBPG-1,%eax 747 movl $NBPG,%ecx 748 subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ 749 cmpl %ecx,%edx 750 jge 3f 751 movl %edx,%ecx /* ecx = min(ecx, edx) */ 7523: 753 orl %ecx,%ecx 754 jz 4f 755 decl %ecx 756 decl %edx 757 lodsb 758 stosb 759 orb %al,%al 760 jnz 3b 761 762 /* Success -- 0 byte reached */ 763 decl %edx 764 xorl %eax,%eax 765 jmp 6f 766 7674: /* next page */ 768 orl %edx,%edx 769 jnz 1b 770 771 /* edx is zero -- return ENAMETOOLONG */ 772 movl $ENAMETOOLONG,%eax 773 jmp cpystrflt_x 774#endif /* I386_CPU */ 775 776#if defined(I486_CPU) || defined(I586_CPU) 7775: 778 incl %edx 7791: 780 decl %edx 781 jz 2f 782 /* 783 * gs override doesn't work for stosb. Use the same explicit check 784 * as in copyout(). It's much slower now because it is per-char. 785 * XXX - however, it would be faster to rewrite this function to use 786 * strlen() and copyout(). 787 */ 788 cmpl $VM_MAXUSER_ADDRESS,%edi 789 jae cpystrflt 790 791 lodsb 792 stosb 793 orb %al,%al 794 jnz 1b 795 796 /* Success -- 0 byte reached */ 797 decl %edx 798 xorl %eax,%eax 799 jmp cpystrflt_x 8002: 801 /* edx is zero -- return ENAMETOOLONG */ 802 movl $ENAMETOOLONG,%eax 803 jmp cpystrflt_x 804 805#endif /* I486_CPU || I586_CPU */ 806 807/* 808 * copyinstr(from, to, maxlen, int *lencopied) 809 * copy a string from from to to, stop when a 0 character is reached. 810 * return ENAMETOOLONG if string is longer than maxlen, and 811 * EFAULT on protection violations. If lencopied is non-zero, 812 * return the actual length in *lencopied. 813 */ 814ENTRY(copyinstr) 815 pushl %esi 816 pushl %edi 817 movl _curpcb,%ecx 818 movl $cpystrflt,PCB_ONFAULT(%ecx) 819 820 movl 12(%esp),%esi /* %esi = from */ 821 movl 16(%esp),%edi /* %edi = to */ 822 movl 20(%esp),%edx /* %edx = maxlen */ 823 movl __udatasel,%eax 824 movl %ax,%gs 825 incl %edx 826 8271: 828 decl %edx 829 jz 4f 830 gs 831 lodsb 832 stosb 833 orb %al,%al 834 jnz 1b 835 836 /* Success -- 0 byte reached */ 837 decl %edx 838 xorl %eax,%eax 839 jmp 6f 8404: 841 /* edx is zero -- return ENAMETOOLONG */ 842 movl $ENAMETOOLONG,%eax 843 jmp 6f 844 845cpystrflt: 846 movl $EFAULT,%eax 847cpystrflt_x: 8486: 849 /* set *lencopied and return %eax */ 850 movl _curpcb,%ecx 851 movl $0,PCB_ONFAULT(%ecx) 852 movl 20(%esp),%ecx 853 subl %edx,%ecx 854 movl 24(%esp),%edx 855 orl %edx,%edx 856 jz 7f 857 movl %ecx,(%edx) 8587: 859 popl %edi 860 popl %esi 861 ret 862 863 864/* 865 * copystr(from, to, maxlen, int *lencopied) 866 */ 867ENTRY(copystr) 868 pushl %esi 869 pushl %edi 870 871 movl 12(%esp),%esi /* %esi = from */ 872 movl 16(%esp),%edi /* %edi = to */ 873 movl 20(%esp),%edx /* %edx = maxlen */ 874 incl %edx 875 8761: 877 decl %edx 878 jz 4f 879 lodsb 880 stosb 881 orb %al,%al 882 jnz 1b 883 884 /* Success -- 0 byte reached */ 885 decl %edx 886 xorl %eax,%eax 887 jmp 6f 8884: 889 /* edx is zero -- return ENAMETOOLONG */ 890 movl $ENAMETOOLONG,%eax 891 8926: 893 /* set *lencopied and return %eax */ 894 movl 20(%esp),%ecx 895 subl %edx,%ecx 896 movl 24(%esp),%edx 897 orl %edx,%edx 898 jz 7f 899 movl %ecx,(%edx) 9007: 901 popl %edi 902 popl %esi 903 ret 904 905/* 906 * Handling of special 386 registers and descriptor tables etc 907 */ 908/* void lgdt(struct region_descriptor *rdp); */ 909ENTRY(lgdt) 910 /* reload the descriptor table */ 911 movl 4(%esp),%eax 912 lgdt (%eax) 913 914 /* flush the prefetch q */ 915 jmp 1f 916 nop 9171: 918 /* reload "stale" selectors */ 919 movl $KDSEL,%eax 920 movl %ax,%ds 921 movl %ax,%es 922 movl %ax,%ss 923 924 /* reload code selector by turning return into intersegmental return */ 925 movl (%esp),%eax 926 pushl %eax 927# movl $KCSEL,4(%esp) 928 movl $8,4(%esp) 929 lret 930 931/* 932 * void lidt(struct region_descriptor *rdp); 933 */ 934ENTRY(lidt) 935 movl 4(%esp),%eax 936 lidt (%eax) 937 ret 938 939/* 940 * void lldt(u_short sel) 941 */ 942ENTRY(lldt) 943 lldt 4(%esp) 944 ret 945 946/* 947 * void ltr(u_short sel) 948 */ 949ENTRY(ltr) 950 ltr 4(%esp) 951 ret 952 953/* ssdtosd(*ssdp,*sdp) */ 954ENTRY(ssdtosd) 955 pushl %ebx 956 movl 8(%esp),%ecx 957 movl 8(%ecx),%ebx 958 shll $16,%ebx 959 movl (%ecx),%edx 960 roll $16,%edx 961 movb %dh,%bl 962 movb %dl,%bh 963 rorl $8,%ebx 964 movl 4(%ecx),%eax 965 movw %ax,%dx 966 andl $0xf0000,%eax 967 orl %eax,%ebx 968 movl 12(%esp),%ecx 969 movl %edx,(%ecx) 970 movl %ebx,4(%ecx) 971 popl %ebx 972 ret 973 974#if 0 975/* tlbflush() */ 976ENTRY(tlbflush) 977 movl %cr3,%eax 978 orl $I386_CR3PAT,%eax 979 movl %eax,%cr3 980 ret 981#endif 982 983/* load_cr0(cr0) */ 984ENTRY(load_cr0) 985 movl 4(%esp),%eax 986 movl %eax,%cr0 987 ret 988 989/* rcr0() */ 990ENTRY(rcr0) 991 movl %cr0,%eax 992 ret 993 994/* rcr2() */ 995ENTRY(rcr2) 996 movl %cr2,%eax 997 ret 998 999/* rcr3() */ 1000ENTRY(rcr3) 1001 movl %cr3,%eax 1002 ret 1003 1004/* void load_cr3(caddr_t cr3) */ 1005ENTRY(load_cr3) 1006 movl 4(%esp),%eax 1007 orl $I386_CR3PAT,%eax 1008 movl %eax,%cr3 1009 ret 1010 1011 1012/*****************************************************************************/ 1013/* setjump, longjump */ 1014/*****************************************************************************/ 1015 1016ENTRY(setjmp) 1017 movl 4(%esp),%eax 1018 movl %ebx,(%eax) /* save ebx */ 1019 movl %esp,4(%eax) /* save esp */ 1020 movl %ebp,8(%eax) /* save ebp */ 1021 movl %esi,12(%eax) /* save esi */ 1022 movl %edi,16(%eax) /* save edi */ 1023 movl (%esp),%edx /* get rta */ 1024 movl %edx,20(%eax) /* save eip */ 1025 xorl %eax,%eax /* return(0); */ 1026 ret 1027 1028ENTRY(longjmp) 1029 movl 4(%esp),%eax 1030 movl (%eax),%ebx /* restore ebx */ 1031 movl 4(%eax),%esp /* restore esp */ 1032 movl 8(%eax),%ebp /* restore ebp */ 1033 movl 12(%eax),%esi /* restore esi */ 1034 movl 16(%eax),%edi /* restore edi */ 1035 movl 20(%eax),%edx /* get rta */ 1036 movl %edx,(%esp) /* put in return frame */ 1037 xorl %eax,%eax /* return(1); */ 1038 incl %eax 1039 ret 1040 1041