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