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