support.s revision 1838
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.13 1994/06/11 05:12:15 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 movl 8(%esp),%edx 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 movl 8(%esp),%edx 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 movl 8(%esp),%edx 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 movl 8(%esp),%edx 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 movl 8(%esp),%edx 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 movl 8(%esp),%edx 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/* 182 * void bzero(void *base, u_int cnt) 183 * Special code for I486 because stosl uses lots 184 * of clocks. Makes little or no difference on DX2 type 185 * machines, but stosl is about 1/2 as fast as 186 * memory moves on a standard DX !!!!! 187 */ 188ALTENTRY(blkclr) 189ENTRY(bzero) 190#if defined(I486_CPU) 191 cmpl $CPUCLASS_486,_cpu_class 192 jz 1f 193#endif 194 195 pushl %edi 196 movl 8(%esp),%edi 197 movl 12(%esp),%ecx 198 xorl %eax,%eax 199 shrl $2,%ecx 200 cld 201 rep 202 stosl 203 movl 12(%esp),%ecx 204 andl $3,%ecx 205 rep 206 stosb 207 popl %edi 208 ret 209 210#if defined(I486_CPU) 211 SUPERALIGN_TEXT 2121: 213 movl 4(%esp),%edx 214 movl 8(%esp),%ecx 215 xorl %eax,%eax 216/ 217/ do 64 byte chunks first 218/ 219/ XXX this is probably over-unrolled at least for DX2's 220/ 2212: 222 cmpl $64,%ecx 223 jb 3f 224 movl %eax,(%edx) 225 movl %eax,4(%edx) 226 movl %eax,8(%edx) 227 movl %eax,12(%edx) 228 movl %eax,16(%edx) 229 movl %eax,20(%edx) 230 movl %eax,24(%edx) 231 movl %eax,28(%edx) 232 movl %eax,32(%edx) 233 movl %eax,36(%edx) 234 movl %eax,40(%edx) 235 movl %eax,44(%edx) 236 movl %eax,48(%edx) 237 movl %eax,52(%edx) 238 movl %eax,56(%edx) 239 movl %eax,60(%edx) 240 addl $64,%edx 241 subl $64,%ecx 242 jnz 2b 243 ret 244 245/ 246/ do 16 byte chunks 247/ 248 SUPERALIGN_TEXT 2493: 250 cmpl $16,%ecx 251 jb 4f 252 movl %eax,(%edx) 253 movl %eax,4(%edx) 254 movl %eax,8(%edx) 255 movl %eax,12(%edx) 256 addl $16,%edx 257 subl $16,%ecx 258 jnz 3b 259 ret 260 261/ 262/ do 4 byte chunks 263/ 264 SUPERALIGN_TEXT 2654: 266 cmpl $4,%ecx 267 jb 5f 268 movl %eax,(%edx) 269 addl $4,%edx 270 subl $4,%ecx 271 jnz 4b 272 ret 273 274/ 275/ do 1 byte chunks 276/ a jump table seems to be faster than a loop or more range reductions 277/ 278/ XXX need a const section for non-text 279/ 280 SUPERALIGN_TEXT 281jtab: 282 .long do0 283 .long do1 284 .long do2 285 .long do3 286 287 SUPERALIGN_TEXT 2885: 289 jmp jtab(,%ecx,4) 290 291 SUPERALIGN_TEXT 292do3: 293 movw %ax,(%edx) 294 movb %al,2(%edx) 295 ret 296 297 SUPERALIGN_TEXT 298do2: 299 movw %ax,(%edx) 300 ret 301 302 SUPERALIGN_TEXT 303do1: 304 movb %al,(%edx) 305 306 SUPERALIGN_TEXT 307do0: 308 ret 309#endif /* I486_CPU */ 310 311/* fillw(pat, base, cnt) */ 312ENTRY(fillw) 313 pushl %edi 314 movl 8(%esp),%eax 315 movl 12(%esp),%edi 316 movl 16(%esp),%ecx 317 cld 318 rep 319 stosw 320 popl %edi 321 ret 322 323/* filli(pat, base, cnt) */ 324ENTRY(filli) 325 pushl %edi 326 movl 8(%esp),%eax 327 movl 12(%esp),%edi 328 movl 16(%esp),%ecx 329 cld 330 rep 331 stosl 332 popl %edi 333 ret 334 335ENTRY(bcopyb) 336bcopyb: 337 pushl %esi 338 pushl %edi 339 movl 12(%esp),%esi 340 movl 16(%esp),%edi 341 movl 20(%esp),%ecx 342 cmpl %esi,%edi /* potentially overlapping? */ 343 jnb 1f 344 cld /* nope, copy forwards */ 345 rep 346 movsb 347 popl %edi 348 popl %esi 349 ret 350 351 ALIGN_TEXT 3521: 353 addl %ecx,%edi /* copy backwards. */ 354 addl %ecx,%esi 355 std 356 decl %edi 357 decl %esi 358 rep 359 movsb 360 popl %edi 361 popl %esi 362 cld 363 ret 364 365ENTRY(bcopyw) 366bcopyw: 367 pushl %esi 368 pushl %edi 369 movl 12(%esp),%esi 370 movl 16(%esp),%edi 371 movl 20(%esp),%ecx 372 cmpl %esi,%edi /* potentially overlapping? */ 373 jnb 1f 374 shrl $1,%ecx /* copy by 16-bit words */ 375 cld /* nope, copy forwards */ 376 rep 377 movsw 378 adc %ecx,%ecx /* any bytes left? */ 379 rep 380 movsb 381 popl %edi 382 popl %esi 383 ret 384 385 ALIGN_TEXT 3861: 387 addl %ecx,%edi /* copy backwards */ 388 addl %ecx,%esi 389 andl $1,%ecx /* any fractional bytes? */ 390 decl %edi 391 decl %esi 392 std 393 rep 394 movsb 395 movl 20(%esp),%ecx /* copy remainder by 16-bit words */ 396 shrl $1,%ecx 397 decl %esi 398 decl %edi 399 rep 400 movsw 401 popl %edi 402 popl %esi 403 cld 404 ret 405 406ENTRY(bcopyx) 407 movl 16(%esp),%eax 408 cmpl $2,%eax 409 je bcopyw /* not _bcopyw, to avoid multiple mcounts */ 410 cmpl $4,%eax 411 je bcopy /* XXX the shared ret's break mexitcount */ 412 jmp bcopyb 413 414/* 415 * (ov)bcopy(src, dst, cnt) 416 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 417 */ 418ALTENTRY(ovbcopy) 419ENTRY(bcopy) 420bcopy: 421 pushl %esi 422 pushl %edi 423 movl 12(%esp),%esi 424 movl 16(%esp),%edi 425 movl 20(%esp),%ecx 426 cmpl %esi,%edi /* potentially overlapping? */ 427 jnb 1f 428 shrl $2,%ecx /* copy by 32-bit words */ 429 cld /* nope, copy forwards */ 430 rep 431 movsl 432 movl 20(%esp),%ecx 433 andl $3,%ecx /* any bytes left? */ 434 rep 435 movsb 436 popl %edi 437 popl %esi 438 ret 439 440 ALIGN_TEXT 4411: 442 addl %ecx,%edi /* copy backwards */ 443 addl %ecx,%esi 444 andl $3,%ecx /* any fractional bytes? */ 445 decl %edi 446 decl %esi 447 std 448 rep 449 movsb 450 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 451 shrl $2,%ecx 452 subl $3,%esi 453 subl $3,%edi 454 rep 455 movsl 456 popl %edi 457 popl %esi 458 cld 459 ret 460 461 462/*****************************************************************************/ 463/* copyout and fubyte family */ 464/*****************************************************************************/ 465/* 466 * Access user memory from inside the kernel. These routines and possibly 467 * the math- and DOS emulators should be the only places that do this. 468 * 469 * We have to access the memory with user's permissions, so use a segment 470 * selector with RPL 3. For writes to user space we have to additionally 471 * check the PTE for write permission, because the 386 does not check 472 * write permissions when we are executing with EPL 0. The 486 does check 473 * this if the WP bit is set in CR0, so we can use a simpler version here. 474 * 475 * These routines set curpcb->onfault for the time they execute. When a 476 * protection violation occurs inside the functions, the trap handler 477 * returns to *curpcb->onfault instead of the function. 478 */ 479 480 481ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 482 movl _curpcb,%eax 483 movl $copyout_fault,PCB_ONFAULT(%eax) 484 pushl %esi 485 pushl %edi 486 pushl %ebx 487 movl 16(%esp),%esi 488 movl 20(%esp),%edi 489 movl 24(%esp),%ebx 490 orl %ebx,%ebx /* anything to do? */ 491 jz done_copyout 492 493 /* 494 * Check explicitly for non-user addresses. If 486 write protection 495 * is being used, this check is essential because we are in kernel 496 * mode so the h/w does not provide any protection against writing 497 * kernel addresses. 498 * 499 * Otherwise, it saves having to load and restore %es to get the 500 * usual segment-based protection (the destination segment for movs 501 * is always %es). The other explicit checks for user-writablility 502 * are not quite sufficient. They fail for the user area because 503 * we mapped the user area read/write to avoid having an #ifdef in 504 * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 505 * addresses including 0xff800000 and 0xfc000000). I'm not sure if 506 * this can be fixed. Marking the PTEs supervisor mode and the 507 * PDE's user mode would almost work, but there may be a problem 508 * with the self-referential PDE. 509 */ 510 movl %edi,%eax 511 addl %ebx,%eax 512 jc copyout_fault 513/* 514 * XXX STOP USING VM_MAXUSER_ADDRESS. 515 * It is an end address, not a max, so every time it is used correctly it 516 * looks like there is an off by one error, and of course it caused an off 517 * by one error in several places. 518 */ 519 cmpl $VM_MAXUSER_ADDRESS,%eax 520 ja copyout_fault 521 522#if defined(I386_CPU) 523 524#if defined(I486_CPU) || defined(I586_CPU) 525 cmpl $CPUCLASS_386,_cpu_class 526 jne 3f 527#endif 528/* 529 * We have to check each PTE for user write permission. 530 * The checking may cause a page fault, so it is important to set 531 * up everything for return via copyout_fault before here. 532 */ 533 /* compute number of pages */ 534 movl %edi,%ecx 535 andl $NBPG-1,%ecx 536 addl %ebx,%ecx 537 decl %ecx 538 shrl $IDXSHIFT+2,%ecx 539 incl %ecx 540 541 /* compute PTE offset for start address */ 542 movl %edi,%edx 543 shrl $IDXSHIFT,%edx 544 andb $0xfc,%dl 545 5461: /* check PTE for each page */ 547 movb _PTmap(%edx),%al 548 andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 549 cmpb $0x07,%al 550 je 2f 551 552 /* simulate a trap */ 553 pushl %edx 554 pushl %ecx 555 shll $IDXSHIFT,%edx 556 pushl %edx 557 call _trapwrite /* trapwrite(addr) */ 558 popl %edx 559 popl %ecx 560 popl %edx 561 562 orl %eax,%eax /* if not ok, return EFAULT */ 563 jnz copyout_fault 564 5652: 566 addl $4,%edx 567 decl %ecx 568 jnz 1b /* check next page */ 569#endif /* I386_CPU */ 570 571 /* bcopy(%esi, %edi, %ebx) */ 5723: 573 movl %ebx,%ecx 574 shrl $2,%ecx 575 cld 576 rep 577 movsl 578 movb %bl,%cl 579 andb $3,%cl 580 rep 581 movsb 582 583done_copyout: 584 popl %ebx 585 popl %edi 586 popl %esi 587 xorl %eax,%eax 588 movl _curpcb,%edx 589 movl %eax,PCB_ONFAULT(%edx) 590 ret 591 592 ALIGN_TEXT 593copyout_fault: 594 popl %ebx 595 popl %edi 596 popl %esi 597 movl _curpcb,%edx 598 movl $0,PCB_ONFAULT(%edx) 599 movl $EFAULT,%eax 600 ret 601 602/* copyin(from_user, to_kernel, len) */ 603ENTRY(copyin) 604 movl _curpcb,%eax 605 movl $copyin_fault,PCB_ONFAULT(%eax) 606 pushl %esi 607 pushl %edi 608 movl 12(%esp),%esi /* caddr_t from */ 609 movl 16(%esp),%edi /* caddr_t to */ 610 movl 20(%esp),%ecx /* size_t len */ 611 612 /* 613 * make sure address is valid 614 */ 615 movl %esi,%edx 616 addl %ecx,%edx 617 jc copyin_fault 618 cmpl $VM_MAXUSER_ADDRESS,%edx 619 ja copyin_fault 620 621 movb %cl,%al 622 shrl $2,%ecx /* copy longword-wise */ 623 cld 624 rep 625 movsl 626 movb %al,%cl 627 andb $3,%cl /* copy remaining bytes */ 628 rep 629 movsb 630 631 popl %edi 632 popl %esi 633 xorl %eax,%eax 634 movl _curpcb,%edx 635 movl %eax,PCB_ONFAULT(%edx) 636 ret 637 638 ALIGN_TEXT 639copyin_fault: 640 popl %edi 641 popl %esi 642 movl _curpcb,%edx 643 movl $0,PCB_ONFAULT(%edx) 644 movl $EFAULT,%eax 645 ret 646 647/* 648 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory 649 */ 650ALTENTRY(fuiword) 651ENTRY(fuword) 652 movl _curpcb,%ecx 653 movl $fusufault,PCB_ONFAULT(%ecx) 654 movl 4(%esp),%edx /* from */ 655 656 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 657 ja fusufault 658 659 movl (%edx),%eax 660 movl $0,PCB_ONFAULT(%ecx) 661 ret 662 663/* 664 * These two routines are called from the profiling code, potentially 665 * at interrupt time. If they fail, that's okay, good things will 666 * happen later. Fail all the time for now - until the trap code is 667 * able to deal with this. 668 */ 669ALTENTRY(suswintr) 670ENTRY(fuswintr) 671 movl $-1,%eax 672 ret 673 674ENTRY(fusword) 675 movl _curpcb,%ecx 676 movl $fusufault,PCB_ONFAULT(%ecx) 677 movl 4(%esp),%edx 678 679 cmpl $VM_MAXUSER_ADDRESS-2,%edx 680 ja fusufault 681 682 movzwl (%edx),%eax 683 movl $0,PCB_ONFAULT(%ecx) 684 ret 685 686ALTENTRY(fuibyte) 687ENTRY(fubyte) 688 movl _curpcb,%ecx 689 movl $fusufault,PCB_ONFAULT(%ecx) 690 movl 4(%esp),%edx 691 692 cmpl $VM_MAXUSER_ADDRESS-1,%edx 693 ja fusufault 694 695 movzbl (%edx),%eax 696 movl $0,PCB_ONFAULT(%ecx) 697 ret 698 699 ALIGN_TEXT 700fusufault: 701 movl _curpcb,%ecx 702 xorl %eax,%eax 703 movl %eax,PCB_ONFAULT(%ecx) 704 decl %eax 705 ret 706 707/* 708 * su{byte,sword,word}: write a byte (word, longword) to user memory 709 */ 710ALTENTRY(suiword) 711ENTRY(suword) 712 movl _curpcb,%ecx 713 movl $fusufault,PCB_ONFAULT(%ecx) 714 movl 4(%esp),%edx 715 716#if defined(I386_CPU) 717 718#if defined(I486_CPU) || defined(I586_CPU) 719 cmpl $CPUCLASS_386,_cpu_class 720 jne 2f /* we only have to set the right segment selector */ 721#endif /* I486_CPU || I586_CPU */ 722 723 /* XXX - page boundary crossing is still not handled */ 724 movl %edx,%eax 725 shrl $IDXSHIFT,%edx 726 andb $0xfc,%dl 727 movb _PTmap(%edx),%dl 728 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 729 cmpb $0x7,%dl 730 je 1f 731 732 /* simulate a trap */ 733 pushl %eax 734 call _trapwrite 735 popl %edx /* remove junk parameter from stack */ 736 movl _curpcb,%ecx /* restore trashed register */ 737 orl %eax,%eax 738 jnz fusufault 7391: 740 movl 4(%esp),%edx 741#endif 742 7432: 744 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 745 ja fusufault 746 747 movl 8(%esp),%eax 748 movl %eax,(%edx) 749 xorl %eax,%eax 750 movl %eax,PCB_ONFAULT(%ecx) 751 ret 752 753ENTRY(susword) 754 movl _curpcb,%ecx 755 movl $fusufault,PCB_ONFAULT(%ecx) 756 movl 4(%esp),%edx 757 758#if defined(I386_CPU) 759 760#if defined(I486_CPU) || defined(I586_CPU) 761 cmpl $CPUCLASS_386,_cpu_class 762 jne 2f 763#endif /* I486_CPU || I586_CPU */ 764 765 /* XXX - page boundary crossing is still not handled */ 766 movl %edx,%eax 767 shrl $IDXSHIFT,%edx 768 andb $0xfc,%dl 769 movb _PTmap(%edx),%dl 770 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 771 cmpb $0x7,%dl 772 je 1f 773 774 /* simulate a trap */ 775 pushl %eax 776 call _trapwrite 777 popl %edx /* remove junk parameter from stack */ 778 movl _curpcb,%ecx /* restore trashed register */ 779 orl %eax,%eax 780 jnz fusufault 7811: 782 movl 4(%esp),%edx 783#endif 784 7852: 786 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 787 ja fusufault 788 789 movw 8(%esp),%ax 790 movw %ax,(%edx) 791 xorl %eax,%eax 792 movl %eax,PCB_ONFAULT(%ecx) 793 ret 794 795ALTENTRY(suibyte) 796ENTRY(subyte) 797 movl _curpcb,%ecx 798 movl $fusufault,PCB_ONFAULT(%ecx) 799 movl 4(%esp),%edx 800 801#if defined(I386_CPU) 802 803#if defined(I486_CPU) || defined(I586_CPU) 804 cmpl $CPUCLASS_386,_cpu_class 805 jne 2f 806#endif /* I486_CPU || I586_CPU */ 807 808 movl %edx,%eax 809 shrl $IDXSHIFT,%edx 810 andb $0xfc,%dl 811 movb _PTmap(%edx),%dl 812 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 813 cmpb $0x7,%dl 814 je 1f 815 816 /* simulate a trap */ 817 pushl %eax 818 call _trapwrite 819 popl %edx /* remove junk parameter from stack */ 820 movl _curpcb,%ecx /* restore trashed register */ 821 orl %eax,%eax 822 jnz fusufault 8231: 824 movl 4(%esp),%edx 825#endif 826 8272: 828 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 829 ja fusufault 830 831 movb 8(%esp),%al 832 movb %al,(%edx) 833 xorl %eax,%eax 834 movl %eax,PCB_ONFAULT(%ecx) 835 ret 836 837/* 838 * copyoutstr(from, to, maxlen, int *lencopied) 839 * copy a string from from to to, stop when a 0 character is reached. 840 * return ENAMETOOLONG if string is longer than maxlen, and 841 * EFAULT on protection violations. If lencopied is non-zero, 842 * return the actual length in *lencopied. 843 */ 844ENTRY(copyoutstr) 845 pushl %esi 846 pushl %edi 847 movl _curpcb,%ecx 848 movl $cpystrflt,PCB_ONFAULT(%ecx) /* XXX rename copyoutstr_fault */ 849 850 movl 12(%esp),%esi /* %esi = from */ 851 movl 16(%esp),%edi /* %edi = to */ 852 movl 20(%esp),%edx /* %edx = maxlen */ 853 cld 854 855#if defined(I386_CPU) 856 857#if defined(I486_CPU) || defined(I586_CPU) 858 cmpl $CPUCLASS_386,_cpu_class 859 jne 5f 860#endif /* I486_CPU || I586_CPU */ 861 8621: 863 /* 864 * It suffices to check that the first byte is in user space, because 865 * we look at a page at a time and the end address is on a page 866 * boundary. 867 */ 868 cmpl $VM_MAXUSER_ADDRESS-1,%edi 869 ja cpystrflt 870 871 movl %edi,%eax 872 shrl $IDXSHIFT,%eax 873 andb $0xfc,%al 874 movb _PTmap(%eax),%al 875 andb $7,%al 876 cmpb $7,%al 877 je 2f 878 879 /* simulate trap */ 880 pushl %edx 881 pushl %edi 882 call _trapwrite 883 cld 884 popl %edi 885 popl %edx 886 orl %eax,%eax 887 jnz cpystrflt 888 8892: /* copy up to end of this page */ 890 movl %edi,%eax 891 andl $NBPG-1,%eax 892 movl $NBPG,%ecx 893 subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ 894 cmpl %ecx,%edx 895 jae 3f 896 movl %edx,%ecx /* ecx = min(ecx, edx) */ 8973: 898 orl %ecx,%ecx 899 jz 4f 900 decl %ecx 901 decl %edx 902 lodsb 903 stosb 904 orb %al,%al 905 jnz 3b 906 907 /* Success -- 0 byte reached */ 908 decl %edx 909 xorl %eax,%eax 910 jmp 6f 911 9124: /* next page */ 913 orl %edx,%edx 914 jnz 1b 915 916 /* edx is zero -- return ENAMETOOLONG */ 917 movl $ENAMETOOLONG,%eax 918 jmp cpystrflt_x 919#endif /* I386_CPU */ 920 921#if defined(I486_CPU) || defined(I586_CPU) 9225: 923 incl %edx 9241: 925 decl %edx 926 jz 2f 927 /* 928 * XXX - would be faster to rewrite this function to use 929 * strlen() and copyout(). 930 */ 931 cmpl $VM_MAXUSER_ADDRESS-1,%edi 932 ja cpystrflt 933 934 lodsb 935 stosb 936 orb %al,%al 937 jnz 1b 938 939 /* Success -- 0 byte reached */ 940 decl %edx 941 xorl %eax,%eax 942 jmp cpystrflt_x 9432: 944 /* edx is zero -- return ENAMETOOLONG */ 945 movl $ENAMETOOLONG,%eax 946 jmp cpystrflt_x 947 948#endif /* I486_CPU || I586_CPU */ 949 950/* 951 * This was split from copyinstr_fault mainly because pushing gs changes the 952 * stack offsets. It's better to have it separate for mcounting too. 953 */ 954cpystrflt: 955 movl $EFAULT,%eax 956cpystrflt_x: 957 /* set *lencopied and return %eax */ 958 movl _curpcb,%ecx 959 movl $0,PCB_ONFAULT(%ecx) 960 movl 20(%esp),%ecx 961 subl %edx,%ecx 962 movl 24(%esp),%edx 963 orl %edx,%edx 964 jz 1f 965 movl %ecx,(%edx) 9661: 967 popl %edi 968 popl %esi 969 ret 970 971 972/* 973 * copyinstr(from, to, maxlen, int *lencopied) 974 * copy a string from from to to, stop when a 0 character is reached. 975 * return ENAMETOOLONG if string is longer than maxlen, and 976 * EFAULT on protection violations. If lencopied is non-zero, 977 * return the actual length in *lencopied. 978 */ 979ENTRY(copyinstr) 980 pushl %esi 981 pushl %edi 982 movl _curpcb,%ecx 983 movl $copyinstr_fault,PCB_ONFAULT(%ecx) 984 985 movl 12(%esp),%esi /* %esi = from */ 986 movl 16(%esp),%edi /* %edi = to */ 987 movl 20(%esp),%edx /* %edx = maxlen */ 988 /* 989 * XXX should avoid touching gs. Either copy the string in and 990 * check the bounds later or get its length and check the bounds 991 * and then use copyin(). 992 */ 993 pushl %gs 994 movl __udatasel,%eax 995 movl %ax,%gs 996 incl %edx 997 cld 9981: 999 decl %edx 1000 jz 2f 1001 gs 1002 lodsb 1003 stosb 1004 orb %al,%al 1005 jnz 1b 1006 1007 /* Success -- 0 byte reached */ 1008 decl %edx 1009 xorl %eax,%eax 1010 jmp 3f 10112: 1012 /* edx is zero -- return ENAMETOOLONG */ 1013 movl $ENAMETOOLONG,%eax 1014 jmp 3f 1015 1016 ALIGN_TEXT 1017copyinstr_fault: 1018 movl $EFAULT,%eax 10193: 1020 /* set *lencopied and return %eax */ 1021 movl _curpcb,%ecx 1022 movl $0,PCB_ONFAULT(%ecx) 1023 movl 24(%esp),%ecx 1024 subl %edx,%ecx 1025 movl 28(%esp),%edx 1026 orl %edx,%edx 1027 jz 4f 1028 movl %ecx,(%edx) 10294: 1030 popl %gs 1031 popl %edi 1032 popl %esi 1033 ret 1034 1035 1036/* 1037 * copystr(from, to, maxlen, int *lencopied) 1038 */ 1039ENTRY(copystr) 1040 pushl %esi 1041 pushl %edi 1042 1043 movl 12(%esp),%esi /* %esi = from */ 1044 movl 16(%esp),%edi /* %edi = to */ 1045 movl 20(%esp),%edx /* %edx = maxlen */ 1046 incl %edx 1047 cld 10481: 1049 decl %edx 1050 jz 4f 1051 lodsb 1052 stosb 1053 orb %al,%al 1054 jnz 1b 1055 1056 /* Success -- 0 byte reached */ 1057 decl %edx 1058 xorl %eax,%eax 1059 jmp 6f 10604: 1061 /* edx is zero -- return ENAMETOOLONG */ 1062 movl $ENAMETOOLONG,%eax 1063 10646: 1065 /* set *lencopied and return %eax */ 1066 movl 20(%esp),%ecx 1067 subl %edx,%ecx 1068 movl 24(%esp),%edx 1069 orl %edx,%edx 1070 jz 7f 1071 movl %ecx,(%edx) 10727: 1073 popl %edi 1074 popl %esi 1075 ret 1076 1077/* 1078 * Miscellaneous kernel support functions 1079 */ 1080ALTENTRY(ntohl) 1081ENTRY(htonl) 1082 movl 4(%esp),%eax 1083#ifndef I386_CPU 1084/* XXX */ 1085/* Since Gas 1.38 does not grok bswap this has been coded as the 1086 * equivalent bytes. This can be changed back to bswap when we 1087 * upgrade to a newer version of Gas 1088 */ 1089 /* bswap %eax */ 1090 .byte 0x0f 1091 .byte 0xc8 1092#else 1093 xchgb %al,%ah 1094 roll $16,%eax 1095 xchgb %al,%ah 1096#endif 1097 ret 1098 1099ALTENTRY(ntohs) 1100ENTRY(htons) 1101 movzwl 4(%esp),%eax 1102 xchgb %al,%ah 1103 ret 1104 1105ENTRY(ffs) 1106 bsfl 4(%esp),%eax 1107 jz 1f 1108 incl %eax 1109 ret 11101: 1111 xorl %eax,%eax 1112 ret 1113 1114ENTRY(bcmp) 1115 pushl %edi 1116 pushl %esi 1117 movl 12(%esp),%edi 1118 movl 16(%esp),%esi 1119 movl 20(%esp),%edx 1120 xorl %eax,%eax 1121 1122 movl %edx,%ecx 1123 shrl $2,%ecx 1124 cld /* compare forwards */ 1125 repe 1126 cmpsl 1127 jne 1f 1128 1129 movl %edx,%ecx 1130 andl $3,%ecx 1131 repe 1132 cmpsb 1133 je 2f 11341: 1135 incl %eax 11362: 1137 popl %esi 1138 popl %edi 1139 ret 1140 1141 1142/* 1143 * Handling of special 386 registers and descriptor tables etc 1144 */ 1145/* void lgdt(struct region_descriptor *rdp); */ 1146ENTRY(lgdt) 1147 /* reload the descriptor table */ 1148 movl 4(%esp),%eax 1149 lgdt (%eax) 1150 1151 /* flush the prefetch q */ 1152 jmp 1f 1153 nop 11541: 1155 /* reload "stale" selectors */ 1156 movl $KDSEL,%eax 1157 movl %ax,%ds 1158 movl %ax,%es 1159 movl %ax,%ss 1160 1161 /* reload code selector by turning return into intersegmental return */ 1162 movl (%esp),%eax 1163 pushl %eax 1164# movl $KCSEL,4(%esp) 1165 movl $8,4(%esp) 1166 lret 1167 1168/* 1169 * void lidt(struct region_descriptor *rdp); 1170 */ 1171ENTRY(lidt) 1172 movl 4(%esp),%eax 1173 lidt (%eax) 1174 ret 1175 1176/* 1177 * void lldt(u_short sel) 1178 */ 1179ENTRY(lldt) 1180 lldt 4(%esp) 1181 ret 1182 1183/* 1184 * void ltr(u_short sel) 1185 */ 1186ENTRY(ltr) 1187 ltr 4(%esp) 1188 ret 1189 1190/* ssdtosd(*ssdp,*sdp) */ 1191ENTRY(ssdtosd) 1192 pushl %ebx 1193 movl 8(%esp),%ecx 1194 movl 8(%ecx),%ebx 1195 shll $16,%ebx 1196 movl (%ecx),%edx 1197 roll $16,%edx 1198 movb %dh,%bl 1199 movb %dl,%bh 1200 rorl $8,%ebx 1201 movl 4(%ecx),%eax 1202 movw %ax,%dx 1203 andl $0xf0000,%eax 1204 orl %eax,%ebx 1205 movl 12(%esp),%ecx 1206 movl %edx,(%ecx) 1207 movl %ebx,4(%ecx) 1208 popl %ebx 1209 ret 1210 1211/* load_cr0(cr0) */ 1212ENTRY(load_cr0) 1213 movl 4(%esp),%eax 1214 movl %eax,%cr0 1215 ret 1216 1217/* rcr0() */ 1218ENTRY(rcr0) 1219 movl %cr0,%eax 1220 ret 1221 1222/* rcr3() */ 1223ENTRY(rcr3) 1224 movl %cr3,%eax 1225 ret 1226 1227/* void load_cr3(caddr_t cr3) */ 1228ENTRY(load_cr3) 1229 movl 4(%esp),%eax 1230 orl $I386_CR3PAT,%eax 1231 movl %eax,%cr3 1232 ret 1233 1234 1235/*****************************************************************************/ 1236/* setjump, longjump */ 1237/*****************************************************************************/ 1238 1239ENTRY(setjmp) 1240 movl 4(%esp),%eax 1241 movl %ebx,(%eax) /* save ebx */ 1242 movl %esp,4(%eax) /* save esp */ 1243 movl %ebp,8(%eax) /* save ebp */ 1244 movl %esi,12(%eax) /* save esi */ 1245 movl %edi,16(%eax) /* save edi */ 1246 movl (%esp),%edx /* get rta */ 1247 movl %edx,20(%eax) /* save eip */ 1248 xorl %eax,%eax /* return(0); */ 1249 ret 1250 1251ENTRY(longjmp) 1252 movl 4(%esp),%eax 1253 movl (%eax),%ebx /* restore ebx */ 1254 movl 4(%eax),%esp /* restore esp */ 1255 movl 8(%eax),%ebp /* restore ebp */ 1256 movl 12(%eax),%esi /* restore esi */ 1257 movl 16(%eax),%edi /* restore edi */ 1258 movl 20(%eax),%edx /* get rta */ 1259 movl %edx,(%esp) /* put in return frame */ 1260 xorl %eax,%eax /* return(1); */ 1261 incl %eax 1262 ret 1263