support.s revision 2689
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.16 1994/09/04 10:24:22 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/* 952 * copyinstr(from, to, maxlen, int *lencopied) 953 * copy a string from from to to, stop when a 0 character is reached. 954 * return ENAMETOOLONG if string is longer than maxlen, and 955 * EFAULT on protection violations. If lencopied is non-zero, 956 * return the actual length in *lencopied. 957 */ 958ENTRY(copyinstr) 959 pushl %esi 960 pushl %edi 961 movl _curpcb,%ecx 962 movl $cpystrflt,PCB_ONFAULT(%ecx) 963 964 movl 12(%esp),%esi /* %esi = from */ 965 movl 16(%esp),%edi /* %edi = to */ 966 movl 20(%esp),%edx /* %edx = maxlen */ 967 968 movl $VM_MAXUSER_ADDRESS,%eax 969 970 /* make sure 'from' is within bounds */ 971 subl %esi,%eax 972 jbe cpystrflt 973 974 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 975 cmpl %edx,%eax 976 jae 1f 977 movl %eax,%edx 978 movl %eax,20(%esp) 9791: 980 incl %edx 981 cld 982 9832: 984 decl %edx 985 jz 3f 986 987 lodsb 988 stosb 989 orb %al,%al 990 jnz 2b 991 992 /* Success -- 0 byte reached */ 993 decl %edx 994 xorl %eax,%eax 995 jmp cpystrflt_x 9963: 997 /* edx is zero - return ENAMETOOLONG or EFAULT */ 998 cmpl $VM_MAXUSER_ADDRESS,%esi 999 jae cpystrflt 10004: 1001 movl $ENAMETOOLONG,%eax 1002 jmp cpystrflt_x 1003 1004cpystrflt: 1005 movl $EFAULT,%eax 1006 1007cpystrflt_x: 1008 /* set *lencopied and return %eax */ 1009 movl _curpcb,%ecx 1010 movl $0,PCB_ONFAULT(%ecx) 1011 movl 20(%esp),%ecx 1012 subl %edx,%ecx 1013 movl 24(%esp),%edx 1014 testl %edx,%edx 1015 jz 1f 1016 movl %ecx,(%edx) 10171: 1018 popl %edi 1019 popl %esi 1020 ret 1021 1022 1023/* 1024 * copystr(from, to, maxlen, int *lencopied) 1025 */ 1026ENTRY(copystr) 1027 pushl %esi 1028 pushl %edi 1029 1030 movl 12(%esp),%esi /* %esi = from */ 1031 movl 16(%esp),%edi /* %edi = to */ 1032 movl 20(%esp),%edx /* %edx = maxlen */ 1033 incl %edx 1034 cld 10351: 1036 decl %edx 1037 jz 4f 1038 lodsb 1039 stosb 1040 orb %al,%al 1041 jnz 1b 1042 1043 /* Success -- 0 byte reached */ 1044 decl %edx 1045 xorl %eax,%eax 1046 jmp 6f 10474: 1048 /* edx is zero -- return ENAMETOOLONG */ 1049 movl $ENAMETOOLONG,%eax 1050 10516: 1052 /* set *lencopied and return %eax */ 1053 movl 20(%esp),%ecx 1054 subl %edx,%ecx 1055 movl 24(%esp),%edx 1056 orl %edx,%edx 1057 jz 7f 1058 movl %ecx,(%edx) 10597: 1060 popl %edi 1061 popl %esi 1062 ret 1063 1064/* 1065 * Miscellaneous kernel support functions 1066 */ 1067ENTRY(ffs) 1068 bsfl 4(%esp),%eax 1069 jz 1f 1070 incl %eax 1071 ret 10721: 1073 xorl %eax,%eax 1074 ret 1075 1076ENTRY(bcmp) 1077 pushl %edi 1078 pushl %esi 1079 movl 12(%esp),%edi 1080 movl 16(%esp),%esi 1081 movl 20(%esp),%edx 1082 xorl %eax,%eax 1083 1084 movl %edx,%ecx 1085 shrl $2,%ecx 1086 cld /* compare forwards */ 1087 repe 1088 cmpsl 1089 jne 1f 1090 1091 movl %edx,%ecx 1092 andl $3,%ecx 1093 repe 1094 cmpsb 1095 je 2f 10961: 1097 incl %eax 10982: 1099 popl %esi 1100 popl %edi 1101 ret 1102 1103 1104/* 1105 * Handling of special 386 registers and descriptor tables etc 1106 */ 1107/* void lgdt(struct region_descriptor *rdp); */ 1108ENTRY(lgdt) 1109 /* reload the descriptor table */ 1110 movl 4(%esp),%eax 1111 lgdt (%eax) 1112 1113 /* flush the prefetch q */ 1114 jmp 1f 1115 nop 11161: 1117 /* reload "stale" selectors */ 1118 movl $KDSEL,%eax 1119 movl %ax,%ds 1120 movl %ax,%es 1121 movl %ax,%ss 1122 1123 /* reload code selector by turning return into intersegmental return */ 1124 movl (%esp),%eax 1125 pushl %eax 1126# movl $KCSEL,4(%esp) 1127 movl $8,4(%esp) 1128 lret 1129 1130/* 1131 * void lidt(struct region_descriptor *rdp); 1132 */ 1133ENTRY(lidt) 1134 movl 4(%esp),%eax 1135 lidt (%eax) 1136 ret 1137 1138/* 1139 * void lldt(u_short sel) 1140 */ 1141ENTRY(lldt) 1142 lldt 4(%esp) 1143 ret 1144 1145/* 1146 * void ltr(u_short sel) 1147 */ 1148ENTRY(ltr) 1149 ltr 4(%esp) 1150 ret 1151 1152/* ssdtosd(*ssdp,*sdp) */ 1153ENTRY(ssdtosd) 1154 pushl %ebx 1155 movl 8(%esp),%ecx 1156 movl 8(%ecx),%ebx 1157 shll $16,%ebx 1158 movl (%ecx),%edx 1159 roll $16,%edx 1160 movb %dh,%bl 1161 movb %dl,%bh 1162 rorl $8,%ebx 1163 movl 4(%ecx),%eax 1164 movw %ax,%dx 1165 andl $0xf0000,%eax 1166 orl %eax,%ebx 1167 movl 12(%esp),%ecx 1168 movl %edx,(%ecx) 1169 movl %ebx,4(%ecx) 1170 popl %ebx 1171 ret 1172 1173/* load_cr0(cr0) */ 1174ENTRY(load_cr0) 1175 movl 4(%esp),%eax 1176 movl %eax,%cr0 1177 ret 1178 1179/* rcr0() */ 1180ENTRY(rcr0) 1181 movl %cr0,%eax 1182 ret 1183 1184/* rcr3() */ 1185ENTRY(rcr3) 1186 movl %cr3,%eax 1187 ret 1188 1189/* void load_cr3(caddr_t cr3) */ 1190ENTRY(load_cr3) 1191 movl 4(%esp),%eax 1192 movl %eax,%cr3 1193 ret 1194 1195 1196/*****************************************************************************/ 1197/* setjump, longjump */ 1198/*****************************************************************************/ 1199 1200ENTRY(setjmp) 1201 movl 4(%esp),%eax 1202 movl %ebx,(%eax) /* save ebx */ 1203 movl %esp,4(%eax) /* save esp */ 1204 movl %ebp,8(%eax) /* save ebp */ 1205 movl %esi,12(%eax) /* save esi */ 1206 movl %edi,16(%eax) /* save edi */ 1207 movl (%esp),%edx /* get rta */ 1208 movl %edx,20(%eax) /* save eip */ 1209 xorl %eax,%eax /* return(0); */ 1210 ret 1211 1212ENTRY(longjmp) 1213 movl 4(%esp),%eax 1214 movl (%eax),%ebx /* restore ebx */ 1215 movl 4(%eax),%esp /* restore esp */ 1216 movl 8(%eax),%ebp /* restore ebp */ 1217 movl 12(%eax),%esi /* restore esi */ 1218 movl 16(%eax),%edi /* restore edi */ 1219 movl 20(%eax),%edx /* get rta */ 1220 movl %edx,(%esp) /* put in return frame */ 1221 xorl %eax,%eax /* return(1); */ 1222 incl %eax 1223 ret 1224