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