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